ipmiutil-3.1.9/0000755000000000000000000000000014403633316012061 5ustar rootrootipmiutil-3.1.9/TODO0000644000000000000000000003400414373712016012553 0ustar rootroot IPMIUTIL PROJECT TODO LIST: IPV6 for IPMI LAN on Windows: Currently support IPV6 on Linux, but need to implement for Windows also . implement IPV6 for Windows (#ifdef WIN32 case) PARTIAL in ipmiutil-3.1.4 07/18/2019 with HAVE_IPV6, not fully enabled Thread-safe changes for IPMI LAN: Change ipmicmd.c/ipmilan.c to be thread-safe if accessing multiple nodes. Currently it is only conditionally safe, if threads access the same node. Will require adding a context struct param to the ipmi_cmd*() funcs. May need to add new thread-safe functions to retain back-compatibility. PARTIAL in ipmiutil-2.9.0, multiple nodes in sequence is fixed . need to change to context structure for ipmilan Add an option/variant of canonical output for CSV (delimiter = ',') The current delimiter for -c is '|' 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 SPD decoding: . handle DDR4 SPD format . 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 c Get/Set SEL UTC Offset (requested 4/22/13) . Forwarded Command PARTIAL in ipmiutil-2.8.1, adding Get/Set System Info functions PARTIAL in ipmiutil-3.0.3, adding Get/Set SEL UTC Offset functions Add more 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 support for MAC OSX AppleBMC.kext driver Not yet implemented, pending some documentation from Apple. Resolve MS ipmidrv.sys WBEM access memory leak: This bug has been reported to Microsoft in Oct 2012 as shown below. The workaround is to use the Intel imbdrv.sys driver instead. See the ipmiutil UserGuide section 5.1 for details. https://sourceforge.net/p/ipmiutil/support-requests/11/ https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/ca4df181-7fd4-4912-83a0-5896b030e3ca/latest-version-of-microsoft-ipmi-driver-ipmidrvsys?forum=wdk OPEN - no update/fix from Microsoft 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 subcommand to consolidate user functions user list (shows max,enabled, lists all users) user enable [chan] user disable user set name user set password [] user set priv [chan] COMPLETE in ipmiutil-3.0.3 03/24/2017 Test SuperMicro DIMM event logic (pending bad DIMM) COMPLETE in ipmiutil-2.9.9, revised code implemented Add support for openssl-1.1.0 for fedora COMPLETE in ipmiutil-3.0.1 Add OEM Lenovo SEL decoding COMPLETE in ipmiutil-3.0.1 Add OEM Lenovo sensor decoding COMPLETE in ipmiutil-3.0.1 Add HP-UX support PARTIAL in ipmiutil-2.8.4 COMPLETE in ipmiutil-2.9.8 stdout/stderr debug messages mixed . have a variable for stderr and if -x debug, set it to stdout. . implemented in util/subs.c lprintf() based on log level COMPLETE in ipmiutil-2.9.7 Add pkg-config support COMPLETE in ipmiutil-2.9.5 (in configure.ac) 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. COMPLETE 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 ipmiutil-3.1.9/README0000644000000000000000000001550314373712016012746 0ustar rootroot ------------------------------ 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/p/ipmiutil/_list/tickets 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, not used unless do configure --enable-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 ipmiutil-3.1.9/NEWS0000644000000000000000000000724314373712016012567 0ustar rootrootIPMIUTIL NEWS In October 2001, this project started 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. In July 2002, this code was first included in MontaVista CGE Linux 2.1. 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 Jul 2002 (1.2.1), released with MontaVista CGE 2.1 In Jan 2004 (1.4.1), added support for Windows 2000 & 2003 In Aug 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 Nov 2004 (1.5.0), support for IPMI LAN was added using FreeIPMI. In May 2006 (1.7.0), built-in IPMI LAN support was added. In Aug 2006 (1.7.5), driverless direct I/O support was added In Jan 2007 (1.8.0), added ipmiutil meta-command, IPMI LAN 2.0 (lanplus) support In Feb 2007 (1.9.2), added Linux Serial-Over-Lan console feature In Oct 2007 (2.0.0), added Windows SOL console and remote soft-shutdown features In Mar 2008 (2.1.0), the Windows SOL client application was completed. In Aug 2008 (2.2.0), iconfig function was added to save/restore the BMC configuration parameters 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 ANSI VT100 emulation for Windows SOL console In Feb 2010 (2.6.0), new subcommand naming scheme (i+subcmd) 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 ipmiutil-2.7.2 In May 2011 (2.7.6), added VLAN support and WIN64 fixes In Sep 2011 (2.7.8), added IPv6, systemd, Dell OEM functions, PICMG 2.3, 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 In Mar 2012 (2.8.2), added Intel Romley OEM support In Jun 2012 (2.8.4), added support for HP-UX builds and DCMI 1.1 commands In Oct 2012 (2.8.6), added pre-built Windows DLL for sample development apps In Feb 2013 (2.8.8), added much more SuperMicro OEM support In Apr 2013 (2.9.0), added iseltime to sync sys/RTC/SEL times In May 2013 (2.9.1), added support for MacOSX client In Dec 2016 (3.0.1), added support for Lenovo OEM sensors In Feb 2017 (3.0.1), added support for ASUS OEM sensors In Mar 2017 (3.0.3), added iuser to consolidate user functions ipmiutil-3.1.9/COPYING0000644000000000000000000001377314373712016013130 0ustar rootrootFormat: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: ipmiutil Upstream-Contact: Andy Cress Source: http://ipmiutil.sourceforge.net Comment: This COPYING file includes detail about each source file in ipmiutil Files: * Copyright: 2001-2008, Intel Corporation 2009-2012, Kontron America 2013, Andy Cress 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: Build does not include this file, unless 'configure --enable-gpl' License: GPL-2.0 Files: util/AnsiTerm.cpp Copyright: 2009 Robert Nelson 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. ipmiutil-3.1.9/AUTHORS0000644000000000000000000000054714373712016013140 0ustar rootrootipmiutil: Andy Cress util/AnsiTerm.cpp Robert Nelson util/oem_dell.c Harsha S util/ihpm.c Frederic.Lelievre at ca.kontron.com, Francois.Isabelle at ca.kontron.com, Jean-Michel.Audet at ca.kontron.com, MarieJosee.Blais at ca.kontron.com ipmiutil-3.1.9/Makefile.in0000644000000000000000000006726014373711044014142 0ustar rootroot# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ 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) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir distdir-am dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \ COPYING ChangeLog INSTALL NEWS README TODO compile \ config.guess config.sub depcomp install-sh ltconfig ltmain.sh \ missing mkinstalldirs DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CROSS_CFLAGS = @CROSS_CFLAGS@ CROSS_LFLAGS = @CROSS_LFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GPL_CFLAGS = @GPL_CFLAGS@ GREP = @GREP@ IA64_CFLAGS = @IA64_CFLAGS@ INIT_DIR = @INIT_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INS_LIB = @INS_LIB@ LANDESK_CFLAGS = @LANDESK_CFLAGS@ LANDESK_LDADD = @LANDESK_LDADD@ LANPLUS_CFLAGS = @LANPLUS_CFLAGS@ LANPLUS_CRYPTO = @LANPLUS_CRYPTO@ LANPLUS_LDADD = @LANPLUS_LDADD@ LANPLUS_LIB = @LANPLUS_LIB@ LANPLUS_SAM = @LANPLUS_SAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LD_SAMX = @LD_SAMX@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSENSORS = @LIBSENSORS@ LIBTOOL = @LIBTOOL@ LIB_DIR = @LIB_DIR@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OS_CFLAGS = @OS_CFLAGS@ OS_DRIVERS = @OS_DRIVERS@ OS_LFLAGS = @OS_LFLAGS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_DIR = @PKG_DIR@ RANLIB = @RANLIB@ SAM2OBJ = @SAM2OBJ@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHR_LINK = @SHR_LINK@ STRIP = @STRIP@ SUBDIR_S = @SUBDIR_S@ SYSTEMD_DIR = @SYSTEMD_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = @SUBDIR_S@ PKGDIR = @PKG_DIR@ SOURCEDIR = $(PKGDIR)/SOURCES BUILDDIR = $(PKGDIR)/BUILD RSPEC = doc/$(PACKAGE).spec PNAME = $(PACKAGE)-$(VERSION) TARDIR = /tmp/iu TMPDIR = $(TARDIR)/$(PNAME) BDIR = $(TMPDIR)-1-root RPMB = rpmbuild all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign 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__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 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) ($(am__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 config.lt # 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. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ 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; \ ($(am__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" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ 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 || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -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 $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-zstd: distdir tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_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*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ *.tar.zst*) \ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(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 \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-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 html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: 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: .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip dist-zstd distcheck distclean \ distclean-generic distclean-hdr distclean-libtool \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # $(RPMB) -bb --buildroot $(BDIR) $(RSPEC) # Note: put files here, until lib/Makefile.am supports # pkg-config support rules # if WITH_PKG_CONFIG # pkgconfig_DATA = lib/libipmiutil.pc # endif rpm: $(RSPEC) make tarball mkdir -p $(SOURCEDIR) cp -f $(TARDIR)/$(PNAME).tar.gz $(SOURCEDIR) $(RPMB) -bb $(RSPEC) $(RPMB) -bs $(RSPEC) tarball: rm -f $(TMPDIR)/../$(PNAME).tar.gz rm -rf $(TMPDIR) mkdir -p $(TMPDIR) find . -print | cpio -pdumv $(TMPDIR) cd $(TMPDIR)/test; make clean; cd .. cd $(TMPDIR)/hpiutil; make clean; cd .. cd $(TMPDIR); make distclean cd $(TMPDIR); rm -rf util/.deps lib/lanplus/.deps cd $(TMPDIR); rm -f lib/libipmiapi*.a* lib/libipmi*.a 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); rm -f cprpm debug*.list *~ .*.swp cd $(TMPDIR); find . -name '*.orig' -delete cd $(TMPDIR); find . -name '*.rej' -delete cd $(TMPDIR); cd ..; tar -czvf $(TARDIR)/$(PNAME).tar.gz $(PNAME) ls $(TARDIR)/*.gz rm -rf $(TMPDIR) # chown -R root:root $(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: ipmiutil-3.1.9/depcomp0000755000000000000000000005602014373711042013440 0ustar rootroot#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2020 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, see . # 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 . 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 outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} 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" # Avoid interferences from the environment. gccflag= dashmflag= # 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 cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc 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. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## 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). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - 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 -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # 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. ## 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. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -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 -ne 0; then 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 ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # 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 ;; 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. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then 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" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; 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. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies 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$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # 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 ;; #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 "X$1" != 'X--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|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | 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 "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi 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. -arch) eat=yes ;; -*|$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" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | 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 "X$1" != 'X--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. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # 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 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: ipmiutil-3.1.9/compile0000755000000000000000000001635014373711042013443 0ustar rootroot#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2020 Free Software Foundation, Inc. # Written by Tom Tromey . # # 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, see . # 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. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN* | MSYS*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: ipmiutil-3.1.9/config.h.in0000644000000000000000000000653414373711041014112 0ustar rootroot/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have a working `mmap' system call. */ #undef HAVE_MMAP /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* if socklen_t is defined, make note of it */ #undef HAVE_SOCKLEN_T /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strcspn' function. */ #undef HAVE_STRCSPN /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strspn' function. */ #undef HAVE_STRSPN /* Define to 1 if you have the `strtoul' function. */ #undef HAVE_STRTOUL /* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vprintf' function. */ #undef HAVE_VPRINTF /* Define to 1 if the system has the type `wchar_t'. */ #undef HAVE_WCHAR_T /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* Version number of package */ #undef VERSION /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `long int' if does not define. */ #undef off_t /* if socklen_t is not defined, provide something useful */ #undef socklen_t ipmiutil-3.1.9/missing0000755000000000000000000001533614373711040013465 0ustar rootroot#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2020 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 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, see . # 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 case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." 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 # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: ipmiutil-3.1.9/ltmain.sh0000644000000000000000000117042614373711040013711 0ustar rootroot#! /bin/sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2014-01-03.01 # libtool (GNU libtool) 2.4.6 # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2015 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. # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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, see . PROGRAM=libtool PACKAGE=libtool VERSION=2.4.6 package_revision=2.4.6 ## ------ ## ## Usage. ## ## ------ ## # Run './libtool --help' for help with using this script from the # command line. ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # After configure completes, it has a better idea of some of the # shell tools we need than the defaults used by the functions shared # with bootstrap, so set those here where they can still be over- # ridden by the user, but otherwise take precedence. : ${AUTOCONF="autoconf"} : ${AUTOMAKE="automake"} ## -------------------------- ## ## Source external libraries. ## ## -------------------------- ## # Much of our low-level functionality needs to be sourced from external # libraries, which are installed to $pkgauxdir. # Set a version string for this script. scriptversion=2015-01-20.17; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # Copyright (C) 2004-2015 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. # 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 3 of the License, or # (at your option) any later version. # As a special exception to the GNU General Public License, if you distribute # this file as part of a program or library that is built using GNU Libtool, # you may include this file under the same distribution terms that you use # for the rest of that program. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNES 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, see . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # Evaluate this file near the top of your script to gain access to # the functions and variables defined here: # # . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # # If you need to override any of the default environment variable # settings, do that before evaluating this file. ## -------------------- ## ## Shell normalisation. ## ## -------------------- ## # Some shells need a little help to be as Bourne compatible as possible. # Before doing anything else, make sure all that help has been provided! DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do 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 # NLS nuisances: We save the old values in case they are required later. _G_user_locale= _G_safe_locale= for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test set = \"\${$_G_var+set}\"; then save_$_G_var=\$$_G_var $_G_var=C export $_G_var _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Make sure IFS has a sensible default sp=' ' nl=' ' IFS="$sp $nl" # There are apparently some retarded systems that use ';' as a PATH separator! if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi ## ------------------------- ## ## Locate command utilities. ## ## ------------------------- ## # func_executable_p FILE # ---------------------- # Check that FILE is an executable regular file. func_executable_p () { test -f "$1" && test -x "$1" } # func_path_progs PROGS_LIST CHECK_FUNC [PATH] # -------------------------------------------- # Search for either a program that responds to --version with output # containing "GNU", or else returned by CHECK_FUNC otherwise, by # trying all the directories in PATH with each of the elements of # PROGS_LIST. # # CHECK_FUNC should accept the path to a candidate program, and # set $func_check_prog_result if it truncates its output less than # $_G_path_prog_max characters. func_path_progs () { _G_progs_list=$1 _G_check_func=$2 _G_PATH=${3-"$PATH"} _G_path_prog_max=0 _G_path_prog_found=false _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} for _G_dir in $_G_PATH; do IFS=$_G_save_IFS test -z "$_G_dir" && _G_dir=. for _G_prog_name in $_G_progs_list; do for _exeext in '' .EXE; do _G_path_prog=$_G_dir/$_G_prog_name$_exeext func_executable_p "$_G_path_prog" || continue case `"$_G_path_prog" --version 2>&1` in *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; *) $_G_check_func $_G_path_prog func_path_progs_result=$func_check_prog_result ;; esac $_G_path_prog_found && break 3 done done done IFS=$_G_save_IFS test -z "$func_path_progs_result" && { echo "no acceptable sed could be found in \$PATH" >&2 exit 1 } } # We want to be able to use the functions in this file before configure # has figured out where the best binaries are kept, which means we have # to search for them ourselves - except when the results are already set # where we skip the searches. # Unless the user overrides by setting SED, search the path for either GNU # sed, or the sed that truncates its output the least. test -z "$SED" && { _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for _G_i in 1 2 3 4 5 6 7; do _G_sed_script=$_G_sed_script$nl$_G_sed_script done echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed _G_sed_script= func_check_prog_sed () { _G_path_prog=$1 _G_count=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo '' >> conftest.nl "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin rm -f conftest.sed SED=$func_path_progs_result } # Unless the user overrides by setting GREP, search the path for either GNU # grep, or the grep that truncates its output the least. test -z "$GREP" && { func_check_prog_grep () { _G_path_prog=$1 _G_count=0 _G_path_prog_max=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo 'GREP' >> conftest.nl "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin GREP=$func_path_progs_result } ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # All uppercase variable names are used for environment variables. These # variables can be overridden by the user before calling a script that # uses them if a suitable command of that name is not already available # in the command search PATH. : ${CP="cp -f"} : ${ECHO="printf %s\n"} : ${EGREP="$GREP -E"} : ${FGREP="$GREP -F"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} ## -------------------- ## ## Useful sed snippets. ## ## -------------------- ## sed_dirname='s|/[^/]*$||' sed_basename='s|^.*/||' # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s|\([`"$\\]\)|\\\1|g' # Same as above, but do not quote variable references. sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' # Sed substitution that converts a w32 file name or path # that contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-'\' parameter expansions in output of sed_double_quote_subst that # were '\'-ed in input to the same. If an odd number of '\' preceded a # '$' in input to sed_double_quote_subst, that '$' was protected from # expansion. Since each input '\' is now two '\'s, look for any number # of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. _G_bs='\\' _G_bs2='\\\\' _G_bs4='\\\\\\\\' _G_dollar='\$' sed_double_backslash="\ s/$_G_bs4/&\\ /g s/^$_G_bs2$_G_dollar/$_G_bs&/ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g s/\n//g" ## ----------------- ## ## Global variables. ## ## ----------------- ## # Except for the global variables explicitly listed below, the following # functions in the '^func_' namespace, and the '^require_' namespace # variables initialised in the 'Resource management' section, sourcing # this file will not pollute your global namespace with anything # else. There's no portable way to scope variables in Bourne shell # though, so actually running these functions will sometimes place # results into a variable named after the function, and often use # temporary variables in the '^_G_' namespace. If you are careful to # avoid using those namespaces casually in your sourcing script, things # should continue to work as you expect. And, of course, you can freely # overwrite any of the functions or variables defined here before # calling anything to customize them. EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. # Allow overriding, eg assuming that you follow the convention of # putting '$debug_cmd' at the start of all your functions, you can get # bash to show function call trace with: # # debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name debug_cmd=${debug_cmd-":"} exit_cmd=: # By convention, finish your script with: # # exit $exit_status # # so that you can set exit_status to non-zero if you want to indicate # something went wrong during execution without actually bailing out at # the point of failure. exit_status=$EXIT_SUCCESS # 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 "$sed_basename"` # Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` progpath=$progdir/$progname ;; *) _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS=$_G_IFS test -x "$progdir/$progname" && break done IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` progpath=$progdir/$progname ;; esac ## ----------------- ## ## Standard options. ## ## ----------------- ## # The following options affect the operation of the functions defined # below, and should be set appropriately depending on run-time para- # meters passed on the command line. opt_dry_run=false opt_quiet=false opt_verbose=false # Categories 'all' and 'none' are always available. Append any others # you will pass as the first argument to func_warning from your own # code. warning_categories= # By default, display warnings according to 'opt_warning_types'. Set # 'warning_func' to ':' to elide all warnings, or func_fatal_error to # treat the next displayed warning as a fatal error. warning_func=func_warn_and_continue # Set to 'all' to display all warnings, 'none' to suppress all # warnings, or a space delimited list of some subset of # 'warning_categories' to display only the listed warnings. opt_warning_types=all ## -------------------- ## ## Resource management. ## ## -------------------- ## # This section contains definitions for functions that each ensure a # particular resource (a file, or a non-empty configuration variable for # example) is available, and if appropriate to extract default values # from pertinent package files. Call them using their associated # 'require_*' variable to ensure that they are executed, at most, once. # # It's entirely deliberate that calling these functions can set # variables that don't obey the namespace limitations obeyed by the rest # of this file, in order that that they be as useful as possible to # callers. # require_term_colors # ------------------- # Allow display of bold text on terminals that support it. require_term_colors=func_require_term_colors func_require_term_colors () { $debug_cmd test -t 1 && { # COLORTERM and USE_ANSI_COLORS environment variables take # precedence, because most terminfo databases neglect to describe # whether color sequences are supported. test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} if test 1 = "$USE_ANSI_COLORS"; then # Standard ANSI escape sequences tc_reset='' tc_bold=''; tc_standout='' tc_red=''; tc_green='' tc_blue=''; tc_cyan='' else # Otherwise trust the terminfo database after all. test -n "`tput sgr0 2>/dev/null`" && { tc_reset=`tput sgr0` test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` tc_standout=$tc_bold test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` } fi } require_term_colors=: } ## ----------------- ## ## Function library. ## ## ----------------- ## # This section contains a variety of useful functions to call in your # scripts. Take note of the portable wrappers for features provided by # some modern shells, which will fall back to slower equivalents on # less featureful shells. # func_append VAR VALUE # --------------------- # Append VALUE onto the existing contents of VAR. # We should try to minimise forks, especially on Windows where they are # unreasonably slow, so skip the feature probes when bash or zsh are # being used: if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then : ${_G_HAVE_ARITH_OP="yes"} : ${_G_HAVE_XSI_OPS="yes"} # The += operator was introduced in bash 3.1 case $BASH_VERSION in [12].* | 3.0 | 3.0*) ;; *) : ${_G_HAVE_PLUSEQ_OP="yes"} ;; esac fi # _G_HAVE_PLUSEQ_OP # Can be empty, in which case the shell is probed, "yes" if += is # useable or anything else if it does not work. test -z "$_G_HAVE_PLUSEQ_OP" \ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ && _G_HAVE_PLUSEQ_OP=yes if test yes = "$_G_HAVE_PLUSEQ_OP" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_append () { $debug_cmd eval "$1+=\$2" }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_append () { $debug_cmd eval "$1=\$$1\$2" } fi # func_append_quoted VAR VALUE # ---------------------------- # Quote VALUE and append to the end of shell variable VAR, separated # by a space. if test yes = "$_G_HAVE_PLUSEQ_OP"; then eval 'func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1+=\\ \$func_quote_for_eval_result" }' else func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1=\$$1\\ \$func_quote_for_eval_result" } fi # func_append_uniq VAR VALUE # -------------------------- # Append unique VALUE onto the existing contents of VAR, assuming # entries are delimited by the first character of VALUE. For example: # # func_append_uniq options " --another-option option-argument" # # will only append to $options if " --another-option option-argument " # is not already present somewhere in $options already (note spaces at # each end implied by leading space in second argument). func_append_uniq () { $debug_cmd eval _G_current_value='`$ECHO $'$1'`' _G_delim=`expr "$2" : '\(.\)'` case $_G_delim$_G_current_value$_G_delim in *"$2$_G_delim"*) ;; *) func_append "$@" ;; esac } # func_arith TERM... # ------------------ # Set func_arith_result to the result of evaluating TERMs. test -z "$_G_HAVE_ARITH_OP" \ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ && _G_HAVE_ARITH_OP=yes if test yes = "$_G_HAVE_ARITH_OP"; then eval 'func_arith () { $debug_cmd func_arith_result=$(( $* )) }' else func_arith () { $debug_cmd func_arith_result=`expr "$@"` } fi # func_basename FILE # ------------------ # Set func_basename_result to FILE with everything up to and including # the last / stripped. if test yes = "$_G_HAVE_XSI_OPS"; then # If this shell supports suffix pattern removal, then use it to avoid # forking. Hide the definitions single quotes in case the shell chokes # on unsupported syntax... _b='func_basename_result=${1##*/}' _d='case $1 in */*) func_dirname_result=${1%/*}$2 ;; * ) func_dirname_result=$3 ;; esac' else # ...otherwise fall back to using sed. _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` if test "X$func_dirname_result" = "X$1"; then func_dirname_result=$3 else func_append func_dirname_result "$2" fi' fi eval 'func_basename () { $debug_cmd '"$_b"' }' # func_dirname FILE APPEND NONDIR_REPLACEMENT # ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. eval 'func_dirname () { $debug_cmd '"$_d"' }' # func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT # -------------------------------------------------------- # Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # For efficiency, we do not delegate to the functions above but instead # duplicate the functionality here. eval 'func_dirname_and_basename () { $debug_cmd '"$_b"' '"$_d"' }' # func_echo ARG... # ---------------- # Echo program name prefixed message. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname: $_G_line" done IFS=$func_echo_IFS } # func_echo_all ARG... # -------------------- # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_echo_infix_1 INFIX ARG... # ------------------------------ # Echo program name, followed by INFIX on the first line, with any # additional lines not showing INFIX. func_echo_infix_1 () { $debug_cmd $require_term_colors _G_infix=$1; shift _G_indent=$_G_infix _G_prefix="$progname: $_G_infix: " _G_message=$* # Strip color escape sequences before counting printable length for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" do test -n "$_G_tc" && { _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` } done _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes func_echo_infix_1_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_infix_1_IFS $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 _G_prefix=$_G_indent done IFS=$func_echo_infix_1_IFS } # func_error ARG... # ----------------- # Echo program name prefixed message to standard error. func_error () { $debug_cmd $require_term_colors func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 } # func_fatal_error ARG... # ----------------------- # Echo program name prefixed message to standard error, and exit. func_fatal_error () { $debug_cmd func_error "$*" exit $EXIT_FAILURE } # func_grep EXPRESSION FILENAME # ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $debug_cmd $GREP "$1" "$2" >/dev/null 2>&1 } # func_len STRING # --------------- # Set func_len_result to the length of STRING. STRING may not # start with a hyphen. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_len () { $debug_cmd func_len_result=${#1} }' else func_len () { $debug_cmd func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } fi # func_mkdir_p DIRECTORY-PATH # --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { $debug_cmd _G_directory_path=$1 _G_dir_list= if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then # Protect directory names starting with '-' case $_G_directory_path in -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` func_mkdir_p_IFS=$IFS; IFS=: for _G_dir in $_G_dir_list; do IFS=$func_mkdir_p_IFS # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$_G_dir" 2>/dev/null || : done IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. test -d "$_G_directory_path" || \ func_fatal_error "Failed to create '$1'" fi } # func_mktempdir [BASENAME] # ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, BASENAME is the basename for that directory. func_mktempdir () { $debug_cmd _G_template=${TMPDIR-/tmp}/${1-$progname} if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race _G_tmpdir=$_G_template-${RANDOM-0}$$ func_mktempdir_umask=`umask` umask 0077 $MKDIR "$_G_tmpdir" umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$_G_tmpdir" || \ func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi $ECHO "$_G_tmpdir" } # func_normal_abspath PATH # ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. func_normal_abspath () { $debug_cmd # These SED scripts presuppose an absolute path with a trailing slash. _G_pathcar='s|^/\([^/]*\).*$|\1|' _G_pathcdr='s|^/[^/]*||' _G_removedotparts=':dotsl s|/\./|/|g t dotsl s|/\.$|/|' _G_collapseslashes='s|/\{1,\}|/|g' _G_finalslash='s|/*$|/|' # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` while :; do # Processed it all yet? if test / = "$func_normal_abspath_tpath"; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result"; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_notquiet ARG... # -------------------- # Echo program name prefixed message only when not in quiet mode. func_notquiet () { $debug_cmd $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_relative_path SRCDIR DSTDIR # -------------------------------- # Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. func_relative_path () { $debug_cmd func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=$func_dirname_result if test -z "$func_relative_path_tlibdir"; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test -n "$func_stripname_result"; then func_append func_relative_path_result "/$func_stripname_result" fi # Normalisation. If bindir is libdir, return '.' else relative path. if test -n "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result" func_relative_path_result=$func_stripname_result fi test -n "$func_relative_path_result" || func_relative_path_result=. : } # func_quote_for_eval ARG... # -------------------------- # Aesthetically quote ARGs to be evaled later. # This function returns two values: # i) func_quote_for_eval_result # double-quoted, suitable for a subsequent eval # ii) func_quote_for_eval_unquoted_result # has all characters that are still active within double # quotes backslashified. func_quote_for_eval () { $debug_cmd func_quote_for_eval_unquoted_result= func_quote_for_eval_result= while test 0 -lt $#; do case $1 in *[\\\`\"\$]*) _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; *) _G_unquoted_arg=$1 ;; esac if test -n "$func_quote_for_eval_unquoted_result"; then func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" else func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" fi case $_G_unquoted_arg in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and variable expansion # for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_quoted_arg=\"$_G_unquoted_arg\" ;; *) _G_quoted_arg=$_G_unquoted_arg ;; esac if test -n "$func_quote_for_eval_result"; then func_append func_quote_for_eval_result " $_G_quoted_arg" else func_append func_quote_for_eval_result "$_G_quoted_arg" fi shift done } # func_quote_for_expand ARG # ------------------------- # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { $debug_cmd case $1 in *[\\\`\"]*) _G_arg=`$ECHO "$1" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; *) _G_arg=$1 ;; esac case $_G_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_arg=\"$_G_arg\" ;; esac func_quote_for_expand_result=$_G_arg } # func_stripname PREFIX SUFFIX NAME # --------------------------------- # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_stripname () { $debug_cmd # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary variable first. func_stripname_result=$3 func_stripname_result=${func_stripname_result#"$1"} func_stripname_result=${func_stripname_result%"$2"} }' else func_stripname () { $debug_cmd case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; esac } fi # func_show_eval CMD [FAIL_EXP] # ----------------------------- # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} func_quote_for_expand "$_G_cmd" eval "func_notquiet $func_quote_for_expand_result" $opt_dry_run || { eval "$_G_cmd" _G_status=$? if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_show_eval_locale CMD [FAIL_EXP] # ------------------------------------ # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} $opt_quiet || { func_quote_for_expand "$_G_cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || { eval "$_G_user_locale $_G_cmd" _G_status=$? eval "$_G_safe_locale" if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_tr_sh # ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { $debug_cmd case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_verbose ARG... # ------------------- # Echo program name prefixed message in verbose mode only. func_verbose () { $debug_cmd $opt_verbose && func_echo "$*" : } # func_warn_and_continue ARG... # ----------------------------- # Echo program name prefixed warning message to standard error. func_warn_and_continue () { $debug_cmd $require_term_colors func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } # func_warning CATEGORY ARG... # ---------------------------- # Echo program name prefixed warning message to standard error. Warning # messages can be filtered according to CATEGORY, where this function # elides messages where CATEGORY is not listed in the global variable # 'opt_warning_types'. func_warning () { $debug_cmd # CATEGORY must be in the warning_categories list! case " $warning_categories " in *" $1 "*) ;; *) func_internal_error "invalid warning category '$1'" ;; esac _G_category=$1 shift case " $opt_warning_types " in *" $_G_category "*) $warning_func ${1+"$@"} ;; esac } # func_sort_ver VER1 VER2 # ----------------------- # 'sort -V' is not generally available. # Note this deviates from the version comparison in automake # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a # but this should suffice as we won't be specifying old # version formats or redundant trailing .0 in bootstrap.conf. # If we did want full compatibility then we should probably # use m4_version_compare from autoconf. func_sort_ver () { $debug_cmd printf '%s\n%s\n' "$1" "$2" \ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n } # func_lt_ver PREV CURR # --------------------- # Return true if PREV and CURR are in the correct order according to # func_sort_ver, otherwise false. Use it like this: # # func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." func_lt_ver () { $debug_cmd test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: #! /bin/sh # Set a version string for this script. scriptversion=2014-01-07.03; # UTC # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # Copyright (C) 2010-2015 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. # 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 3 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, see . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # This file is a library for parsing options in your shell scripts along # with assorted other useful supporting features that you can make use # of too. # # For the simplest scripts you might need only: # # #!/bin/sh # . relative/path/to/funclib.sh # . relative/path/to/options-parser # scriptversion=1.0 # func_options ${1+"$@"} # eval set dummy "$func_options_result"; shift # ...rest of your script... # # In order for the '--version' option to work, you will need to have a # suitably formatted comment like the one at the top of this file # starting with '# Written by ' and ending with '# warranty; '. # # For '-h' and '--help' to work, you will also need a one line # description of your script's purpose in a comment directly above the # '# Written by ' line, like the one at the top of this file. # # The default options also support '--debug', which will turn on shell # execution tracing (see the comment above debug_cmd below for another # use), and '--verbose' and the func_verbose function to allow your script # to display verbose messages only when your user has specified # '--verbose'. # # After sourcing this file, you can plug processing for additional # options by amending the variables from the 'Configuration' section # below, and following the instructions in the 'Option parsing' # section further down. ## -------------- ## ## Configuration. ## ## -------------- ## # You should override these variables in your script after sourcing this # file so that they reflect the customisations you have added to the # option parser. # The usage line for option parsing errors and the start of '-h' and # '--help' output messages. You can embed shell variables for delayed # expansion at the time the message is displayed, but you will need to # quote other shell meta-characters carefully to prevent them being # expanded when the contents are evaled. usage='$progpath [OPTION]...' # Short help message in response to '-h' and '--help'. Add to this or # override it after sourcing this library to reflect the full set of # options your script accepts. usage_message="\ --debug enable verbose shell tracing -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -v, --verbose verbosely report processing --version print version information and exit -h, --help print short or long help message and exit " # Additional text appended to 'usage_message' in response to '--help'. long_help_message=" Warning categories include: 'all' show all warnings 'none' turn off all the warnings 'error' warnings are treated as fatal errors" # Help message printed before fatal option parsing errors. fatal_help="Try '\$progname --help' for more information." ## ------------------------- ## ## Hook function management. ## ## ------------------------- ## # This section contains functions for adding, removing, and running hooks # to the main code. A hook is just a named list of of function, that can # be run in order later on. # func_hookable FUNC_NAME # ----------------------- # Declare that FUNC_NAME will run hooks added with # 'func_add_hook FUNC_NAME ...'. func_hookable () { $debug_cmd func_append hookable_fns " $1" } # func_add_hook FUNC_NAME HOOK_FUNC # --------------------------------- # Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must # first have been declared "hookable" by a call to 'func_hookable'. func_add_hook () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not accept hook functions." ;; esac eval func_append ${1}_hooks '" $2"' } # func_remove_hook FUNC_NAME HOOK_FUNC # ------------------------------------ # Remove HOOK_FUNC from the list of functions called by FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It is assumed that the list of hook functions contains nothing more # than a whitespace-delimited list of legal shell function names, and # no effort is wasted trying to catch shell meta-characters or preserve # whitespace. func_run_hooks () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook funcions.n" ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do eval $_G_hook '"$@"' # store returned options list back into positional # parameters for next 'cmd' execution. eval _G_hook_result=\$${_G_hook}_result eval set dummy "$_G_hook_result"; shift done func_quote_for_eval ${1+"$@"} func_run_hooks_result=$func_quote_for_eval_result } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list in your hook function, remove any # options that you action, and then pass back the remaining unprocessed # options in '_result', escaped suitably for # 'eval'. Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # func_quote_for_eval ${1+"$@"} # my_options_prep_result=$func_quote_for_eval_result # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # # Note that for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in # --silent|-s) opt_silent=: ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift # ;; # *) set dummy "$_G_opt" "$*"; shift; break ;; # esac # done # # func_quote_for_eval ${1+"$@"} # my_silent_option_result=$func_quote_for_eval_result # } # func_add_hook func_parse_options my_silent_option # # # my_option_validation () # { # $debug_cmd # # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # # func_quote_for_eval ${1+"$@"} # my_option_validation_result=$func_quote_for_eval_result # } # func_add_hook func_validate_options my_option_validation # # You'll alse need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd func_options_prep ${1+"$@"} eval func_parse_options \ ${func_options_prep_result+"$func_options_prep_result"} eval func_validate_options \ ${func_parse_options_result+"$func_parse_options_result"} eval func_run_hooks func_options \ ${func_validate_options_result+"$func_validate_options_result"} # save modified positional parameters for caller func_options_result=$func_run_hooks_result } # func_options_prep [ARG]... # -------------------------- # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and # needs to propogate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before # returning. func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= func_run_hooks func_options_prep ${1+"$@"} # save modified positional parameters for caller func_options_prep_result=$func_run_hooks_result } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd func_parse_options_result= # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. func_run_hooks func_parse_options ${1+"$@"} # Adjust func_parse_options positional parameters to match eval set dummy "$func_run_hooks_result"; shift # Break out of the loop if we already parsed every option. test $# -gt 0 || break _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) test $# = 0 && func_missing_arg $_G_opt && break case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above func_append_uniq opt_warning_types " $1" ;; *all) opt_warning_types=$warning_categories ;; *none) opt_warning_types=none warning_func=: ;; *error) opt_warning_types=$warning_categories warning_func=func_fatal_error ;; *) func_fatal_error \ "unsupported warning category: '$1'" ;; esac shift ;; --verbose|-v) opt_verbose=: ;; --version) func_version ;; -\?|-h) func_usage ;; --help) func_help ;; # Separate optargs to long options (plugins may need this): --*=*) func_split_equals "$_G_opt" set dummy "$func_split_equals_lhs" \ "$func_split_equals_rhs" ${1+"$@"} shift ;; # Separate optargs to short options: -W*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "$func_split_short_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-v*|-x*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} func_parse_options_result=$func_quote_for_eval_result } # func_validate_options [ARG]... # ------------------------------ # Perform any sanity checks on option settings and/or unconsumed # arguments. func_hookable func_validate_options func_validate_options () { $debug_cmd # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" func_run_hooks func_validate_options ${1+"$@"} # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE # save modified positional parameters for caller func_validate_options_result=$func_run_hooks_result } ## ----------------- ## ## Helper functions. ## ## ----------------- ## # This section contains the helper functions used by the rest of the # hookable option parser framework in ascii-betical order. # func_fatal_help ARG... # ---------------------- # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { $debug_cmd eval \$ECHO \""Usage: $usage"\" eval \$ECHO \""$fatal_help"\" func_error ${1+"$@"} exit $EXIT_FAILURE } # func_help # --------- # Echo long help message to standard output and exit. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message" exit 0 } # func_missing_arg ARGNAME # ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $debug_cmd func_error "Missing argument for '$1'." exit_cmd=exit } # func_split_equals STRING # ------------------------ # Set func_split_equals_lhs and func_split_equals_rhs shell variables after # splitting STRING at the '=' sign. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_equals () { $debug_cmd func_split_equals_lhs=${1%%=*} func_split_equals_rhs=${1#*=} test "x$func_split_equals_lhs" = "x$1" \ && func_split_equals_rhs= }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_equals () { $debug_cmd func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` func_split_equals_rhs= test "x$func_split_equals_lhs" = "x$1" \ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` } fi #func_split_equals # func_split_short_opt SHORTOPT # ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_short_opt () { $debug_cmd func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"} }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_short_opt () { $debug_cmd func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` } fi #func_split_short_opt # func_usage # ---------- # Echo short help message to standard output and exit. func_usage () { $debug_cmd func_usage_message $ECHO "Run '$progname --help |${PAGER-more}' for full usage" exit 0 } # func_usage_message # ------------------ # Echo short help message to standard output. func_usage_message () { $debug_cmd eval \$ECHO \""Usage: $usage"\" echo $SED -n 's|^# || /^Written by/{ x;p;x } h /^Written by/q' < "$progpath" echo eval \$ECHO \""$usage_message"\" } # func_version # ------------ # Echo version message to standard output and exit. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /(C)/!b go :more /\./!{ N s|\n# | | b more } :go /^# Written by /,/# warranty; / { s|^# || s|^# *$|| s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| p } /^# Written by / { s|^# || p } /^warranty; /q' < "$progpath" exit $? } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: # Set a version string. scriptversion='(GNU libtool) 2.4.6' # func_echo ARG... # ---------------- # Libtool also displays the current mode in messages, so override # funclib.sh func_echo with this custom definition. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" done IFS=$func_echo_IFS } # func_warning ARG... # ------------------- # Libtool warnings are not categorized, so override funclib.sh # func_warning with this simpler definition. func_warning () { $debug_cmd $warning_func ${1+"$@"} } ## ---------------- ## ## Options parsing. ## ## ---------------- ## # Hook in the functions to make sure our own options are parsed during # the option parsing loop. usage='$progpath [OPTION]... [MODE-ARG]...' # Short help message in response to '-h'. usage_message="Options: --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 --mode=MODE use operation mode MODE --no-warnings equivalent to '-Wnone' --preserve-dup-deps don't remove duplicate dependency libraries --quiet, --silent don't print informational messages --tag=TAG use configuration variables from tag TAG -v, --verbose print more informational messages than default --version print version information -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -h, --help, --help-all print short, long, or detailed help message " # Additional text appended to 'usage_message' in response to '--help'. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message 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. When passed as first option, '--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. Try '$progname --help --mode=MODE' for a more detailed description of MODE. When reporting a bug, please describe a test case to reproduce it and include the following information: host-triplet: $host shell: $SHELL compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) version: $progname (GNU libtool) 2.4.6 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . GNU libtool home page: . General help using GNU software: ." exit 0 } # func_lo2o OBJECT-NAME # --------------------- # Transform OBJECT-NAME from a '.lo' suffix to the platform specific # object suffix. lo2o=s/\\.lo\$/.$objext/ o2lo=s/\\.$objext\$/.lo/ if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_lo2o () { case $1 in *.lo) func_lo2o_result=${1%.lo}.$objext ;; * ) func_lo2o_result=$1 ;; esac }' # func_xform LIBOBJ-OR-SOURCE # --------------------------- # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) # suffix to a '.lo' libtool-object suffix. eval 'func_xform () { func_xform_result=${1%.*}.lo }' else # ...otherwise fall back to using sed. func_lo2o () { func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` } func_xform () { func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` } fi # func_fatal_configuration ARG... # ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func__fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } # func_config # ----------- # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # ------------- # Display the features supported by this script. func_features () { echo "host: $host" if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag TAGNAME # ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname=$1 re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf=/$re_begincf/,/$re_endcf/p # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # libtool_options_prep [ARG]... # ----------------------------- # Preparation for options parsed by libtool. libtool_options_prep () { $debug_mode # Option defaults: opt_config=false opt_dlopen= opt_dry_run=false opt_help=false opt_mode= opt_preserve_dup_deps=false opt_quiet=false nonopt= preserve_args= # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Pass back the list of options. func_quote_for_eval ${1+"$@"} libtool_options_prep_result=$func_quote_for_eval_result } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_opt=$1 shift case $_G_opt in --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) func_config ;; --dlopen|-dlopen) opt_dlopen="${opt_dlopen+$opt_dlopen }$1" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) func_features ;; --finish) set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $_G_opt && break opt_mode=$1 case $1 in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $_G_opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_quiet=false func_append preserve_args " $_G_opt" ;; --no-warnings|--no-warning|--no-warn) opt_warning=false func_append preserve_args " $_G_opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $_G_opt" ;; --silent|--quiet) opt_quiet=: opt_verbose=false func_append preserve_args " $_G_opt" ;; --tag) test $# = 0 && func_missing_arg $_G_opt && break opt_tag=$1 func_append preserve_args " $_G_opt $1" func_enable_tag "$1" shift ;; --verbose|-v) opt_quiet=false opt_verbose=: func_append preserve_args " $_G_opt" ;; # An option not handled by this hook function: *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} libtool_parse_options_result=$func_quote_for_eval_result } func_add_hook func_parse_options libtool_parse_options # libtool_validate_options [ARG]... # --------------------------------- # Perform any sanity checks on option settings and/or unconsumed # arguments. libtool_validate_options () { # save first non-option argument if test 0 -lt $#; then nonopt=$1 shift fi # preserve --debug test : = "$debug_cmd" || func_append preserve_args " --debug" # Keeping compiler generated duplicates in $postdeps and $predeps is not # harmful, and is necessary in a majority of systems that use it to satisfy # symbol dependencies. opt_duplicate_compiler_generated_deps=: $opt_help || { # Sanity checks first: func_check_version_match test yes != "$build_libtool_libs" \ && test yes != "$build_old_libs" \ && func_fatal_configuration "not configured to build any kind of library" # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test execute != "$opt_mode"; then func_error "unrecognized option '-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help=$help help="Try '$progname --help --mode=$opt_mode' for more information." } # Pass back the unparsed argument list func_quote_for_eval ${1+"$@"} libtool_validate_options_result=$func_quote_for_eval_result } func_add_hook func_validate_options libtool_validate_options # Process options as early as possible so that --help and --version # can return quickly. func_options ${1+"$@"} eval set dummy "$func_options_result"; shift ## ----------- ## ## Main. ## ## ----------- ## magic='%%%MAGIC variable%%%' magic_exe='%%%MAGIC EXE variable%%%' # Global variables. extracted_archives= extracted_serial=0 # 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= # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # func_generated_by_libtool # True iff stdin has been generated by Libtool. This function is only # a basic sanity check; it will hardly flush out determined imposters. func_generated_by_libtool_p () { $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test yes = "$lalib_p" } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { test -f "$1" && $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $debug_cmd save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE 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. func_source () { $debug_cmd case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # 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 () { $debug_cmd if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` 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 "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # 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. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # 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 func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=$1 if test yes = "$build_libtool_libs"; then write_lobj=\'$2\' else write_lobj=none fi if test yes = "$build_old_libs"; then write_oldobj=\'$3\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $debug_cmd # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $debug_cmd if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $debug_cmd # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $debug_cmd if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result=$1 fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $debug_cmd if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result=$3 fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $debug_cmd case $4 in $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $debug_cmd $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $debug_cmd case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result=$1 } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $debug_cmd if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd=func_convert_path_$func_stripname_result fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $debug_cmd func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result=$1 } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_dll_def_p FILE # True iff FILE is a Windows DLL '.def' file. # Keep in sync with _LT_DLL_DEF_P in libtool.m4 func_dll_def_p () { $debug_cmd func_dll_def_p_tmp=`$SED -n \ -e 's/^[ ]*//' \ -e '/^\(;.*\)*$/d' \ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ -e q \ "$1"` test DEF = "$func_dll_def_p_tmp" } # func_mode_compile arg... func_mode_compile () { $debug_cmd # 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= pie_flag= 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) test -n "$libobj" && \ func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append 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,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs=$IFS; IFS=, for arg in $args; do IFS=$save_ifs func_append_quoted lastarg "$arg" done IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append 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. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj=$func_basename_result } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test yes = "$build_libtool_libs" \ || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname=$func_basename_result xdir=$func_dirname_result lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; 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 no = "$compiler_c_o"; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext lockfile=$output_obj.lock 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 yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test warn = "$need_locks"; 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." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && 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." $opt_dry_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 func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test yes = "$build_old_libs"; then if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && 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." $opt_dry_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 func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [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: $progname [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 -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a '.o' file suitable for static linking -static only build a '.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler 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: $progname [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: $progname [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: $progname [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 following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [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 -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -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 -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -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 -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -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] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) 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: $progname [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." ;; *) func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test : = "$opt_help"; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | $SED '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $debug_cmd # The first argument is the command name. cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "'$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir=$func_dirname_result ;; *) func_warning "'-dlopen' is ignored for non-libtool libraries and objects" 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 -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file=$progdir/$program fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if $opt_dry_run; then # 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 else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE 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 fi } test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $debug_cmd libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "'$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument '$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" 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" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $debug_cmd # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=false stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=: if $isdir; then destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." destdir=$func_dirname_result destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "'$destdir' must be an absolute directory name" ;; 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. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir=$func_dirname_result func_append 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 -e "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. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking '$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname=$1 shift srcname=$realname test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme= ;; esac ;; os2*) case $realname in *_dll.a) tstripme= ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_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 test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name=$func_basename_result instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append 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 func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest=$destfile destfile= ;; *) func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_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 func_basename "$file" destfile=$func_basename_result 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 func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=.exe fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script '$wrapper'" finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then func_warning "'$lib' has not been installed in '$libdir'" finalize=false fi done relink_command= func_source "$wrapper" outputname= if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file=$func_basename_result outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file=$outputname else func_warning "cannot relink '$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "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) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name=$func_basename_result # Set up the ranlib parameters. oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $debug_cmd my_outputname=$1 my_originator=$2 my_pic_p=${3-false} my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* External symbol declarations for the compiler. */\ " if test yes = "$dlself"; then func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # 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 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/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) 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*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; 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 "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # 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. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd 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 # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac 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_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= 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 func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result 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 func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_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've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # 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. sed_quote_subst='$sed_quote_subst' # 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+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # 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 variables: generated_by_libtool_version='$macro_version' 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 file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED '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 \"\$file\" | $SED '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 \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ 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 "\ # 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 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # 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 \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} 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 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #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 # define FOPEN_WB "wb" # 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 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ 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]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); 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 = (size_t) (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 (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); 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 (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); 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 * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } 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 (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what 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 that 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= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" 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 func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append 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 dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; 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 func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" 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 # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir 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 func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework 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*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # 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-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext 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 ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -stdlib=* select c++ std lib with clang -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_for_eval "$arg" arg=$func_quote_for_eval_result fi ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append 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 dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; 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 func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" 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. func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'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\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. 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 $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; 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 $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append 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 notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; 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 .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # 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 yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else 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 use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # 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 func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" 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. func_append dlprefiles " $lib $dependency_libs" else func_append 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 func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && 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 func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; 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 prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || 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 *"$absdir:"*) ;; *) func_append 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 "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && 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 built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; 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 lib = "$linkmode" && test yes = "$hardcode_into_libs"; 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 "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 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* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' 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 prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; 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 (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; 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 elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; 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 yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; 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 [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; 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 prog = "$linkmode"; 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 unsupported != "$hardcode_direct"; 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 yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; 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 cannot 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 yes = "$module"; 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 no = "$build_old_libs"; 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 lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= 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 "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # 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 "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=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 "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # 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 func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; 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 test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # 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=$1 number_minor=$2 number_revision=$3 # # 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 # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; esac ;; no) current=$1 revision=$2 age=$3 ;; 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]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; 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]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; 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]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" 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 func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result 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 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; 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 no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; 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 | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "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 func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; 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 "*) ;; *) func_append 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 "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-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 yes = "$build_libtool_need_lc"; then func_append 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. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi 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 "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append 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 ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append 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 func_append 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 ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; 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 ;; esac ;; 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 with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; 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 no = "$build_old_libs"; 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 no = "$allow_undefined"; 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 no = "$build_old_libs"; 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 # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; 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 " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append 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 yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result 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"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append 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 "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append 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 relink = "$opt_mode" || 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 shift realname=$1 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 func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "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" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && 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 : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # 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 func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result 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~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "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 $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } 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\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && 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 fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( 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 relink = "$opt_mode"; then $opt_dry_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 func_show_eval '${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 func_show_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 yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_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= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${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" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; 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 "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append 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 "*) ;; *) func_append 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"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append 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"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append 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 yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } 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 func_append 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 func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; 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 "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "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}\" || $lt_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 func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result 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 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # 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 func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$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 eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$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= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "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}\" || $lt_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 func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; 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 "$relink_command" | $SED "$sed_quote_subst"` if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; 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) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # 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' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_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 no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false 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) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; 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 $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where 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 build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: ipmiutil-3.1.9/aclocal.m40000644000000000000000000132725414373711040013734 0ustar rootroot# generated automatically by aclocal 1.16.2 -*- Autoconf -*- # Copyright (C) 1996-2020 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. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # 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. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 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. # GNU Libtool 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 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool 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, see . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl 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 set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. 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 delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # 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 sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -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 Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, 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 TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_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 set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # 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" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])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_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$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. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$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 -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_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$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed '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$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # 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. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || 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 what ABI is being produced by ac_compile, and set mode # options accordingly. 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 what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; 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* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. 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-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; 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-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) 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_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. 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*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # 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:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $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 "$_lt_compiler_boilerplate" | $SED '/^$/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 yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$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 "$_lt_linker_boilerplate" | $SED '/^$/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 -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # 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* | cegcc*) # 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; ;; mint*) # On MiNT this can take a long time and run out of memory. 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; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # 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 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; 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 ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then 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` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # 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. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` 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` fi ;; 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 max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #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 /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 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; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_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_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; 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* | cegcc*) 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 ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) 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=-ldld], [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=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && 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_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 yes = "$lt_cv_dlopen_self"; 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_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 _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$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:$LINENO: $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:$LINENO: \$? = $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 "$_lt_compiler_boilerplate" | $SED '/^$/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_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 .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; 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 no = "$hard_links"; 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 _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_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 _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # 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 no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) 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" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # 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. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) 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" 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 AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor 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' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; 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 # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.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' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # 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' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) 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=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $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' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor 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* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc 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~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' 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' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; 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 dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. 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 # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # 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' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # 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$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`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor 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 ;; 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[[23]].*) 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$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' 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 ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" 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=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' 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 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; 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' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor 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 yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor 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 ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # 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 dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor 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 # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # 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 # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) 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/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $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' ;; 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 # correct to gnu/linux during the next big refactor 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=qnx 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='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi 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 shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec 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~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; 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 ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor 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 yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor 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 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 # correct to gnu/linux during the next big refactor 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=sco 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 shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' 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' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor 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 no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[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]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_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="m4_if([$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 <<_LT_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 _LT_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 _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_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 _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; 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 yes = "$with_gnu_ld"; 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 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize 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 # that 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 aix[[4-9]]*) 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', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | 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 ;; haiku*) 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])(-bit)?( [LM]SB)? 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 ;; interix[[3-9]]*) # 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 glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) 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=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; 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 ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) 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 ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi 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 _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (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 # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) 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 : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-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_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # 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]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' 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 # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # 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 # Try without a prefix underscore, 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. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_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 <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_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_globsym_save_LIBS CFLAGS=$lt_globsym_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 -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; 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 # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # 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_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # 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). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # 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_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_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 ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # 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). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_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_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_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_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_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_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # 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_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # 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). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # 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_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # 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). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_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_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_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_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # 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. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # 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 yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; 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_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_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_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[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 aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, 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 install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_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_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_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, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); 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_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_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_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_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' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$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' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_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 '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_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~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $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_TAGVAR(ld_shlibs, $1)=no cat <<_LT_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. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_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_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** 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 ;; *) # 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. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_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_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_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_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_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_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; 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 GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | 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 # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; 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_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; 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 : else # We have old collect2 _LT_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_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; 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 yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_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_SYS_MODULE_PATH_AIX([$1]) _LT_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_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_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_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # 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. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # 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_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_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' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_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_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $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_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_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_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_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 no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_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_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_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_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_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' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_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 -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_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 CANNOT 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_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_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_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$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_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl 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_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what 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 no = "$can_build_shared" && 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 yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac 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 yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_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_CFLAGS=$CFLAGS 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++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_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 yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_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_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_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_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 -v "^Configured with:" | $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_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; 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 # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; 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_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; 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 : else # We have old collect2 _LT_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_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; 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 yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_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_SYS_MODULE_PATH_AIX([$1]) _LT_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_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # 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_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_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, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); 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_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_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_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_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 "x$output_objdir/$soname" = "x$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) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_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_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_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; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $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_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_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_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_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_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-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_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) 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_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_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; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_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_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # 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_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_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_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_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_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_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' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_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_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_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=`func_echo_all "$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; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_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 -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # 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_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_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::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_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_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | 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_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_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_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_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_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=`func_echo_all "$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; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_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" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_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 -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_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_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # 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_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_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_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -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 -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_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 $wl-h $wl$soname -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 -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_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 CANNOT 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_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$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_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC 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 fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([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. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= 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... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac 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 for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev 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_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_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_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$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 no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_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 CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # 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_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_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_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_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_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && 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 yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac 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 yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_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_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && 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 yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac 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 yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_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_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_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_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # 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_TAG_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_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ # 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. # m4_defun([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 10 -lt "$lt_ac_count" && 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]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # 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 lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # 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 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_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=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_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=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_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=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # 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 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # 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. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # 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 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) # Copyright (C) 2002-2020 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. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.2], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.2])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2020 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], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2020 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_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl 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-2020 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. # 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", "OBJC", "OBJCXX", "UPC", or "GJC". # 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 m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$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". rm -rf conftest.dir 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 am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) 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 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # 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. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; 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 ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj 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], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2020 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_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _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. # This creates each '.Po' and '.Plo' makefile fragment that we'll 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" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2020 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 macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # 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.65])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 if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi 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], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])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]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). 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])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # 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_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2020 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 if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2020 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. # 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-2020 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_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2020 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_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 is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2020 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_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], [m4_foreach_w([_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])]) # Copyright (C) 1999-2020 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_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2020 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_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2020 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_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # 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 ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file 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 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 if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done 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]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2020 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_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2020 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="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2020 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_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2020 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_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. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} 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 /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 ipmiutil-3.1.9/vcvars64.bat0000644000000000000000000000176214144515623014237 0ustar rootroot@echo off REM Copy saved 64bit libraries into place, if present REM iphlpapi.lib libeay32.dll libeay32.lib ssleay32.dll ssleay32.lib REM Modify SAVLIB64 to a directory where these libs are saved. set SAVLIB64=lib64 IF NOT EXIST %SAVLIB64% GOTO NOSAVLIB copy /Y %SAVLIB64%\*.lib lib copy /Y %SAVLIB64%\*.dll util REM (do not copy mak) copy /Y util\x64\ipmiutil.mak util :NOSAVLIB REM sample VCINSTALLDIR from VS 2008 set VCDIR=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC IF DEFINED VCINSTALLDIR GOTO HAVEVC IF DEFINED VSINSTALLDIR GOTO HAVEVS GOTO HAVEDEF :HAVEVS set VCDIR=%VSINSTALLDIR%\VC :HAVEVC set VCDIR=%VCINSTALLDIR% :HAVEDEF REM Run MS 64bit vcvars set VCBAT="%VCDIR%\bin\x86_amd64\vcvarsx86_amd64.bat" set VCBATDIR="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build" set VCBAT=%VCBATDIR%\vcvarsx86_amd64.bat IF EXIST %VCBAT% GOTO RUNVC echo "Cannot locate vcvars for amd64, please run it manually." GOTO DONE :RUNVC %VCBAT% :DONE ipmiutil-3.1.9/vcvars32.bat0000644000000000000000000000172714144515623014233 0ustar rootroot@echo off REM Copy saved 32bit libraries into place, if present REM iphlpapi.lib libeay32.dll libeay32.lib ssleay32.dll ssleay32.lib REM Modify SAVLIB32 to a directory where these libs are saved. set SAVLIB32=lib32 IF NOT EXIST %SAVLIB32% GOTO NOSAVLIB copy /Y %SAVLIB32%\*.lib lib copy /Y %SAVLIB32%\*.dll util REM (do not copy mak) copy /Y util\x32\ipmiutil.mak util :NOSAVLIB REM sample VCINSTALLDIR from VS 2008 set VCDIR=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC IF DEFINED VCINSTALLDIR GOTO HAVEVC IF DEFINED VSINSTALLDIR GOTO HAVEVS GOTO HAVEDEF :HAVEVS set VCDIR=%VSINSTALLDIR%\VC :HAVEVC set VCDIR=%VCINSTALLDIR% :HAVEDEF REM Run MS 32bit vcvars set VCBAT="%VCDIR%\bin\vcvars32.bat" set VCBATDIR="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build" set VCBAT=%VCBATDIR%\vcvars32.bat IF EXIST %VCBAT% GOTO RUNVC echo "Cannot locate vcvars32.bat, please run it manually." GOTO DONE :RUNVC %VCBAT% :DONE ipmiutil-3.1.9/util/0000755000000000000000000000000014403640651013036 5ustar rootrootipmiutil-3.1.9/util/Makefile.in0000644000000000000000000012262714373711044015116 0ustar rootroot# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = ipmiutil$(EXEEXT) ievents$(EXEEXT) idiscover$(EXEEXT) sbin_PROGRAMS = ipmi_port$(EXEEXT) iseltime$(EXEEXT) EXTRA_PROGRAMS = ipmi_sample$(EXEEXT) ipmi_sample_evt$(EXEEXT) subdir = util 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) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS) am_idiscover_OBJECTS = idiscover.$(OBJEXT) idiscover_OBJECTS = $(am_idiscover_OBJECTS) idiscover_LDADD = $(LDADD) am__DEPENDENCIES_1 = idiscover_DEPENDENCIES = $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_ievents_OBJECTS = ievents.$(OBJEXT) ievents_OBJECTS = $(am_ievents_OBJECTS) ievents_LDADD = $(LDADD) ievents_DEPENDENCIES = $(am__DEPENDENCIES_1) am_ipmi_port_OBJECTS = ipmi_port.$(OBJEXT) ipmi_port_OBJECTS = $(am_ipmi_port_OBJECTS) ipmi_port_LDADD = $(LDADD) ipmi_port_DEPENDENCIES = $(am__DEPENDENCIES_1) ipmi_sample_SOURCES = ipmi_sample.c ipmi_sample_OBJECTS = ipmi_sample.$(OBJEXT) ipmi_sample_LDADD = $(LDADD) ipmi_sample_DEPENDENCIES = $(am__DEPENDENCIES_1) ipmi_sample_evt_SOURCES = ipmi_sample_evt.c ipmi_sample_evt_OBJECTS = ipmi_sample_evt.$(OBJEXT) ipmi_sample_evt_LDADD = $(LDADD) ipmi_sample_evt_DEPENDENCIES = $(am__DEPENDENCIES_1) am__objects_1 = oem_kontron.$(OBJEXT) oem_fujitsu.$(OBJEXT) \ oem_intel.$(OBJEXT) oem_sun.$(OBJEXT) oem_supermicro.$(OBJEXT) \ oem_dell.$(OBJEXT) oem_quanta.$(OBJEXT) oem_hp.$(OBJEXT) \ oem_newisys.$(OBJEXT) oem_lenovo.$(OBJEXT) oem_asus.$(OBJEXT) \ iekanalyzer.$(OBJEXT) am__objects_2 = ipmicmd.$(OBJEXT) mem_if.$(OBJEXT) ipmidir.$(OBJEXT) \ imbapi.$(OBJEXT) ipmimv.$(OBJEXT) ipmild.$(OBJEXT) \ ipmibmc.$(OBJEXT) ipmilipmi.$(OBJEXT) subs.$(OBJEXT) \ md5.$(OBJEXT) md2.$(OBJEXT) ipmilan.$(OBJEXT) \ ipmilanplus.$(OBJEXT) am__objects_3 = ipmiutil.$(OBJEXT) ialarms.$(OBJEXT) ihealth.$(OBJEXT) \ ievents.$(OBJEXT) ifru.$(OBJEXT) ifru_picmg.$(OBJEXT) \ igetevent.$(OBJEXT) ireset.$(OBJEXT) icmd.$(OBJEXT) \ ilan.$(OBJEXT) isensor.$(OBJEXT) isel.$(OBJEXT) \ iserial.$(OBJEXT) iwdt.$(OBJEXT) isol.$(OBJEXT) \ idiscover.$(OBJEXT) iconfig.$(OBJEXT) ipicmg.$(OBJEXT) \ ifirewall.$(OBJEXT) ifwum.$(OBJEXT) ihpm.$(OBJEXT) \ itsol.$(OBJEXT) idcmi.$(OBJEXT) iuser.$(OBJEXT) \ $(am__objects_1) $(am__objects_2) am_ipmiutil_OBJECTS = $(am__objects_3) ipmiutil_OBJECTS = $(am_ipmiutil_OBJECTS) ipmiutil_LDADD = $(LDADD) ipmiutil_DEPENDENCIES = $(am__DEPENDENCIES_1) iseltime_SOURCES = iseltime.c iseltime_OBJECTS = iseltime.$(OBJEXT) iseltime_LDADD = $(LDADD) iseltime_DEPENDENCIES = $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/ialarms.Po ./$(DEPDIR)/icmd.Po \ ./$(DEPDIR)/iconfig.Po ./$(DEPDIR)/idcmi.Po \ ./$(DEPDIR)/idiscover.Po ./$(DEPDIR)/iekanalyzer.Po \ ./$(DEPDIR)/ievents.Po ./$(DEPDIR)/ifirewall.Po \ ./$(DEPDIR)/ifru.Po ./$(DEPDIR)/ifru_picmg.Po \ ./$(DEPDIR)/ifwum.Po ./$(DEPDIR)/igetevent.Po \ ./$(DEPDIR)/ihealth.Po ./$(DEPDIR)/ihpm.Po ./$(DEPDIR)/ilan.Po \ ./$(DEPDIR)/imbapi.Po ./$(DEPDIR)/ipicmg.Po \ ./$(DEPDIR)/ipmi_port.Po ./$(DEPDIR)/ipmi_sample.Po \ ./$(DEPDIR)/ipmi_sample_evt.Po ./$(DEPDIR)/ipmibmc.Po \ ./$(DEPDIR)/ipmicmd.Po ./$(DEPDIR)/ipmidir.Po \ ./$(DEPDIR)/ipmilan.Po ./$(DEPDIR)/ipmilanplus.Po \ ./$(DEPDIR)/ipmild.Po ./$(DEPDIR)/ipmilipmi.Po \ ./$(DEPDIR)/ipmimv.Po ./$(DEPDIR)/ipmiutil.Po \ ./$(DEPDIR)/ireset.Po ./$(DEPDIR)/isel.Po \ ./$(DEPDIR)/iseltime.Po ./$(DEPDIR)/isensor.Po \ ./$(DEPDIR)/iserial.Po ./$(DEPDIR)/isol.Po \ ./$(DEPDIR)/itsol.Po ./$(DEPDIR)/iuser.Po ./$(DEPDIR)/iwdt.Po \ ./$(DEPDIR)/md2.Po ./$(DEPDIR)/md5.Po ./$(DEPDIR)/mem_if.Po \ ./$(DEPDIR)/oem_asus.Po ./$(DEPDIR)/oem_dell.Po \ ./$(DEPDIR)/oem_fujitsu.Po ./$(DEPDIR)/oem_hp.Po \ ./$(DEPDIR)/oem_intel.Po ./$(DEPDIR)/oem_kontron.Po \ ./$(DEPDIR)/oem_lenovo.Po ./$(DEPDIR)/oem_newisys.Po \ ./$(DEPDIR)/oem_quanta.Po ./$(DEPDIR)/oem_sun.Po \ ./$(DEPDIR)/oem_supermicro.Po ./$(DEPDIR)/subs.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = 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 am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ $(top_srcdir)/mkinstalldirs DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CROSS_CFLAGS = @CROSS_CFLAGS@ CROSS_LFLAGS = @CROSS_LFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GPL_CFLAGS = @GPL_CFLAGS@ GREP = @GREP@ IA64_CFLAGS = @IA64_CFLAGS@ INIT_DIR = @INIT_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INS_LIB = @INS_LIB@ LANDESK_CFLAGS = @LANDESK_CFLAGS@ LANDESK_LDADD = @LANDESK_LDADD@ LANPLUS_CFLAGS = @LANPLUS_CFLAGS@ LANPLUS_CRYPTO = @LANPLUS_CRYPTO@ LANPLUS_LDADD = @LANPLUS_LDADD@ LANPLUS_LIB = @LANPLUS_LIB@ LANPLUS_SAM = @LANPLUS_SAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LD_SAMX = @LD_SAMX@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSENSORS = @LIBSENSORS@ LIBTOOL = @LIBTOOL@ LIB_DIR = @LIB_DIR@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OS_CFLAGS = @OS_CFLAGS@ OS_DRIVERS = @OS_DRIVERS@ OS_LFLAGS = @OS_LFLAGS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_DIR = @PKG_DIR@ RANLIB = @RANLIB@ SAM2OBJ = @SAM2OBJ@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SHR_LINK = @SHR_LINK@ STRIP = @STRIP@ SUBDIR_S = @SUBDIR_S@ SYSTEMD_DIR = @SYSTEMD_DIR@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = $(datadir)/locale localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ OS_CF = @OS_CFLAGS@ @CROSS_CFLAGS@ OS_LF = @OS_LFLAGS@ @CROSS_LFLAGS@ # To build ipmiutil, need to use METACFLAGS for each .c/.o # The LanDesk library is proprietary, so it is incompatible with ALLOW_GPL. # To build with LanDesk support: # First copy the library to ../lib/libipmiapi.a # Then ./configure --enable-landesk # Result: # AM_CPPFLAGS += -DLINK_LANDESK # LDADD += -lipmiapi -L../lib # For lanplus plugin support (IPMI LAN 2.0 RMCP+) used by SOL: # If ./configure --disable-lanplus # AM_CPPFLAGS += # LDADD += # Otherwise default result is lanplus enabled: # AM_CPPFLAGS += -DHAVE_LANPLUS # LDADD += -L../lib -lipmi_lanplus -L/usr/local/lib -lcrypto # LDADD += -L../lib -lintf_lanplus -L/usr/local/lib -lcrypto (older) # Could also use CMDMOD += ipmilan2.c instead, if completed. AM_CPPFLAGS = $(OS_CF) -DLOCALEDIR=\"$(localedir)\" -I.. @IA64_CFLAGS@ \ @GPL_CFLAGS@ -I. -I.. -DMETACOMMAND @LANDESK_CFLAGS@ \ @LANPLUS_CFLAGS@ $(am__empty) LDADD = $(OS_LF) -lpthread @LANDESK_LDADD@ @LANPLUS_LIB@ \ @LANPLUS_CRYPTO@ $(am__empty) # usu LD_SAMX = ../lib/libipmi_lanplus.a -lcrypto LDSAM = $(OS_LF) @LD_SAMX@ CFLAGS_SAMX = -O2 -g -I. -I.. $(OS_CF) @LANPLUS_CFLAGS@ CFLAGS_SAM = -O2 -g -I. -I.. $(OS_CF) # May be /usr/bin/install or /bin/install INSTALLBIN = install -c extradir = $(datadir)/ipmiutil inc_dir = $(includedir) tmpobj = obj tmpwin = tmp LIBDIR = @LIB_DIR@ CMDMOD = ipmicmd.c mem_if.c ipmidir.c imbapi.c ipmimv.c ipmild.c \ ipmibmc.c ipmilipmi.c subs.c md5.c md2.c ipmilan.c \ ipmilanplus.c # CMDMOD = ipmicmd.c mem_if.c @OS_DRIVERS@ # am: configure substitutions are not allowed in _SOURCES variables TMPOBJL = $(tmpobj)/ipmilanL.o $(tmpobj)/ipmilanplusL.o TMPOBJA = $(tmpobj)/ipmilanA.o $(tmpobj)/ipmilanplusA.o LIBOBJ = ipmicmd.o mem_if.o ipmidir.o imbapi.o ipmimv.o ipmild.o ipmibmc.o ipmilipmi.o subs.o md5.o md2.o @LIBSENSORS@ OEMMOD = oem_kontron.c oem_fujitsu.c oem_intel.c oem_sun.c oem_supermicro.c oem_dell.c oem_quanta.c oem_hp.c oem_newisys.c oem_lenovo.c oem_asus.c iekanalyzer.c # usu SAM2OBJ = isensor2.o ievents2.o L2OBJ = @SAM2OBJ@ METASOURCE = ipmiutil.c ialarms.c ihealth.c ievents.c ifru.c ifru_picmg.c igetevent.c ireset.c icmd.c ilan.c isensor.c isel.c iserial.c iwdt.c isol.c idiscover.c iconfig.c ipicmg.c ifirewall.c ifwum.c ihpm.c itsol.c idcmi.c iuser.c $(OEMMOD) $(CMDMOD) LANPLUS_OBJ = $(shell ar t @LANPLUS_LIB@ 2>/dev/null) DEV_LIB = libipmiutil.a # SHRLINK is libipmiutil.so.1 if OS supports it SHRLINK = @SHR_LINK@ SHR_LIB = $(SHRLINK) SHR_BLIB = libipmiutil.so LDNAME = -Wl,-soname,$(SHR_LIB) TESTPROGS = libimbapi.a iconfig ipmimv ifruset ipmi_sample2 ialarms_enc # OLDPROGS are old/previous binaries that may exist and need to be deleted. OLDPROGS = alarms bmchealth fruconfig getevent hwreset icmd isolconsole pefconfig sensor showsel tmconfig wdt ipmiutil_SOURCES = $(METASOURCE) ievents_SOURCES = ievents.c idiscover_SOURCES = idiscover.c ipmi_port_SOURCES = ipmi_port.c EXTRA_DIST = imb_api.h ipmicmd.h ipmidir.h ipmilan.h ipmilanplus.h AnsiTerm.h ifirewall.h ifwum.h ihpm.h ipicmg.h ipmiutil.h md2.h oem_dell.h oem_fujitsu.h oem_intel.h oem_kontron.h oem_sun.h idcmi.h isensor.h iekanalyzer.h all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign util/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign util/Makefile 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__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ialarms.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icmd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iconfig.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idcmi.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idiscover.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iekanalyzer.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ievents.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifirewall.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifru.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifru_picmg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifwum.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/igetevent.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ihealth.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ihpm.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ilan.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imbapi.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipicmg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_port.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sample.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sample_evt.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmibmc.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmicmd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmidir.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmilan.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmilanplus.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmild.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmilipmi.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmimv.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmiutil.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ireset.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isel.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iseltime.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isensor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iserial.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isol.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/itsol.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iuser.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iwdt.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem_if.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_asus.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_dell.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_fujitsu.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_hp.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_intel.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_kontron.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_lenovo.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_newisys.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_quanta.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_sun.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oem_supermicro.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subs.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/ialarms.Po -rm -f ./$(DEPDIR)/icmd.Po -rm -f ./$(DEPDIR)/iconfig.Po -rm -f ./$(DEPDIR)/idcmi.Po -rm -f ./$(DEPDIR)/idiscover.Po -rm -f ./$(DEPDIR)/iekanalyzer.Po -rm -f ./$(DEPDIR)/ievents.Po -rm -f ./$(DEPDIR)/ifirewall.Po -rm -f ./$(DEPDIR)/ifru.Po -rm -f ./$(DEPDIR)/ifru_picmg.Po -rm -f ./$(DEPDIR)/ifwum.Po -rm -f ./$(DEPDIR)/igetevent.Po -rm -f ./$(DEPDIR)/ihealth.Po -rm -f ./$(DEPDIR)/ihpm.Po -rm -f ./$(DEPDIR)/ilan.Po -rm -f ./$(DEPDIR)/imbapi.Po -rm -f ./$(DEPDIR)/ipicmg.Po -rm -f ./$(DEPDIR)/ipmi_port.Po -rm -f ./$(DEPDIR)/ipmi_sample.Po -rm -f ./$(DEPDIR)/ipmi_sample_evt.Po -rm -f ./$(DEPDIR)/ipmibmc.Po -rm -f ./$(DEPDIR)/ipmicmd.Po -rm -f ./$(DEPDIR)/ipmidir.Po -rm -f ./$(DEPDIR)/ipmilan.Po -rm -f ./$(DEPDIR)/ipmilanplus.Po -rm -f ./$(DEPDIR)/ipmild.Po -rm -f ./$(DEPDIR)/ipmilipmi.Po -rm -f ./$(DEPDIR)/ipmimv.Po -rm -f ./$(DEPDIR)/ipmiutil.Po -rm -f ./$(DEPDIR)/ireset.Po -rm -f ./$(DEPDIR)/isel.Po -rm -f ./$(DEPDIR)/iseltime.Po -rm -f ./$(DEPDIR)/isensor.Po -rm -f ./$(DEPDIR)/iserial.Po -rm -f ./$(DEPDIR)/isol.Po -rm -f ./$(DEPDIR)/itsol.Po -rm -f ./$(DEPDIR)/iuser.Po -rm -f ./$(DEPDIR)/iwdt.Po -rm -f ./$(DEPDIR)/md2.Po -rm -f ./$(DEPDIR)/md5.Po -rm -f ./$(DEPDIR)/mem_if.Po -rm -f ./$(DEPDIR)/oem_asus.Po -rm -f ./$(DEPDIR)/oem_dell.Po -rm -f ./$(DEPDIR)/oem_fujitsu.Po -rm -f ./$(DEPDIR)/oem_hp.Po -rm -f ./$(DEPDIR)/oem_intel.Po -rm -f ./$(DEPDIR)/oem_kontron.Po -rm -f ./$(DEPDIR)/oem_lenovo.Po -rm -f ./$(DEPDIR)/oem_newisys.Po -rm -f ./$(DEPDIR)/oem_quanta.Po -rm -f ./$(DEPDIR)/oem_sun.Po -rm -f ./$(DEPDIR)/oem_supermicro.Po -rm -f ./$(DEPDIR)/subs.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/ialarms.Po -rm -f ./$(DEPDIR)/icmd.Po -rm -f ./$(DEPDIR)/iconfig.Po -rm -f ./$(DEPDIR)/idcmi.Po -rm -f ./$(DEPDIR)/idiscover.Po -rm -f ./$(DEPDIR)/iekanalyzer.Po -rm -f ./$(DEPDIR)/ievents.Po -rm -f ./$(DEPDIR)/ifirewall.Po -rm -f ./$(DEPDIR)/ifru.Po -rm -f ./$(DEPDIR)/ifru_picmg.Po -rm -f ./$(DEPDIR)/ifwum.Po -rm -f ./$(DEPDIR)/igetevent.Po -rm -f ./$(DEPDIR)/ihealth.Po -rm -f ./$(DEPDIR)/ihpm.Po -rm -f ./$(DEPDIR)/ilan.Po -rm -f ./$(DEPDIR)/imbapi.Po -rm -f ./$(DEPDIR)/ipicmg.Po -rm -f ./$(DEPDIR)/ipmi_port.Po -rm -f ./$(DEPDIR)/ipmi_sample.Po -rm -f ./$(DEPDIR)/ipmi_sample_evt.Po -rm -f ./$(DEPDIR)/ipmibmc.Po -rm -f ./$(DEPDIR)/ipmicmd.Po -rm -f ./$(DEPDIR)/ipmidir.Po -rm -f ./$(DEPDIR)/ipmilan.Po -rm -f ./$(DEPDIR)/ipmilanplus.Po -rm -f ./$(DEPDIR)/ipmild.Po -rm -f ./$(DEPDIR)/ipmilipmi.Po -rm -f ./$(DEPDIR)/ipmimv.Po -rm -f ./$(DEPDIR)/ipmiutil.Po -rm -f ./$(DEPDIR)/ireset.Po -rm -f ./$(DEPDIR)/isel.Po -rm -f ./$(DEPDIR)/iseltime.Po -rm -f ./$(DEPDIR)/isensor.Po -rm -f ./$(DEPDIR)/iserial.Po -rm -f ./$(DEPDIR)/isol.Po -rm -f ./$(DEPDIR)/itsol.Po -rm -f ./$(DEPDIR)/iuser.Po -rm -f ./$(DEPDIR)/iwdt.Po -rm -f ./$(DEPDIR)/md2.Po -rm -f ./$(DEPDIR)/md5.Po -rm -f ./$(DEPDIR)/mem_if.Po -rm -f ./$(DEPDIR)/oem_asus.Po -rm -f ./$(DEPDIR)/oem_dell.Po -rm -f ./$(DEPDIR)/oem_fujitsu.Po -rm -f ./$(DEPDIR)/oem_hp.Po -rm -f ./$(DEPDIR)/oem_intel.Po -rm -f ./$(DEPDIR)/oem_kontron.Po -rm -f ./$(DEPDIR)/oem_lenovo.Po -rm -f ./$(DEPDIR)/oem_newisys.Po -rm -f ./$(DEPDIR)/oem_quanta.Po -rm -f ./$(DEPDIR)/oem_sun.Po -rm -f ./$(DEPDIR)/oem_supermicro.Po -rm -f ./$(DEPDIR)/subs.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool \ clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-sbinPROGRAMS install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-sbinPROGRAMS .PRECIOUS: Makefile # To build an imb api library (libimbapi.a): libimbapi.a: imbapi.c mkdir -p $(tmpobj) $(CC) -I. -I.. $(OS_CF) -fPIC $(CFLAGS) -o $(tmpobj)/imbapi.o -c imbapi.c $(AR) cru libimbapi.a $(tmpobj)/imbapi.o $(RANLIB) libimbapi.a rm -f $(tmpobj)/imbapi.o $(tmpobj)/ipmilanplusL.o: ipmilanplus.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanplusL.o -c ipmilanplus.c; $(tmpobj)/ipmilanL.o: ipmilan.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAMX) -o $(tmpobj)/ipmilanL.o -c ipmilan.c; $(tmpobj)/ipmilanplusA.o: ipmilanplus.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanplusA.o -c ipmilanplus.c; $(tmpobj)/ipmilanA.o: ipmilan.c mkdir -p $(tmpobj) $(CC) $(CFLAGS_SAM) -o $(tmpobj)/ipmilanA.o -c ipmilan.c; # Build a lib to support all of the IPMI drivers (libipmiutil.a) # If LANPLUS_SAM = yes, include LANPLUS_OBJ, else do not. # See configure --enable-liblanplus to change this $(DEV_LIB): $(CMDMOD:.c=.o) @LANPLUS_LIB@ @LIBSENSORS@ $(TMPOBJL) $(TMPOBJA) if [ "x@LANPLUS_SAM@" = "xyes" ]; then \ ar x @LANPLUS_LIB@ ; \ $(AR) cru $(DEV_LIB) $(LIBOBJ) $(TMPOBJL) $(LANPLUS_OBJ); \ $(RANLIB) $(DEV_LIB); \ else \ $(AR) cru $(DEV_LIB) $(LIBOBJ) $(TMPOBJA) ; \ $(RANLIB) $(DEV_LIB) ; \ fi $(SHR_LIB): $(CMDMOD:.c=.o) @LANPLUS_LIB@ @LIBSENSORS@ $(TMPOBJL) $(TMPOBJA) if [ "x@LANPLUS_SAM@" = "xyes" ]; then \ ar x @LANPLUS_LIB@ ; \ $(CC) $(LDFLAGS) -shared $(LDNAME) -o $(SHR_LIB) $(LIBOBJ) $(TMPOBJL) $(LANPLUS_OBJ); \ else \ $(CC) $(LDFLAGS) -shared $(LDNAME) -o $(SHR_LIB) $(LIBOBJ) $(TMPOBJA) ; \ fi $(SHR_BLIB): $(SHR_LIB) ln -s $(SHR_LIB) $(SHR_BLIB) idiscover$(EXEEXT): idiscover.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) $(OS_LF) -o idiscover idiscover.c ipmimv$(EXEEXT): ipmimv.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) -DTEST_BIN -o ipmimv ipmimv.c ievents$(EXEEXT): ievents.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) -DALONE -o ievents ievents.c isensor2.o: isensor.c $(CC) $(CFLAGS_SAM) -o isensor2.o -c isensor.c ievents2.o: ievents.c $(CC) $(CFLAGS_SAM) -DSENSORS_OK -o ievents2.o -c ievents.c ifru_picmg2.o: ifru_picmg.c $(CC) $(CFLAGS_SAM) -o ifru_picmg2.o -c ifru_picmg.c ifru2.o: ifru.c $(CC) $(CFLAGS_SAM) -o ifru2.o -c ifru.c isel2.o: isel.c $(CC) $(CFLAGS_SAM) -o isel2.o -c isel.c ipmi_sample.o: ipmi_sample.c $(CC) $(CFLAGS_SAM) -c ipmi_sample.c ipmi_sample2.o: ipmi_sample.c $(CC) $(CFLAGS_SAM) -D GET_SENSORS -D GET_FRU -o ipmi_sample2.o -c ipmi_sample.c ipmi_sample_evt.o: ipmi_sample_evt.c $(CC) $(CFLAGS_SAM) -o ipmi_sample_evt.o -c ipmi_sample_evt.c ipmi_sample$(EXEEXT): $(DEV_LIB) ipmi_sample.o isensor.o ievents.o $(CC) -g -O2 -o ipmi_sample ipmi_sample.o $(DEV_LIB) $(LDFLAGS) $(LDSAM) # To build ipmi_sample with GET_SENSORS enabled, need isensors.o, ievents.o # Note that this does not include oem_intel, etc. for OEM SEL decoding. ipmi_sample2$(EXEEXT): $(DEV_LIB) ipmi_sample2.o ifru2.o isel2.o ifru_picmg2.o $(L2OBJ) $(CC) -g -O2 -o ipmi_sample2 ipmi_sample2.o $(L2OBJ) ifru2.o ifru_picmg2.o isel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM) ipmi_sample_evt$(EXEEXT): $(DEV_LIB) ipmi_sample_evt.o $(L2OBJ) $(CC) -g -O2 -o ipmi_sample_evt ipmi_sample_evt.o $(L2OBJ) $(DEV_LIB) $(LDFLAGS) $(LDSAM) ialarms2.o: ialarms.c $(CC) $(CFLAGS_SAM) -DTEST_ENC -o ialarms2.o -c ialarms.c oem_intel2.o: oem_intel.c $(CC) $(CFLAGS_SAM) -DNO_EVENTS -o oem_intel2.o -c oem_intel.c ialarms_enc$(EXEEXT): $(DEV_LIB) ialarms2.o oem_intel2.o $(CC) -g -O2 -o ialarms_enc ialarms2.o oem_intel2.o $(DEV_LIB) $(LDFLAGS) $(LDSAM) ifruset.o: ifruset.c $(CC) $(CFLAGS_SAM) -c ifruset.c ifruset$(EXEEXT): $(DEV_LIB) ifruset.o ifru_picmg2.o $(CC) -g -O2 -o ifruset ifruset.o ifru_picmg2.o $(DEV_LIB) $(LDFLAGS) $(LDADD) iseltime.o: iseltime.c $(CC) $(CFLAGS_SAM) -c iseltime.c iseltime$(EXEEXT): $(DEV_LIB) iseltime.o $(CC) -g -O2 -o iseltime iseltime.o $(DEV_LIB) $(LDFLAGS) $(LDADD) iconfig$(EXEEXT): iconfig.c $(DEV_LIB) $(CC) $(CFLAGS_SAM) $(LDFLAGS) -o iconfig iconfig.c $(DEV_LIB) @LANPLUS_CRYPTO@ ipmi_port$(EXEEXT): ipmi_port.c $(CC) $(CFLAGS_SAM) $(LDFLAGS) -o ipmi_port ipmi_port.c # @LANPLUS_LIB@ is ../lib/libipmi_lanplus.a ../lib/libipmi_lanplus.a: cd ../lib; make ipmiutil$(EXEEXT): $(METASOURCE:.c=.o) @LANPLUS_LIB@ $(CC) $(CFLAGS) $(LDFLAGS) -o ipmiutil $(METASOURCE:.c=.o) $(LDADD) all-am: Makefile $(bin_PROGRAMS) $(sbin_PROGRAMS) $(EXTRA_PROGRAMS) $(DEV_LIB) $(SHRLINK) install-data-am: $(EXTRA_PROGRAMS) $(DEV_LIB) $(SHRLINK) @INS_LIB@ mkdir -p $(DESTDIR)$(extradir) @INS_LIB@ mkdir -p $(DESTDIR)$(LIBDIR) @INS_LIB@ mkdir -p $(DESTDIR)$(inc_dir) @INS_LIB@ cp -f ipmi_sample.c $(DESTDIR)$(extradir) @INS_LIB@ cp -f ipmi_sample_evt.c $(DESTDIR)$(extradir) @INS_LIB@ cp -f ipmicmd.h $(DESTDIR)$(inc_dir) @INS_LIB@ cp -f isensor.c ievents.c $(DESTDIR)$(extradir) @INS_LIB@ cp -f isensor.h ievents.h $(DESTDIR)$(extradir) @INS_LIB@ cp -f Makefile.sample $(DESTDIR)$(extradir)/Makefile @INS_LIB@ cp -f $(DEV_LIB) $(DESTDIR)$(LIBDIR) @INS_LIB@ if [ "x$(SHRLINK)" != "x" ]; then \ @INS_LIB@ cp -f $(SHRLINK) $(DESTDIR)$(LIBDIR) ; \ @INS_LIB@ cd $(DESTDIR); ln -sf $(LIBDIR)/$(SHRLINK) $(DESTDIR)$(LIBDIR)/$(SHR_BLIB); \ @INS_LIB@ fi clean-generic: rm -f $(DEV_LIB) $(EXTRA_PROGRAMS) $(OLDPROGS) $(TESTPROGS) $(SHRLINK) if [ -d $(tmpobj) ]; then rm -rf $(tmpobj) ; fi if [ -d $(tmpwin) ]; then rm -rf $(tmpwin) ; fi rm -f *.log *.tmp debug*.list *.o *.pdb *.lo *.la *.so # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ipmiutil-3.1.9/util/ireset.c0000644000000000000000000007100614373710655014511 0ustar rootroot/* * 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 #include #include #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 #include #include #elif defined(DOS) #include #include #include #include "getopt.h" #else #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include "ipmicmd.h" #include "oem_intel.h" /* 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 */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil reset"; #else static char * progver = "3.08"; static char * progname = "ireset"; #endif 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 BMC"; 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((char *)&idata[5],&istr[n],13); n += 13; } else { strncpy((char *)&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(%x) ok\n",bpower); //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 set boot Initiator mailbox string\n"); printf(" -j 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(0); } #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 to BMC */ 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 */ #ifdef OBSOLETE if (is_romley(vendid,prodid) || (prodid == 0x003E)) { /* Romley or Thurley/S5520UR */ platform = platS5500; /* not like Intel Sahalee */ set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/ } #endif } else if (vendid == VENDOR_KONTRON) { /* Kontron */ fignore_opterr = 1; /* ignore boot options errors */ /* supports Chassis Soft Power command 0x05, so not platIntel */ 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 to BMC */ 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 to BMC ok\n",progname); else printf("%s: Cold_Reset to BMC 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 */ ipmiutil-3.1.9/util/mem_if.c0000644000000000000000000006752414357051035014454 0ustar rootroot/*----------------------------------------------------------------------* * 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 * 01/09/23 ARCress - try UEFI_MEM_RANGE_BASE 0x6d5a7000 if error *----------------------------------------------------------------------*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2002-2008, Intel Corporation Copyright (c) 2009 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------*/ #ifdef WIN32 #define _WIN32_DCOM #pragma once #include #include #include //deprecated iostream.h #include //ole32.lib #include #include //Wbemcli.h,Wbemidl.h Wbemuuid.lib #elif defined(DOS) #include #include #include #else // Linux or Solaris #include #include #include #include #include #include #include #include #include #ifdef __linux__ #include #endif #endif #if defined(SOLARIS) || defined(BSD) || defined(HPUX) #define EXEC_PAGESIZE 4096 #endif #define DOS_MEM_RANGE_BASE 0xF0000 //starting memory range for smbios tables #define UEFI_MEM_RANGE_BASE 0x6d5a7000 //starting memory range for UEFI tables #define DOS_NUM_BYTES_TO_MAP 0x0FFFE //number bytes to map for smbios tables //smbios defines #define SMBIOS_STRING "_SM_" //server management bios string #define SMBIOS_MAJOR_REV 2 //major rev for smbios spec 2.3 #define SMBIOS_MINOR_REV 1 //minor rev for smbios spce 2.3 #define SMBIOS_STRUCTURE_TYPE_OFFSET 0 //offset in structure for type #define SMBIOS_STRUCTURE_LENGTH_OFFSET 1 //offset in structure for length #define SMBIOS_TABLE_LENGTH_OFFSET 0x5 //offset for length of table #define SMBIOS_MAJOR_REV_OFFSET 0x6 //offset for major rev of smbios #define SMBIOS_MINOR_REV_OFFSET 0x7 //offset for minor rev of smbios #define SMBIOS_TABLE_ENTRY_POINT_OFFSET 0x18 //offset for smbios structure table entry point #define SMBIOS_TABLE_SIZE_OFFSET 0x16 //offset for smbios structure table size #define NIBBLE_SIZE 4 //bit size of a nibble #ifdef WIN32 extern "C" { char fsm_debug = 0; } /*=1 to show smbios debug messages*/ #else char fsm_debug = 0; /*=1 to show smbios debug messages*/ #endif static int s_iTableRev = 0; //static globabl var to store table revision #ifndef WIN32 typedef int BOOL; typedef unsigned long ULONG; typedef unsigned char UCHAR; typedef unsigned short USHORT; BOOL MapPhysicalMemory(ULONG tdStartAddress, ULONG ulSize, ULONG* ptdVirtualAddress); BOOL UnMapPhysicalMemory(ULONG tdVirtualAddress, ULONG ulSize); int OpenIMemoryInterface(void); int CloseIMemoryInterface(void); #endif // Linux, not __WINDOWS__ #ifdef WIN32 /* Windows Memory routines */ static BYTE m_byMajorVersion = 0; static BYTE m_byMinorVersion = 0; static BYTE * m_pbBIOSData = NULL; static DWORD m_dwLen = 0; extern "C" { int getSmBiosTables(UCHAR **ptableAddress) { int bRet = 0; HRESULT hres; IWbemLocator *pLoc = 0; IWbemServices *pSvc = 0; IEnumWbemClassObject* pEnumerator = NULL; // Initialize COM. hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { return bRet; } // Obtain the initial locator to Windows Management // on a particular host computer. hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hres)) { CoUninitialize(); return bRet; } // Connect to the root\cimv2 namespace with the // current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\WMI"), // WMI namespace NULL, // User name NULL, // User password 0, // Locale NULL, // Security flags 0, // Authority 0, // Context object &pSvc // IWbemServices proxy ); if (FAILED(hres)) { pLoc->Release(); CoUninitialize(); return bRet; } // Set the IWbemServices proxy so that impersonation // of the user (client) occurs. hres = CoSetProxyBlanket( pSvc, // the proxy to set RPC_C_AUTHN_WINNT, // authentication service RPC_C_AUTHZ_NONE, // authorization service NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // authentication level RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level NULL, // client identity EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return bRet; // Program has failed. } hres = pSvc->CreateInstanceEnum( L"MSSMBios_RawSMBiosTables", 0, NULL, &pEnumerator); if (FAILED(hres)) { pSvc->Release(); pLoc->Release(); CoUninitialize(); return bRet; // Program has failed. } else { do { IWbemClassObject* pInstance = NULL; ULONG dwCount = NULL; hres = pEnumerator->Next(WBEM_INFINITE, 1, &pInstance, &dwCount); if (SUCCEEDED(hres)) { VARIANT varBIOSData; VariantInit(&varBIOSData); CIMTYPE type; hres = pInstance->Get(bstr_t("SmbiosMajorVersion"),0,&varBIOSData,&type,NULL); if (FAILED(hres)) { VariantClear(&varBIOSData); } else { m_byMajorVersion = (BYTE)varBIOSData.iVal; VariantInit(&varBIOSData); hres = pInstance->Get(bstr_t("SmbiosMinorVersion"),0,&varBIOSData,&type,NULL); if(FAILED(hres)) { VariantClear(&varBIOSData); } else { m_byMinorVersion = (BYTE)varBIOSData.iVal; s_iTableRev = (m_byMajorVersion << 4) + m_byMinorVersion; VariantInit(&varBIOSData); hres = pInstance->Get(bstr_t("SMBiosData"),0,&varBIOSData,&type,NULL); if(SUCCEEDED(hres)) { if ( ( VT_UI1 | VT_ARRAY ) != varBIOSData.vt ) { } else { SAFEARRAY *parray = NULL; parray = V_ARRAY(&varBIOSData); BYTE* pbData = (BYTE*)parray->pvData; m_dwLen = parray->rgsabound[0].cElements; m_pbBIOSData = (BYTE *)malloc(m_dwLen); memcpy(m_pbBIOSData,pbData,m_dwLen); *ptableAddress = m_pbBIOSData; bRet = m_dwLen; } } VariantClear(&varBIOSData); } } break; } } while (hres == WBEM_S_NO_ERROR); } // Cleanup // ======== pSvc->Release(); pLoc->Release(); CoUninitialize(); return(bRet); } /*end getSmBiosTables*/ int closeSmBios(UCHAR *ptableAddress, ULONG ulSmBiosLen) { int rv = 0; /* memory interface already closed */ free(ptableAddress); return(rv); } } /*end extern C*/ #else /* Linux Memory routines */ #define MEM_DRIVER "/dev/mem" #define FALSE 0 #define TRUE 1 //intialize static handle amd counter static int m_iDriver = 0; static int m_iCount = 0; ////////////////////////////////////////////////////////////////////////////// // OpenIMemoryInterface ////////////////////////////////////////////////////////////////////////////// // Name: OpenIMemoryInterface // Purpose: create handle to driver if first time // Context: static m_iDriver & m_iCount // Returns: int rv (0 = success) // Parameters: none // Notes: /////////////////////////////////////////////////////////////////////////////// int OpenIMemoryInterface(void) { int rv = -1; /* ARM64 does not handle /dev/mem the same. * It exposes SMBIOS at /sys/firmware/dmi/tables/, but because * IO memory is memory mapped, cannot use legacy /dev/mem. */ #ifndef __arm__ #ifndef __aarch64__ //check to see if driver has been previously defined if (!m_iDriver) { //open the driver m_iDriver = open(MEM_DRIVER, O_RDONLY); if (m_iDriver > 0) { //increment instance counter m_iCount++; } else { //couldn't open the driver...so make it zero again m_iDriver = 0; } } else { //handle exists...so inc instance counter. m_iCount++; } if (m_iDriver > 0) rv = 0; #endif #endif return(rv); } /////////////////////////////////////////////////////////////////////////////// // CloseIMemoryInterface // Name: destructor // Purpose: close driver handle and null out field // Context: // Returns: // Parameters: none // Notes: /////////////////////////////////////////////////////////////////////////////// int CloseIMemoryInterface(void) { int rv = 0; //check if an instance has been created by looking at the counter if (!m_iCount) { m_iCount--; //decrement instance counter if (m_iCount == 0) { close(m_iDriver); m_iDriver = 0; //and null it out } } return(rv); } /////////////////////////////////////////////////////////////////////////////// // MapPhysicalMemory /////////////////////////////////////////////////////////////////////////////// // Name: MapPhysicalMemory // Purpose: given the starting address and size, the virtualize // memory is mapped. // Returns: True if success // Parameters: [IN] tdStartAddress = physical address to map // [IN] ulSize = number of bytes to map // [OUT] ptdVirtualAddress = ptr to virtual address /////////////////////////////////////////////////////////////////////////////// BOOL MapPhysicalMemory(ULONG tdStartAddress, ULONG ulSize, ULONG* ptdVirtualAddress) { long tdVirtualAddr = 0; ULONG ulDiff; //check if we have a valid driver handle if (!m_iDriver) return FALSE; //error //check for valid input params if (!tdStartAddress || !ulSize) return FALSE; //error //align the offset to a valid page boundary and adust its length ulDiff = (ULONG)(tdStartAddress % EXEC_PAGESIZE); if (fsm_debug) printf("MapPhys: tdStart=%lx, page=%x, diff=%lx\n", tdStartAddress,EXEC_PAGESIZE,ulDiff); tdStartAddress -= ulDiff; ulSize += ulDiff; tdVirtualAddr = (long)mmap((caddr_t)0, (size_t)ulSize, PROT_READ, MAP_SHARED, m_iDriver, (off_t)tdStartAddress); if (fsm_debug) printf("MapPhys: mmap(tdStart=%lx,size=%lx) = %lx\n", tdStartAddress,ulSize,tdVirtualAddr); if (tdVirtualAddr == -1) return FALSE; *ptdVirtualAddress = tdVirtualAddr + ulDiff; return TRUE; } /////////////////////////////////////////////////////////////////////////////// // UnMapPhysicalMemory /////////////////////////////////////////////////////////////////////////////// // Name: UnMapPhysicalMemory // Purpose: given the virtual address, unmaps it...frees memory. // Returns: True if success // Parameters: [IN] tdVirtualAddress = virtual address to unmap // [IN] ulSize = not needed for windows // Notes: none /////////////////////////////////////////////////////////////////////////////// BOOL UnMapPhysicalMemory(ULONG tdVirtualAddress, ULONG ulSize) { ULONG ulDiff = 0; ulDiff = (ULONG)(tdVirtualAddress % EXEC_PAGESIZE); tdVirtualAddress -= ulDiff; ulSize += ulDiff; if (munmap((void *)tdVirtualAddress,ulSize) != 0) return FALSE; return TRUE; } /////////////////////////////////////////////////////////////////////////////// // getSmBiosTables // Purpose: returns smbios tables pointer // Returns: pointer to the virtual address where SMBIOS tables begins ////////////////////////////////////////////////////////////////////////////// int getSmBiosTables(UCHAR **ptableAddress) { ULONG tdStartAddress = DOS_MEM_RANGE_BASE; ULONG ulSize = DOS_NUM_BYTES_TO_MAP; ULONG ulSmBiosLen = 0; ULONG tdVirtualAddress = 0; int iInc; UCHAR *pSmBios = NULL; UCHAR ucCheckSum = 0; UCHAR ucVal, ucVal1; int rv; if (fsm_debug) printf("getSmBiosTables start\n"); //get interface to Memory rv = OpenIMemoryInterface(); if (fsm_debug) printf("OpenIMemoryInterface rv = %d\n",rv); //map memory into user space if ((rv != 0) || !MapPhysicalMemory(tdStartAddress,ulSize,&tdVirtualAddress)) { #ifdef SOLARIS /* mmap always fails on Solaris, so skip the error message, * unless in debug mode. */ if (fsm_debug) #endif fprintf(stderr, "Cannot map SMBIOS memory.\n"); /* Try UEFI address */ tdStartAddress = UEFI_MEM_RANGE_BASE; if (!MapPhysicalMemory(tdStartAddress,ulSize,&tdVirtualAddress)) { fprintf(stderr, "Cannot map UEFI SMBIOS memory.\n"); return ulSmBiosLen; /*==0*/ } } //now find the entry point for smbios for(iInc=0; iInc < (long)ulSize; iInc+=sizeof(int) ) { if (!memcmp((UCHAR *)(tdVirtualAddress+iInc),SMBIOS_STRING,sizeof(int))) { //cast entry point to a byte pointer pSmBios = (UCHAR *)(tdVirtualAddress+iInc); break; } } if (pSmBios == NULL) { fprintf(stderr, "Can't find SMBIOS address entry point.\n"); UnMapPhysicalMemory(tdVirtualAddress,ulSize); return ulSmBiosLen; } if (fsm_debug) { printf("Found pSmBios=%p tdV=%lx, inc=%x\n",pSmBios, tdVirtualAddress,iInc); // dump_buf("SMBIOS",pSmBios,64,1); } //now sum up the bytes in the table for checksum checking for(iInc=0; iInc= 18)) { switch(VirtualAddress[i+16] >>6) { case 0x00: *inc = 1; break; /* 1-byte bound*/ case 0x01: *inc = 4; break; /* 4-byte bound*/ case 0x02: *inc = 16; break; /*16-byte bound*/ default: break; /**inc = 1; above*/ } } rv = 0; break; } //Skip this record and go to the end of it. for (j = i+length; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j+1] == 0x00) { i = j+2; break; } } } closeSmBios(VirtualAddress,SMBiosLen); return rv; } //getIPMI_struct /////////////////////////////////////////////////////////////////////////////// // get_MemDesc ////////////////////////////////////////////////////////////////////////////// // Name: get_MemDesc // Purpose: find Type 17 record to get the Memory Locator Description // Returns: 0 for success, or -1 if not found. // if success, the desc string will have valid data ////////////////////////////////////////////////////////////////////////////// int get_MemDesc(UCHAR array, UCHAR dimm, char *desc, int *psize) { UCHAR *VirtualAddress; ULONG SMBiosLen = 0; int length, j, i; int iarray, idimm; UCHAR Type; int rv = -1; char dimmstr[32]; char bankstr[32]; SMBiosLen = getSmBiosTables( &VirtualAddress); if ((SMBiosLen == 0) || !VirtualAddress) return rv; if (desc == NULL) return(-1); bankstr[0] = 0; dimmstr[0] = 0; if (fsm_debug) printf("get_MemDesc(%d,%d)\n",array,dimm); iarray = 0; idimm = 0; for(i=0; i<(int)SMBiosLen; ) { Type = VirtualAddress[i]; length = (int)VirtualAddress[i+1]; if (Type == 127) //end of table record break; else if (Type == 16) //Found a Memory Array */ { /* usually only one onboard memory array */ if (array == iarray) ; /*match*/ else iarray++; } else if (Type == 17) //Found a Memory Device */ { int bank, k, n, nStr, nBLoc, sz; if (dimm == idimm) { if (fsm_debug) { printf("Memory record %d.%d: ",iarray,idimm); for (j = i; j < (i+length+16); j++) { if (((j-i) % 16) == 0) printf("\n"); printf("%02x ",VirtualAddress[j]); } printf("\n"); } /* * Memory Device record * walk through strings to find Locator */ sz = VirtualAddress[i+12] + (VirtualAddress[i+13] << 8); /*Size*/ bank = VirtualAddress[i+15]; /*Set*/ nStr = VirtualAddress[i+16]; /*Locator string num*/ nBLoc = VirtualAddress[i+17]; /*BankLocator string num*/ if (fsm_debug) printf("bank=%d nStr=%d sz=%x\n",bank,nStr,sz); k = i + length; /*hdr len (usu 0x1B)*/ n = 1; /* string number index */ for (j = k; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j-1] == 0x00) break; else if (VirtualAddress[j] == 0x00) { if (fsm_debug) printf("str[%d] = %s\n", n,&VirtualAddress[k]); if (n == nBLoc) { /*bank string*/ strcpy(bankstr,(char *)&VirtualAddress[k]); break; /*string number*/ } if (n == nStr) { strcpy(dimmstr,(char *)&VirtualAddress[k]); } n++; k = j + 1; } } if ((desc != NULL) && (j < (int)SMBiosLen)) { sprintf(desc,"%s/%s",bankstr,dimmstr); rv = 0; } else { /* have header, but not string */ char b; if ((idimm % 2) == 0) b = 'A'; else b = 'B'; sprintf(desc,"DIMM%d%c",bank,b); rv = 0; } *psize = sz; break; } else idimm++; /*else go to next dimm*/ } //Skip this record and go to the end of it. for (j = i+length; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j+1] == 0x00) { i = j+2; break; } } } closeSmBios(VirtualAddress,SMBiosLen); /* fill in a default if error */ if ((rv != 0) && (desc != NULL)) sprintf(desc,"DIMM(%d)",dimm); return rv; } //get_MemDesc /////////////////////////////////////////////////////////////////////////////// // get_BiosVersion ////////////////////////////////////////////////////////////////////////////// // Name: get_BiosVersion // Purpose: finds Type 0 record and gets the BIOS ID string // Returns: -1 if not found and 0 if found. Param contains the string ////////////////////////////////////////////////////////////////////////////// int get_BiosVersion(char *bios_str) { #define BIOS_VERSION 0x05 //Specifies string number of BIOS Ver string UCHAR *VirtualAddress; ULONG SMBiosLen = 0; int recLength, j, i, k = 0, str_num; UCHAR recType; int rv = -1; SMBiosLen = getSmBiosTables( &VirtualAddress); if ((SMBiosLen == 0) || !VirtualAddress) return rv; i=0; while (i<(int)SMBiosLen) { recType = VirtualAddress[i]; recLength = (int)VirtualAddress[i+1]; // end of table record, error if (recType == 127) return -1; else if (recType == 0) { // BIOS Information (Type 0) record found //Set index j to the end of the formated part of record. j = i + recLength; //First grab string number of the BIOS Version string //This non-zero number specifies which string at the end //of the record is the BIOS Version string. str_num = VirtualAddress[i + BIOS_VERSION]; //Now skip over strings at the end of the record till we //get to the BIOS Version string for (str_num--;str_num > 0; str_num--) { //Skipping over one string at a time for (; VirtualAddress[j] != 0x00; j++); j++; //Advance index past EOS. } //Copy the BIOS Version string into buffer from caller. for (; VirtualAddress[j] != 0x00; j++) { bios_str[k++] = VirtualAddress[j]; } bios_str[k] = '\0'; rv = 0; break; /*exit while loop*/ } else { //Not a Type 0, so skip to the end of this structure for (j = i+recLength; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j+1] == 0x00) { i = j+2; break; } } } } /*end while*/ closeSmBios(VirtualAddress,SMBiosLen); return rv; } int get_ChassisSernum(char *chs_str, char fdbg) { #define CHASSIS_SERNUM 0x07 //Specifies string number of BIOS Ver string UCHAR *VirtualAddress; ULONG SMBiosLen = 0; int recLength, j, i, k = 0, str_num; UCHAR recType; int rv = -1; SMBiosLen = getSmBiosTables( &VirtualAddress); if ((SMBiosLen == 0) || !VirtualAddress) return rv; i=0; while (i<(int)SMBiosLen) { recType = VirtualAddress[i]; recLength = (int)VirtualAddress[i+1]; if (recType == 127) return -1; // end of table record, error else if (recType == 3) { // Chassis Information (Type 3) record found j = i + recLength; str_num = VirtualAddress[i + CHASSIS_SERNUM]; for (str_num--;str_num > 0; str_num--) { for (; VirtualAddress[j] != 0x00; j++); j++; } for (; VirtualAddress[j] != 0x00; j++) { chs_str[k++] = VirtualAddress[j]; } chs_str[k] = '\0'; /* also copy Chassis Manuf */ j = i + recLength; memcpy(&chs_str[k+1],&VirtualAddress[j],20); rv = 0; break; /*exit while loop*/ } else { //Not a Type 0, so skip to the end of this structure for (j = i+recLength; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j+1] == 0x00) { i = j+2; break; } } } } /*end while*/ closeSmBios(VirtualAddress,SMBiosLen); return rv; } int get_SystemGuid(UCHAR *guid) { UCHAR *VirtualAddress; ULONG SMBiosLen = 0; int recLength, i, j, n, k = 0; UCHAR recType; int rv = -1; SMBiosLen = getSmBiosTables( &VirtualAddress); if ((SMBiosLen == 0) || !VirtualAddress) return rv; i=0; while (i<(int)SMBiosLen) { recType = VirtualAddress[i]; recLength = (int)VirtualAddress[i+1]; // end of table record, error if (recType == 127) return -1; else if (recType == 1) { // System Board Information (Type 1) record found //Set index j to the end of the formated part of record. j = i + recLength; n = i + 8; /*UUID offset 8*/ //Copy the UUID string into buffer from caller. for (k = 0; k < 16; k++) { guid[k] = VirtualAddress[n + k]; } rv = 0; break; /*exit while loop*/ } else { //else skip to the end of this structure for (j = i+recLength; j < (int)SMBiosLen; j++) { if (VirtualAddress[j] == 0x00 && VirtualAddress[j+1] == 0x00) { i = j+2; break; } } } } /*end while*/ closeSmBios(VirtualAddress,SMBiosLen); return rv; } #ifdef WIN32 } #endif #ifdef COMP_BIN int main(int argc, char **argv) { char biosver[80]; UCHAR ifs,ver,sa,inc; int rv; int base; biosver[0] = 0; rv = get_BiosVersion(biosver); printf("get_BiosVersion rv=%d Ver=%s\n",rv,biosver); rv = get_IpmiStruct( &ifs, &ver, &sa, &base, &inc); printf("get_IpmiStruct rv=%d if=%02x ver=%02x sa=%02x base=%x, spacing=%d\n", rv, ifs,ver,sa,base,inc); rv = get_SystemGuid(biosver); printf("get_SystemGuid rv=%d Ver=%s\n",rv,biosver); // exit(rv); return(rv); } #endif /* end mem_if.c */ ipmiutil-3.1.9/util/isensor.c0000644000000000000000000036421514351570202014673 0ustar rootroot/* * isensor.c * * This tool reads the SDR records to return sensor information. * It can use either the Intel /dev/imb driver or VALinux /dev/ipmikcs. * * Author: arcress at users.sourceforge.net * Copyright (c) 2002-2006 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 07/25/02 Andy Cress created * 10/09/02 Andy Cress v1.1 added decodeValue(RawToFloat) routine * 10/11/02 Andy Cress v1.2 added expon routine * 10/30/02 Andy Cress v1.3 added SDR types 08 & 14 * 12/04/02 Andy Cress v1.4 changed dstatus descriptions * 01/29/03 Andy Cress v1.5 added MV OpenIPMI driver support * Hannes Schulz * 1) correct raw readings to floatval * 2) allow extra SDR bytes returned from HP netserver 1000r * Guo Min * add -l option for simpler list display * 02/25/03 Andy Cress v1.6 misc cleanup * 05/02/03 Andy Cress v1.7 add PowerOnHours * 07/28/03 Andy Cress v1.8 added -t option for threshold values, * added sample Discovery routine (unfinished), * added ipmi_getdeviceid for completeness. * 09/05/03 Andy Cress v1.9 show SDR OEM subtypes, * fix GetSDR multi-part get for OEM SDRs * stop if SDR Repository is empty * 09/23/03 Andy Cress v1.10 Add options to set thresholds * 10/14/03 Andy Cress v1.11 Fixed sdr offset for ShowThreshold values * 01/15/04 Andy Cress v1.12 Fixed SetThreshold to set hysteresis, * Fixed sens_cap testing in ShowThresh(Full) * 01/30/04 Andy Cress v1.13 Changed field display order, added header, * check for sdr sz below min, added WIN32. * 02/19/04 Andy Cress v1.14 Added SDR type 3 parsing for mBMC * 02/27/04 Andy Cress v1.15 Added check for superuser, more mBMC logic * 03/11/04 Andy Cress v1.16 Added & removed private mBMC code for set * thresholds due to licensing issues * 04/13/04 Andy Cress v1.17 Added -r to show raw SDRs also * 05/05/04 Andy Cress v1.18 call ipmi_close before exit, * fix sresp in GetSDR for WIN32. * 07/07/04 Andy Cress v1.19 Added -a to reArm sensor, * show debug raw reading values only in hex * 08/18/04 Andy Cress v1.20 Added decoding for DIMM status * 11/01/04 Andy Cress v1.21 add -N / -R for remote nodes, * added -U for remote username * 11/19/04 Andy Cress v1.22 added more decoding for compact reading types, * added -w option to wrap thresholds * 11/24/04 ARCress v1.23 added sens_type to display output * 12/10/04 ARCress v1.24 added support for device sdrs also, * fixed sens_cap byte, * 01/10/05 ARCress v1.25 change ShowThresh order, highest to lowest, * change signed exponent type in RawToFloat * 01/13/05 ARCress v1.26 added time display if fwrap * 01/28/05 ARCress v1.27 mod for Power Redundancy SDR status * 02/15/05 ARCress v1.28 added FloatToRaw for -h/-l threshold set funcs, * always take -n sensor_num as hex (like displayed) * 03/07/05 ARCress v1.29 added "LAN Leash Lost" decoding in decode_comp_ * added -v to show max/min & hysteresis. * 03/22/05 ARCress v1.30 added OEM subtype 0x60 for BMC TAM * 03/26/05 ARCress v1.31 added battery type to decode_comp_reading * 04/21/05 ARCress v1.32 added error message if -n sensor_num not found, * added more decoding for Power Redund sensor * 06/20/05 ARCress v1.33 if GetSDRRepository cc=0xc1 switch fdevsdrs mode, * also detect fdevsdrs better for ATCA. * 07/28/05 ARCress v1.34 check for Reading init state, * add extra byte to decode_comp_reading() * 09/12/05 ARCress v1.35 don't check superuser for fipmi_lan * 01/26/06 ARCress v1.36 added -i option to only show one sensor index * 03/14/06 ARCress v1.37 added -p option to save persistent thresholds * 04/06/06 ARCress v1.38 show auto/manual rearm * 07/17/06 ARCress v1.39 add -V, add -L, handle RepInfo rc=0xc1 * 11/28/06 ARCress v1.46 added -c -m for ATCA child MCs * 08/15/07 ARCress v1.58 filter display if -n sensor_num * 08/29/07 ARCress v1.59 fixed Battery sensor interpretation * 10/31/07 ARCress v2.3 retry GetSDR if cc=0xC5 (lost reservationID) * 01/14/08 ARCress v2.6 add -u param for setting unique thresholds, * always show float when setting thresholds, * fixup in decoding Proc,PS Comp readings * 01/25/08 ARCress v2.7 allow float input with -u thresholds, * add -p persist logic for -u thresholds. * 09/20/19 ARCress v3.15 workaround for Pigeon Point bad sa in SDR * 07/08/22 ARCress v3.19 fix -i get_idx_range to show last idx in range */ /*M* Copyright (c) 2002-2006 Intel Corporation. Copyright (c) 2009 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #include #include #include // for: double pow(double x, double y); #include #include #ifdef WIN32 #include #include "getopt.h" #elif defined(DOS) #include #include "getopt.h" #else #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #if defined(LINUX) #include #include #endif #include "ipmicmd.h" #include "isensor.h" #define PICMG_CHILD 1 /* show child MCs if -b */ #define MIN_SDR_SZ 8 #define SZCHUNK 16 /* SDR chunksize was 8, now 16 */ #define INIT_SNUM 0xff #define N_SGRP 16 #define THR_EMPTY 999 /* prototypes */ int get_LastError( void ); /* ipmilan.c */ extern int use_devsdrs(int picmg); /* ipmicmd.c */ extern int get_MemDesc(int array, int dimm, char *desc, int *psz); /*mem_if.c*/ extern char *get_sensor_type_desc(uchar stype); /*ievents.c*/ #ifdef METACOMMAND #include "oem_intel.h" /* void show_oemsdr_intel(uchar *sdr); in oem_intel.h */ /* int decode_sensor_intel(); in oem_intel.h */ /* int is_romley(int vend, int prod); in oem_intel.h */ extern int decode_sensor_kontron(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_kontron.c*/ extern int decode_sensor_fujitsu(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_fujitsu.c*/ extern int decode_sensor_sun(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_sun.c*/ extern int decode_sensor_supermicro(uchar *sdr,uchar *reading,char *pstring, int slen, int fsimple, char fdbg); /*see oem_supermicro.c*/ extern int decode_sensor_quanta(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_quanta.c*/ extern int decode_sensor_dell(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_dell.c*/ extern int decode_sensor_lenovo(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_lenovo.c*/ extern int decode_sensor_asus(uchar *sdr,uchar *reading,char *pstring,int slen); extern int decode_sensor_hp(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_hp.c*/ extern void show_oemsdr_hp(uchar *sdr); #else int is_romley(int vend, int prod) { if ((vend == VENDOR_INTEL) && ((prod >= 0x0048) && (prod <= 0x005e))) return(1); return(0); } int is_grantley(int vend, int prod) { if ((vend == VENDOR_INTEL) && (prod == 0x0071)) return(1); return(0); } int is_thurley(int vend, int prod) { if ((vend == VENDOR_INTEL) && ((prod >= 0x003A) && (prod <= 0x0040))) return(1); return(0); } #endif #ifdef ALONE #define NENTID 53 static char *entity_id_str[NENTID] = { /* 00 */ "unspecified", /* 01 */ "other", /* 02 */ "unknown", /* 03 */ "processor", /* 04 */ "disk", /* 05 */ "peripheral bay", /* 06 */ "management module", /* 07 */ "system board", /* 08 */ "memory module", /* 09 */ "processor module", /* 10 */ "power supply", /* 11 */ "add-in card", /* 12 */ "front panel bd", /* 13 */ "back panel board", /* 14 */ "power system bd", /* 15 */ "drive backplane", /* 16 */ "expansion board", /* 17 */ "Other system board", /* 18 */ "processor board", /* 19 */ "power unit", /* 20 */ "power module", /* 21 */ "power distr board", /* 22 */ "chassis back panel bd", /* 23 */ "system chassis", /* 24 */ "sub-chassis", /* 25 */ "Other chassis board", /* 26 */ "Disk Drive Bay", /* 27 */ "Peripheral Bay", /* 28 */ "Device Bay", /* 29 */ "fan", /* 30 */ "cooling unit", /* 31 */ "cable/interconnect", /* 32 */ "memory device ", /* 33 */ "System Mgt Software", /* 34 */ "BIOS", /* 35 */ "Operating System", /* 36 */ "system bus", /* 37 */ "Group", /* 38 */ "Remote Mgt Comm Device", /* 39 */ "External Environment", /* 40 */ "battery", /* 41 */ "Processing blade", /* 43 */ "Processor/memory module", /* 44 */ "I/O module", /* 45 */ "Processor/IO module", /* 46 */ "Mgt Controller Firmware", /* 47 */ "IPMI Channel", /* 48 */ "PCI Bus", /* 49 */ "PCI Express Bus", /* 50 */ "SCSI Bus", /* 51 */ "SATA/SAS bus", /* 52 */ "Processor FSB" }; char *decode_entity_id(int id) { if (id < NENTID) return (""); else return(entity_id_str[id]); } #else /* char *decode_entity_id(int id); *isensor.h, from ievents.c*/ #endif /************************ * Global Data ************************/ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil sensor"; #else static char * progver = "3.15"; static char * progname = "isensor"; #endif #ifdef WIN32 static char savefile[] = "%ipmiutildir%\\thresholds.cmd"; #else static char savefile[] = "/var/lib/ipmiutil/thresholds.sh"; // static char savefile[] = "/usr/share/ipmiutil/thresholds.sh"; #endif extern char fdebug; /*from ipmicmd.c*/ int sens_verbose = 0; /* =1 show max/min & hysteresis also */ static int fdevsdrs = 0; static int fReserveOK = 1; static int fDoReserve = 1; static int fsimple = 0; /*=1 simple, canonical output*/ static int fshowthr = 0; /* =1 show thresholds, =2 show thr in ::: fmt */ static int fwrap = 0; static int frawsdr = 0; static int frearm = 0; static int fshowidx = 0; /* only show a specific SDR index/range */ static int fshowgrp = 0; /* =1 show group of sensors by sensor type */ static int fdoloop = 0; /* =1 if user specified number of loops */ static int fpicmg = 0; static int fchild = 0; /* =1 show child SDRs */ static int fset_mc = 0; /* =1 -m to set_mc */ static int fbadsdr = 0; /* =1 to ignore bad SDR mc */ static int fdump = 0; static int frestore = 0; static int fjumpstart = 0; static int fgetmem = 0; static int fprivset = 0; static char fremote = 0; static int nloops = 1; /* num times to show repeated sensor readings */ static int loopsec = 1; /* wait N sec between loops, default 1 */ static char bdelim = BDELIM; /* delimiter for canonical output */ static char tmpstr[20]; /* temp string */ static char *binfile = NULL; static int fsetthresh = 0; static int fsavethresh = 0; static uchar sensor_grps[N_SGRP] = {0, 0}; /*sensor type groups*/ static ushort sensor_idx1 = 0xffff; static ushort sensor_idxN = 0xffff; static uchar sensor_num = INIT_SNUM; static uchar sensor_hi = 0xff; static uchar sensor_lo = 0xff; static uchar sensor_thr[6] = {0,0,0,0,0,0}; static double sensor_thrf[6] = {0,0,0,0,0,0}; static double sensor_hi_f = 0; static double sensor_lo_f = 0; static int fmBMC = 0; static int fRomley = 0; static int fGrantley = 0; static char chEol = '\n'; /* newline by default, space if option -w */ static uchar resid[2] = {0,0}; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = 0; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int vend_id = 0; static int prod_id; /* sensor_dstatus * This is used to decode the sensor reading types and meanings. * Use IPMI Table 36-1 and 36-2 for this. */ #define N_DSTATUS 101 #define STR_CUSTOM 58 #define STR_OEM 71 #define STR_AC_LOST 76 #define STR_PS_FAIL 77 #define STR_PS_CONFIG 78 #define STR_HSC_OFF 79 #define STR_REBUILDING 80 #define STR_OTHER 81 static char oem_string[50] = "OEM"; static char *sensor_dstatus[N_DSTATUS] = { /* 0 00h */ "OK ", /* Threshold event states */ /* 1 01h */ "Warn-lo", // "Warning-lo", /* 2 02h */ "Crit-lo", // "Critical-lo", /* 3 04h */ "BelowCrit", // "BelowCrit-lo", /* 4 08h */ "Warn-hi", // "Warning-hi", /* 5 10h */ "Crit-hi", // "Critical-hi", /* 6 20h */ "AboveCrit", // "AboveCrit-hi", /* 7 40h */ "Init ", /*in init state, no reading*/ /* 8 80h */ "OK* ", /* Hotswap Controller event states, also Availability */ /* 9 HSC */ "Present", /*present,inserted*/ /*10 HSC */ "Absent", /*absent,removed,empty,missing*/ /*11 HSC */ "Ready", /*12 HSC */ "Faulty", /* Digital/Discrete event states */ /*13 D-D */ "Asserted", /*14 D-D */ "Deassert", /*15 D-D */ "Predict ", /* Availability event states */ /*16 Avl */ "Disabled", /*17 Avl */ "Enabled ", /*18 Avl */ "Redundant", /*19 Avl */ "RedunLost", /*20 Avl */ "RedunDegr", /* ACPI Device Power States */ /*21 ACPI*/ "Off ", /*D3*/ /*22 ACPI*/ "Working", /*D1*/ /*23 ACPI*/ "Sleeping", /*D2/S2*/ /*24 ACPI*/ "On", /*D0*/ /* Critical Interrupt event states */ /*25 CrI */ "FP_NMI ", /*26 CrI */ "Bus_TimOut", /*27 CrI */ "IOch_NMI", /*28 CrI */ "SW_NMI ", /*29 CrI */ "PCI_PERR", /*30 CrI */ "PCI_SERR", /*31 CrI */ "EISA_TimOut", /*32 CrI */ "Bus_Warn ", /*Correctable*/ /*33 CrI */ "Bus_Error", /*Uncorrectable*/ /*34 CrI */ "Fatal_NMI", /*35 CrI */ "Bus_Fatal", /*0x0A*/ /*36 CrI */ "Bus_Degraded", /*0x0B*/ /* Physical Security event states */ /*37 Phys*/ "LanLeashLost", /*38 Phys*/ "ChassisIntrus", /* Memory states */ /*39 Mem */ "ECCerror", /*40 Mem */ "ParityErr", /* Discrete sensor invalid readings (error or init state) */ /*41 D-D */ "Unknown", /*42 D-D */ "NotAvailable", /* Discrete sensor OEM reading states */ /*43 OEM */ "Enabled ", /*44 OEM */ "Disabled", /* Session Audit states */ /*45 OEM */ "Activated ", /*46 OEM */ "Deactivated", /*47 HSC */ "Unused ", /* Processor event states */ /*48 Proc*/ "IERR", /*49 Proc*/ "ThermalTrip", /*50 Proc*/ "FRB1Failure", /*51 Proc*/ "FRB2Failure", /*52 Proc*/ "FRB3Failure", /*53 Proc*/ "ConfigError", /*54 Proc*/ "SMBIOSError", /*55 Proc*/ "ProcPresent", /*56 Proc*/ "ProcDisabled", /*57 Proc*/ "TermPresent", /* Custom data string, 15 bytes */ /*58 Custom*/ "CustomData12345", /* Event Log */ /*59 EvLog*/ "MemLogDisab", /*60 EvLog*/ "TypLogDisab", /*61 EvLog*/ "LogCleared", /*62 EvLog*/ "AllLogDisab", /*63 EvLog*/ "SelFull", /*64 EvLog*/ "SelNearFull", /* more Digital Discrete */ /*65 D-D */ "Exceeded", /*66 Alert*/ "AlertPage", /*67 Alert*/ "AlertLAN", /*68 Alert*/ "AlertPET", /*69 Alert*/ "AlertSNMP", /*70 Alert*/ "None", /*71 OEM str*/ &oem_string[0], /* Version Change */ /*72 Change*/ "HW Changed", /*73 Change*/ "SW Changed", /*74 Change*/ "HW incompatibility", /*75 Change*/ "Change Error", /* Power Supply event states */ /*76 PS */ "AC_Lost ", /*77 PS */ "PS_Failed", /* Power Supply event states */ /*78 PS */ "Config_Err", /*79 HSC */ "Offline", /*80 HSC */ "Rebuilding", /*81 other*/ " _ ", /*82 Avl */ "NonRedund_Sufficient", /*83 Avl */ "NonRedund_Insufficient", /*84 Usage */ "Idle", /*85 Usage */ "Active", /*86 Usage */ "Busy", /*87 Trans */ "Non-Critical", /*88 Trans */ "Critical", /*89 Trans */ "Non-Recoverable", /*90 Trans */ "Monitor", /*91 Trans */ "Informational", /*92 State */ "Running", /*93 State */ "In_Test", /*94 State */ "Power_Off", /*95 State */ "Online", /*96 State */ "Offline", /*97 State */ "Off_Duty", /*98 State */ "Degraded", /*99 State */ "PowerSave", /*100 State */ "InstallError" }; static char *raid_states[9] = { /*for sensor type 0x0d drive status */ "Faulty", "Rebuilding", "InFailedArray", "InCriticalArray", "ParityCheck", "PredictedFault", "Un-configured", "HotSpare", "NoRaid" }; #define NSENSTYPES 0x2a #ifdef OLD /* see ievents.c */ static const char *sensor_types[NSENSTYPES] = { /*IPMI 2.0 Table 42-3*/ /* 00h */ "reserved", /* 01h */ "Temperature", /* 02h */ "Voltage", /* 03h */ "Current", /* 04h */ "Fan", /* 05h */ "Platform Chassis Intrusion", /* 06h */ "Platform Security Violation", /* 07h */ "Processor", /* 08h */ "Power Supply", /* 09h */ "Power Unit", /* 0Ah */ "Cooling Device", /* 0Bh */ "FRU Sensor", /* 0Ch */ "Memory", /* 0Dh */ "Drive Slot", /* 0Eh */ "POST Memory Resize", /* 0Fh */ "System Firmware", /* 10h */ "SEL Disabled", /* 11h */ "Watchdog 1", /* 12h */ "System Event", /* offset 0,1,2 */ /* 13h */ "Critical Interrupt", /* offset 0,1,2 */ /* 14h */ "Button", /* offset 0,1,2 */ /* 15h */ "Board", /* 16h */ "Microcontroller", /* 17h */ "Add-in Card", /* 18h */ "Chassis", /* 19h */ "Chip Set", /* 1Ah */ "Other FRU", /* 1Bh */ "Cable / Interconnect", /* 1Ch */ "Terminator", /* 1Dh */ "System Boot Initiated", /* 1Eh */ "Boot Error", /* 1Fh */ "OS Boot", /* 20h */ "OS Critical Stop", /* 21h */ "Slot / Connector", /* 22h */ "ACPI Power State", /* 23h */ "Watchdog 2", /* 24h */ "Platform Alert", /* 25h */ "Entity Presence", /* 26h */ "Monitor ASIC", /* 27h */ "LAN", /* 28h */ "Management Subsystem Health", /* 29h */ "Battery", }; #endif #define NUNITS 30 static char *unit_types[] = { /* 00 */ "unspecified", /* 01 */ "degrees C", /* 02 */ "degrees F", /* 03 */ "degrees K", /* 04 */ "Volts", /* 05 */ "Amps", /* 06 */ "Watts", /* 07 */ "Joules", /* 08 */ "Coulombs", /* 09 */ "VA", /* 10 */ "Nits", /* 11 */ "lumen", /* 12 */ "lux", /* 13 */ "Candela", /* 14 */ "kPa", /* 15 */ "PSI", /* 16 */ "Newton", /* 17 */ "CFM", /* 18 */ "RPM", /* 19 */ "Hz", /* 20 */ "microseconds", /* 21 */ "milliseconds", /* 22 */ "seconds", /* 23 */ "minutes", /* 24 */ "hours", /* 25 */ "days", /* 26 */ "weeks", /* 27 */ "mil", /* 28 */ "inches", /* 29 */ "feet", /* 42 */ "cycles" }; /* 68 * "megabit", */ /* 72 * "megabyte", */ /* 90 * "uncorrectable error" (last defined)*/ static char *unit_types_short[] = { /* 00 */ "?", /*unknown, not specified*/ /* 01 */ "C", /* 02 */ "F", /* 03 */ "K", /* 04 */ "V", /* 05 */ "A", /* 06 */ "W", /* 07 */ "J", /* 08 */ "Coul", /* 09 */ "VA", /* 10 */ "Nits", /* 11 */ "lumen", /* 12 */ "lux", /* 13 */ "Cand", /* 14 */ "kPa", /* 15 */ "PSI", /* 16 */ "Newton", /* 17 */ "CFM", /* 18 */ "RPM", /* 19 */ "Hz", /* 20 */ "usec", /* 21 */ "msec", /* 22 */ "sec", /* 23 */ "min", /* 24 */ "hrs", /* 25 */ "days", /* 26 */ "wks", /* 27 */ "mil", /* 28 */ "in", /* 29 */ "ft", /* 42 */ "cyc" }; ushort parse_idx(char *str) { int i, n; char istr[5]; if (strncmp(str,"0x",2) == 0) str += 2; n = strlen_(str); if (n == 4) { i = (htoi(str) << 8) + htoi(&str[2]); } else if (n == 3) { istr[0] = '0'; memcpy(&istr[1],str,3); i = (htoi(istr) << 8) + htoi(&istr[2]); } else i = htoi(str); /*was atoi()*/ printf("idx = 0x%x\n",i); return((ushort)i); } int get_idx_range(char *str) { // int i = 0; char *p; char *p2; p = strchr(str,'-'); if (p == NULL) p = strchr(str,','); if (p != NULL) { /*range*/ *p = 0; p++; sensor_idx1 = parse_idx(str); sensor_idxN = parse_idx(p) + 1; /*end if >=, so + 1*/ } else { /*single sensor*/ sensor_idx1 = parse_idx(str); sensor_idxN = sensor_idx1; /*end if >=*/ } return(0); } char *get_unit_type(int iunits, int ibase, int imod, int fshort) { char *pstr = NULL; char **punittypes; static char unitstr[32]; int jbase, jmod; uchar umod; punittypes = unit_types; if (fshort) punittypes = unit_types_short; if (fdebug) printf("get_unit_type(%x,%d,%d,%d)\n",iunits,ibase,imod,fshort); umod = (iunits & 0x06) >> 1; if (ibase < NUNITS) jbase = ibase; else { if (fdebug) printf("units base %02x > %d\n",ibase,NUNITS); if (ibase == 42) jbase = NUNITS; /*"cycles"*/ else jbase = 0; } if (imod < NUNITS) jmod = imod; else { if (fdebug) printf("units mod %02x > %d\n",imod,NUNITS); jmod = 0; } switch (umod) { case 2: snprintf(unitstr,sizeof(unitstr),"%s * %s", punittypes[jbase],punittypes[jmod]); pstr = unitstr; break; case 1: snprintf(unitstr,sizeof(unitstr),"%s/%s", punittypes[jbase],punittypes[jmod]); pstr = unitstr; break; case 0: default: pstr = punittypes[jbase]; break; } if ((umod == 0) && (iunits > 0)) { /* special cases for other SensorUnits1 bits */ if ((iunits & 0x01) != 0) { /*percentage*/ if (fshort) pstr = "%"; else pstr = "percent"; } else if (iunits == 0xC0) { /*no analog reading*/ pstr = "na"; } else if (iunits == 0x18) { /* For Tyan fans: base=42, units=24.(0x18) -> cycles/hour */ snprintf(unitstr,sizeof(unitstr),"%s/hour",punittypes[jbase]); pstr = unitstr; } } return(pstr); } char *decode_capab(uchar c) { static char cstr[50]; char *arm; char *thr; char *evt; // char *hys; uchar b; /* decode sens_capab bits */ if ((c & 0x40) == 0) arm = "man"; /*manual rearm*/ else arm = "auto"; /*automatic rearm*/ /* skip hysteresis bits (0x30) */ b = ((c & 0x0c) >> 2); switch(b) { case 0x00: thr = "none"; break; /*no thresholds*/ case 0x01: thr = "read"; break; case 0x02: thr = "write"; break; /*read & write*/ case 0x03: default: thr = "fixed"; break; } b = (c & 0x03) ; switch(b) { case 0x00: evt = "state"; break; /*threshold or discrete state*/ case 0x01: evt = "entire"; break; /*entire sensor only*/ case 0x02: evt = "disab"; break; /*global disable only*/ case 0x03: default: evt = "none"; break; /*no events*/ } sprintf(cstr,"arm=%s thr=%s evts=%s",arm,thr,evt); return(cstr); } int get_group_id(char *pstr) { int i, j, n, sz, len; char *p; int rv = -1; sz = strlen_(pstr); p = &pstr[0]; n = 0; for (i = 0; i <= sz; i++) { if (n >= N_SGRP) break; switch(pstr[i]) { case ',': /*delimiter*/ case '\n': case '\0': pstr[i] = 0; /*stringify this word*/ len = strlen_(p); for (j = 0; j < NSENSTYPES; j++) { if (strncasecmp(get_sensor_type_desc(j),p,len) == 0) { sensor_grps[n++] = (uchar)j; rv = 0; break; } } /*endfor(j)*/ if (i+1 < sz) p = &pstr[i+1]; /*set p for next word*/ if (j >= NSENSTYPES) { /* sensor type not found */ rv = -1; i = sz; /*exit loop*/ } break; default: break; } /*end switch*/ } /*end for(i)*/ if (rv == 0) rv = n; else rv = -1; return(rv); } static int validate_thresholds(void *pthrs, char flag, uchar *sdr) { double *thrf; uchar *thr; int rv = 0; uchar bits; if (sdr == NULL) bits = 0xff; /*assume all are used*/ else bits = sdr[18]; /*18=indicates which are readable/used */ if (bits == 0) { printf("No threshold values can be set for this sensor.\n"); return(3); } if (flag == 1) { /*float*/ thrf = (double *)pthrs; if (fdebug) printf("validate_thresh: bits=%02x, values: %f>=%f>=%f, %f<=%f<=%f\n", bits, thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]); if ((bits & 0x02) != 0) { /*thrf[1] lo-crit is valid*/ if ((thrf[1] > thrf[0]) && ((bits & 0x01) != 0)) rv = 1; if ((thrf[2] > thrf[1]) && ((bits & 0x04) != 0)) rv = 1; /*lo is wrong*/ } if ((bits & 0x10) != 0) { /*thrf[4] hi-crit is valid*/ if ((thrf[4] < thrf[3]) && ((bits & 0x08) != 0)) rv = 2; if ((thrf[5] < thrf[4]) && ((bits & 0x20) != 0)) rv = 2; /*hi is wrong*/ } if (rv != 0) { printf("Threshold values: %f>=%f>=%f, %f<=%f<=%f\n", thrf[0], thrf[1], thrf[2], thrf[3], thrf[4], thrf[5]); printf("Invalid threshold order in %s range.\n", ((rv == 1)? "lo": "hi")); } } else { thr = (uchar *)pthrs; if ((bits & 0x02) != 0) { /*thr[1] lo-crit is valid*/ if ((thr[1] > thr[0]) && ((bits & 0x01) != 0)) rv = 1; if ((thr[2] > thr[1]) && ((bits & 0x04) != 0)) rv = 1; /*lo is wrong*/ } if ((bits & 0x10) != 0) { /*thr[4] hi-crit is valid*/ if ((thr[4] < thr[3]) && ((bits & 0x08) != 0)) rv = 2; if ((thr[5] < thr[4]) && ((bits & 0x20) != 0)) rv = 2; /*hi is wrong*/ } if (rv != 0) { printf("Threshold values: %02x>=%02x>=%02x %02x<=%02x<=%02x\n", thr[0], thr[1], thr[2], thr[3], thr[4], thr[5]); printf("Invalid threshold order within -u (%s)\n", ((rv == 1)? "lo": "hi")); } } return(rv); } int GetSDRRepositoryInfo(int *nret, int *fdev) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; int rc; int nSDR; int freespace; ushort cmd; uchar cc = 0; int i; memset(resp,0,6); /* init first part of buffer */ if (nret != NULL) *nret = 0; if (fdev != NULL) fdevsdrs = *fdev; if (fdevsdrs) cmd = GET_DEVSDR_INFO; else cmd = GET_SDR_REPINFO; rc = ipmi_cmd_mc(cmd, NULL, 0, resp,&sresp, &cc, fdebug); if (fdebug) printf("ipmi_cmd[%04x] repinf(%d) status=%d cc=%x\n", cmd, fdevsdrs,rc,cc); /* some drivers return cc in rc */ if ((rc == 0xc1) || (rc == 0xd4)) cc = rc; else if (rc != 0) return(rc); if (cc != 0) { if ((cc == 0xc1) || /*0xC1 (193.) means unsupported command */ (cc == 0xd4)) /*0xD4 means insufficient privilege (Sun/HP)*/ { /* Must be reporting wrong bit for fdevsdrs, * so switch & retry */ if (fdevsdrs) { fdevsdrs = 0; cmd = GET_SDR_REPINFO; } else { fdevsdrs = 1; cmd = GET_DEVSDR_INFO; } sresp = MAX_BUFFER_SIZE; rc = ipmi_cmd_mc(cmd, NULL, 0, resp,&sresp, &cc, fdebug); if (fdebug) printf("ipmi_cmd[%04x] repinf status=%d cc=%x\n",cmd,rc,cc); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); } else return(cc); } if (fdevsdrs) { nSDR = resp[0]; freespace = 1; fReserveOK = 1; } else { nSDR = resp[1] + (resp[2] << 8); freespace = resp[3] + (resp[4] << 8); if ((resp[13] & 0x02) == 0) fReserveOK = 0; else fReserveOK = 1; } if (nret != NULL) *nret = nSDR; if (fdev != NULL) *fdev = fdevsdrs; if (fdebug) { //successful, show data printf("SDR Repository (len=%d): ",sresp); for (i = 0; i < sresp; i++) printf("%02x ",resp[i]); printf("\n"); printf("SDR Info: fdevsdrs=%d nSDRs=%d free space = %x ReserveOK=%d\n", fdevsdrs,nSDR,freespace,fReserveOK); } return(0); } /*end GetSDRRepositoryInfo()*/ int GetSensorThresholds(uchar sens_num, uchar *thr_data) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[6]; int rc; uchar cc = 0; inputData[0] = sens_num; rc = ipmi_cmd_mc(GET_SENSOR_THRESHOLD, inputData,1, resp,&sresp, &cc,fdebug); if (fdebug) printf("GetSensorThreshold[%02x] rc = %d, resp(%d) %02x %02x %02x %02x %02x %02x %02x\n", sens_num,rc, sresp,resp[0],resp[1],resp[2],resp[3], resp[4],resp[5],resp[6]); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); if (sresp == 0) return(-2); memcpy(thr_data,resp,sresp); return(0); } int RearmSensor(uchar sens_num) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[8]; int rc; uchar cc = 0; memset(inputData,0,6); memset(resp,0,6); inputData[0] = sens_num; rc = ipmi_cmd_mc(GET_SEVT_ENABLE, inputData, 1, resp,&sresp, &cc, fdebug); if (rc == 0 && cc != 0) rc = cc; if (rc != 0 || fdebug) printf("GetSensorEventEnable(%02x) rc = %d, cc = %x %02x %02x %02x\n", sens_num,rc,cc,resp[0],resp[1],resp[3]); if (rc == 0 && resp[0] != 0xc0) { printf("EventEnable(%02x) = %02x, is not 0xc0\n", sens_num,resp[0]); memset(inputData,0,6); inputData[0] = sens_num; inputData[1] = resp[0] | 0xc0; inputData[2] = resp[1]; inputData[3] = resp[2]; inputData[4] = resp[3]; inputData[5] = resp[4]; rc = ipmi_cmd_mc(SET_SEVT_ENABLE, inputData, 6, resp,&sresp, &cc, fdebug); if (rc == 0 && cc != 0) rc = cc; if (rc != 0 || fdebug) printf("SetSensorEventEnable(%02x) rc = %d, cc = %x\n", sens_num,rc,cc); } memset(inputData,0,6); inputData[0] = sens_num; inputData[1] = 0; /* rearm all events for this sensor */ rc = ipmi_cmd_mc(REARM_SENSOR, inputData, 6, resp,&sresp, &cc, fdebug); if (fdebug) printf("RearmSensor(%02x) rc = %d, cc = %x %02x %02x\n", sens_num,rc,cc,resp[0],resp[1]); if (rc == 0 && cc != 0) rc = cc; /* Could also do a global rearm via SetEventReceiver. */ return(rc); } /*end RearmSensor*/ int SetSensorThresholds(uchar sens_num, uchar hi, uchar lo, uchar *thr_data, uchar *thr_set) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[8]; int rc; uchar cc = 0; uchar sets = 0; int i; /* * Set the sensor Hysteresis before setting the threshold. */ memset(inputData,0,8); inputData[0] = sens_num; inputData[1] = 0xff; rc = ipmi_cmd_mc(GET_SENSOR_HYSTERESIS,inputData,2, resp,&sresp, &cc,fdebug); if (fdebug) printf("GetSensorHysteresis(%02x) rc = %d, cc = %x %02x %02x\n", sens_num,rc,cc,resp[0],resp[1]); if (rc != ACCESS_OK) return(rc); inputData[0] = sens_num; inputData[1] = 0xff; inputData[2] = resp[0]; inputData[3] = resp[1]; rc = ipmi_cmd_mc(SET_SENSOR_HYSTERESIS,inputData,4, resp,&sresp, &cc,fdebug); if (fdebug) printf("SetSensorHysteresis(%02x) rc = %d, cc = %x\n", sens_num,rc,cc); if (rc != ACCESS_OK) return(rc); /* * The application should validate that values are ordered, * e.g. upper critical should be greater than upper * non-critical. * Due to the limited command line parameter interface, * use the hi & lo values to set each of the thresholds. * For a full implemenation, these thresholds should be set * individually. */ memset(inputData,0,8); inputData[0] = sens_num; sets = thr_data[0]; if (thr_set != NULL) { /* use specific thr_set values */ memcpy(&inputData[2],thr_set,6); } else { /*default, use hi/lo params */ if (lo == 0xff) sets &= 0x38; /* don't set lowers */ else { inputData[2] = lo; /* lower non-crit (& 0x01) */ inputData[3] = lo - 1; /* lower critical (& 0x02) */ inputData[4] = lo - 2; /* lower non-recov (& 0x04) */ } if (hi == 0xff) sets &= 0x07; /* don't set uppers */ else { inputData[5] = hi; /* upper non-crit (& 0x08) */ inputData[6] = hi + 1; /* upper critical (& 0x10) */ inputData[7] = hi + 2; /* upper non-recov (& 0x20) */ } } inputData[1] = sets; /* which ones to set */ { /* show from/to changes */ printf("GetThreshold[%02x]: %02x ",sens_num,sens_num); for (i = 0; i < 7; i++) printf("%02x ",thr_data[i]); printf("\n"); printf("SetThreshold[%02x]: ",sens_num); for (i = 0; i < 8; i++) printf("%02x ",inputData[i]); printf("\n"); } rc = ipmi_cmd_mc(SET_SENSOR_THRESHOLD, inputData, 8, resp,&sresp, &cc, fdebug); if (fdebug) printf("SetSensorThreshold(%02x) rc = %d, cc = %x\n", sens_num,rc,cc); if (rc == 0 && cc != 0) rc = cc; /* mBMC gets cc = 0xD5 (213.) here, setting thresholds disabled. */ return(rc); } int GetSensorReading(uchar sens_num, void *psdr, uchar *sens_data) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[6]; SDR02REC *sdr = NULL; int mc; int rc; uchar cc = 0; uchar lun = 0; uchar chan = 0; if (psdr != NULL && fbadsdr == 0) { sdr = (SDR02REC *)psdr; mc = sdr->sens_ownid; if (mc != BMC_SA) { /* not BMC, e.g. HSC or ME sensor */ uchar a = ADDR_IPMB; if (mc == HSC_SA) a = ADDR_SMI; chan = (sdr->sens_ownlun & 0xf0) >> 4; lun = (sdr->sens_ownlun & 0x03); ipmi_set_mc(chan,(uchar)mc, lun,a); } } else mc = BMC_SA; inputData[0] = sens_num; rc = ipmi_cmd_mc(GET_SENSOR_READING,inputData,1, resp,&sresp,&cc,fdebug); if (fdebug) printf("GetSensorReading mc=%x,%x,%x status=%d cc=%x sz=%d resp: %02x %02x %02x %02x\n", chan,mc,lun,rc,cc,sresp,resp[0],resp[1],resp[2],resp[3]); if (mc != BMC_SA) ipmi_restore_mc(); if ((rc == 0) && (cc != 0)) { if (fdebug) printf("GetSensorReading error %x %s\n",cc, decode_cc((ushort)0,(uchar)cc)); rc = cc; } if (rc != 0) return(rc); if (resp[1] & 0x20) { /* init state, reading invalid */ if (fdebug) printf("sensor[%x] in init state, no reading\n", sens_num); sens_data[1] = resp[1]; sens_data[2] = 0x40; /*set bit num for init state*/ } else { /*valid reading, copy it*/ /* only returns 4 bytes, no matter what type */ memcpy(sens_data,resp,4); } return(0); } /*end GetSensorReading()*/ int GetSensorReadingFactors(uchar snum, uchar raw, int *m, int *b, int * b_exp, int *r, int *a) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[6]; int rc; uchar cc = 0; int toler, a_exp; inputData[0] = snum; inputData[1] = raw; rc = ipmi_cmd_mc(GET_SENSOR_READING_FACTORS, inputData, 2, resp,&sresp, &cc, fdebug); if (fdebug) printf("GetSensorReadingFactors status = %d\n",rc); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); /* successful, copy values */ *m = resp[1] + ((resp[2] & 0xc0) << 2); toler = resp[2] & 0x3f; *b = resp[3] + ((resp[4] & 0xc0) << 2); *a = (resp[4] & 0x3f) + ((resp[5] & 0xf0) << 4); a_exp = (resp[5] & 0xc0) >> 2; *r = (resp[6] &0xf0) >> 4; *b_exp = resp[6] & 0x0f; if (fdebug) { printf("factors: next=%x m=%d b=%d b_exp=%d a=%d a_exp=%d r=%d\n", resp[0],*m,*b,*b_exp,*a,a_exp,*r); } return(0); } int GetSensorType(uchar snum, uchar *stype, uchar *rtype) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[6]; int rc; uchar cc = 0; inputData[0] = snum; rc = ipmi_cmd_mc(GET_SENSOR_TYPE, inputData, 1, resp,&sresp, &cc, fdebug); if (fdebug) printf("GetSensorType: ipmi_cmd rv = %d, cc = %x\n",rc,cc); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); /* successful, copy values */ if (stype != NULL) *stype = resp[0]; if (rtype != NULL) *rtype = resp[1] & 0x7f; return(rc); } void set_reserve(int val) { fDoReserve = val; } int sdr_get_reservation(uchar *res_id, int fdev) { int sresp; uchar resp[MAX_BUFFER_SIZE]; uchar cc = 0; ushort cmd; int rc = -1; if (fDoReserve == 1) { fDoReserve = 0; /* only reserve SDR the first time */ sresp = sizeof(resp);; if (fdev) cmd = RESERVE_DEVSDR_REP; else cmd = RESERVE_SDR_REP; rc = ipmi_cmd_mc(cmd, NULL, 0, resp, &sresp, &cc, fdebug); if (rc == 0 && cc != 0) rc = cc; if (rc == 0) { /* ok, so set the reservation id */ resid[0] = resp[0]; resid[1] = resp[1]; } /* A reservation is cancelled by the next reserve request. */ if (fdebug) printf("ipmi_cmd RESERVE status=%d cc=%x id=%02x%02x\n", rc,cc,resid[0],resid[1]); } else rc = 0; /* if not first time, or if error, return existing resid. */ res_id[0] = resid[0]; res_id[1] = resid[1]; return(rc); } /*end sdr_get_reservation*/ int sdr_clear_repo(int fdev) { int sresp; uchar resp[MAX_BUFFER_SIZE]; uchar inputData[6]; uchar cc = 0; int rc = -1; ushort cmd; uchar resv[2] = {0,0}; if (fReserveOK) rc = sdr_get_reservation(resv,fdev); cmd = 0x27 + (NETFN_STOR << 8); /*Clear SDR Repository*/ inputData[0] = resv[0]; /*res id LSB*/ inputData[1] = resv[1]; /*res id MSB*/ inputData[2] = 'C'; inputData[3] = 'L'; inputData[4] = 'R'; inputData[5] = 0xAA; sresp = sizeof(resp);; rc = ipmi_cmd_mc(cmd, inputData, 6, resp, &sresp,&cc, fdebug); if (fdebug) printf("sdr_clear_repo: rc = %d, cc = %x, sz=%d\n",rc,cc,sresp); if (rc == 0 && cc != 0) rc = cc; if (rc == 0 && (resp[0] & 1) != 1) { if (fdebug) printf("Wait for sdr_clear_repo to complete\n"); os_usleep(1,0); } return(rc); } int sdr_add_record(uchar *sdr, int fdev) { int sresp; uchar resp[MAX_BUFFER_SIZE]; uchar inputData[6+SZCHUNK]; uchar cc = 0; int rc = -1; ushort cmd; uchar resv[2] = {0,0}; int reclen, len, i; int recid, chunksz; uchar prog; reclen = sdr[4] + 5; recid = sdr[0] + (sdr[1] << 8); /* OEM SDRs can be min 8 bytes, less is an error. */ if (reclen < 8) return(LAN_ERR_BADLENGTH); if (fReserveOK) rc = sdr_get_reservation(resv,fdev); if (fdebug) printf("sdr_add_record[%x]: reclen = %d, reserve rc = %d\n", recid,reclen,rc); cmd = 0x25 + (NETFN_STOR << 8); /*PartialAddSdr*/ recid = 0; /*first chunk must be added as 0000*/ chunksz = SZCHUNK; for (i = 0; i < reclen; ) { prog = 0; len = chunksz; if ((i+chunksz) >= reclen) { /*last record*/ len = reclen - i; prog = 1; } inputData[0] = resv[0]; /*res id LSB*/ inputData[1] = resv[1]; /*res id MSB*/ inputData[2] = recid & 0x00ff; /*record id LSB*/ inputData[3] = (recid >> 8) & 0x00ff; /*record id MSB*/ inputData[4] = (uchar)i; /*offset */ inputData[5] = prog; /*progress: 1=last record*/ memcpy(&inputData[6],&sdr[i],len); sresp = sizeof(resp); rc = ipmi_cmd_mc(cmd, inputData, 6+len, resp, &sresp,&cc, fdebug); if (fdebug) printf("sdr_add_record[%x,%x]: rc = %d, cc = %x, sz=%d\n", recid,i,rc,cc,sresp); if (rc == 0 && cc != 0) rc = cc; if (rc != 0) break; if (recid == 0 && rc == 0) /*first time, so set recid*/ recid = resp[0] + (resp[1] << 8); i += len; } return(rc); } int GetSDR(int r_id, int *r_next, uchar *recdata, int srecdata, int *rlen) { int sresp; uchar resp[MAX_BUFFER_SIZE+SZCHUNK]; uchar respchunk[SZCHUNK+10]; uchar inputData[6]; uchar cc = 0; int rc = -1; int i, chunksz, thislen, off; int reclen; ushort cmd; uchar resv[2] = {0,0}; chunksz = SZCHUNK; reclen = srecdata; /*max size of SDR record*/ off = 0; *rlen = 0; *r_next = 0xffff; /*default*/ if (fReserveOK) rc = sdr_get_reservation(resv,fdevsdrs); if (fdevsdrs) cmd = GET_DEVICE_SDR; else cmd = GET_SDR; if (reclen == 0xFFFF) { /* get it all in one call */ inputData[0] = resv[0]; /*res id LSB*/ inputData[1] = resv[1]; /*res id MSB*/ inputData[2] = r_id & 0x00ff; /*record id LSB*/ inputData[3] = (r_id & 0xff00) >> 8; /*record id MSB*/ inputData[4] = 0; /*offset */ inputData[5] = 0xFF; /*bytes to read, ff=all*/ sresp = sizeof(resp);; if (fdebug) printf("ipmi_cmd SDR id=%d read_all, len=%d\n", r_id,sresp); rc = ipmi_cmd_mc(cmd, inputData, 6, recdata, &sresp,&cc, fdebug); /* This will usually return cc = 0xCA (invalid length). */ if (fdebug) printf("ipmi_cmd SDR data status = %d, cc = %x, sz=%d\n", rc,cc,sresp); reclen = sresp; *r_next = recdata[0] + (recdata[1] << 8); } else /* if (reclen > chunksz) do multi-part chunks */ for (off = 0; off < reclen; ) { thislen = chunksz; if ((off+chunksz) > reclen) thislen = reclen - off; inputData[0] = resv[0]; /*res id LSB*/ inputData[1] = resv[1]; /*res id MSB*/ inputData[2] = r_id & 0x00ff; /*record id LSB*/ inputData[3] = (r_id & 0xff00) >> 8; /*record id MSB*/ inputData[4] = (uchar)off; /*offset */ inputData[5] = (uchar)thislen; /*bytes to read, ff=all*/ sresp = sizeof(respchunk); rc = ipmi_cmd_mc(cmd, inputData, 6, respchunk, &sresp,&cc, fdebug); if (fdebug) printf("ipmi_cmd SDR[%x] off=%d ilen=%d status=%d cc=%x sz=%d\n", r_id,off,thislen,rc,cc,sresp); if (off == 0 && cc == 0xCA && thislen == SZCHUNK) { /* maybe shorter than SZCHUNK, try again */ chunksz = 0x06; if (fdebug) printf("sdr[%x] try again with chunksz=%d\n", r_id,chunksz); continue; } if (off > chunksz) { /* already have first part of the SDR, ok to truncate */ if (rc == -3) { /* if LAN_ERR_RECV_FAIL */ if (fdebug) printf("sdr[%x] error rc=%d len=%d truncated\n", r_id,rc,sresp); sresp = 0; rc = 0; } if (cc == 0xC8 || cc == 0xCA) { /* length errors */ /* handle certain MCs that report wrong length, * at least use what we already have (sresp==0) */ if (fdebug) printf("sdr[%x] error cc=%02x len=%d truncated\n", r_id,cc,sresp); cc = 0; } } if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); /* if here, successful, chunk was read */ if (sresp < (thislen+2)) { /* There are some SDRs that may report the wrong length, and * return less bytes than they reported, so just truncate. */ if (fdebug) printf("sdr[%x] off=%d, expected %d, got %d\n", r_id,off,thislen+2,sresp); if (sresp >= 2) thislen = sresp - 2; else thislen = 0; reclen = off + thislen; /* truncate, stop reading */ fprintf(stderr,"SDR record %x is malformed, length %d is less than minimum %d\n",r_id,sresp,thislen+2); rc = ERR_SDR_MALFORMED; } /* successful */ memcpy(&resp[off],&respchunk[2],thislen); if (off == 0 && sresp >= 5) { *r_next = respchunk[0] + (respchunk[1] << 8); reclen = respchunk[6] + 5; /*get actual record size*/ if (reclen > srecdata) { if (fdebug) printf("sdr[%x] chunk0, reclen=%d srecdata=%d\n", r_id, reclen, srecdata); reclen = srecdata; /*truncate*/ } } off += thislen; *rlen = off; } if (fdebug) { printf("GetSDR[%04x] next=%x (len=%d): ",r_id,*r_next,reclen); for (i = 0; i < reclen; i++) printf("%02x ",resp[i]); printf("\n"); } memcpy(recdata,&resp[0],reclen); *rlen = reclen; return(rc); } /*end GetSDR*/ static int nsdrs = 0; /*number of sdrs*/ static int sz_sdrs = 0; /*actual size used with sdrs*/ static uchar *psdrcache = NULL; void free_sdr_cache(uchar *ptr) { if (ptr != NULL) free(ptr); if ((ptr != psdrcache) && (psdrcache != NULL)) free(psdrcache); psdrcache = NULL; } int get_sdr_file(char *sdrfile, uchar **sdrlist) { int rv = -1; FILE *fp = NULL; int i, n, num, nsdr, isdr, len; uchar *sdrbuf; char buff[255]; uchar hbuf[85]; char fvalid; fp = fopen(sdrfile,"r"); if (fp == NULL) { printf("Cannot open file %s\n",sdrfile); return(ERR_FILE_OPEN); } /* determine number of SDRs by number of lines in the file */ num = 0; while (fgets(buff, 255, fp)) { num++; } if (fdebug) { printf("Reading %d SDRs from file %s\n",num,sdrfile); if ((psdrcache != NULL) && (nsdrs > 0)) { /*already have sdrcache*/ printf("get_sdr_file: Already have cache\n"); /*fdebug*/ free_sdr_cache(psdrcache); /*free previous sdrcache*/ } } sdrbuf = malloc(num * SDR_SZ); if (sdrbuf == NULL) { fclose(fp); return(rv); } fseek(fp, 0L, SEEK_SET); *sdrlist = sdrbuf; psdrcache = sdrbuf; nsdrs = num; isdr = 0; nsdr = 0; while (fgets(buff, 255, fp)) { len = strlen_(buff); fvalid = 0; if (buff[0] >= '0' && (buff[0] <= '9')) fvalid = 1; else if (buff[0] >= 'a' && (buff[0] <= 'f')) fvalid = 1; else if (buff[0] >= 'A' && (buff[0] <= 'F')) fvalid = 1; if (fvalid == 0) continue; i = 0; for (n = 0; n < len; ) { if (buff[n] < 0x20) break; /* '\n', etc. */ hbuf[i++] = htoi(&buff[n]); n += 3; } memcpy(&sdrbuf[isdr],hbuf,i); isdr += i; nsdr++; } /*end while*/ if (fdebug) printf("Read %d SDRs, %d bytes\n",nsdr,isdr); fclose(fp); rv = 0; return(rv); } int get_sdr_cache(uchar **pret) { int rv = -1; int i, n, sz, len, asz; int recid, recnext; uchar *pcache; uchar *psdr; if (pret == NULL) return(rv); fdevsdrs = use_devsdrs(fpicmg); if ((psdrcache != NULL) && (nsdrs > 0)) { /*already have sdrcache*/ *pret = psdrcache; if (fdebug) printf("get_sdr_cache: already have cache (%p)\n",*pret); return(0); } else if (fdebug) printf("get_sdr_cache: Allocating cache\n"); rv = GetSDRRepositoryInfo(&n,&fdevsdrs); if (rv != 0) return(rv); if (n == 0) { /* this is an error, probably because fdevsdrs is wrong.*/ if (fdebug) printf("get_sdr_cache: nsdrs=0, retrying\n"); fdevsdrs = (fdevsdrs ^ 1); n = 150; /*try some default num SDRs*/ } sz = n * SDR_SZ; /*estimate max size for n sdrs*/ pcache = malloc(sz); if (pcache == NULL) return(rv); psdrcache = pcache; *pret = pcache; memset(pcache,0,sz); recid = 0; asz = 0; for (i = 0; i <= n; i++) { if (recid == 0xffff) break; // psdr = &pcache[i * SDR_SZ]; psdr = &pcache[asz]; rv = GetSDR(recid,&recnext,psdr,SDR_SZ,&len); if (fdebug) printf("GetSDR[%x] rv = %d len=%d next=%x\n",recid,rv,len,recnext); if (rv != 0) { if (rv == 0xC5) { set_reserve(1); i--; } /*retry*/ else break; } else { /*success*/ /* if sdrlen!=len, adjust */ if ((len > 5) && (len != (psdr[4] + 5)) ) { if (fdebug) printf("SDR[%x] adjust len from %d to %d\n", recid,psdr[4]+5,len); psdr[4] = len - 5; } asz += len; if (recnext == recid) recid = 0xffff; else recid = recnext; } } nsdrs = n; sz_sdrs = asz; /* save the size for later*/ if (fdebug) { printf("get_sdr_cache, n=%d sz=%d asz=%d\n",n,sz,asz); if (i < n) printf("get_sdr_cache error, i=%d < n=%d, rv=%d\n",i,n,rv); } return(rv); } int find_nsdrs(uchar *pcache) { int num = 0; ulong asz = 0; int i, len; uchar *sdr; ushort recid = 0; if (pcache == NULL) return(num); for (i = 0; (int)asz < sz_sdrs; i++) { sdr = &pcache[asz]; if (sdr[2] != 0x51) { /* Dell SDR length error */ printf("SDR[%x] length error at %ld\n",recid,asz); sdr = &pcache[++asz]; /*try it if off-by-one*/ } len = sdr[4] + 5; recid = sdr[0] + (sdr[1] << 8); if (fdebug) printf("SDR[%x] len=%d i=%d offset=%lx\n",recid,len,i,asz); asz += len; } num = i; return(num); } int find_sdr_by_snum(uchar *psdr, uchar *pcache, uchar snum, uchar sa) { int rv = -1; uchar *sdr; int i, k, len; int asz = 0; if (psdr == NULL) return(rv); if (pcache == NULL) return(rv); for (i = 0; i <= nsdrs; i++) { // sdr = &pcache[i * SDR_SZ]; sdr = &pcache[asz]; len = sdr[4] + 5; asz += len; switch(sdr[3]) { case 0x01: k = 7; break; /*full sensor*/ case 0x02: k = 7; break; /*compact sensor*/ case 0x03: k = 7; break;/*compact sensor*/ default: k = 0; break; } if (k == 0) continue; else { if ((sdr[5] == sa) && (sdr[k] == snum)) { memcpy(psdr,sdr,len); return(0); } } } return(rv); } int find_sdr_by_tag(uchar *psdr, uchar *pcache, char *tag, uchar dbg) { int rv = -1; uchar *sdr; int i, k, n, len; int asz = 0; if (psdr == NULL) return(rv); if (pcache == NULL) return(rv); if (tag == NULL) return(rv); if (dbg) fdebug = 1; n = strlen_(tag); if (fdebug) printf("find_sdr_by_tag(%s) nsdrs=%d\n",tag,nsdrs); for (i = 0; i <= nsdrs; i++) { // sdr = &pcache[i * SDR_SZ]; sdr = &pcache[asz]; len = sdr[4] + 5; asz += len; switch(sdr[3]) { /* set tag offset by SDR type */ case 0x01: k = 48; break; /*full SDR*/ case 0x02: k = 32; break; /*compact SDR*/ case 0x03: k = 17; break; /*event-only SDR*/ case 0x10: k = 16; break; /*device locator SDR*/ case 0x11: k = 16; break; /*FRU device locator SDR*/ case 0x12: k = 16; break; /*IPMB device locator SDR*/ default: k = 0; break; /*else do not have an ID string/tag*/ } if (k == 0) { if (fdebug) printf("sdr[%d] idx=%02x%02x num=%x type=%x skip\n", i,sdr[1],sdr[0],sdr[7],sdr[3]); continue; } else { if (len > SDR_SZ) len = SDR_SZ; if (fdebug) { char tmp[17]; memset(tmp,0,sizeof(tmp)); memcpy(tmp,&sdr[k],(len - k)); tmp[16] = 0; /*force stringify*/ printf("sdr[%d] idx=%02x%02x num=%x tag: %s\n",i,sdr[1],sdr[0], sdr[7],tmp); } if (strncmp(tag,(char *)&sdr[k],n) == 0) { memcpy(psdr,sdr,len); return(0); } } } return(rv); } int find_sdr_next(uchar *psdr, uchar *pcache, ushort id) { int rv = -1; uchar *sdr; int i, imatch, len; ushort recid; int asz = 0; if (psdr == NULL) return(rv); if (pcache == NULL) return(rv); imatch = nsdrs; for (i = 0; i < nsdrs; i++) { // sdr = &pcache[i * SDR_SZ]; sdr = &pcache[asz]; if (sdr[2] != 0x51) /* Dell SDR off-by-one error */ sdr = &pcache[++asz]; len = sdr[4] + 5; recid = sdr[0] + (sdr[1] << 8); asz += len; // if (fdebug) printf("SDR[%x] len=%d id=%x i=%d imatch=%d\n", // recid,len,id,i,imatch); if (recid == id) imatch = i + 1; /*matches prev, return next one*/ else if (id == 0) { rv = 0; break; } /* 0000 = first one */ if (i == imatch) { rv = 0; break; } } if (rv == 0) memcpy(psdr,sdr,len); return(rv); } int find_sdr_by_id(uchar *psdr, uchar *pcache, ushort id) { int rv = -1; uchar *sdr; int i, imatch, len; ushort recid; int asz = 0; if (psdr == NULL) return(rv); if (pcache == NULL) return(rv); imatch = nsdrs; for (i = 0; i < nsdrs; i++) { sdr = &pcache[asz]; len = sdr[4] + 5; recid = sdr[0] + (sdr[1] << 8); asz += len; if (recid == id) { rv = 0; break; } else if (id == 0) { rv = 0; break; } /* 0000 = first one */ } if (rv == 0) memcpy(psdr,sdr,len); return(rv); } uchar bitnum(ushort value) { uchar ret = 0; int i; /* returns the highest bit number number set in this word. */ /* Bit numbers are 1-based in this routine, 0 means no bits set. */ /* scan 15 bits (0x7FFF). */ for (i = 0; i < 15; i++) { if (value & 0x01) ret = i+1; /*was ret++;*/ value = (value >> 1); } return(ret); } static double expon(int x, int y) { double res; int i; /* compute exponent: x to the power y */ res = 1; if (y > 0) { for (i = 0; i < y; i++) res = res * x; } else if (y < 0) { for (i = 0; i > y; i--) res = res / x; } /* else if if (y == 0) do nothing, res=1 */ return(res); } double RawToFloat(uchar raw, uchar *psdr) { double floatval; int m, b, a; uchar ax; int rx, b_exp; SDR01REC *sdr; int signval; sdr = (SDR01REC *)psdr; floatval = (double)raw; /*default*/ // if (raw == 0xff) floatval = 0; else if (sdr->rectype == 0x01) { /* SDR rectype == full */ if (fdebug) printf("units=%x base=%d mod=%d (raw=%x, nom_rd=%x)\n", sdr->sens_units,sdr->sens_base,sdr->sens_mod, raw, sdr->nom_reading); m = sdr->m + ((sdr->m_t & 0xc0) << 2); b = sdr->b + ((sdr->b_a & 0xc0) << 2); if (b & 0x0200) b = (b - 0x0400); /*negative*/ if (m & 0x0200) m = (m - 0x0400); /*negative*/ rx = (sdr->rx_bx & 0xf0) >> 4; if (rx & 0x08) rx = (rx - 0x10); /*negative, fix sign w ARM compilers*/ a = (sdr->b_a & 0x3f) + ((sdr->a_ax & 0xf0) << 2); ax = (sdr->a_ax & 0x0c) >> 2; b_exp = (sdr->rx_bx & 0x0f); if (b_exp & 0x08) b_exp = (b_exp - 0x10); /*negative*/ //b_exp |= 0xf0; /* negative 8-bit */ if ((sdr->sens_units & 0xc0) == 0) { /*unsigned*/ floatval = (double)raw; } else { /*signed*/ if (raw & 0x80) signval = (raw - 0x100); else signval = raw; floatval = (double)signval; } floatval *= (double) m; #ifdef MATH_OK floatval += (b * pow (10,b_exp)); floatval *= pow (10,rx); #else floatval += (b * expon (10,b_exp)); floatval *= expon (10,rx); #endif if (fdebug) printf("decode1: m=%d b=%d b_exp=%x rx=%d, a=%d ax=%d l=%x, floatval=%f\n", m,b,b_exp,rx,a,ax,sdr->linear,floatval); switch(sdr->linear) { case 0: /*linear*/ break; case 7: /*invert 1/x*/ /* skip if zero to avoid dividing by zero */ if (raw != 0) floatval = 1 / floatval; break; case 1: /*ln*/ case 2: /*log10, log2, e, exp10, exp2, */ case 3: /*log2*/ case 4: /*e*/ case 5: /*exp10*/ case 6: /*exp2*/ case 8: /*sqr(x)*/ case 9: /*cube(x)*/ case 10: /*sqrt(x)*/ case 11: /*cube-1(x)*/ default: if (fdebug) printf("linear mode %x not implemented\n",sdr->linear); break; } /*end-switch linear*/ } #ifdef NOT_LINEAR /* else if (sdr->linear != 7) */ { double be, re; rc = GetSensorType(sdr->sens_num,&stype,&rtype); if (fdebug) printf("decode: rc=%x, stype=%x, rtype=%x\n",rc,stype,rtype); if (rc != 0) return(floatval); /* GetSensorReadingFactors */ rc = GetSensorReadingFactors(sdr->sens_num,raw,&m,&b,&b_exp,&r,&a); if (rc == 0) { // floatval = ((m * raw) + (b * be)) * re; } if (fdebug) printf("decode: rc=%x, floatval=%f\n",rc,floatval); } #endif return(floatval); } #define IpmiAnalogDataFormatUnsigned 0 #define IpmiAnalogDataFormat1Compl 1 #define IpmiAnalogDataFormat2Compl 2 uchar FloatToRaw(double val, uchar *psdr, int rounding) { double cval; int lowraw, highraw, raw, maxraw, minraw, next_raw; int analog_dfmt; analog_dfmt = (psdr[20] >> 6) & 0x03; switch( analog_dfmt ) { case IpmiAnalogDataFormat1Compl: lowraw = -127; highraw = 127; minraw = -127; maxraw = 127; next_raw = 0; break; case IpmiAnalogDataFormat2Compl: lowraw = -128; highraw = 127; minraw = -128; maxraw = 127; next_raw = 0; break; case IpmiAnalogDataFormatUnsigned: default: lowraw = 0; highraw = 255; minraw = 0; maxraw = 255; next_raw = 128; break; } /* do a binary search for the right nth root value */ do { raw = next_raw; cval = RawToFloat( (uchar)raw, psdr ); if ( cval < val ) { next_raw = ((highraw - raw) / 2) + raw; lowraw = raw; } else { next_raw = ((raw - lowraw) / 2) + lowraw; highraw = raw; } } while ( raw != next_raw ); /* Do rounding to get the final value */ switch( rounding ) { case 0: /* Round Normal = Round to nearest value */ if ( val > cval ) { if ( raw < maxraw ) { double nval; nval = RawToFloat((uchar)(raw+1),psdr); nval = cval + ((nval - cval) / 2.0); if ( val >= nval ) raw++; } } else { if ( raw > minraw ) { double pval; pval = RawToFloat((uchar)(raw-1),psdr); pval = pval + ((cval - pval) / 2.0); if ( val < pval ) raw--; } } break; case 1: /*Round Down*/ if ((val < cval) && (raw > minraw )) raw--; break; case 2: /*Round Up*/ if ((val > cval) && (raw < maxraw)) raw++; break; } if ( analog_dfmt == IpmiAnalogDataFormat1Compl ) if ( raw < 0 ) raw -= 1; return((uchar)raw); } /*end FloatToRaw()*/ static int fill_thresholds(double *thrf, uchar *sdr) { int rv = 0; uchar *vals; uchar bits; // snum = sdr[7]; bits = sdr[19]; /*which are settable*/ vals = &sdr[36]; if (fdebug) printf("fill_thresholds: bits=%02x, values: %f>=%f>=%f, %f<=%f<=%f\n", bits, thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]); if (thrf[0] == THR_EMPTY) { if ((bits & 0x01) != 0) { /*lo-noncrit*/ thrf[0] = RawToFloat(vals[5],sdr); rv++; } else thrf[0] = 0; } if (thrf[1] == THR_EMPTY) { if ((bits & 0x02) != 0) { /*lo-crit*/ thrf[1] = RawToFloat(vals[4],sdr); rv++; } else thrf[1] = 0; } if (thrf[2] == THR_EMPTY) { if ((bits & 0x04) != 0) { /*lo-unrec*/ thrf[2] = RawToFloat(vals[3],sdr); rv++; } else thrf[2] = 0; } if (thrf[3] == THR_EMPTY) { if ((bits & 0x08) != 0) { /*hi-noncrit*/ thrf[3] = RawToFloat(vals[2],sdr); rv++; } else thrf[3] = 0; } if (thrf[4] == THR_EMPTY) { if ((bits & 0x10) != 0) { /*hi-crit*/ thrf[4] = RawToFloat(vals[1],sdr); rv++; } else thrf[4] = 0; } if (thrf[5] == THR_EMPTY) { if ((bits & 0x20) != 0) { /*hi-unrec*/ thrf[5] = RawToFloat(vals[0],sdr); rv++; } else thrf[5] = 0; } if (fdebug) printf("fill_thresholds: after rv=%d values: %f>=%f>=%f, %f<=%f<=%f\n", rv,thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]); return(rv); } char * decode_itype(uchar itype) { char *retstr; int i; /* Decode the Interrupt Type from Entity Assoc records */ retstr = tmpstr; if (itype <= 0x0f) sprintf(retstr,"IRQ_%d",itype); else if (itype <= 0x13) { strcpy(retstr,"PCI-A"); for (i=0x10;i= 0x20 && itype <= 0x5f) sprintf(retstr,"SysInt_%d",itype-0x20); else if (itype == 0x60) strcpy(retstr,"ACPI/PnP"); else if (itype == 0xFF) strcpy(retstr,"NoInt"); else strcpy(retstr,"Invalid"); return(retstr); } int decode_oem_sensor(uchar *sdr,uchar *reading,char *pstring,int slen) { int rv = -1; #ifdef METACOMMAND switch(vend_id) { case VENDOR_INTEL: rv = decode_sensor_intel(sdr, reading, pstring, slen); break; case VENDOR_KONTRON: rv = decode_sensor_kontron(sdr, reading, pstring, slen); break; case VENDOR_FUJITSU: rv = decode_sensor_fujitsu(sdr,reading,pstring,slen); break; case VENDOR_SUN: rv = decode_sensor_sun(sdr, reading, pstring, slen); break; case VENDOR_MAGNUM: case VENDOR_SUPERMICRO: case VENDOR_SUPERMICROX: rv = decode_sensor_supermicro(sdr,reading,pstring,slen,fsimple,fdebug); break; case VENDOR_QUANTA: rv = decode_sensor_quanta(sdr, reading, pstring, slen); break; case VENDOR_HP: rv = decode_sensor_hp(sdr, reading, pstring, slen); break; case VENDOR_DELL: rv = decode_sensor_dell(sdr, reading, pstring, slen); break; case VENDOR_IBM: case VENDOR_LENOVO: case VENDOR_LENOVO2: rv = decode_sensor_lenovo(sdr, reading, pstring, slen); break; case VENDOR_ASUS: rv = decode_sensor_asus(sdr, reading, pstring, slen); break; default: break; } /*end-switch vend_id*/ if (fdebug) // && rv == 0) printf("decode_oem_sensor rv=%d vend=%x string=%s\n",rv,vend_id,pstring); #endif return (rv); } int show_oemsdr(int vend, uchar *sdr) { int rv = -1; int i, len; #ifdef METACOMMAND if (vend == VENDOR_INTEL) { show_oemsdr_intel(sdr); /*show subtypes for Intel BMC_TAM*/ rv = 0; } else if (vend == 4156) { /*special HP/NewAccess OEM SDR*/ show_oemsdr_hp(sdr); rv = 0; } else if (vend == VENDOR_QUANTA) { printf("Quanta: "); show_oemsdr_nm(sdr); rv = 0; } #endif if (rv != 0) { len = sdr[4] + 5; if (vend == VENDOR_FUJITSU) printf("Fujitsu: "); else if (vend == VENDOR_INTEL) printf("Intel: "); else printf("manuf=%d: ",vend); for (i = 8; i < len; i++) printf("%02x ",sdr[i]); printf("\n"); } return(rv); } void ShowThresh(int flg, uchar bits, uchar *vals, uchar *sdr) { char str[128] = ""; char part[24]; /* ~15 bytes used */ double ival; char sep[4]; char *tag; tag = ""; if (fsimple) { sprintf(sep,"%c ",bdelim); tag = "Thresholds"; } else sep[0] = 0; /*null string*/ if (fshowthr == 2) { double i0, i1, i2, i3, i4, i5; i0 = RawToFloat(vals[0],sdr); i1 = RawToFloat(vals[1],sdr); i2 = RawToFloat(vals[2],sdr); i3 = RawToFloat(vals[3],sdr); i4 = RawToFloat(vals[4],sdr); i5 = RawToFloat(vals[5],sdr); sprintf(str,"%.2f:%.2f:%.2f:%.2f:%.2f:%.2f",i0,i1,i2,i3,i4,i5); printf("\t%s%s%s%c",sep,"Thresh ",str,chEol); } else if (flg != 0) { /* Compact, did GetThresholds, reverse order */ if (bits & 0x20) { ival = RawToFloat(vals[5],sdr); sprintf(part,"%shi-unrec %.2f ",sep,ival); strcat(str,part); } if (bits & 0x10) { ival = RawToFloat(vals[4],sdr); sprintf(part,"%shi-crit %.2f ", sep,ival); strcat(str,part); } if (bits & 0x08) { ival = RawToFloat(vals[3],sdr); sprintf(part,"%shi-noncr %.2f ",sep,ival); strcat(str,part); } if (bits & 0x01) { ival = RawToFloat(vals[0],sdr); sprintf(part,"%slo-noncr %.2f ",sep,ival); strcat(str,part); } if (bits & 0x02) { ival = RawToFloat(vals[1],sdr); sprintf(part,"%slo-crit %.2f ", sep,ival); strcat(str,part); } if (bits & 0x04) { ival = RawToFloat(vals[2],sdr); sprintf(part,"%slo-unrec %.2f ",sep,ival); strcat(str,part); } if (flg == 2) { if (sens_verbose) tag = "Volatile "; printf("\t%s%s%s%c",sep,tag,str,chEol); } else printf("\t%s%s%s%c",sep,tag,str,chEol); } else { /*Full SDR*/ if (fdebug) printf("ShowThresh[%x]: bits=%02x, sdr18=%02x %02x\n", sdr[7],bits,sdr[18],sdr[19]); if (bits & 0x20) { ival = RawToFloat(vals[0],sdr); sprintf(part,"%shi-unrec %.2f ",sep,ival); strcat(str,part); } if (bits & 0x10) { ival = RawToFloat(vals[1],sdr); sprintf(part,"%shi-crit %.2f ",sep,ival); strcat(str,part); } if (bits & 0x08) { ival = RawToFloat(vals[2],sdr); sprintf(part,"%shi-noncr %.2f ",sep,ival); strcat(str,part); } if (bits & 0x01) { ival = RawToFloat(vals[5],sdr); sprintf(part,"%slo-noncr %.2f ",sep,ival); strcat(str,part); } if (bits & 0x02) { ival = RawToFloat(vals[4],sdr); sprintf(part,"%slo-crit %.2f ",sep,ival); strcat(str,part); } if (bits & 0x04) { ival = RawToFloat(vals[3],sdr); sprintf(part,"%slo-unrec %.2f ",sep,ival); strcat(str,part); } if (sens_verbose) tag = "SdrThres "; printf("\t%s%s%s%c",sep,tag,str,chEol); if (sens_verbose) { /* show max/min & hysteresis from full sdr */ str[0] = 0; ival = RawToFloat(sdr[31],sdr); sprintf(part,"%snom %.2f ",sep,ival); strcat(str,part); ival = RawToFloat(sdr[32],sdr); sprintf(part,"%snmax %.2f ",sep,ival); strcat(str,part); ival = RawToFloat(sdr[33],sdr); sprintf(part,"%snmin %.2f ",sep,ival); strcat(str,part); ival = RawToFloat(sdr[34],sdr); sprintf(part,"%ssmax %.2f ",sep,ival); strcat(str,part); ival = RawToFloat(sdr[35],sdr); sprintf(part,"%ssmin %.2f ",sep,ival); strcat(str,part); #ifdef OLD ival = RawToFloat(sdr[42],sdr); sprintf(part,"%s+hyst %.2f ",sep,ival); strcat(str,part); ival = RawToFloat(sdr[43],sdr); sprintf(part,"%s-hyst %.2f ",sep,ival); strcat(str,part); #endif printf("\t%s%c",str,chEol); } } /*endif full sdr*/ } int decode_comp_generic(uchar type, uchar evtype, uchar num, ushort reading) { int istr = 0; uchar b; /* decode via evtype */ switch(evtype) { case 0x02: if (reading & 0x01) istr = 85; /* Active */ if (reading & 0x02) istr = 86; /* Busy */ else istr = 84; /* Idle (OK)) */ case 0x03: if (reading & 0x01) istr = 13; /* Asserted */ else istr = 0; /* "OK" Deasserted */ break; case 0x04: if (reading & 0x01) istr = 15; /* Predictive Failure */ else istr = 0; /* "OK" Deasserted */ break; case 0x05: if (reading & 0x01) istr = 65; /* Limit Exceeded*/ else istr = 0; /* "OK" LimitNotExceeded*/ break; case 0x07: /* transition */ b = bitnum(reading); switch(b) { case 0: istr = 0; break; /*no bits set, OK*/ case 1: istr = 87; break; /*transition up to Non-Critical*/ case 2: istr = 88; break; /*transition up to Critical */ case 3: istr = 89; break; /*transition up to Non-recoverable */ case 4: istr = 87; break; /*transition down to Non-Critical */ case 5: istr = 88; break; /*transition down to Critical */ case 6: istr = 89; break; /*transition to Non-recoverable */ case 7: istr = 90; break; /*Monitor*/ case 8: istr = 91; break; /*Informational*/ default: istr = 8; break; /*'OK*'*/ } break; case 0x08: if (reading & 0x01) istr = 9; /* Present */ else istr = 10; /*Absent*/ break; case 0x09: /* Availability event states */ if (reading & 0x01) istr = 17; /* Enabled */ else istr = 16; /*Disabled*/ break; case 0x0A: /* */ b = (reading & 0x7f); switch(b) { case 0x00: istr = 8; break; /* 00 'OK*'*/ case 0x01: istr = 92; break; /* transition to Running */ case 0x02: istr = 93; break; /* transition to In Test */ case 0x04: istr = 94; break; /* transition to Power Off */ case 0x08: istr = 95; break; /* transition to On Line */ case 0x10: istr = 96; break; /* transition to Off Line */ case 0x20: istr = 97; break; /* transition to Off Duty */ case 0x40: istr = 98; break; /* transition to Degraded */ case 0x80: istr = 99; break; /* transition to Power Save */ default: istr = 100; break; /* Install Error */ } break; case 0x0B: /* Redundancy */ b = (reading & 0x7f); switch(b) { case 0x00: istr = 8; break; /* 00 'OK*'*/ case 0x01: istr = 18; break; /* 01 Fully Redundant */ case 0x02: istr = 19; break; /* 02 Redundancy Lost */ case 0x04: istr = 20; break; /* 04 Redundancy Degraded */ case 0x08: istr = 82; break; /* 08 Non-Redundant/Sufficient down */ case 0x10: istr = 82; break; /* 10 Non-Redundant/Sufficient up*/ case 0x20: istr = 83; break; /* 20 Non-Redundant/Insufficient */ case 0x40: istr = 20; break; /* 40 Redundancy Degraded down */ default: istr = 20; break; /* Redundancy Degraded up */ } break; case 0x0C: /* ACPI Power States */ if (reading & 0x04) istr = 21; /* D3, Off */ else if (reading & 0x02) istr = 23; /* D2, Sleeping */ else if (reading & 0x01) istr = 22; /* D1, Working */ else istr = 24; /*D0, On*/ break; default: if (fdebug) printf("sensor[%x] et %02x type %02x not decoded, reading = %04x\n", num,evtype,type,reading); istr = STR_OTHER; /* other " - " */ break; } return(istr); } /* * decode_comp_reading * * Decodes the readings from compact SDR sensors. * Use sensor_dstatus array for sensor reading types and meaning strings. * Refer to IPMI Table 36-1 and 36-2 for this. * * Note that decoding should be based on sensor type and ev_type only, * except for end cases. * * Note reading1 = sens_reading[2], reading2 = sens_reading[3] */ int decode_comp_reading(uchar type, uchar evtype, uchar num, uchar reading1, uchar reading2) { int istr = 0; /*string index into sensor_dstatus[] */ uchar b; ushort reading; static char customstr[35]; /* usually reading2 has h.o. bit set (0x80). */ reading = reading1 | ((reading2 & 0x7f) << 8); switch(type) { case 0x01: /*Discrete Thermal, Temperature*/ if (fdebug) printf("Discrete Thermal snum %x evtype=%x reading=%x\n", num,evtype,reading); if (evtype == 0x07) { b = bitnum(reading); if (b == 0) istr = 8; /*no bits set, "OK*"*/ else if (b < 3) istr = 0; /*bits 1,2 "OK"*/ else istr = 65; /*transition to error, Limit Exceeded*/ } else if (evtype == 0x05) { /* see CPU1 VRD Temp on S5000, snum 0xc0 thru 0xcf */ if (reading & 0x01) istr = 65; /* Limit Exceeded*/ else istr = 0; /* "OK" LimitNotExceeded*/ } else if (evtype == 0x03) { if (reading & 0x01) istr = 13; /* Asserted */ else istr = 0; /* "OK" Deasserted */ } else { /* evtype == other 0x05 */ if (reading & 0x01) istr = 0; /* 8="OK*", 0="OK" */ else istr = 5; /*state asserted, Crit-hi */ } break; case 0x02: /*Discrete Voltage*/ { /* evtype == 0x05 for VBat, 0x03 for VR Watchdog */ if (reading & 0x01) istr = 65; /*LimitExceeded, was Crit-hi*/ else istr = 0; /* "OK" LimitNotExceeded*/ } break; case 0x04: /*Fan*/ if (evtype == 0x0b) { /*redundancy*/ b = reading & 0x3f; if (b == 0x00) istr = 16; /*sensor disabled*/ else if (b == 0x01) istr = 18; /*fully redundant*/ else if (b == 0x02) istr = 19; /*redundancy lost*/ else if (b == 0x0b) istr = STR_AC_LOST; /*ac lost*/ else istr = 20; /*redundancy degraded*/ } else if (evtype == 0x08) { /*presence*/ if (reading & 0x02) istr = 9; /*Present/Inserted*/ else if (reading & 0x01) istr = 10; /*Absent/Removed*/ else /*reading==00*/ istr = 47; /*Unused*/ } else if (evtype == 0x03) { /*PS Fan Fail*/ if (reading == 0) istr = 0; /*OK*/ else istr = 12; /*faulty*/ } else { /*other evtype*/ b = reading & 0x0f; if (b == 0) istr = 12; /*faulty*/ else if (b & 0x01) istr = 11; /*ready*/ else istr = 41; /*Unknown*/ } break; case 0x05: /*Physical Security, Chassis */ if (reading == 0) istr = 0; /*OK*/ else if (reading & 0x01) istr = 38; /*chassis intrusion*/ /* 0x02 Drive bay intrusion */ /* 0x04 IO area intrusion */ /* 0x08 Processor area intrusion */ else if (reading & 0x10) istr = 37; /*lan leash lost*/ /* 0x20 Dock/Undock */ /* 0x40 Fan area intrusion */ else istr = 41; /* Unknown, was bitnum(reading); */ break; case 0x07: /*Processor Status - 0x80 is OK/Present */ b = bitnum(reading); if (evtype == 0x03) { if (b <= 1) istr = 0; /*bit1 Deasserted, OK* */ else istr = 13; /*bit2 Asserted*/ } else { /*usu 0x6f*/ if (b > 10) istr = 41; /*Unknown*/ else if (b == 0) istr = 0; /*OK*/ else istr = 47 + b; /*Proc strings 48 thru 57*/ } break; case 0x08: /*Power Supply*/ b = reading & 0x7f; if (b == 0) istr = 10; /*absent*/ else if (b & 0x40) istr = STR_PS_CONFIG; /*Config Err*/ else if (b & 0x08) istr = STR_AC_LOST; /*AC Lost*/ else if (b & 0x04) istr = 15; /*Predictive Fail*/ else if (b & 0x02) istr = STR_PS_FAIL; /*PS Fail*/ else if (b & 0x01) istr = 9; /*present*/ break; case 0x09: /*Power Unit*/ b = reading & 0x3f; if (evtype == 0x0b) { /*Power Redundancy*/ if (b == 0x00) istr = 16; /*sensor disabled*/ else if (b == 0x01) istr = 18; /*fully redundant*/ else if (b == 0x02) istr = 19; /*redundancy lost*/ else if (b == 0x0b) istr = STR_AC_LOST; /*ac lost*/ else istr = 20; /*redundancy degraded*/ } else { /* Power Unit (evtype==0x6f or 0xef) */ if (b == 0) istr = 17; /*enabled*/ else if ((b & 0x01) == 1) istr = 16; /*disabled*/ } break; case 0x0C: /* Memory */ b = reading & 0x3f; if (b == 0) istr = 0; /*OK*/ else if (b & 0x01) istr = 8; /*Correctable ECC (OK*)*/ else if ((b & 0x02) || (b & 0x20)) istr = 39; /*ECC Error*/ else if (b & 0x04) istr = 40; /*Parity Error*/ else istr = bitnum(b); /* ECC or other error */ break; case 0x0D: /* drive slot - usually HSC sens_ownid == 0xc0 */ if (fRomley || fGrantley) { /* evtype==0x6f, has both status and presence */ if (reading & 0x02) istr = 12; /*Faulty*/ else if (reading & 0x80) istr = STR_REBUILDING; /*Rebuilding*/ else if (reading & 0x01) istr = 9; /*Present (OK)*/ else istr = 10; /*Absent*/ } else { if (evtype == 8) { /* HSC slot presence sensors (num > 8)*/ if (reading1 & 0x02) istr = 9; /*Present/Inserted*/ else if (reading1 & 0x01) istr = 10; /*Absent/Removed*/ else /*reading1==00*/ istr = 47; /*Unused*/ } else { /* HSC slot status sensors (evtype==0x6f)*/ /* usually reading2 == 0x82 or 0x8E if healthy */ if (reading2 & 0x01) istr = 12; /*state8=Rebuild stopped*/ else if (reading2 & 0x02) istr = 11; /*state9=Inserted/Ready */ else if (reading2 & 0x04) istr = 11; /*state10=Safe_to_Remove*/ else if (reading2 & 0x08) istr = 11; /*state11=Ready */ else if (reading2 == 0x80) istr = 47; /*no states, Unused*/ else istr = 12; /*faulty*/ b = 8; /*if no bits set, no raid state */ if (reading1 & 0x01) { b = 0; } /*state0=Faulty*/ else if (reading1 & 0x02) b = 1; /*state1=Rebuilding*/ else if (reading1 & 0x04) b = 2; /*state2=InFailedArray*/ else if (reading1 & 0x08) b = 3; /*state3=InCriticalArray*/ else if (reading1 & 0x10) b = 4; /*state4=ParityCheck*/ else if (reading1 & 0x20) b = 5; /*state5=PredictedFault*/ else if (reading1 & 0x40) b = 6; /*state6=Un-configured*/ else if (reading1 & 0x80) b = 7; /*state7=HotSpare*/ if (b < 8) { /* also include a raid_state, via custom string */ sprintf(customstr,"%s %s", sensor_dstatus[istr], raid_states[b]); istr = STR_CUSTOM; sensor_dstatus[istr] = customstr; if (fdebug) printf("dstatus=%s\n",sensor_dstatus[istr]); } } /*end-else-if HSC slot status (0x6f)*/ } break; case 0x10: /*Event Logging*/ /* usu evtype==0x6f*/ b = bitnum(reading & 0x3f); switch (b) { case 0x00: istr = 0; break; /*OK*/ case 0x01: istr = 59; break; /*MemLogDisabled*/ case 0x02: istr = 60; break; /*TypLogDisabled*/ case 0x03: istr = 61; break; /*LogCleared*/ case 0x04: istr = 62; break; /*AllLogDisabled*/ case 0x05: istr = 63; break; /*SelFull*/ case 0x06: istr = 64; break; /*SelNearFull*/ default: istr = 41; break; /*Unknown*/ } break; case 0x12: /*System Event*/ if (reading == 0) istr = 0; else istr = 13; /*Asserted*/ break; case 0x13: /*Critical Interrupt*/ /* valid bits: 0x03FF */ if (reading == 0) istr = 0; /*OK*/ else { b = bitnum(reading); /* ECC or other error */ if (b > 10) b = 10; istr = 24 + b; } break; case 0x14: /*Button*/ if (reading == 0) istr = 0; /*OK*/ else istr = 13; /*Asserted*/ break; case 0x15: /*Module/ Board */ if (evtype == 0x08) { /*presence*/ if (reading & 0x02) istr = 9; /*Present/Inserted*/ else if (reading & 0x01) istr = 10; /*Absent/Removed*/ else /*reading==00*/ istr = 47; /*Unused*/ } break; case 0x16: /* HSBP Status (esp. Romley) */ if (reading & 0x010) istr = STR_HSC_OFF; /*Offline*/ else istr = 0; /*OK*/ break; case 0x17: /* ATCA CDM, Air Filter, Filter Tray */ if (reading == 0) istr = 0; /*OK*/ else if (reading & 0x01) istr = 10; /*Absent*/ else istr = bitnum(reading); /* other error, TODO: fix this */ break; case 0x1C: /*Terminator (usu SCSI)*/ if (reading & 0x01) istr = 9; /*present*/ else istr = 10; /*missing,absent*/ break; case 0x21: /*DIMM memory slot*/ if ((reading & 0x04) != 0) istr = 9; /*present*/ else istr = 10; /*absent*/ sprintf(customstr,"%s", sensor_dstatus[istr]); if ((reading & 0x01) != 0) strcat(customstr,",Fault"); if ((reading & 0x0100) != 0) strcat(customstr,",Disabled"); istr = 58; /*use a custom string*/ sensor_dstatus[istr] = customstr; if (fdebug) printf("dstatus=%s\n",sensor_dstatus[istr]); break; case 0x22: /*ACPI Power State*/ b = bitnum(reading); switch(b) { case 0: istr = 0; break; /*OK*/ case 1: istr = 22; break; /*Working*/ case 2: case 3: case 4: case 5: case 9: case 10: istr = 23; break; /*Sleeping*/ case 6: case 7: case 8: case 11: case 12: istr = 24; break; /*On*/ case 13: istr = 21; break; /*Off*/ default: istr = 41; /*unknown*/ } break; case 0x23: /*Watchdog*/ if (reading == 0) istr = 0; else istr = 13; /*Asserted*/ break; case 0x24: /*Platform Alert*/ b = bitnum(reading); switch(b) { case 0: istr = 0; break; /*OK, no bits set*/ case 1: istr = 66; break; /*Page, bit 0 set*/ case 2: istr = 67; break; /*LAN, bit 1 set*/ case 3: istr = 68; break; /*PET*/ case 4: istr = 69; break; /*SNMP OEM*/ default: istr = 70; /*None*/ } break; case 0x25: /* Entity Presence */ if (reading & 0x01) istr = 8; /*Present*/ else if (reading & 0x02) istr = 9; /*Absent*/ else if (reading & 0x04) istr = 16; /*Disabled*/ else istr = 42; /* NotAvailable */ break; case 0x28: /* BMC FW Health */ if (evtype == 0x6F) { /*Sensor-specific*/ if (reading == 0) istr = 0; /*OK*/ else istr = 12; /*Faulty*/ } else { /*use event/reading type*/ istr = decode_comp_generic(type, evtype, num, reading); } break; case 0x29: /* Battery */ switch(reading & 0x7f) { case 0x00: istr = 0; break; /*OK*/ case 0x01: istr = 15; break; /*Predict Fail*/ case 0x04: istr = 9; break; /*Present*/ case 0x02: default: istr = 12; break; /*Failed/Faulty*/ } break; case 0x2A: /* Session Audit (IPMI 2.0) */ if (reading == 0x00) istr = 45; /*Activated*/ else istr = 46; /*Deactivated*/ break; case 0x2B: /* Version Change */ b = bitnum(reading1); switch(b) { case 0: istr = 0; break; /*OK, no bits set*/ case 1: istr = 72; break; /*HW Changed, bit 0 set*/ case 2: istr = 73; break; /*SW Changed, bit 1 set*/ case 3: istr = 74; break; /*HW incompatibility*/ default: istr = 75; break; /*Change error*/ } break; /* sensor types 0xC0 - 0xFF are OEM RESERVED */ case 0xF1: /* ATCA IPMB-0 Sensor */ if ((reading & 0x7fff) == 0x0008) istr = 0; /*OK*/ else istr = bitnum(reading1); /* other error, TODO: refine this */ break; case 0xC0: /* SMI State, NMI State */ case 0xD8: /* BIST */ case 0xF0: /* ATCA FRU HotSwap, TODO: refine this */ case 0xF2: /* ATCA Module HotSwap, TODO: refine this */ case 0xF3: /* SMI Timeout, etc. */ if (reading & 0x01) istr = 13; /* Asserted */ else istr = 0; /* "OK", Deasserted */ break; case 0x60: /* SCSI 1 Term Flt */ case 0x61: /* SCSI 2 Term Flt */ default: istr = decode_comp_generic(type, evtype, num, reading); break; } return(istr); } /* end decode_comp_reading */ #define STYPSZ 15 static char *get_stype_str(uchar stype) { /*return sensor type string, with fixed length */ static char stype_str[STYPSZ+1]; char *tmpstr; int i, n; tmpstr = get_sensor_type_desc(stype); n = strlen_(tmpstr); if (n > STYPSZ) n = STYPSZ; strncpy(stype_str,tmpstr,n); for (i = n; i < STYPSZ; i++) stype_str[i] = ' '; stype_str[i] = 0; tmpstr = stype_str; return(tmpstr); } void ShowSDR(char *tag, uchar *sdr) { SDR01REC *sdr01; SDR02REC *sdr02; SDR08REC *sdr08; SDR11REC *sdr11; SDR12REC *sdr12; SDR14REC *sdr14; SDRc0REC *sdrc0; char idstr[32]; char *typestr = NULL; int vend; int len, ilen, i, j; int ioff; uchar sens[4]; uchar sens_cap; uchar shar_cnt; int rc; double val; char brearm; uchar sep[4]; char rdgstr[50]; len = sdr[4] + 5; sens_cap = 0x80; /*ignore*/ if (fdebug) printf("ShowSDR: len=%d, type=%x\n",len,sdr[3]); memset(sens,0,4); if (frawsdr || fdebug) { /* raw is different than dump_buf */ printf("raw SDR: "); for (i = 0; i < len; i++) printf("%02x ",sdr[i]); printf("\n"); } strcpy(idstr,"INIT"); /*always set idstr to some initial string*/ switch(sdr[3]) { case 0x01: /* Full sensor record */ sdr01 = (SDR01REC *)sdr; ioff = 48; if (ioff > len) { if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n", sdr[3],len,ioff); fprintf(stderr,"Bad SDR Length %d, please apply the correct FRU/SDR diskette\n",len); return; } sens_cap = sdr[11]; /*sdr01->sens_capab*/ // ilen = (sdr[ioff] & 0x1f); /*sdr01->id_typelen*/ ilen = len - ioff; if (fdebug) printf("SDR[%x] Full ioff=%d idTypLen=0x%02x ilen=%d\n", sdr01->recid, ioff,sdr[ioff] ,ilen); if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; if (ilen <= 0) { /*bug if true*/ fprintf(stderr,"Bad SDR Length %d, omits ID string\n",len); ilen = 16; /*less than sizeof(idstr)*/ } memcpy(idstr,&sdr[ioff],ilen); for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; } idstr[ilen] = 0; /* stringify */ if ((sdr01->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/ else brearm = 'a'; /*automatic rearm*/ if (fdebug) printf("entity %d.%d, idlen=%d sizeof=%lu idstr0=%c s0=%x\n", sdr01->entity_id, sdr01->entity_inst, ilen,sizeof(SDR01REC),idstr[0],sdr[ioff]); rc = GetSensorReading(sdr01->sens_num,sdr01,sens); if (rc != 0) { /* if rc != 0, leave sens values zero */ i = 41; /* Unknown */ val = 0; if (rc == 0xCB) { /*sensor not present*/ i = 10; /* Absent */ typestr = "na"; } else typestr = decode_rv(rc); } else { j = (sens[2] & 0x3f); /*sensor reading state*/ i = bitnum((ushort)j); /*sensor_dstatus index*/ if (fdebug) printf("bitnum(%02x)=%d raw=%02x init=%x base/units=%x/%x\n", sens[2],i,sens[0],sens[1],sdr01->sens_base, sdr01->sens_units); if ((sens[1] & 0x20) != 0) { i = 7; val = 0; } /* Init state */ else if (sdr01->sens_units == 0xC0) i = 42; /*reading NotAvailable*/ else if (sens[2] == 0xc7) { i = 10; val = 0; /* Absent (Intel) */ if (fdebug) printf("sensor[%x] is absent (c7), no reading\n", sdr01->sens_num); } else val = RawToFloat(sens[0],sdr); typestr = get_unit_type(sdr01->sens_units, sdr01->sens_base, sdr01->sens_mod, fsimple); #ifdef WRONG if (is_romley(vend_id,prod_id) && (sdr01->sens_type == 0x0C) && (sdr01->sens_units & 0x01)) { /* Intel Memory Thermal Throttling %, raw 0x01 == 0.5 % */ val = (val / 2); /* handle MTT SDR errata */ } /*correct solution is to fix the SDR m-value instead */ #endif } rc = decode_oem_sensor(sdr,sens,oem_string,sizeof(oem_string)); if (rc == 0) { if (fsimple) strncpy(rdgstr,oem_string,sizeof(rdgstr)); else snprintf(rdgstr,sizeof(rdgstr),"%02x %s",sens[0],oem_string); } else { if (fsimple) snprintf(rdgstr,sizeof(rdgstr),"%s %c %.2f %s", sensor_dstatus[i],bdelim,val,typestr); else snprintf(rdgstr,sizeof(rdgstr),"%02x %s %.2f %s", sens[0], sensor_dstatus[i],val,typestr); } sep[0] = 0; /*null string*/ printf("%s", tag); if (fsimple) { sprintf(sep,"%c ",bdelim); printf("%04x %c Full %c %s %c %02x %c %s %c %s%c", sdr01->recid, bdelim, bdelim, get_stype_str(sdr01->sens_type), bdelim, sdr01->sens_num,bdelim, idstr, bdelim,rdgstr,chEol); } else printf("%04x SDR Full %02x %02x %02x %c %02x snum %02x %s = %s%c", sdr01->recid, sdr01->rectype, sdr01->ev_type, sdr01->sens_ownid, brearm, sdr01->sens_type, sdr01->sens_num, idstr, rdgstr, chEol); if (fdebug && fshowthr) printf("cap=%02x settable=%02x, readable=%02x\n", sens_cap,sdr[19],sdr[18]); if (sens_verbose) /* if -v, also show Entity ID */ printf("\t%sEntity ID %d.%d (%s), Capab: %s%c", sep, sdr01->entity_id, sdr01->entity_inst, decode_entity_id(sdr01->entity_id), // sens_cap, decode_capab(sens_cap),chEol); if (fshowthr && (sens_cap & 0x0f) != 0x03) { uchar thresh[7]; /* Thresholds, so show them */ /* Use settable bits to show thresholds, since the * readable values will be off for Full SDRs. * If cant set any thresholds, only show SDR thresholds */ if (sdr[19] == 0) rc = 1; else { /* Show volatile thresholds. */ rc = GetSensorThresholds(sdr01->sens_num,&thresh[0]); if (rc == 0) ShowThresh(2,thresh[0],&thresh[1],sdr); } /* Show SDR non-volatile thresholds. */ if (sens_verbose || rc !=0) ShowThresh(0,sdr[18],&sdr[36],sdr); // ShowThresh(0,0x3f,&sdr[36],sdr); /* to show all %%%% */ } if (fwrap) { /* (chEol != '\n') include time */ time_t ltime; time(<ime); if (fsimple) printf("%c %s",bdelim,ctime(<ime)); /*ctime has '\n' */ else printf("at %s",ctime(<ime)); /*ctime has '\n' */ } break; case 0x02: /* Compact sensor record */ sdr02 = (SDR02REC *)sdr; ioff = 32; if (ioff > len) { if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n", sdr[3],len,ioff); fprintf(stderr,"Bad SDR Length, please apply the correct FRU/SDR diskette\n"); return; } sens_cap = sdr[11]; /*sdr02->sens_capab*/ shar_cnt = sdr02->shar_cnt & 0x0f; /*sdr[23]*/ ilen = len - ioff; if ((ilen+1) >= sizeof(idstr)) ilen = sizeof(idstr) - 2; memcpy(idstr,&sdr[ioff],ilen); if ((shar_cnt > 1) && (sdr02->shar_off & 0x80) != 0) { /*do shared SDR*/ j = (sdr02->shar_off & 0x7f); /*sdr[24] = modifier offset*/ if (fdebug) printf("share count = %d, mod_offset = %d\n",shar_cnt,j); if ((sdr02->shar_cnt & 0x10) != 0) { /*alpha*/ idstr[ilen++] = 0x40 + j; /* j=1 -> 'A' */ idstr[ilen] = 0; /* stringify */ } else { /*numeric*/ sprintf(&idstr[ilen],"%d",j); ilen = strlen_(idstr); } } /* else normal idstr */ for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; } idstr[ilen] = 0; /* stringify */ if ((sdr02->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/ else brearm = 'a'; /*automatic rearm*/ if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%zu, s0=%x\n", ilen,idstr[0],sizeof(SDR02REC),sdr[ioff]); memset(sens,0,sizeof(sens)); rc = GetSensorReading(sdr02->sens_num,sdr02,sens); if (rc != 0) { /* if rc != 0, leave sens values zero */ i = 41; /* Unknown */ val = 0; if (rc == 0xCB) { /*sensor not present*/ i = 10; /* Absent */ typestr = "na"; } else typestr = decode_rv(rc); } else { if ((sens[1] & 0x20) != 0) i = 42; /*init state, NotAvailable*/ else { rc = decode_oem_sensor(sdr,sens,oem_string,sizeof(oem_string)); if (rc == 0) i = STR_OEM; else i = decode_comp_reading(sdr02->sens_type,sdr02->ev_type, sdr02->sens_num,sens[2],sens[3]); } } if (fdebug) printf("snum %x type %x evt %x reading %02x%02x i=%d rc=%d %s\n", sdr02->sens_num,sdr02->sens_type,sdr02->ev_type, sens[3],sens[2],i,rc, decode_rv(rc)); j = sens[2] | ((sens[3] & 0x7f) << 8); /*full reading, less h.o. bit*/ sep[0] = 0; /*null string*/ printf("%s", tag); if (fsimple) { sprintf(sep,"%c ",bdelim); printf("%04x %c Compact %c %s %c %02x %c %s %c %s %c%c", sdr02->recid, bdelim, bdelim, get_stype_str(sdr02->sens_type), bdelim, sdr02->sens_num, bdelim, idstr, bdelim, sensor_dstatus[i],bdelim,chEol); } else if (i == STR_OEM) { // idstr[ilen] = 0; /*cut out padding in idstr*/ printf("%04x SDR Comp %02x %02x %02x %c %02x snum %02x %s = %04x %s%c", sdr02->recid, sdr02->rectype, sdr02->ev_type, sdr02->sens_ownid, brearm, sdr02->sens_type, sdr02->sens_num, idstr, j, sensor_dstatus[i],chEol); // sensor_dstatus[i] == oem_string } else { printf("%04x SDR Comp %02x %02x %02x %c %02x snum %02x %s = %04x %s%c", sdr02->recid, sdr02->rectype, sdr02->ev_type, sdr02->sens_ownid, brearm, sdr02->sens_type, sdr02->sens_num, idstr, j, sensor_dstatus[i],chEol); /* idstr, sens[0], sens[1], sens[2], sens[3], */ } if (fdebug && fshowthr) printf("cap=%02x settable=%02x, readable=%02x\n", sens_cap,sdr[19],sdr[18]); if (fshowthr) /*also show Entity ID */ printf("\t%sEntity ID %d.%d (%s), Capab: %s%c", sep, sdr02->entity_id, sdr02->entity_inst, decode_entity_id(sdr02->entity_id), // sens_cap, decode_capab(sens_cap),chEol); if (fshowthr && ((sens_cap & 0x80) == 0) && (sens_cap & 0x0C) != 0) { uchar thresh[7]; /* Thresholds, show them */ /* Use readable bits to get & show thresholds */ if (sdr[20] != 0) { rc = GetSensorThresholds(sdr02->sens_num,&thresh[0]); if (rc == 0) ShowThresh(1,thresh[0],&thresh[1],sdr); } } if (fwrap) { /*include time and \n */ time_t ltime; time(<ime); if (fsimple) printf("%c %s",bdelim,ctime(<ime)); /*ctime has '\n' */ else printf("at %s",ctime(<ime)); /*ctime has '\n' */ } break; case 0x03: /* Event-only sensor record, treat like Compact SDR */ sdr02 = (SDR02REC *)sdr; ioff = 17; if (ioff > len) { fprintf(stderr,"Bad SDR %x Length %d. Please apply the correct FRU/SDR diskette\n", sdr02->recid, len); return; } if (!fsimple) { ilen = len - ioff; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[ioff],ilen); for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; } idstr[ilen] = 0; /* stringify */ sens_cap = sdr[11]; memset(sens,0,sizeof(sens)); if ((sdr02->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/ else brearm = 'a'; /*automatic rearm*/ // rc = GetSensorReading(sdr02->sens_num,sdr02,sens); /* EvtOnly SDRs do not support readings. * GetSensorReading would return ccode=0xCB (not present), * but this skips error msg */ rc = 0xCB; i = bitnum((ushort)sens[2]); j = sens[2] | ((sens[3] & 0x7f) << 8); printf("%s",tag); printf("%04x SDR EvtO %02x %02x %02x %c %02x snum %02x %s = %04x %s\n", sdr02->recid, sdr02->rectype, sdr02->reclen, sdr02->sens_ownid, 'a', sdr[10], sdr02->sens_num, idstr, j, sensor_dstatus[i]); // sens[0], sens[1], sens[2], sens[3], sensor_dstatus[i] } break; case 0x08: /* Entity Association record */ sdr08 = (SDR08REC *)sdr; if (!fsimple) { printf("%s",tag); printf("%04x SDR EntA %02x %02x %02x %02x %02x: ", sdr08->recid, sdr08->rectype, sdr08->reclen, sdr08->contid, sdr08->continst, sdr08->flags); for (i = 0; i < 8; i++) printf("%02x ",sdr08->edata[i]); printf("\n"); } break; case 0x09: /* Device-relative Entity Association record */ sdr08 = (SDR08REC *)sdr; /*but SDR09 is 26 bytes*/ if (!fsimple) { printf("%s",tag); printf("%04x SDR DEnt %02x %02x %02x %02x %02x %02x %02x: ", sdr08->recid, sdr08->rectype, sdr08->reclen, sdr08->contid, sdr08->continst, sdr08->flags, sdr08->edata[0], sdr08->edata[1]); /*display 2 of 4 contained entity devices edata[2-10] */ for (i = 2; i < 8; i++) printf("%02x ",sdr08->edata[i]); printf("\n"); } break; case 0x10: /* Generic Device Locator record */ sdr11 = (SDR11REC *)sdr; ioff = 16; if (ioff > len) { if (fdebug) printf("SDR %x bad length: type=%x, len=%d, ioff=%d\n", sdr11->recid, sdr[3],len,ioff); return; } if (!fsimple) { ilen = len - ioff; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[ioff],ilen); idstr[ilen] = 0; /* stringify */ printf("%s", tag); if (fsimple) printf("DevLocator record[%x]%c device %02x %c %s\n", sdr11->recid, bdelim,sdr11->dev_slave_adr,bdelim,idstr); else printf("%04x SDR DLoc %02x %02x dev: %02x %02x %02x %02x %02x %02x %s\n", sdr11->recid, sdr11->rectype, sdr11->reclen, sdr11->dev_access_adr, sdr11->dev_slave_adr, sdr11->access_lun, sdr[8], sdr[10], sdr[11], idstr); } break; case 0x11: /* FRU record */ sdr11 = (SDR11REC *)sdr; ioff = 16; if (ioff > len) { if (fdebug) printf("SDR %x bad length: type=%x len=%d ioff=%d\n", sdr11->recid, sdr[3],len,ioff); printf("Please apply the correct FRU/SDR diskette\n"); return; } if (!fsimple) { ilen = len - ioff; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[ioff],ilen); idstr[ilen] = 0; /* stringify */ if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%zu, s0=%x\n", ilen,idstr[0],sizeof(SDR11REC),sdr[ioff]); printf("%s", tag); if (fsimple) printf("FRU record[%x]: device %02x : %s\n", sdr11->recid, sdr11->dev_slave_adr,idstr); else printf("%04x SDR FRU %02x %02x dev: %02x %02x %02x %02x %02x %02x %s\n", sdr11->recid, sdr11->rectype, sdr11->reclen, sdr11->dev_access_adr, sdr11->dev_slave_adr /*fru_id*/, sdr11->access_lun, sdr11->chan_num, sdr11->entity_id, sdr11->entity_inst, idstr); } break; case 0x12: /* IPMB record */ sdr12 = (SDR12REC *)sdr; ioff = 16; if (ioff > len) { if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n", sdr[3],len,ioff); printf("Please apply the correct FRU/SDR diskette\n"); return; } if (!fsimple) { ilen = len - ioff; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[ioff],ilen); idstr[ilen] = 0; /* stringify */ if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%zu, s0=%x\n", ilen,idstr[0],sizeof(SDR12REC),sdr[ioff]); printf("%s", tag); if (fsimple) printf("IPMB record[%x]%c addr %02x %02x %c %s\n", sdr12->recid, bdelim,sdr12->dev_slave_adr, sdr12->chan_num,bdelim,idstr); else printf("%04x SDR IPMB %02x %02x dev: %02x %02x %02x %02x %02x %s\n", sdr12->recid, sdr12->rectype, sdr12->reclen, sdr12->dev_slave_adr, sdr12->chan_num, sdr12->dev_capab, sdr12->entity_id, sdr12->entity_inst, idstr); } break; case 0x14: /* BMC Message Channel Info record */ sdr14 = (SDR14REC *)sdr; if(!fsimple){ printf("%s", tag); printf("%04x SDR BMsg %02x %02x: ", sdr14->recid, sdr14->rectype, sdr14->reclen ); for (i = 0; i < 8; i++) printf("%02x ",sdr14->mdata[i]); printf("%s %s %02x\n",decode_itype(sdr14->mint), decode_itype(sdr14->eint), sdr14->rsvd); } break; case 0xc0: /* OEM SDR record (manuf_id 343. = Intel) */ sdrc0 = (SDRc0REC *)sdr; if(!fsimple) { vend = sdrc0->manuf_id[0] + (sdrc0->manuf_id[1] << 8) + (sdrc0->manuf_id[2] << 16); printf("%s",tag); printf("%04x SDR OEM %02x %02x ", sdrc0->recid, sdrc0->rectype, sdrc0->reclen); show_oemsdr(vend,sdr); } break; default: sdrc0 = (SDRc0REC *)sdr; /* also saw type = 0x08 & 0x14 on STL2s */ if (!fsimple){ printf("%s", tag); printf("%04x SDR type=%02x ", sdrc0->recid, sdr[3]); for (i = 0; i < len; i++) printf("%02x ",sdr[i]); printf("\n"); } } return; } static int ShowPowerOnHours(void) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar cc; int rc = -1; int i; unsigned int hrs; if (fmBMC) return(0); if (fsimple) return(0); sresp = MAX_BUFFER_SIZE; memset(resp,0,6); /* default response size is 5 */ rc = ipmi_cmd_mc(GET_POWERON_HOURS, NULL, 0, resp, &sresp, &cc, fdebug); if (rc == 0 && cc == 0) { /* show the hours (32-bits) */ hrs = resp[1] | (resp[2] << 8) | (resp[3] << 16) | (resp[4] << 24); /*60=normal, more is OOB, so avoid div-by-zero*/ if ((resp[0] <= 0) || (resp[0] >= 60)) i = 1; else { i = 60 / resp[0]; hrs = hrs / i; } printf(" SDR IPMI sensor: Power On Hours \t = %d hours\n", hrs); } if (fdebug) { printf("PowerOnHours (rc=%d cc=%x len=%d): ",rc,cc,sresp); if (rc == 0) for (i = 0; i < sresp; i++) printf("%02x ",resp[i]); printf("\n"); } return(rc); } int SaveThreshold(int id, int sensor_num, int sensor_lo, int sensor_hi, uchar *thr_set) { int rv = 0; char lostr[20]; char histr[20]; FILE *fd; /* persist the thresholds by re-applying with ipmiutil sensor commands.*/ if (thr_set != NULL) { sprintf(lostr,"-u 0x%02x%02x%02x%02x%02x%02x", sensor_thr[0], sensor_thr[1], sensor_thr[2], sensor_thr[3], sensor_thr[4], sensor_thr[5]); histr[0] = 0; /*empty string*/ } else { if (sensor_lo != 0xff) { sprintf(lostr,"-l 0x%02x",sensor_lo); } else lostr[0] = 0; if (sensor_hi != 0xff) { sprintf(histr,"-h 0x%02x",sensor_hi); } else histr[0] = 0; } fd = fopen(savefile,"a+"); if (fd == NULL) return(-1); fprintf(fd, "ipmiutil sensor -i 0x%04x -n 0x%02x %s %s\n", id, sensor_num, lostr,histr); fclose(fd); return(rv); } #ifdef NOT_USED #define PICMG_GET_ADDR_INFO 0x01 static int get_picmg_addrinfo(uchar a1, uchar a2, uchar *addrdata) { uchar idata[5]; uchar rdata[16]; int rlen; ushort icmd; uchar ilen, cc; int rv; idata[0] = 0x00; idata[1] = 0x00; idata[2] = 0x03; idata[3] = a1; /* 01 thru 0f */ idata[4] = a2; /* 00, 01 thru 09 */ ilen = 5; rlen = sizeof(rdata); icmd = PICMG_GET_ADDR_INFO | (NETFN_PICMG << 8); rv = ipmi_cmd_mc(icmd, idata, ilen, rdata, &rlen, &cc, fdebug); if (rv == 0 && cc != 0) rv = cc; if (rv == 0) { if (fdebug) { printf("picmg_addr(%02x,%02x)",a1,a2); dump_buf("picmg_addr",rdata,rlen,0); } memcpy(addrdata,rdata,rlen); } return(rv); } #endif #ifdef WIN32 static int get_filesize(char *fileName, ulong *psize) { int rv; WIN32_FILE_ATTRIBUTE_DATA fileInfo; if (fileName == NULL) return -1; if (psize == NULL) return -1; rv = GetFileAttributesEx(fileName, GetFileExInfoStandard, (void*)&fileInfo); if (!rv) return -1; *psize = (long)fileInfo.nFileSizeLow; return 0; } #endif int write_sdr_binfile(char *binfile) { uchar *pbuf = NULL; FILE *fp; int len, ret; ret = get_sdr_cache(&pbuf); /* sets nsdrs, sz_sdrs */ if (ret == 0) { fp = fopen(binfile,"wb"); if (fp == NULL) { ret = get_LastError(); printf("Cannot open file %s for writing, error %d\n",binfile,ret); } else { printf("Writing SDR size %d to %s ...\n",sz_sdrs,binfile); len = (int)fwrite(pbuf, 1, sz_sdrs, fp); fclose(fp); if (len <= 0) { ret = get_LastError(); printf("Error %d writing file %s\n",ret,binfile); } else ret = 0; } free_sdr_cache(pbuf); } return(ret); } int read_sdr_binfile(char *binfile, uchar **pbufret, int *buflen) { uchar *pbuf = NULL; FILE *fp; int len; int ret; #ifdef WIN32 { ulong flen; ret = get_filesize(binfile, &flen); if (ret == 0) len = flen; else { ret = get_LastError(); printf("Cannot get file size for %s, error %d\n",binfile,ret); return(ret); } } #endif fp = fopen(binfile,"rb"); if (fp == NULL) { ret = get_LastError(); printf("Cannot open file %s, error %d\n",binfile,ret); return(ret); } fseek(fp, 0L, SEEK_SET); #ifndef WIN32 { /*not windows but Linux, etc.*/ struct stat st; /* use fstat to get file size and allocate buffer */ ret = fstat(fileno(fp), &st); len = st.st_size; /*file size in bytes*/ if (ret != 0) { ret = get_LastError(); printf("Cannot stat file %s, error %d\n",binfile,ret); return(ret); } } #endif /* Could estimate size for nsdrs*SDR_SZ, but we don't yet know nsdrs. * It is better to use the real file size detected above. */ sz_sdrs = len; pbuf = malloc(len); if (fdebug) printf("sdr_binfile: malloc(%d) pbuf=%p\n",len,pbuf); if (pbuf == NULL) { ret = -2; fclose(fp); return(ret); } psdrcache = pbuf; /*ok, so proceed with restore*/ ret = 0; len = (int)fread(pbuf, 1, sz_sdrs, fp); if (len <= 0) { ret = get_LastError(); printf("Error %d reading file %s\n",ret,binfile); sz_sdrs = 0; /*for safety*/ } else if (len < sz_sdrs) { /* Show error if this happens in Windows */ ret = get_LastError(); printf("truncated fread(%s): attempted %d, got %d, error %d\n", binfile,sz_sdrs,len,ret); ret = 0; /*try to keep going*/ } fclose(fp); if (fdebug) { printf("SDR buffer from file (len=%d,sz=%d)\n",len,sz_sdrs); dump_buf("SDR buffer",pbuf,len,1); } *pbufret = pbuf; *buflen = len; return(ret); } #ifdef ALONE #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #else /* METACOMMAND or libipmiutil */ int i_sensor(int argc, char **argv) #endif { int ret, rv; int c; int recid, recnext; uchar sdrdata[MAX_BUFFER_SIZE]; uchar devrec[16]; int sz, i, j; int fsetfound = 0; int iloop, irec; int ipass, npass; uchar *pset; char *p; char *s1; printf("%s version %s\n",progname,progver); while ( (c = getopt( argc, argv,"a:bcd:ef:g:h:i:j:k:l:m:n:opqrstu:vwxT:V:J:L:EYF:P:N:R:U:Z:?")) != EOF ) switch(c) { case 'a': /* reArm sensor number N */ if (strncmp(optarg,"0x",2) == 0) frearm = htoi(&optarg[2]); else frearm = htoi(optarg); /*was atoi()*/ break; case 'c': fsimple = 1; break; /* Canonical/simple output*/ case 'd': fdump = 1; /* Dump SDRs to a file*/ binfile = optarg; break; case 'b': fchild = 1; break; /* Bladed, so get child SDRs */ case 'e': fchild = 1; break; /* Extra bladed child SDRs */ case 'f': frestore = 1; /* Restore SDRs from a file*/ binfile = optarg; break; case 's': fsimple = 1; break; /* Simple/canonical output */ /*fcanonical==fsimple*/ case 'g': rv = get_group_id(optarg); if (rv < 0) { printf("Unrecognized sensor type group (%s)\n",optarg); ret = ERR_BAD_PARAM; goto do_exit; } else fshowgrp = rv; if (fdebug) printf("num sensor type groups = %d\n",fshowgrp); break; case 'i': fshowidx = 1; get_idx_range(optarg); break; case 'j': fjumpstart = 1; /* Load SDR cache from a file*/ binfile = optarg; break; case 'k': loopsec = atoi(optarg); break; /*N sec between loops*/ case 'm': /* specific MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; printf("set MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'o': fgetmem = 1; break; case 'n': if (strncmp(optarg,"0x",2) == 0) i = htoi(&optarg[2]); else i = htoi(optarg); /*was atoi()*/ sensor_num = (uchar)i; printf("sensor_num = 0x%x\n",sensor_num); break; case 'h': /* highest threshold */ if (strncmp(optarg,"0x",2) == 0) { i = htoi(&optarg[2]); sensor_hi = (uchar)i; fsetthresh = 1; } else { sensor_hi_f = atof(optarg); fsetthresh = 2; /*indicates float conversion*/ } break; case 'l': /* lowest threshold */ if (strncmp(optarg,"0x",2) == 0) { i = htoi(&optarg[2]); sensor_lo = (uchar)i; fsetthresh = 1; } else { sensor_lo_f = atof(optarg); fsetthresh = 2; /*indicates float conversion*/ } break; case 'p': fsavethresh = 1; break; case 'q': fshowthr = 2; fwrap = 1; break; case 'r': frawsdr = 1; break; case 't': fshowthr = 1; break; case 'v': fshowthr = 1; sens_verbose = 1; break; case 'u': /* specify unique thresholds in hex or float */ /* raw hex format: 0xLNLCLUHNHCHU, all 6 required */ if (strncmp(optarg,"0x",2) == 0) { /*raw hex thresholds*/ sensor_thr[0] = htoi(&optarg[2]); /*lo noncrit*/ sensor_thr[1] = htoi(&optarg[4]); /*lo crit*/ sensor_thr[2] = htoi(&optarg[6]); /*lo unrec*/ sensor_thr[3] = htoi(&optarg[8]); /*hi noncrit*/ sensor_thr[4] = htoi(&optarg[10]); /*hi crit*/ sensor_thr[5] = htoi(&optarg[12]); /*hi unrec*/ /* validate sensor threshold ordering */ rv = validate_thresholds(&sensor_thr[0],0,NULL); if (rv == 0) { sensor_lo = sensor_thr[0]; sensor_hi = sensor_thr[3]; fsetthresh = 3; /*indicates unique raw thresholds */ } else { ret = ERR_BAD_PARAM; goto do_exit; } } else { /* assume float input thresholds, with ':' separator*/ /* format LN:LC:LU:HN:HC:HU */ sz = strlen_(optarg); p = &optarg[0]; for (i = 0; i < 6; i++) sensor_thrf[i] = THR_EMPTY; j = 0; for (i = 0; i <= sz; i++) { if (j >= 6) break; switch(optarg[i]) { case ':': case '\n': case '\0': optarg[i] = 0; if (p[0] == 0) sensor_thrf[j] = THR_EMPTY; else sensor_thrf[j] = atof(p); if (i+1 < sz) p = &optarg[i+1]; j++; break; default: break; } } /* validate sensor threshold ordering later */ // rv = validate_thresholds(&sensor_thrf[0],1,NULL); // if (rv == 0) { sensor_lo_f = sensor_thrf[0]; sensor_hi_f = sensor_thrf[3]; fsetthresh = 4; /*indicates unique float thresholds */ // } else { // ret = ERR_BAD_PARAM; // goto do_exit; // } } /*end-else -u float thresholds*/ break; case 'w': fwrap = 1; break; case 'x': fdebug = 1; break; case 'L': /* Loop */ nloops = atoi(optarg); fdoloop = 1; break; case 'V': /* priv level */ fprivset = 1; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: /*usage*/ printf("Usage: %s [-abcdefghijlmnprstuvwxL -NUPREFTVYZ]\n",progname); printf("where -x shows eXtra debug messages\n"); printf(" -a snum reArms the sensor (snum) for events\n"); printf(" -b show Bladed child MCs for PICMG (same as -e)\n"); printf(" -c displays a simpler, Canonical output fmt\n"); printf(" -d file Dump SDRs to a binary file\n"); printf(" -e show Every bladed child MC for PICMG\n"); // printf(" -f file Restore SDRs from a binary dump file\n"); printf(" -g fan show only this sensor type group\n"); printf(" -h tval specifies the Highest threshold to set\n"); printf(" -i id only show these sensor id numbers\n"); printf(" -j file Jump-start SDR cache from a binary file\n"); printf(" -k K If -L, wait K sec between loops (default=1)\n"); printf(" -l tval specifies the Lowest threshold to set\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -n snum specifies the sensor Number to set hi/lo\n"); printf(" -o output memory DIMM information\n"); printf(" -p persist the threshold being set\n"); printf(" -q shows threshold values in d:d:d format\n"); printf(" -r show Raw SDR bytes\n"); printf(" -s displays a Simpler output format\n"); printf(" -t shows Threshold values in text format\n"); printf(" -u thr set Unique threshold values (e.g. 3:2:1:48:49:50)\n"); printf(" -v Verbose: thresholds, max/min, hysteresis\n"); printf(" -w Wrap thresholds on sensor line\n"); printf(" -L n Loop n times every k seconds (default k=1)\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto do_exit; } if (fjumpstart && fchild) { printf("Cannot use -j jumpstart cache with -c child SDRs\n"); ret = ERR_BAD_PARAM; goto do_exit; } fremote = is_remote(); #ifndef WIN32 if (fremote == 0) { /* only run this as superuser for accessing IPMI devices. */ i = geteuid(); if (i > 1) { printf("Not superuser (%d)\n", i); /* Show warning, but could be ok if /dev/ipmi0 is accessible */ //ret = ERR_NOT_ALLOWED; //goto do_exit; } } #endif if (fremote) { if (!fprivset) { /* on many systems, getting the SDR Reservation ID requires admin */ /* if ((fsetthresh != 0) || (frearm != 0)) also require admin */ parse_lan_options('V',"4",0); } } ret = ipmi_getdeviceid(devrec,sizeof(devrec),fdebug); if (ret == 0) { uchar ipmi_maj; uchar ipmi_min; char *pstr; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; if ((devrec[1] & 0x80) == 0x80) fdevsdrs = 1; vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); if (vend_id == VENDOR_NSC) { /*NSC mBMC*/ pstr = "mBMC"; fmBMC = 1; fdevsdrs = 0; } else if (vend_id == VENDOR_INTEL) { /*Intel BMC*/ /*Intel Sahalee BMC */ pstr = "BMC"; fmBMC = 0; if (is_romley(vend_id,prod_id)) fRomley = 1; if (is_grantley(vend_id,prod_id)) fGrantley = 1; if (prod_id == 0x003E || fRomley || fGrantley) /*Urbanna,CG2100*/ set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/ } else if ((vend_id == VENDOR_SUPERMICRO) || (vend_id == VENDOR_SUPERMICROX)) { set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/ } else if (vend_id == 16394) { /*Pigeon Point*/ fbadsdr = 1; /* SDR has bad sa/mc value, so ignore it */ } else { /* Other products */ pstr = "BMC"; fmBMC = 0; if (vend_id == VENDOR_NEC) fdevsdrs = 0; } show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); // "-- %s version %x.%x, IPMI version %d.%d \n", pstr, } else { goto do_exit; } ret = ipmi_getpicmg( devrec, sizeof(devrec),fdebug); if (ret == 0) fpicmg = 1; /*if not PICMG, some vendors override to SDR Rep*/ fdevsdrs = use_devsdrs(fpicmg); if (fdevsdrs) printf("supports device sdrs\n"); npass = 1; if (g_sa != 0) { /* target a specific MC via IPMB (usu a picmg blade) */ ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); fchild = 0; /* no children, only the specified address */ } else { #ifdef PICMG_CHILD /* fchild set above if -b is specified to get Blade child SDRs */ /* npass = 2 will get both SdrRep & DevSdr passes on CMM */ if (fpicmg && fdevsdrs) { npass = 2; g_addrtype = ADDR_IPMB; } #endif g_sa = BMC_SA; } if (fgetmem) { if (fremote) printf("Cannot get memory DIMM information remotely.\n"); else { int msz; char desc[80]; char szstr[25]; ret = -1; for (j = 0; j < 1; j++) { for (i = 0; i < 16; i++) { rv = get_MemDesc(j, i, desc,&msz); if (rv == 0) { if (msz == 0) strcpy(szstr,"not present"); else if (msz & 0x8000) sprintf(szstr,"size=%dKB",(msz & 0x7FFF)); else sprintf(szstr,"size=%dMB",msz); printf("Memory Device (%d,%d): %s : %s\n", j,i,desc,szstr); ret = 0; } } } } /*end-else*/ goto do_exit; } if (fdump) { ret = write_sdr_binfile(binfile); goto do_exit; } /*endif fdump*/ if (frestore) { uchar sdr[MAX_BUFFER_SIZE]; ushort id; int slen; uchar *pbuf = NULL; ret = read_sdr_binfile(binfile,&pbuf,&slen); if (ret == 0) { /*successful, so write SDRs */ nsdrs = find_nsdrs(pbuf); printf("Ready to restore %d SDRs\n",nsdrs); set_reserve(1); ret = sdr_clear_repo(fdevsdrs); if (ret != 0) { printf("SDR Clear Repository error %d\n",ret); goto do_exit; } id = 0; while(find_sdr_next(sdr,pbuf,id) == 0) { id = sdr[0] + (sdr[1] << 8); if (fdebug) printf("adding SDR[%x]\n",id); set_reserve(1); ret = sdr_add_record(sdr,fdevsdrs); if (ret != 0) { printf("SDR[%x] add error %d\n",id,ret); break; } } /*end while sdr*/ } if (ret == 0) printf("Restored %d SDRs successfully.\n",nsdrs); free_sdr_cache(pbuf); /* does nothing if (pbuf == NULL) */ goto do_exit; } /*endif frestore*/ if (fjumpstart) { uchar *pbuf = NULL; int slen; ret = read_sdr_binfile(binfile,&pbuf,&slen); if (ret != 0) { /* Try to dump sdrs to this file if not there */ ret = write_sdr_binfile(binfile); if (ret == 0) ret = read_sdr_binfile(binfile,&pbuf,&slen); if (ret != 0) { fjumpstart = 0; /*cannot do jumpstart*/ } } else { /* set this as the SDR cache */ psdrcache = pbuf; sz_sdrs = slen; nsdrs = find_nsdrs(pbuf); if (fdebug) printf("jumpstart cache: nsdrs=%d size=%d\n",nsdrs,slen); } } /*endif fjumpstart*/ for (ipass = 0; ipass < npass; ipass++) { if (fjumpstart) ; /*already got this above*/ else { ret = GetSDRRepositoryInfo(&j,&fdevsdrs); if (fdebug) printf("GetSDRRepositoryInfo: ret=%x nSDRs=%d\n",ret,j); if (ret == 0 && j == 0) { printf("SDR Repository is empty\n"); goto do_exit; } nsdrs = j; } /* show header for SDR records */ if (fsimple) printf(" ID | SDRType | Type |SNum| Name |Status| Reading\n"); else printf("_ID_ SDR_Type_xx ET Own Typ S_Num Sens_Description Hex & Interp Reading\n"); if (fwrap) chEol = ' '; if (!fdoloop) nloops = 1; for (iloop = 0; iloop < nloops; iloop++) { if (fshowidx) recid = sensor_idx1; else recid = 0; irec = 0; /*first sdr record*/ while (recid != 0xffff) { if (fjumpstart) { if (irec == 0) /*need sdr_by_id if fshowid recid>0*/ ret = find_sdr_by_id(sdrdata,psdrcache,recid); else ret = find_sdr_next(sdrdata,psdrcache,recid); if (ret != 0) { /*end of sdrs*/ if (fdebug) printf("find_sdr_next(%04x): ret = %d\n", recid,ret); ret = 0; break; } recnext = sdrdata[0] + (sdrdata[1] << 8); /*same as recid*/ if (fdebug) printf("find_sdr_next(%04x): ret = %d, next=%04x\n", recid,ret,recnext); if (recid > 0 && recnext == 0) { if (fdebug) printf("Error recid=%04x recnext=%04x\n",recid,recnext); ret = 0; break; } sz = sdrdata[4] + 5; } else { int try; for (try = 0; try < 10; try++) { ret = GetSDR(recid,&recnext,sdrdata,sizeof(sdrdata),&sz); if (fdebug) printf("GetSDR[%04x]: ret = %x, next=%x\n",recid,ret,recnext); if (ret != 0) { if (ret == 0xC5) { /* lost Reservation ID, retry */ /*fprintf(stderr,"%04x lost reservation retrying to get, try: %d, %d, rlen = %d\n", recid,try,ret,sz);*/ os_usleep((rand() & 3000),0); fDoReserve = 1; } else { fprintf(stderr,"%04x GetSDR error %d, rlen = %d\n", recid,ret,sz); break; } } else { break; } if (try==9){ sz=0; fprintf(stderr,"%04x GetSDR error %d, rlen = %d\n", recid,ret,sz); } } if (sz < MIN_SDR_SZ) { /* don't have recnext, so abort */ break; } /* else fall through & continue */ } /*end-else*/ if (ret == 0) { /* (ret == 0) OK, got full SDR */ if (fdebug) { dump_buf("got SDR",sdrdata,sz,0); } if (sz < MIN_SDR_SZ) goto NextSdr; /* if recid == 0, get real record id */ if (recid == 0) recid = sdrdata[0] + (sdrdata[1] << 8); if (fshowgrp > 0) { for (i = 0; i < fshowgrp; i++) { uchar styp; if (sdrdata[3] == 0x03) styp = sdrdata[10]; /*EvtOnly*/ else styp = sdrdata[12]; if (fdebug) printf("sdrt=%02x styp=%02x sgrp[%d]=%02x\n", sdrdata[3],styp,i,sensor_grps[i]); if (sdrdata[3] == 0xc0) continue; /*skip OEM SDRs*/ if (styp == sensor_grps[i]) break; } if (i >= fshowgrp) goto NextSdr; } if ((sensor_num == INIT_SNUM) || (sdrdata[7] == sensor_num) || fsetthresh) { /* if -n not set or if -n matches, parse and show the SDR */ ShowSDR("",sdrdata); } /* else filter SDRs if not matching -n sensor_num */ #ifdef PICMG_CHILD /* * Special logic for blade child MCs in PICMG ATCA systems * if fchild, try all child MCs within the chassis. * SDR type 12 capabilities bits (sdrdata[8]): * 80 = Chassis Device * 40 = Bridge * 20 = IPMB Event Generator * 10 = IPMB Event Receiver * 08 = FRU Device * 04 = SEL Device * 02 = SDR Repository Device * 01 = Sensor Device * But all child MCs use Device SDRs anyway. */ if (fpicmg && fchild && (sdrdata[3] == 0x12)) { /* PICMG MC DLR */ int _recid, _recnext, _sz; uchar _sdrdata[MAX_SDR_SIZE]; int devsdrs_save; uchar cc; /* save the BMC globals, use IPMB MC */ devsdrs_save = fdevsdrs; fdevsdrs = 1; /* use Device SDRs for the children*/ if (fdebug) printf(" --- IPMB MC (sa=%02x cap=%02x id=%02x devsdrs=%d):\n", sdrdata[5],sdrdata[8],sdrdata[12],fdevsdrs); fDoReserve = 1; /* get a new SDR Reservation ID */ ipmi_set_mc(PICMG_SLAVE_BUS,sdrdata[5],sdrdata[6],g_addrtype); _sz = 16; ret = ipmi_cmd_mc(GET_DEVICE_ID,NULL,0,_sdrdata,&_sz,&cc,fdebug); if (ret == 0 && cc == 0) { /* Get the SDRs from the IPMB MC */ _recid = 0; while (_recid != 0xffff) { ret = GetSDR(_recid,&_recnext,_sdrdata,sizeof(_sdrdata),&_sz); if (ret != 0) { fprintf(stderr,"%04x GetSDR error %d, rlen = %d\n",_recid,ret,_sz); break; } else if (_sz >= MIN_SDR_SZ) ShowSDR(" ",_sdrdata); if (_recnext == _recid) _recid = 0xffff; else _recid = _recnext; } /*end while*/ } /*endif ret==0*/ /* restore BMC globals */ fdevsdrs = devsdrs_save; ipmi_restore_mc(); fDoReserve = 1; /* get a new SDR Reservation ID */ } /*endif fpicmg && fchild*/ #endif if (fdebug) printf("fsetthresh=%d snum=%02x(%02x) sa=%02x(%02x)\n", fsetthresh,sdrdata[7],sensor_num,sdrdata[5],g_sa); if (fsetthresh && (sdrdata[7] == sensor_num) && (sdrdata[5] == g_sa)) /*g_sa usu is BMC_SA*/ { /* setting threshold, compute threshold raw values */ if (fsetthresh == 2) { /*set from float*/ if (fdebug) printf("lof=%.2f hif=%.2f\n", sensor_lo_f,sensor_hi_f); if (sensor_lo_f != 0) sensor_lo = FloatToRaw(sensor_lo_f,sdrdata,0); if (sensor_hi_f != 0) sensor_hi = FloatToRaw(sensor_hi_f,sdrdata,0); } else if (fsetthresh == 1) { /*raw thresholds*/ if (sensor_hi != 0xff) sensor_hi_f = RawToFloat(sensor_hi,sdrdata); if (sensor_lo != 0xff) sensor_lo_f = RawToFloat(sensor_lo,sdrdata); } else if (fsetthresh == 3) { /*unique raw thresholds*/ if (sensor_hi != 0xff) sensor_hi_f = RawToFloat(sensor_hi,sdrdata); if (sensor_lo != 0xff) sensor_lo_f = RawToFloat(sensor_lo,sdrdata); } else if (fsetthresh == 4) { /*set unique from float*/ i = fill_thresholds(&sensor_thrf[0], sdrdata); /* if (i > 0) ; * filled in some thresholds */ { /* always set lo/hi if any are non-zero */ for (j = 0; j < 3; j++) { if (sensor_thrf[j] != 0) { sensor_lo_f = sensor_thrf[j]; break; } } for (j = 3; j < 6; j++) { if (sensor_thrf[j] != 0) { sensor_hi_f = sensor_thrf[j]; break; } } } if (fdebug) printf("lof=%.2f hif=%.2f\n", sensor_lo_f,sensor_hi_f); /* convert thrf (float) to thr (raw) */ if (sensor_lo_f != 0) { sensor_lo = FloatToRaw(sensor_lo_f,sdrdata,0); sensor_thr[0] = FloatToRaw(sensor_thrf[0],sdrdata,0); sensor_thr[1] = FloatToRaw(sensor_thrf[1],sdrdata,0); sensor_thr[2] = FloatToRaw(sensor_thrf[2],sdrdata,0); } if (sensor_hi_f != 0) { sensor_hi = FloatToRaw(sensor_hi_f,sdrdata,0); sensor_thr[3] = FloatToRaw(sensor_thrf[3],sdrdata,0); sensor_thr[4] = FloatToRaw(sensor_thrf[4],sdrdata,0); sensor_thr[5] = FloatToRaw(sensor_thrf[5],sdrdata,0); } /* validate threshold ordering */ if (validate_thresholds(sensor_thrf,1,sdrdata) != 0) { ret = ERR_BAD_PARAM; goto do_exit; } } { printf("\tSetting SDR %04x sensor %02x to lo=%02x hi=%02x\n", recid,sensor_num,sensor_lo,sensor_hi); if (recid == 0) fsetfound = 1; else fsetfound = recid; } } /*endif fsetthresh */ } /*endif ok, got full SDR */ NextSdr: if (ret == ERR_SDR_MALFORMED) break; if (fjumpstart) recid = recnext; else { if (recnext == recid) recid = 0xffff; /*break;*/ else recid = recnext; } if (fshowidx) { /* if we have already read the last in the range, done. */ if (recid >= sensor_idxN) break; // recnext = 0xffff; // break; } irec++; } /*end while recid*/ if (fdoloop && (nloops > 1)) { printf("\n"); /* output an empty separator line */ os_usleep(loopsec,0); /*delay 1 sec between loops*/ } } /*end for nloops*/ if (npass > 1) { /* npass==2 for PICMG */ /* Switch fdevsdrs from Device to Repository */ if (fdevsdrs == 0) fdevsdrs = 1; else fdevsdrs = 0; fDoReserve = 1; /* get a new SDR Reservation ID */ } } /*end for npass*/ if ((fshowidx == 0) && (fshowgrp == 0)) { /* use local rv, errors are ignored for POH */ rv = ShowPowerOnHours(); } if (frearm != 0) { ret = RearmSensor((uchar)frearm); printf("RearmSensor(0x%02x) ret = %d\n",frearm,ret); } if (fsetthresh != 0) { uchar tdata[7]; if (fsetfound == 0) { printf("Did not find sensor number %02x.\nPlease enter the sensor number parameter in hex, as it is displayed above.\n",sensor_num); } ret = GetSensorThresholds(sensor_num,tdata); if (ret != 0) goto do_exit; #ifdef TEST printf("thresh(%02x): %02x %02x %02x %02x %02x %02x %02x %02x\n", sensor_num, sensor_num, tdata[0], tdata[1], tdata[2], tdata[3], tdata[4], tdata[5], tdata[6]); printf(" set(%02x): %02x %02x \n", sensor_num,sensor_lo,sensor_hi); #endif if (fsetthresh == 3 || fsetthresh == 4) { /* apply unique sensor thresholds */ pset = &sensor_thr[0]; } else pset = NULL; /* use just hi/lo */ ret = SetSensorThresholds(sensor_num,sensor_hi,sensor_lo,tdata,pset); printf("SetSensorThreshold[%02x] to lo=%02x(%4.3f) hi=%02x(%4.3f), ret = %d\n", sensor_num,sensor_lo,sensor_lo_f,sensor_hi,sensor_hi_f,ret); if (fsavethresh && ret == 0) { recid = fsetfound; rv = SaveThreshold(recid,sensor_num,sensor_lo,sensor_hi,pset); if (rv == 0) printf("Saved thresholds for sensor %02x\n",sensor_num); } fsetthresh = 0; /*only set threshold once*/ } do_exit: // if (fjumpstart) free_sdr_cache(psdrcache); /* does nothing if ==NULL*/ /* show_outcome(progname,ret); *handled in ipmiutil.c*/ ipmi_close_(); return(ret); } /* end isensor.c */ ipmiutil-3.1.9/util/isensor.c-old0000644000000000000000000036376014144515623015461 0ustar rootroot/* * isensor.c * * This tool reads the SDR records to return sensor information. * It can use either the Intel /dev/imb driver or VALinux /dev/ipmikcs. * * Author: arcress at users.sourceforge.net * Copyright (c) 2002-2006 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 07/25/02 Andy Cress created * 10/09/02 Andy Cress v1.1 added decodeValue(RawToFloat) routine * 10/11/02 Andy Cress v1.2 added expon routine * 10/30/02 Andy Cress v1.3 added SDR types 08 & 14 * 12/04/02 Andy Cress v1.4 changed dstatus descriptions * 01/29/03 Andy Cress v1.5 added MV OpenIPMI driver support * Hannes Schulz * 1) correct raw readings to floatval * 2) allow extra SDR bytes returned from HP netserver 1000r * Guo Min * add -l option for simpler list display * 02/25/03 Andy Cress v1.6 misc cleanup * 05/02/03 Andy Cress v1.7 add PowerOnHours * 07/28/03 Andy Cress v1.8 added -t option for threshold values, * added sample Discovery routine (unfinished), * added ipmi_getdeviceid for completeness. * 09/05/03 Andy Cress v1.9 show SDR OEM subtypes, * fix GetSDR multi-part get for OEM SDRs * stop if SDR Repository is empty * 09/23/03 Andy Cress v1.10 Add options to set thresholds * 10/14/03 Andy Cress v1.11 Fixed sdr offset for ShowThreshold values * 01/15/04 Andy Cress v1.12 Fixed SetThreshold to set hysteresis, * Fixed sens_cap testing in ShowThresh(Full) * 01/30/04 Andy Cress v1.13 Changed field display order, added header, * check for sdr sz below min, added WIN32. * 02/19/04 Andy Cress v1.14 Added SDR type 3 parsing for mBMC * 02/27/04 Andy Cress v1.15 Added check for superuser, more mBMC logic * 03/11/04 Andy Cress v1.16 Added & removed private mBMC code for set * thresholds due to licensing issues * 04/13/04 Andy Cress v1.17 Added -r to show raw SDRs also * 05/05/04 Andy Cress v1.18 call ipmi_close before exit, * fix sresp in GetSDR for WIN32. * 07/07/04 Andy Cress v1.19 Added -a to reArm sensor, * show debug raw reading values only in hex * 08/18/04 Andy Cress v1.20 Added decoding for DIMM status * 11/01/04 Andy Cress v1.21 add -N / -R for remote nodes, * added -U for remote username * 11/19/04 Andy Cress v1.22 added more decoding for compact reading types, * added -w option to wrap thresholds * 11/24/04 ARCress v1.23 added sens_type to display output * 12/10/04 ARCress v1.24 added support for device sdrs also, * fixed sens_cap byte, * 01/10/05 ARCress v1.25 change ShowThresh order, highest to lowest, * change signed exponent type in RawToFloat * 01/13/05 ARCress v1.26 added time display if fwrap * 01/28/05 ARCress v1.27 mod for Power Redundancy SDR status * 02/15/05 ARCress v1.28 added FloatToRaw for -h/-l threshold set funcs, * always take -n sensor_num as hex (like displayed) * 03/07/05 ARCress v1.29 added "LAN Leash Lost" decoding in decode_comp_ * added -v to show max/min & hysteresis. * 03/22/05 ARCress v1.30 added OEM subtype 0x60 for BMC TAM * 03/26/05 ARCress v1.31 added battery type to decode_comp_reading * 04/21/05 ARCress v1.32 added error message if -n sensor_num not found, * added more decoding for Power Redund sensor * 06/20/05 ARCress v1.33 if GetSDRRepository cc=0xc1 switch fdevsdrs mode, * also detect fdevsdrs better for ATCA. * 07/28/05 ARCress v1.34 check for Reading init state, * add extra byte to decode_comp_reading() * 09/12/05 ARCress v1.35 don't check superuser for fipmi_lan * 01/26/06 ARCress v1.36 added -i option to only show one sensor index * 03/14/06 ARCress v1.37 added -p option to save persistent thresholds * 04/06/06 ARCress v1.38 show auto/manual rearm * 07/17/06 ARCress v1.39 add -V, add -L, handle RepInfo rc=0xc1 * 11/28/06 ARCress v1.46 added -c -m for ATCA child MCs * 08/15/07 ARCress v1.58 filter display if -n sensor_num * 08/29/07 ARCress v1.59 fixed Battery sensor interpretation * 10/31/07 ARCress v2.3 retry GetSDR if cc=0xC5 (lost reservationID) * 01/14/08 ARCress v2.6 add -u param for setting unique thresholds, * always show float when setting thresholds, * fixup in decoding Proc,PS Comp readings * 01/25/08 ARCress v2.7 allow float input with -u thresholds, * add -p persist logic for -u thresholds. * 09/20/19 ARCress v3.15 workaround for Pigeon Point bad sa in SDR */ /*M* Copyright (c) 2002-2006 Intel Corporation. Copyright (c) 2009 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #include #include #include // for: double pow(double x, double y); #include #include #ifdef WIN32 #include #include "getopt.h" #elif defined(DOS) #include #include "getopt.h" #else #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #if defined(LINUX) #include #include #endif #include "ipmicmd.h" #include "isensor.h" #define PICMG_CHILD 1 /* show child MCs if -b */ #define MIN_SDR_SZ 8 #define SZCHUNK 16 /* SDR chunksize was 8, now 16 */ #define INIT_SNUM 0xff #define N_SGRP 16 #define THR_EMPTY 999 /* prototypes */ int get_LastError( void ); /* ipmilan.c */ extern int use_devsdrs(int picmg); /* ipmicmd.c */ extern int get_MemDesc(int array, int dimm, char *desc, int *psz); /*mem_if.c*/ extern char *get_sensor_type_desc(uchar stype); /*ievents.c*/ #ifdef METACOMMAND #include "oem_intel.h" /* void show_oemsdr_intel(uchar *sdr); in oem_intel.h */ /* int decode_sensor_intel(); in oem_intel.h */ /* int is_romley(int vend, int prod); in oem_intel.h */ extern int decode_sensor_kontron(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_kontron.c*/ extern int decode_sensor_fujitsu(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_fujitsu.c*/ extern int decode_sensor_sun(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_sun.c*/ extern int decode_sensor_supermicro(uchar *sdr,uchar *reading,char *pstring, int slen, int fsimple, char fdbg); /*see oem_supermicro.c*/ extern int decode_sensor_quanta(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_quanta.c*/ extern int decode_sensor_dell(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_dell.c*/ extern int decode_sensor_lenovo(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_lenovo.c*/ extern int decode_sensor_asus(uchar *sdr,uchar *reading,char *pstring,int slen); extern int decode_sensor_hp(uchar *sdr,uchar *reading,char *pstring, int slen); /*see oem_hp.c*/ extern void show_oemsdr_hp(uchar *sdr); #else int is_romley(int vend, int prod) { if ((vend == VENDOR_INTEL) && ((prod >= 0x0048) && (prod <= 0x005e))) return(1); return(0); } int is_grantley(int vend, int prod) { if ((vend == VENDOR_INTEL) && (prod == 0x0071)) return(1); return(0); } int is_thurley(int vend, int prod) { if ((vend == VENDOR_INTEL) && ((prod >= 0x003A) && (prod <= 0x0040))) return(1); return(0); } #endif #ifdef ALONE #define NENTID 53 static char *entity_id_str[NENTID] = { /* 00 */ "unspecified", /* 01 */ "other", /* 02 */ "unknown", /* 03 */ "processor", /* 04 */ "disk", /* 05 */ "peripheral bay", /* 06 */ "management module", /* 07 */ "system board", /* 08 */ "memory module", /* 09 */ "processor module", /* 10 */ "power supply", /* 11 */ "add-in card", /* 12 */ "front panel bd", /* 13 */ "back panel board", /* 14 */ "power system bd", /* 15 */ "drive backplane", /* 16 */ "expansion board", /* 17 */ "Other system board", /* 18 */ "processor board", /* 19 */ "power unit", /* 20 */ "power module", /* 21 */ "power distr board", /* 22 */ "chassis back panel bd", /* 23 */ "system chassis", /* 24 */ "sub-chassis", /* 25 */ "Other chassis board", /* 26 */ "Disk Drive Bay", /* 27 */ "Peripheral Bay", /* 28 */ "Device Bay", /* 29 */ "fan", /* 30 */ "cooling unit", /* 31 */ "cable/interconnect", /* 32 */ "memory device ", /* 33 */ "System Mgt Software", /* 34 */ "BIOS", /* 35 */ "Operating System", /* 36 */ "system bus", /* 37 */ "Group", /* 38 */ "Remote Mgt Comm Device", /* 39 */ "External Environment", /* 40 */ "battery", /* 41 */ "Processing blade", /* 43 */ "Processor/memory module", /* 44 */ "I/O module", /* 45 */ "Processor/IO module", /* 46 */ "Mgt Controller Firmware", /* 47 */ "IPMI Channel", /* 48 */ "PCI Bus", /* 49 */ "PCI Express Bus", /* 50 */ "SCSI Bus", /* 51 */ "SATA/SAS bus", /* 52 */ "Processor FSB" }; char *decode_entity_id(int id) { if (id < NENTID) return (""); else return(entity_id_str[id]); } #else /* char *decode_entity_id(int id); *isensor.h, from ievents.c*/ #endif /************************ * Global Data ************************/ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil sensor"; #else static char * progver = "3.15"; static char * progname = "isensor"; #endif #ifdef WIN32 static char savefile[] = "%ipmiutildir%\\thresholds.cmd"; #else static char savefile[] = "/var/lib/ipmiutil/thresholds.sh"; // static char savefile[] = "/usr/share/ipmiutil/thresholds.sh"; #endif extern char fdebug; /*from ipmicmd.c*/ int sens_verbose = 0; /* =1 show max/min & hysteresis also */ static int fdevsdrs = 0; static int fReserveOK = 1; static int fDoReserve = 1; static int fsimple = 0; /*=1 simple, canonical output*/ static int fshowthr = 0; /* =1 show thresholds, =2 show thr in ::: fmt */ static int fwrap = 0; static int frawsdr = 0; static int frearm = 0; static int fshowidx = 0; /* only show a specific SDR index/range */ static int fshowgrp = 0; /* =1 show group of sensors by sensor type */ static int fdoloop = 0; /* =1 if user specified number of loops */ static int fpicmg = 0; static int fchild = 0; /* =1 show child SDRs */ static int fset_mc = 0; /* =1 -m to set_mc */ static int fbadsdr = 0; /* =1 to ignore bad SDR mc */ static int fdump = 0; static int frestore = 0; static int fjumpstart = 0; static int fgetmem = 0; static int fprivset = 0; static char fremote = 0; static int nloops = 1; /* num times to show repeated sensor readings */ static int loopsec = 1; /* wait N sec between loops, default 1 */ static char bdelim = BDELIM; /* delimiter for canonical output */ static char tmpstr[20]; /* temp string */ static char *binfile = NULL; static int fsetthresh = 0; static int fsavethresh = 0; static uchar sensor_grps[N_SGRP] = {0, 0}; /*sensor type groups*/ static ushort sensor_idx1 = 0xffff; static ushort sensor_idxN = 0xffff; static uchar sensor_num = INIT_SNUM; static uchar sensor_hi = 0xff; static uchar sensor_lo = 0xff; static uchar sensor_thr[6] = {0,0,0,0,0,0}; static double sensor_thrf[6] = {0,0,0,0,0,0}; static double sensor_hi_f = 0; static double sensor_lo_f = 0; static int fmBMC = 0; static int fRomley = 0; static int fGrantley = 0; static char chEol = '\n'; /* newline by default, space if option -w */ static uchar resid[2] = {0,0}; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = 0; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int vend_id = 0; static int prod_id; /* sensor_dstatus * This is used to decode the sensor reading types and meanings. * Use IPMI Table 36-1 and 36-2 for this. */ #define N_DSTATUS 101 #define STR_CUSTOM 58 #define STR_OEM 71 #define STR_AC_LOST 76 #define STR_PS_FAIL 77 #define STR_PS_CONFIG 78 #define STR_HSC_OFF 79 #define STR_REBUILDING 80 #define STR_OTHER 81 static char oem_string[50] = "OEM"; static char *sensor_dstatus[N_DSTATUS] = { /* 0 00h */ "OK ", /* Threshold event states */ /* 1 01h */ "Warn-lo", // "Warning-lo", /* 2 02h */ "Crit-lo", // "Critical-lo", /* 3 04h */ "BelowCrit", // "BelowCrit-lo", /* 4 08h */ "Warn-hi", // "Warning-hi", /* 5 10h */ "Crit-hi", // "Critical-hi", /* 6 20h */ "AboveCrit", // "AboveCrit-hi", /* 7 40h */ "Init ", /*in init state, no reading*/ /* 8 80h */ "OK* ", /* Hotswap Controller event states, also Availability */ /* 9 HSC */ "Present", /*present,inserted*/ /*10 HSC */ "Absent", /*absent,removed,empty,missing*/ /*11 HSC */ "Ready", /*12 HSC */ "Faulty", /* Digital/Discrete event states */ /*13 D-D */ "Asserted", /*14 D-D */ "Deassert", /*15 D-D */ "Predict ", /* Availability event states */ /*16 Avl */ "Disabled", /*17 Avl */ "Enabled ", /*18 Avl */ "Redundant", /*19 Avl */ "RedunLost", /*20 Avl */ "RedunDegr", /* ACPI Device Power States */ /*21 ACPI*/ "Off ", /*D3*/ /*22 ACPI*/ "Working", /*D1*/ /*23 ACPI*/ "Sleeping", /*D2/S2*/ /*24 ACPI*/ "On", /*D0*/ /* Critical Interrupt event states */ /*25 CrI */ "FP_NMI ", /*26 CrI */ "Bus_TimOut", /*27 CrI */ "IOch_NMI", /*28 CrI */ "SW_NMI ", /*29 CrI */ "PCI_PERR", /*30 CrI */ "PCI_SERR", /*31 CrI */ "EISA_TimOut", /*32 CrI */ "Bus_Warn ", /*Correctable*/ /*33 CrI */ "Bus_Error", /*Uncorrectable*/ /*34 CrI */ "Fatal_NMI", /*35 CrI */ "Bus_Fatal", /*0x0A*/ /*36 CrI */ "Bus_Degraded", /*0x0B*/ /* Physical Security event states */ /*37 Phys*/ "LanLeashLost", /*38 Phys*/ "ChassisIntrus", /* Memory states */ /*39 Mem */ "ECCerror", /*40 Mem */ "ParityErr", /* Discrete sensor invalid readings (error or init state) */ /*41 D-D */ "Unknown", /*42 D-D */ "NotAvailable", /* Discrete sensor OEM reading states */ /*43 OEM */ "Enabled ", /*44 OEM */ "Disabled", /* Session Audit states */ /*45 OEM */ "Activated ", /*46 OEM */ "Deactivated", /*47 HSC */ "Unused ", /* Processor event states */ /*48 Proc*/ "IERR", /*49 Proc*/ "ThermalTrip", /*50 Proc*/ "FRB1Failure", /*51 Proc*/ "FRB2Failure", /*52 Proc*/ "FRB3Failure", /*53 Proc*/ "ConfigError", /*54 Proc*/ "SMBIOSError", /*55 Proc*/ "ProcPresent", /*56 Proc*/ "ProcDisabled", /*57 Proc*/ "TermPresent", /* Custom data string, 15 bytes */ /*58 Custom*/ "CustomData12345", /* Event Log */ /*59 EvLog*/ "MemLogDisab", /*60 EvLog*/ "TypLogDisab", /*61 EvLog*/ "LogCleared", /*62 EvLog*/ "AllLogDisab", /*63 EvLog*/ "SelFull", /*64 EvLog*/ "SelNearFull", /* more Digital Discrete */ /*65 D-D */ "Exceeded", /*66 Alert*/ "AlertPage", /*67 Alert*/ "AlertLAN", /*68 Alert*/ "AlertPET", /*69 Alert*/ "AlertSNMP", /*70 Alert*/ "None", /*71 OEM str*/ &oem_string[0], /* Version Change */ /*72 Change*/ "HW Changed", /*73 Change*/ "SW Changed", /*74 Change*/ "HW incompatibility", /*75 Change*/ "Change Error", /* Power Supply event states */ /*76 PS */ "AC_Lost ", /*77 PS */ "PS_Failed", /* Power Supply event states */ /*78 PS */ "Config_Err", /*79 HSC */ "Offline", /*80 HSC */ "Rebuilding", /*81 other*/ " _ ", /*82 Avl */ "NonRedund_Sufficient", /*83 Avl */ "NonRedund_Insufficient", /*84 Usage */ "Idle", /*85 Usage */ "Active", /*86 Usage */ "Busy", /*87 Trans */ "Non-Critical", /*88 Trans */ "Critical", /*89 Trans */ "Non-Recoverable", /*90 Trans */ "Monitor", /*91 Trans */ "Informational", /*92 State */ "Running", /*93 State */ "In_Test", /*94 State */ "Power_Off", /*95 State */ "Online", /*96 State */ "Offline", /*97 State */ "Off_Duty", /*98 State */ "Degraded", /*99 State */ "PowerSave", /*100 State */ "InstallError" }; static char *raid_states[9] = { /*for sensor type 0x0d drive status */ "Faulty", "Rebuilding", "InFailedArray", "InCriticalArray", "ParityCheck", "PredictedFault", "Un-configured", "HotSpare", "NoRaid" }; #define NSENSTYPES 0x2a #ifdef OLD /* see ievents.c */ static const char *sensor_types[NSENSTYPES] = { /*IPMI 2.0 Table 42-3*/ /* 00h */ "reserved", /* 01h */ "Temperature", /* 02h */ "Voltage", /* 03h */ "Current", /* 04h */ "Fan", /* 05h */ "Platform Chassis Intrusion", /* 06h */ "Platform Security Violation", /* 07h */ "Processor", /* 08h */ "Power Supply", /* 09h */ "Power Unit", /* 0Ah */ "Cooling Device", /* 0Bh */ "FRU Sensor", /* 0Ch */ "Memory", /* 0Dh */ "Drive Slot", /* 0Eh */ "POST Memory Resize", /* 0Fh */ "System Firmware", /* 10h */ "SEL Disabled", /* 11h */ "Watchdog 1", /* 12h */ "System Event", /* offset 0,1,2 */ /* 13h */ "Critical Interrupt", /* offset 0,1,2 */ /* 14h */ "Button", /* offset 0,1,2 */ /* 15h */ "Board", /* 16h */ "Microcontroller", /* 17h */ "Add-in Card", /* 18h */ "Chassis", /* 19h */ "Chip Set", /* 1Ah */ "Other FRU", /* 1Bh */ "Cable / Interconnect", /* 1Ch */ "Terminator", /* 1Dh */ "System Boot Initiated", /* 1Eh */ "Boot Error", /* 1Fh */ "OS Boot", /* 20h */ "OS Critical Stop", /* 21h */ "Slot / Connector", /* 22h */ "ACPI Power State", /* 23h */ "Watchdog 2", /* 24h */ "Platform Alert", /* 25h */ "Entity Presence", /* 26h */ "Monitor ASIC", /* 27h */ "LAN", /* 28h */ "Management Subsystem Health", /* 29h */ "Battery", }; #endif #define NUNITS 30 static char *unit_types[] = { /* 00 */ "unspecified", /* 01 */ "degrees C", /* 02 */ "degrees F", /* 03 */ "degrees K", /* 04 */ "Volts", /* 05 */ "Amps", /* 06 */ "Watts", /* 07 */ "Joules", /* 08 */ "Coulombs", /* 09 */ "VA", /* 10 */ "Nits", /* 11 */ "lumen", /* 12 */ "lux", /* 13 */ "Candela", /* 14 */ "kPa", /* 15 */ "PSI", /* 16 */ "Newton", /* 17 */ "CFM", /* 18 */ "RPM", /* 19 */ "Hz", /* 20 */ "microseconds", /* 21 */ "milliseconds", /* 22 */ "seconds", /* 23 */ "minutes", /* 24 */ "hours", /* 25 */ "days", /* 26 */ "weeks", /* 27 */ "mil", /* 28 */ "inches", /* 29 */ "feet", /* 42 */ "cycles" }; /* 68 * "megabit", */ /* 72 * "megabyte", */ /* 90 * "uncorrectable error" (last defined)*/ static char *unit_types_short[] = { /* 00 */ "?", /*unknown, not specified*/ /* 01 */ "C", /* 02 */ "F", /* 03 */ "K", /* 04 */ "V", /* 05 */ "A", /* 06 */ "W", /* 07 */ "J", /* 08 */ "Coul", /* 09 */ "VA", /* 10 */ "Nits", /* 11 */ "lumen", /* 12 */ "lux", /* 13 */ "Cand", /* 14 */ "kPa", /* 15 */ "PSI", /* 16 */ "Newton", /* 17 */ "CFM", /* 18 */ "RPM", /* 19 */ "Hz", /* 20 */ "usec", /* 21 */ "msec", /* 22 */ "sec", /* 23 */ "min", /* 24 */ "hrs", /* 25 */ "days", /* 26 */ "wks", /* 27 */ "mil", /* 28 */ "in", /* 29 */ "ft", /* 42 */ "cyc" }; ushort parse_idx(char *str) { int i, n; char istr[5]; if (strncmp(str,"0x",2) == 0) str += 2; n = strlen_(str); if (n == 4) { i = (htoi(str) << 8) + htoi(&str[2]); } else if (n == 3) { istr[0] = '0'; memcpy(&istr[1],str,3); i = (htoi(istr) << 8) + htoi(&istr[2]); } else i = htoi(str); /*was atoi()*/ printf("idx = 0x%x\n",i); return((ushort)i); } int get_idx_range(char *str) { // int i = 0; char *p; p = strchr(str,'-'); if (p == NULL) p = strchr(str,','); if (p != NULL) { *p = 0; p++; sensor_idx1 = parse_idx(str); sensor_idxN = parse_idx(p); } else { sensor_idx1 = parse_idx(str); sensor_idxN = sensor_idx1; } return(0); } char *get_unit_type(int iunits, int ibase, int imod, int fshort) { char *pstr = NULL; char **punittypes; static char unitstr[32]; int jbase, jmod; uchar umod; punittypes = unit_types; if (fshort) punittypes = unit_types_short; if (fdebug) printf("get_unit_type(%x,%d,%d,%d)\n",iunits,ibase,imod,fshort); umod = (iunits & 0x06) >> 1; if (ibase < NUNITS) jbase = ibase; else { if (fdebug) printf("units base %02x > %d\n",ibase,NUNITS); if (ibase == 42) jbase = NUNITS; /*"cycles"*/ else jbase = 0; } if (imod < NUNITS) jmod = imod; else { if (fdebug) printf("units mod %02x > %d\n",imod,NUNITS); jmod = 0; } switch (umod) { case 2: snprintf(unitstr,sizeof(unitstr),"%s * %s", punittypes[jbase],punittypes[jmod]); pstr = unitstr; break; case 1: snprintf(unitstr,sizeof(unitstr),"%s/%s", punittypes[jbase],punittypes[jmod]); pstr = unitstr; break; case 0: default: pstr = punittypes[jbase]; break; } if ((umod == 0) && (iunits > 0)) { /* special cases for other SensorUnits1 bits */ if ((iunits & 0x01) != 0) { /*percentage*/ if (fshort) pstr = "%"; else pstr = "percent"; } else if (iunits == 0xC0) { /*no analog reading*/ pstr = "na"; } else if (iunits == 0x18) { /* For Tyan fans: base=42, units=24.(0x18) -> cycles/hour */ snprintf(unitstr,sizeof(unitstr),"%s/hour",punittypes[jbase]); pstr = unitstr; } } return(pstr); } char *decode_capab(uchar c) { static char cstr[50]; char *arm; char *thr; char *evt; // char *hys; uchar b; /* decode sens_capab bits */ if ((c & 0x40) == 0) arm = "man"; /*manual rearm*/ else arm = "auto"; /*automatic rearm*/ /* skip hysteresis bits (0x30) */ b = ((c & 0x0c) >> 2); switch(b) { case 0x00: thr = "none"; break; /*no thresholds*/ case 0x01: thr = "read"; break; case 0x02: thr = "write"; break; /*read & write*/ case 0x03: default: thr = "fixed"; break; } b = (c & 0x03) ; switch(b) { case 0x00: evt = "state"; break; /*threshold or discrete state*/ case 0x01: evt = "entire"; break; /*entire sensor only*/ case 0x02: evt = "disab"; break; /*global disable only*/ case 0x03: default: evt = "none"; break; /*no events*/ } sprintf(cstr,"arm=%s thr=%s evts=%s",arm,thr,evt); return(cstr); } int get_group_id(char *pstr) { int i, j, n, sz, len; char *p; int rv = -1; sz = strlen_(pstr); p = &pstr[0]; n = 0; for (i = 0; i <= sz; i++) { if (n >= N_SGRP) break; switch(pstr[i]) { case ',': /*delimiter*/ case '\n': case '\0': pstr[i] = 0; /*stringify this word*/ len = strlen_(p); for (j = 0; j < NSENSTYPES; j++) { if (strncasecmp(get_sensor_type_desc(j),p,len) == 0) { sensor_grps[n++] = (uchar)j; rv = 0; break; } } /*endfor(j)*/ if (i+1 < sz) p = &pstr[i+1]; /*set p for next word*/ if (j >= NSENSTYPES) { /* sensor type not found */ rv = -1; i = sz; /*exit loop*/ } break; default: break; } /*end switch*/ } /*end for(i)*/ if (rv == 0) rv = n; else rv = -1; return(rv); } static int validate_thresholds(void *pthrs, char flag, uchar *sdr) { double *thrf; uchar *thr; int rv = 0; uchar bits; if (sdr == NULL) bits = 0xff; /*assume all are used*/ else bits = sdr[18]; /*18=indicates which are readable/used */ if (bits == 0) { printf("No threshold values can be set for this sensor.\n"); return(3); } if (flag == 1) { /*float*/ thrf = (double *)pthrs; if (fdebug) printf("validate_thresh: bits=%02x, values: %f>=%f>=%f, %f<=%f<=%f\n", bits, thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]); if ((bits & 0x02) != 0) { /*thrf[1] lo-crit is valid*/ if ((thrf[1] > thrf[0]) && ((bits & 0x01) != 0)) rv = 1; if ((thrf[2] > thrf[1]) && ((bits & 0x04) != 0)) rv = 1; /*lo is wrong*/ } if ((bits & 0x10) != 0) { /*thrf[4] hi-crit is valid*/ if ((thrf[4] < thrf[3]) && ((bits & 0x08) != 0)) rv = 2; if ((thrf[5] < thrf[4]) && ((bits & 0x20) != 0)) rv = 2; /*hi is wrong*/ } if (rv != 0) { printf("Threshold values: %f>=%f>=%f, %f<=%f<=%f\n", thrf[0], thrf[1], thrf[2], thrf[3], thrf[4], thrf[5]); printf("Invalid threshold order in %s range.\n", ((rv == 1)? "lo": "hi")); } } else { thr = (uchar *)pthrs; if ((bits & 0x02) != 0) { /*thr[1] lo-crit is valid*/ if ((thr[1] > thr[0]) && ((bits & 0x01) != 0)) rv = 1; if ((thr[2] > thr[1]) && ((bits & 0x04) != 0)) rv = 1; /*lo is wrong*/ } if ((bits & 0x10) != 0) { /*thr[4] hi-crit is valid*/ if ((thr[4] < thr[3]) && ((bits & 0x08) != 0)) rv = 2; if ((thr[5] < thr[4]) && ((bits & 0x20) != 0)) rv = 2; /*hi is wrong*/ } if (rv != 0) { printf("Threshold values: %02x>=%02x>=%02x %02x<=%02x<=%02x\n", thr[0], thr[1], thr[2], thr[3], thr[4], thr[5]); printf("Invalid threshold order within -u (%s)\n", ((rv == 1)? "lo": "hi")); } } return(rv); } int GetSDRRepositoryInfo(int *nret, int *fdev) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; int rc; int nSDR; int freespace; ushort cmd; uchar cc = 0; int i; memset(resp,0,6); /* init first part of buffer */ if (nret != NULL) *nret = 0; if (fdev != NULL) fdevsdrs = *fdev; if (fdevsdrs) cmd = GET_DEVSDR_INFO; else cmd = GET_SDR_REPINFO; rc = ipmi_cmd_mc(cmd, NULL, 0, resp,&sresp, &cc, fdebug); if (fdebug) printf("ipmi_cmd[%04x] repinf(%d) status=%d cc=%x\n", cmd, fdevsdrs,rc,cc); /* some drivers return cc in rc */ if ((rc == 0xc1) || (rc == 0xd4)) cc = rc; else if (rc != 0) return(rc); if (cc != 0) { if ((cc == 0xc1) || /*0xC1 (193.) means unsupported command */ (cc == 0xd4)) /*0xD4 means insufficient privilege (Sun/HP)*/ { /* Must be reporting wrong bit for fdevsdrs, * so switch & retry */ if (fdevsdrs) { fdevsdrs = 0; cmd = GET_SDR_REPINFO; } else { fdevsdrs = 1; cmd = GET_DEVSDR_INFO; } sresp = MAX_BUFFER_SIZE; rc = ipmi_cmd_mc(cmd, NULL, 0, resp,&sresp, &cc, fdebug); if (fdebug) printf("ipmi_cmd[%04x] repinf status=%d cc=%x\n",cmd,rc,cc); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); } else return(cc); } if (fdevsdrs) { nSDR = resp[0]; freespace = 1; fReserveOK = 1; } else { nSDR = resp[1] + (resp[2] << 8); freespace = resp[3] + (resp[4] << 8); if ((resp[13] & 0x02) == 0) fReserveOK = 0; else fReserveOK = 1; } if (nret != NULL) *nret = nSDR; if (fdev != NULL) *fdev = fdevsdrs; if (fdebug) { //successful, show data printf("SDR Repository (len=%d): ",sresp); for (i = 0; i < sresp; i++) printf("%02x ",resp[i]); printf("\n"); printf("SDR Info: fdevsdrs=%d nSDRs=%d free space = %x ReserveOK=%d\n", fdevsdrs,nSDR,freespace,fReserveOK); } return(0); } /*end GetSDRRepositoryInfo()*/ int GetSensorThresholds(uchar sens_num, uchar *thr_data) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[6]; int rc; uchar cc = 0; inputData[0] = sens_num; rc = ipmi_cmd_mc(GET_SENSOR_THRESHOLD, inputData,1, resp,&sresp, &cc,fdebug); if (fdebug) printf("GetSensorThreshold[%02x] rc = %d, resp(%d) %02x %02x %02x %02x %02x %02x %02x\n", sens_num,rc, sresp,resp[0],resp[1],resp[2],resp[3], resp[4],resp[5],resp[6]); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); if (sresp == 0) return(-2); memcpy(thr_data,resp,sresp); return(0); } int RearmSensor(uchar sens_num) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[8]; int rc; uchar cc = 0; memset(inputData,0,6); memset(resp,0,6); inputData[0] = sens_num; rc = ipmi_cmd_mc(GET_SEVT_ENABLE, inputData, 1, resp,&sresp, &cc, fdebug); if (rc == 0 && cc != 0) rc = cc; if (rc != 0 || fdebug) printf("GetSensorEventEnable(%02x) rc = %d, cc = %x %02x %02x %02x\n", sens_num,rc,cc,resp[0],resp[1],resp[3]); if (rc == 0 && resp[0] != 0xc0) { printf("EventEnable(%02x) = %02x, is not 0xc0\n", sens_num,resp[0]); memset(inputData,0,6); inputData[0] = sens_num; inputData[1] = resp[0] | 0xc0; inputData[2] = resp[1]; inputData[3] = resp[2]; inputData[4] = resp[3]; inputData[5] = resp[4]; rc = ipmi_cmd_mc(SET_SEVT_ENABLE, inputData, 6, resp,&sresp, &cc, fdebug); if (rc == 0 && cc != 0) rc = cc; if (rc != 0 || fdebug) printf("SetSensorEventEnable(%02x) rc = %d, cc = %x\n", sens_num,rc,cc); } memset(inputData,0,6); inputData[0] = sens_num; inputData[1] = 0; /* rearm all events for this sensor */ rc = ipmi_cmd_mc(REARM_SENSOR, inputData, 6, resp,&sresp, &cc, fdebug); if (fdebug) printf("RearmSensor(%02x) rc = %d, cc = %x %02x %02x\n", sens_num,rc,cc,resp[0],resp[1]); if (rc == 0 && cc != 0) rc = cc; /* Could also do a global rearm via SetEventReceiver. */ return(rc); } /*end RearmSensor*/ int SetSensorThresholds(uchar sens_num, uchar hi, uchar lo, uchar *thr_data, uchar *thr_set) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[8]; int rc; uchar cc = 0; uchar sets = 0; int i; /* * Set the sensor Hysteresis before setting the threshold. */ memset(inputData,0,8); inputData[0] = sens_num; inputData[1] = 0xff; rc = ipmi_cmd_mc(GET_SENSOR_HYSTERESIS,inputData,2, resp,&sresp, &cc,fdebug); if (fdebug) printf("GetSensorHysteresis(%02x) rc = %d, cc = %x %02x %02x\n", sens_num,rc,cc,resp[0],resp[1]); if (rc != ACCESS_OK) return(rc); inputData[0] = sens_num; inputData[1] = 0xff; inputData[2] = resp[0]; inputData[3] = resp[1]; rc = ipmi_cmd_mc(SET_SENSOR_HYSTERESIS,inputData,4, resp,&sresp, &cc,fdebug); if (fdebug) printf("SetSensorHysteresis(%02x) rc = %d, cc = %x\n", sens_num,rc,cc); if (rc != ACCESS_OK) return(rc); /* * The application should validate that values are ordered, * e.g. upper critical should be greater than upper * non-critical. * Due to the limited command line parameter interface, * use the hi & lo values to set each of the thresholds. * For a full implemenation, these thresholds should be set * individually. */ memset(inputData,0,8); inputData[0] = sens_num; sets = thr_data[0]; if (thr_set != NULL) { /* use specific thr_set values */ memcpy(&inputData[2],thr_set,6); } else { /*default, use hi/lo params */ if (lo == 0xff) sets &= 0x38; /* don't set lowers */ else { inputData[2] = lo; /* lower non-crit (& 0x01) */ inputData[3] = lo - 1; /* lower critical (& 0x02) */ inputData[4] = lo - 2; /* lower non-recov (& 0x04) */ } if (hi == 0xff) sets &= 0x07; /* don't set uppers */ else { inputData[5] = hi; /* upper non-crit (& 0x08) */ inputData[6] = hi + 1; /* upper critical (& 0x10) */ inputData[7] = hi + 2; /* upper non-recov (& 0x20) */ } } inputData[1] = sets; /* which ones to set */ { /* show from/to changes */ printf("GetThreshold[%02x]: %02x ",sens_num,sens_num); for (i = 0; i < 7; i++) printf("%02x ",thr_data[i]); printf("\n"); printf("SetThreshold[%02x]: ",sens_num); for (i = 0; i < 8; i++) printf("%02x ",inputData[i]); printf("\n"); } rc = ipmi_cmd_mc(SET_SENSOR_THRESHOLD, inputData, 8, resp,&sresp, &cc, fdebug); if (fdebug) printf("SetSensorThreshold(%02x) rc = %d, cc = %x\n", sens_num,rc,cc); if (rc == 0 && cc != 0) rc = cc; /* mBMC gets cc = 0xD5 (213.) here, setting thresholds disabled. */ return(rc); } int GetSensorReading(uchar sens_num, void *psdr, uchar *sens_data) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[6]; SDR02REC *sdr = NULL; int mc; int rc; uchar cc = 0; uchar lun = 0; uchar chan = 0; if (psdr != NULL && fbadsdr == 0) { sdr = (SDR02REC *)psdr; mc = sdr->sens_ownid; if (mc != BMC_SA) { /* not BMC, e.g. HSC or ME sensor */ uchar a = ADDR_IPMB; if (mc == HSC_SA) a = ADDR_SMI; chan = (sdr->sens_ownlun & 0xf0) >> 4; lun = (sdr->sens_ownlun & 0x03); ipmi_set_mc(chan,(uchar)mc, lun,a); } } else mc = BMC_SA; inputData[0] = sens_num; rc = ipmi_cmd_mc(GET_SENSOR_READING,inputData,1, resp,&sresp,&cc,fdebug); if (fdebug) printf("GetSensorReading mc=%x,%x,%x status=%d cc=%x sz=%d resp: %02x %02x %02x %02x\n", chan,mc,lun,rc,cc,sresp,resp[0],resp[1],resp[2],resp[3]); if (mc != BMC_SA) ipmi_restore_mc(); if ((rc == 0) && (cc != 0)) { if (fdebug) printf("GetSensorReading error %x %s\n",cc, decode_cc((ushort)0,(uchar)cc)); rc = cc; } if (rc != 0) return(rc); if (resp[1] & 0x20) { /* init state, reading invalid */ if (fdebug) printf("sensor[%x] in init state, no reading\n", sens_num); sens_data[1] = resp[1]; sens_data[2] = 0x40; /*set bit num for init state*/ } else { /*valid reading, copy it*/ /* only returns 4 bytes, no matter what type */ memcpy(sens_data,resp,4); } return(0); } /*end GetSensorReading()*/ int GetSensorReadingFactors(uchar snum, uchar raw, int *m, int *b, int * b_exp, int *r, int *a) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[6]; int rc; uchar cc = 0; int toler, a_exp; inputData[0] = snum; inputData[1] = raw; rc = ipmi_cmd_mc(GET_SENSOR_READING_FACTORS, inputData, 2, resp,&sresp, &cc, fdebug); if (fdebug) printf("GetSensorReadingFactors status = %d\n",rc); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); /* successful, copy values */ *m = resp[1] + ((resp[2] & 0xc0) << 2); toler = resp[2] & 0x3f; *b = resp[3] + ((resp[4] & 0xc0) << 2); *a = (resp[4] & 0x3f) + ((resp[5] & 0xf0) << 4); a_exp = (resp[5] & 0xc0) >> 2; *r = (resp[6] &0xf0) >> 4; *b_exp = resp[6] & 0x0f; if (fdebug) { printf("factors: next=%x m=%d b=%d b_exp=%d a=%d a_exp=%d r=%d\n", resp[0],*m,*b,*b_exp,*a,a_exp,*r); } return(0); } int GetSensorType(uchar snum, uchar *stype, uchar *rtype) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar inputData[6]; int rc; uchar cc = 0; inputData[0] = snum; rc = ipmi_cmd_mc(GET_SENSOR_TYPE, inputData, 1, resp,&sresp, &cc, fdebug); if (fdebug) printf("GetSensorType: ipmi_cmd rv = %d, cc = %x\n",rc,cc); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); /* successful, copy values */ if (stype != NULL) *stype = resp[0]; if (rtype != NULL) *rtype = resp[1] & 0x7f; return(rc); } void set_reserve(int val) { fDoReserve = val; } int sdr_get_reservation(uchar *res_id, int fdev) { int sresp; uchar resp[MAX_BUFFER_SIZE]; uchar cc = 0; ushort cmd; int rc = -1; if (fDoReserve == 1) { fDoReserve = 0; /* only reserve SDR the first time */ sresp = sizeof(resp);; if (fdev) cmd = RESERVE_DEVSDR_REP; else cmd = RESERVE_SDR_REP; rc = ipmi_cmd_mc(cmd, NULL, 0, resp, &sresp, &cc, fdebug); if (rc == 0 && cc != 0) rc = cc; if (rc == 0) { /* ok, so set the reservation id */ resid[0] = resp[0]; resid[1] = resp[1]; } /* A reservation is cancelled by the next reserve request. */ if (fdebug) printf("ipmi_cmd RESERVE status=%d cc=%x id=%02x%02x\n", rc,cc,resid[0],resid[1]); } else rc = 0; /* if not first time, or if error, return existing resid. */ res_id[0] = resid[0]; res_id[1] = resid[1]; return(rc); } /*end sdr_get_reservation*/ int sdr_clear_repo(int fdev) { int sresp; uchar resp[MAX_BUFFER_SIZE]; uchar inputData[6]; uchar cc = 0; int rc = -1; ushort cmd; uchar resv[2] = {0,0}; if (fReserveOK) rc = sdr_get_reservation(resv,fdev); cmd = 0x27 + (NETFN_STOR << 8); /*Clear SDR Repository*/ inputData[0] = resv[0]; /*res id LSB*/ inputData[1] = resv[1]; /*res id MSB*/ inputData[2] = 'C'; inputData[3] = 'L'; inputData[4] = 'R'; inputData[5] = 0xAA; sresp = sizeof(resp);; rc = ipmi_cmd_mc(cmd, inputData, 6, resp, &sresp,&cc, fdebug); if (fdebug) printf("sdr_clear_repo: rc = %d, cc = %x, sz=%d\n",rc,cc,sresp); if (rc == 0 && cc != 0) rc = cc; if (rc == 0 && (resp[0] & 1) != 1) { if (fdebug) printf("Wait for sdr_clear_repo to complete\n"); os_usleep(1,0); } return(rc); } int sdr_add_record(uchar *sdr, int fdev) { int sresp; uchar resp[MAX_BUFFER_SIZE]; uchar inputData[6+SZCHUNK]; uchar cc = 0; int rc = -1; ushort cmd; uchar resv[2] = {0,0}; int reclen, len, i; int recid, chunksz; uchar prog; reclen = sdr[4] + 5; recid = sdr[0] + (sdr[1] << 8); /* OEM SDRs can be min 8 bytes, less is an error. */ if (reclen < 8) return(LAN_ERR_BADLENGTH); if (fReserveOK) rc = sdr_get_reservation(resv,fdev); if (fdebug) printf("sdr_add_record[%x]: reclen = %d, reserve rc = %d\n", recid,reclen,rc); cmd = 0x25 + (NETFN_STOR << 8); /*PartialAddSdr*/ recid = 0; /*first chunk must be added as 0000*/ chunksz = SZCHUNK; for (i = 0; i < reclen; ) { prog = 0; len = chunksz; if ((i+chunksz) >= reclen) { /*last record*/ len = reclen - i; prog = 1; } inputData[0] = resv[0]; /*res id LSB*/ inputData[1] = resv[1]; /*res id MSB*/ inputData[2] = recid & 0x00ff; /*record id LSB*/ inputData[3] = (recid >> 8) & 0x00ff; /*record id MSB*/ inputData[4] = (uchar)i; /*offset */ inputData[5] = prog; /*progress: 1=last record*/ memcpy(&inputData[6],&sdr[i],len); sresp = sizeof(resp); rc = ipmi_cmd_mc(cmd, inputData, 6+len, resp, &sresp,&cc, fdebug); if (fdebug) printf("sdr_add_record[%x,%x]: rc = %d, cc = %x, sz=%d\n", recid,i,rc,cc,sresp); if (rc == 0 && cc != 0) rc = cc; if (rc != 0) break; if (recid == 0 && rc == 0) /*first time, so set recid*/ recid = resp[0] + (resp[1] << 8); i += len; } return(rc); } int GetSDR(int r_id, int *r_next, uchar *recdata, int srecdata, int *rlen) { int sresp; uchar resp[MAX_BUFFER_SIZE+SZCHUNK]; uchar respchunk[SZCHUNK+10]; uchar inputData[6]; uchar cc = 0; int rc = -1; int i, chunksz, thislen, off; int reclen; ushort cmd; uchar resv[2] = {0,0}; chunksz = SZCHUNK; reclen = srecdata; /*max size of SDR record*/ off = 0; *rlen = 0; *r_next = 0xffff; /*default*/ if (fReserveOK) rc = sdr_get_reservation(resv,fdevsdrs); if (fdevsdrs) cmd = GET_DEVICE_SDR; else cmd = GET_SDR; if (reclen == 0xFFFF) { /* get it all in one call */ inputData[0] = resv[0]; /*res id LSB*/ inputData[1] = resv[1]; /*res id MSB*/ inputData[2] = r_id & 0x00ff; /*record id LSB*/ inputData[3] = (r_id & 0xff00) >> 8; /*record id MSB*/ inputData[4] = 0; /*offset */ inputData[5] = 0xFF; /*bytes to read, ff=all*/ sresp = sizeof(resp);; if (fdebug) printf("ipmi_cmd SDR id=%d read_all, len=%d\n", r_id,sresp); rc = ipmi_cmd_mc(cmd, inputData, 6, recdata, &sresp,&cc, fdebug); /* This will usually return cc = 0xCA (invalid length). */ if (fdebug) printf("ipmi_cmd SDR data status = %d, cc = %x, sz=%d\n", rc,cc,sresp); reclen = sresp; *r_next = recdata[0] + (recdata[1] << 8); } else /* if (reclen > chunksz) do multi-part chunks */ for (off = 0; off < reclen; ) { thislen = chunksz; if ((off+chunksz) > reclen) thislen = reclen - off; inputData[0] = resv[0]; /*res id LSB*/ inputData[1] = resv[1]; /*res id MSB*/ inputData[2] = r_id & 0x00ff; /*record id LSB*/ inputData[3] = (r_id & 0xff00) >> 8; /*record id MSB*/ inputData[4] = (uchar)off; /*offset */ inputData[5] = (uchar)thislen; /*bytes to read, ff=all*/ sresp = sizeof(respchunk); rc = ipmi_cmd_mc(cmd, inputData, 6, respchunk, &sresp,&cc, fdebug); if (fdebug) printf("ipmi_cmd SDR[%x] off=%d ilen=%d status=%d cc=%x sz=%d\n", r_id,off,thislen,rc,cc,sresp); if (off == 0 && cc == 0xCA && thislen == SZCHUNK) { /* maybe shorter than SZCHUNK, try again */ chunksz = 0x06; if (fdebug) printf("sdr[%x] try again with chunksz=%d\n", r_id,chunksz); continue; } if (off > chunksz) { /* already have first part of the SDR, ok to truncate */ if (rc == -3) { /* if LAN_ERR_RECV_FAIL */ if (fdebug) printf("sdr[%x] error rc=%d len=%d truncated\n", r_id,rc,sresp); sresp = 0; rc = 0; } if (cc == 0xC8 || cc == 0xCA) { /* length errors */ /* handle certain MCs that report wrong length, * at least use what we already have (sresp==0) */ if (fdebug) printf("sdr[%x] error cc=%02x len=%d truncated\n", r_id,cc,sresp); cc = 0; } } if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); /* if here, successful, chunk was read */ if (sresp < (thislen+2)) { /* There are some SDRs that may report the wrong length, and * return less bytes than they reported, so just truncate. */ if (fdebug) printf("sdr[%x] off=%d, expected %d, got %d\n", r_id,off,thislen+2,sresp); if (sresp >= 2) thislen = sresp - 2; else thislen = 0; reclen = off + thislen; /* truncate, stop reading */ fprintf(stderr,"SDR record %x is malformed, length %d is less than minimum %d\n",r_id,sresp,thislen+2); rc = ERR_SDR_MALFORMED; } /* successful */ memcpy(&resp[off],&respchunk[2],thislen); if (off == 0 && sresp >= 5) { *r_next = respchunk[0] + (respchunk[1] << 8); reclen = respchunk[6] + 5; /*get actual record size*/ if (reclen > srecdata) { if (fdebug) printf("sdr[%x] chunk0, reclen=%d srecdata=%d\n", r_id, reclen, srecdata); reclen = srecdata; /*truncate*/ } } off += thislen; *rlen = off; } if (fdebug) { printf("GetSDR[%04x] next=%x (len=%d): ",r_id,*r_next,reclen); for (i = 0; i < reclen; i++) printf("%02x ",resp[i]); printf("\n"); } memcpy(recdata,&resp[0],reclen); *rlen = reclen; return(rc); } /*end GetSDR*/ static int nsdrs = 0; /*number of sdrs*/ static int sz_sdrs = 0; /*actual size used with sdrs*/ static uchar *psdrcache = NULL; void free_sdr_cache(uchar *ptr) { if (ptr != NULL) free(ptr); if ((ptr != psdrcache) && (psdrcache != NULL)) free(psdrcache); psdrcache = NULL; } int get_sdr_file(char *sdrfile, uchar **sdrlist) { int rv = -1; FILE *fp = NULL; int i, n, num, nsdr, isdr, len; uchar *sdrbuf; char buff[255]; uchar hbuf[85]; char fvalid; fp = fopen(sdrfile,"r"); if (fp == NULL) { printf("Cannot open file %s\n",sdrfile); return(ERR_FILE_OPEN); } /* determine number of SDRs by number of lines in the file */ num = 0; while (fgets(buff, 255, fp)) { num++; } if (fdebug) { printf("Reading %d SDRs from file %s\n",num,sdrfile); if ((psdrcache != NULL) && (nsdrs > 0)) { /*already have sdrcache*/ printf("get_sdr_file: Already have cache\n"); /*fdebug*/ free_sdr_cache(psdrcache); /*free previous sdrcache*/ } } sdrbuf = malloc(num * SDR_SZ); if (sdrbuf == NULL) { fclose(fp); return(rv); } fseek(fp, 0L, SEEK_SET); *sdrlist = sdrbuf; psdrcache = sdrbuf; nsdrs = num; isdr = 0; nsdr = 0; while (fgets(buff, 255, fp)) { len = strlen_(buff); fvalid = 0; if (buff[0] >= '0' && (buff[0] <= '9')) fvalid = 1; else if (buff[0] >= 'a' && (buff[0] <= 'f')) fvalid = 1; else if (buff[0] >= 'A' && (buff[0] <= 'F')) fvalid = 1; if (fvalid == 0) continue; i = 0; for (n = 0; n < len; ) { if (buff[n] < 0x20) break; /* '\n', etc. */ hbuf[i++] = htoi(&buff[n]); n += 3; } memcpy(&sdrbuf[isdr],hbuf,i); isdr += i; nsdr++; } /*end while*/ if (fdebug) printf("Read %d SDRs, %d bytes\n",nsdr,isdr); fclose(fp); rv = 0; return(rv); } int get_sdr_cache(uchar **pret) { int rv = -1; int i, n, sz, len, asz; int recid, recnext; uchar *pcache; uchar *psdr; if (pret == NULL) return(rv); fdevsdrs = use_devsdrs(fpicmg); if ((psdrcache != NULL) && (nsdrs > 0)) { /*already have sdrcache*/ *pret = psdrcache; if (fdebug) printf("get_sdr_cache: already have cache (%p)\n",*pret); return(0); } else if (fdebug) printf("get_sdr_cache: Allocating cache\n"); rv = GetSDRRepositoryInfo(&n,&fdevsdrs); if (rv != 0) return(rv); if (n == 0) { /* this is an error, probably because fdevsdrs is wrong.*/ if (fdebug) printf("get_sdr_cache: nsdrs=0, retrying\n"); fdevsdrs = (fdevsdrs ^ 1); n = 150; /*try some default num SDRs*/ } sz = n * SDR_SZ; /*estimate max size for n sdrs*/ pcache = malloc(sz); if (pcache == NULL) return(rv); psdrcache = pcache; *pret = pcache; memset(pcache,0,sz); recid = 0; asz = 0; for (i = 0; i <= n; i++) { if (recid == 0xffff) break; // psdr = &pcache[i * SDR_SZ]; psdr = &pcache[asz]; rv = GetSDR(recid,&recnext,psdr,SDR_SZ,&len); if (fdebug) printf("GetSDR[%x] rv = %d len=%d next=%x\n",recid,rv,len,recnext); if (rv != 0) { if (rv == 0xC5) { set_reserve(1); i--; } /*retry*/ else break; } else { /*success*/ /* if sdrlen!=len, adjust */ if ((len > 5) && (len != (psdr[4] + 5)) ) { if (fdebug) printf("SDR[%x] adjust len from %d to %d\n", recid,psdr[4]+5,len); psdr[4] = len - 5; } asz += len; if (recnext == recid) recid = 0xffff; else recid = recnext; } } nsdrs = n; sz_sdrs = asz; /* save the size for later*/ if (fdebug) { printf("get_sdr_cache, n=%d sz=%d asz=%d\n",n,sz,asz); if (i < n) printf("get_sdr_cache error, i=%d < n=%d, rv=%d\n",i,n,rv); } return(rv); } int find_nsdrs(uchar *pcache) { int num = 0; ulong asz = 0; int i, len; uchar *sdr; ushort recid = 0; if (pcache == NULL) return(num); for (i = 0; (int)asz < sz_sdrs; i++) { sdr = &pcache[asz]; if (sdr[2] != 0x51) { /* Dell SDR length error */ printf("SDR[%x] length error at %ld\n",recid,asz); sdr = &pcache[++asz]; /*try it if off-by-one*/ } len = sdr[4] + 5; recid = sdr[0] + (sdr[1] << 8); if (fdebug) printf("SDR[%x] len=%d i=%d offset=%lx\n",recid,len,i,asz); asz += len; } num = i; return(num); } int find_sdr_by_snum(uchar *psdr, uchar *pcache, uchar snum, uchar sa) { int rv = -1; uchar *sdr; int i, k, len; int asz = 0; if (psdr == NULL) return(rv); if (pcache == NULL) return(rv); for (i = 0; i <= nsdrs; i++) { // sdr = &pcache[i * SDR_SZ]; sdr = &pcache[asz]; len = sdr[4] + 5; asz += len; switch(sdr[3]) { case 0x01: k = 7; break; /*full sensor*/ case 0x02: k = 7; break; /*compact sensor*/ case 0x03: k = 7; break;/*compact sensor*/ default: k = 0; break; } if (k == 0) continue; else { if ((sdr[5] == sa) && (sdr[k] == snum)) { memcpy(psdr,sdr,len); return(0); } } } return(rv); } int find_sdr_by_tag(uchar *psdr, uchar *pcache, char *tag, uchar dbg) { int rv = -1; uchar *sdr; int i, k, n, len; int asz = 0; if (psdr == NULL) return(rv); if (pcache == NULL) return(rv); if (tag == NULL) return(rv); if (dbg) fdebug = 1; n = strlen_(tag); if (fdebug) printf("find_sdr_by_tag(%s) nsdrs=%d\n",tag,nsdrs); for (i = 0; i <= nsdrs; i++) { // sdr = &pcache[i * SDR_SZ]; sdr = &pcache[asz]; len = sdr[4] + 5; asz += len; switch(sdr[3]) { /* set tag offset by SDR type */ case 0x01: k = 48; break; /*full SDR*/ case 0x02: k = 32; break; /*compact SDR*/ case 0x03: k = 17; break; /*event-only SDR*/ case 0x10: k = 16; break; /*device locator SDR*/ case 0x11: k = 16; break; /*FRU device locator SDR*/ case 0x12: k = 16; break; /*IPMB device locator SDR*/ default: k = 0; break; /*else do not have an ID string/tag*/ } if (k == 0) { if (fdebug) printf("sdr[%d] idx=%02x%02x num=%x type=%x skip\n", i,sdr[1],sdr[0],sdr[7],sdr[3]); continue; } else { if (len > SDR_SZ) len = SDR_SZ; if (fdebug) { char tmp[17]; memset(tmp,0,sizeof(tmp)); memcpy(tmp,&sdr[k],(len - k)); tmp[16] = 0; /*force stringify*/ printf("sdr[%d] idx=%02x%02x num=%x tag: %s\n",i,sdr[1],sdr[0], sdr[7],tmp); } if (strncmp(tag,(char *)&sdr[k],n) == 0) { memcpy(psdr,sdr,len); return(0); } } } return(rv); } int find_sdr_next(uchar *psdr, uchar *pcache, ushort id) { int rv = -1; uchar *sdr; int i, imatch, len; ushort recid; int asz = 0; if (psdr == NULL) return(rv); if (pcache == NULL) return(rv); imatch = nsdrs; for (i = 0; i < nsdrs; i++) { // sdr = &pcache[i * SDR_SZ]; sdr = &pcache[asz]; if (sdr[2] != 0x51) /* Dell SDR off-by-one error */ sdr = &pcache[++asz]; len = sdr[4] + 5; recid = sdr[0] + (sdr[1] << 8); asz += len; // if (fdebug) printf("SDR[%x] len=%d id=%x i=%d imatch=%d\n", // recid,len,id,i,imatch); if (recid == id) imatch = i + 1; /*matches prev, return next one*/ else if (id == 0) { rv = 0; break; } /* 0000 = first one */ if (i == imatch) { rv = 0; break; } } if (rv == 0) memcpy(psdr,sdr,len); return(rv); } int find_sdr_by_id(uchar *psdr, uchar *pcache, ushort id) { int rv = -1; uchar *sdr; int i, imatch, len; ushort recid; int asz = 0; if (psdr == NULL) return(rv); if (pcache == NULL) return(rv); imatch = nsdrs; for (i = 0; i < nsdrs; i++) { sdr = &pcache[asz]; len = sdr[4] + 5; recid = sdr[0] + (sdr[1] << 8); asz += len; if (recid == id) { rv = 0; break; } else if (id == 0) { rv = 0; break; } /* 0000 = first one */ } if (rv == 0) memcpy(psdr,sdr,len); return(rv); } uchar bitnum(ushort value) { uchar ret = 0; int i; /* returns the highest bit number number set in this word. */ /* Bit numbers are 1-based in this routine, 0 means no bits set. */ /* scan 15 bits (0x7FFF). */ for (i = 0; i < 15; i++) { if (value & 0x01) ret = i+1; /*was ret++;*/ value = (value >> 1); } return(ret); } static double expon(int x, int y) { double res; int i; /* compute exponent: x to the power y */ res = 1; if (y > 0) { for (i = 0; i < y; i++) res = res * x; } else if (y < 0) { for (i = 0; i > y; i--) res = res / x; } /* else if if (y == 0) do nothing, res=1 */ return(res); } double RawToFloat(uchar raw, uchar *psdr) { double floatval; int m, b, a; uchar ax; int rx, b_exp; SDR01REC *sdr; int signval; sdr = (SDR01REC *)psdr; floatval = (double)raw; /*default*/ // if (raw == 0xff) floatval = 0; else if (sdr->rectype == 0x01) { /* SDR rectype == full */ if (fdebug) printf("units=%x base=%d mod=%d (raw=%x, nom_rd=%x)\n", sdr->sens_units,sdr->sens_base,sdr->sens_mod, raw, sdr->nom_reading); m = sdr->m + ((sdr->m_t & 0xc0) << 2); b = sdr->b + ((sdr->b_a & 0xc0) << 2); if (b & 0x0200) b = (b - 0x0400); /*negative*/ if (m & 0x0200) m = (m - 0x0400); /*negative*/ rx = (sdr->rx_bx & 0xf0) >> 4; if (rx & 0x08) rx = (rx - 0x10); /*negative, fix sign w ARM compilers*/ a = (sdr->b_a & 0x3f) + ((sdr->a_ax & 0xf0) << 2); ax = (sdr->a_ax & 0x0c) >> 2; b_exp = (sdr->rx_bx & 0x0f); if (b_exp & 0x08) b_exp = (b_exp - 0x10); /*negative*/ //b_exp |= 0xf0; /* negative 8-bit */ if ((sdr->sens_units & 0xc0) == 0) { /*unsigned*/ floatval = (double)raw; } else { /*signed*/ if (raw & 0x80) signval = (raw - 0x100); else signval = raw; floatval = (double)signval; } floatval *= (double) m; #ifdef MATH_OK floatval += (b * pow (10,b_exp)); floatval *= pow (10,rx); #else floatval += (b * expon (10,b_exp)); floatval *= expon (10,rx); #endif if (fdebug) printf("decode1: m=%d b=%d b_exp=%x rx=%d, a=%d ax=%d l=%x, floatval=%f\n", m,b,b_exp,rx,a,ax,sdr->linear,floatval); switch(sdr->linear) { case 0: /*linear*/ break; case 7: /*invert 1/x*/ /* skip if zero to avoid dividing by zero */ if (raw != 0) floatval = 1 / floatval; break; case 1: /*ln*/ case 2: /*log10, log2, e, exp10, exp2, */ case 3: /*log2*/ case 4: /*e*/ case 5: /*exp10*/ case 6: /*exp2*/ case 8: /*sqr(x)*/ case 9: /*cube(x)*/ case 10: /*sqrt(x)*/ case 11: /*cube-1(x)*/ default: if (fdebug) printf("linear mode %x not implemented\n",sdr->linear); break; } /*end-switch linear*/ } #ifdef NOT_LINEAR /* else if (sdr->linear != 7) */ { double be, re; rc = GetSensorType(sdr->sens_num,&stype,&rtype); if (fdebug) printf("decode: rc=%x, stype=%x, rtype=%x\n",rc,stype,rtype); if (rc != 0) return(floatval); /* GetSensorReadingFactors */ rc = GetSensorReadingFactors(sdr->sens_num,raw,&m,&b,&b_exp,&r,&a); if (rc == 0) { // floatval = ((m * raw) + (b * be)) * re; } if (fdebug) printf("decode: rc=%x, floatval=%f\n",rc,floatval); } #endif return(floatval); } #define IpmiAnalogDataFormatUnsigned 0 #define IpmiAnalogDataFormat1Compl 1 #define IpmiAnalogDataFormat2Compl 2 uchar FloatToRaw(double val, uchar *psdr, int rounding) { double cval; int lowraw, highraw, raw, maxraw, minraw, next_raw; int analog_dfmt; analog_dfmt = (psdr[20] >> 6) & 0x03; switch( analog_dfmt ) { case IpmiAnalogDataFormat1Compl: lowraw = -127; highraw = 127; minraw = -127; maxraw = 127; next_raw = 0; break; case IpmiAnalogDataFormat2Compl: lowraw = -128; highraw = 127; minraw = -128; maxraw = 127; next_raw = 0; break; case IpmiAnalogDataFormatUnsigned: default: lowraw = 0; highraw = 255; minraw = 0; maxraw = 255; next_raw = 128; break; } /* do a binary search for the right nth root value */ do { raw = next_raw; cval = RawToFloat( (uchar)raw, psdr ); if ( cval < val ) { next_raw = ((highraw - raw) / 2) + raw; lowraw = raw; } else { next_raw = ((raw - lowraw) / 2) + lowraw; highraw = raw; } } while ( raw != next_raw ); /* Do rounding to get the final value */ switch( rounding ) { case 0: /* Round Normal = Round to nearest value */ if ( val > cval ) { if ( raw < maxraw ) { double nval; nval = RawToFloat((uchar)(raw+1),psdr); nval = cval + ((nval - cval) / 2.0); if ( val >= nval ) raw++; } } else { if ( raw > minraw ) { double pval; pval = RawToFloat((uchar)(raw-1),psdr); pval = pval + ((cval - pval) / 2.0); if ( val < pval ) raw--; } } break; case 1: /*Round Down*/ if ((val < cval) && (raw > minraw )) raw--; break; case 2: /*Round Up*/ if ((val > cval) && (raw < maxraw)) raw++; break; } if ( analog_dfmt == IpmiAnalogDataFormat1Compl ) if ( raw < 0 ) raw -= 1; return((uchar)raw); } /*end FloatToRaw()*/ static int fill_thresholds(double *thrf, uchar *sdr) { int rv = 0; uchar *vals; uchar bits; // snum = sdr[7]; bits = sdr[19]; /*which are settable*/ vals = &sdr[36]; if (fdebug) printf("fill_thresholds: bits=%02x, values: %f>=%f>=%f, %f<=%f<=%f\n", bits, thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]); if (thrf[0] == THR_EMPTY) { if ((bits & 0x01) != 0) { /*lo-noncrit*/ thrf[0] = RawToFloat(vals[5],sdr); rv++; } else thrf[0] = 0; } if (thrf[1] == THR_EMPTY) { if ((bits & 0x02) != 0) { /*lo-crit*/ thrf[1] = RawToFloat(vals[4],sdr); rv++; } else thrf[1] = 0; } if (thrf[2] == THR_EMPTY) { if ((bits & 0x04) != 0) { /*lo-unrec*/ thrf[2] = RawToFloat(vals[3],sdr); rv++; } else thrf[2] = 0; } if (thrf[3] == THR_EMPTY) { if ((bits & 0x08) != 0) { /*hi-noncrit*/ thrf[3] = RawToFloat(vals[2],sdr); rv++; } else thrf[3] = 0; } if (thrf[4] == THR_EMPTY) { if ((bits & 0x10) != 0) { /*hi-crit*/ thrf[4] = RawToFloat(vals[1],sdr); rv++; } else thrf[4] = 0; } if (thrf[5] == THR_EMPTY) { if ((bits & 0x20) != 0) { /*hi-unrec*/ thrf[5] = RawToFloat(vals[0],sdr); rv++; } else thrf[5] = 0; } if (fdebug) printf("fill_thresholds: after rv=%d values: %f>=%f>=%f, %f<=%f<=%f\n", rv,thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]); return(rv); } char * decode_itype(uchar itype) { char *retstr; int i; /* Decode the Interrupt Type from Entity Assoc records */ retstr = tmpstr; if (itype <= 0x0f) sprintf(retstr,"IRQ_%d",itype); else if (itype <= 0x13) { strcpy(retstr,"PCI-A"); for (i=0x10;i= 0x20 && itype <= 0x5f) sprintf(retstr,"SysInt_%d",itype-0x20); else if (itype == 0x60) strcpy(retstr,"ACPI/PnP"); else if (itype == 0xFF) strcpy(retstr,"NoInt"); else strcpy(retstr,"Invalid"); return(retstr); } int decode_oem_sensor(uchar *sdr,uchar *reading,char *pstring,int slen) { int rv = -1; #ifdef METACOMMAND switch(vend_id) { case VENDOR_INTEL: rv = decode_sensor_intel(sdr, reading, pstring, slen); break; case VENDOR_KONTRON: rv = decode_sensor_kontron(sdr, reading, pstring, slen); break; case VENDOR_FUJITSU: rv = decode_sensor_fujitsu(sdr,reading,pstring,slen); break; case VENDOR_SUN: rv = decode_sensor_sun(sdr, reading, pstring, slen); break; case VENDOR_MAGNUM: case VENDOR_SUPERMICRO: case VENDOR_SUPERMICROX: rv = decode_sensor_supermicro(sdr,reading,pstring,slen,fsimple,fdebug); break; case VENDOR_QUANTA: rv = decode_sensor_quanta(sdr, reading, pstring, slen); break; case VENDOR_HP: rv = decode_sensor_hp(sdr, reading, pstring, slen); break; case VENDOR_DELL: rv = decode_sensor_dell(sdr, reading, pstring, slen); break; case VENDOR_IBM: case VENDOR_LENOVO: case VENDOR_LENOVO2: rv = decode_sensor_lenovo(sdr, reading, pstring, slen); break; case VENDOR_ASUS: rv = decode_sensor_asus(sdr, reading, pstring, slen); break; default: break; } /*end-switch vend_id*/ if (fdebug) // && rv == 0) printf("decode_oem_sensor rv=%d vend=%x string=%s\n",rv,vend_id,pstring); #endif return (rv); } int show_oemsdr(int vend, uchar *sdr) { int rv = -1; int i, len; #ifdef METACOMMAND if (vend == VENDOR_INTEL) { show_oemsdr_intel(sdr); /*show subtypes for Intel BMC_TAM*/ rv = 0; } else if (vend == 4156) { /*special HP/NewAccess OEM SDR*/ show_oemsdr_hp(sdr); rv = 0; } else if (vend == VENDOR_QUANTA) { printf("Quanta: "); show_oemsdr_nm(sdr); rv = 0; } #endif if (rv != 0) { len = sdr[4] + 5; if (vend == VENDOR_FUJITSU) printf("Fujitsu: "); else if (vend == VENDOR_INTEL) printf("Intel: "); else printf("manuf=%d: ",vend); for (i = 8; i < len; i++) printf("%02x ",sdr[i]); printf("\n"); } return(rv); } void ShowThresh(int flg, uchar bits, uchar *vals, uchar *sdr) { char str[128] = ""; char part[24]; /* ~15 bytes used */ double ival; char sep[4]; char *tag; tag = ""; if (fsimple) { sprintf(sep,"%c ",bdelim); tag = "Thresholds"; } else sep[0] = 0; /*null string*/ if (fshowthr == 2) { double i0, i1, i2, i3, i4, i5; i0 = RawToFloat(vals[0],sdr); i1 = RawToFloat(vals[1],sdr); i2 = RawToFloat(vals[2],sdr); i3 = RawToFloat(vals[3],sdr); i4 = RawToFloat(vals[4],sdr); i5 = RawToFloat(vals[5],sdr); sprintf(str,"%.2f:%.2f:%.2f:%.2f:%.2f:%.2f",i0,i1,i2,i3,i4,i5); printf("\t%s%s%s%c",sep,"Thresh ",str,chEol); } else if (flg != 0) { /* Compact, did GetThresholds, reverse order */ if (bits & 0x20) { ival = RawToFloat(vals[5],sdr); sprintf(part,"%shi-unrec %.2f ",sep,ival); strcat(str,part); } if (bits & 0x10) { ival = RawToFloat(vals[4],sdr); sprintf(part,"%shi-crit %.2f ", sep,ival); strcat(str,part); } if (bits & 0x08) { ival = RawToFloat(vals[3],sdr); sprintf(part,"%shi-noncr %.2f ",sep,ival); strcat(str,part); } if (bits & 0x01) { ival = RawToFloat(vals[0],sdr); sprintf(part,"%slo-noncr %.2f ",sep,ival); strcat(str,part); } if (bits & 0x02) { ival = RawToFloat(vals[1],sdr); sprintf(part,"%slo-crit %.2f ", sep,ival); strcat(str,part); } if (bits & 0x04) { ival = RawToFloat(vals[2],sdr); sprintf(part,"%slo-unrec %.2f ",sep,ival); strcat(str,part); } if (flg == 2) { if (sens_verbose) tag = "Volatile "; printf("\t%s%s%s%c",sep,tag,str,chEol); } else printf("\t%s%s%s%c",sep,tag,str,chEol); } else { /*Full SDR*/ if (fdebug) printf("ShowThresh[%x]: bits=%02x, sdr18=%02x %02x\n", sdr[7],bits,sdr[18],sdr[19]); if (bits & 0x20) { ival = RawToFloat(vals[0],sdr); sprintf(part,"%shi-unrec %.2f ",sep,ival); strcat(str,part); } if (bits & 0x10) { ival = RawToFloat(vals[1],sdr); sprintf(part,"%shi-crit %.2f ",sep,ival); strcat(str,part); } if (bits & 0x08) { ival = RawToFloat(vals[2],sdr); sprintf(part,"%shi-noncr %.2f ",sep,ival); strcat(str,part); } if (bits & 0x01) { ival = RawToFloat(vals[5],sdr); sprintf(part,"%slo-noncr %.2f ",sep,ival); strcat(str,part); } if (bits & 0x02) { ival = RawToFloat(vals[4],sdr); sprintf(part,"%slo-crit %.2f ",sep,ival); strcat(str,part); } if (bits & 0x04) { ival = RawToFloat(vals[3],sdr); sprintf(part,"%slo-unrec %.2f ",sep,ival); strcat(str,part); } if (sens_verbose) tag = "SdrThres "; printf("\t%s%s%s%c",sep,tag,str,chEol); if (sens_verbose) { /* show max/min & hysteresis from full sdr */ str[0] = 0; ival = RawToFloat(sdr[31],sdr); sprintf(part,"%snom %.2f ",sep,ival); strcat(str,part); ival = RawToFloat(sdr[32],sdr); sprintf(part,"%snmax %.2f ",sep,ival); strcat(str,part); ival = RawToFloat(sdr[33],sdr); sprintf(part,"%snmin %.2f ",sep,ival); strcat(str,part); ival = RawToFloat(sdr[34],sdr); sprintf(part,"%ssmax %.2f ",sep,ival); strcat(str,part); ival = RawToFloat(sdr[35],sdr); sprintf(part,"%ssmin %.2f ",sep,ival); strcat(str,part); #ifdef OLD ival = RawToFloat(sdr[42],sdr); sprintf(part,"%s+hyst %.2f ",sep,ival); strcat(str,part); ival = RawToFloat(sdr[43],sdr); sprintf(part,"%s-hyst %.2f ",sep,ival); strcat(str,part); #endif printf("\t%s%c",str,chEol); } } /*endif full sdr*/ } int decode_comp_generic(uchar type, uchar evtype, uchar num, ushort reading) { int istr = 0; uchar b; /* decode via evtype */ switch(evtype) { case 0x02: if (reading & 0x01) istr = 85; /* Active */ if (reading & 0x02) istr = 86; /* Busy */ else istr = 84; /* Idle (OK)) */ case 0x03: if (reading & 0x01) istr = 13; /* Asserted */ else istr = 0; /* "OK" Deasserted */ break; case 0x04: if (reading & 0x01) istr = 15; /* Predictive Failure */ else istr = 0; /* "OK" Deasserted */ break; case 0x05: if (reading & 0x01) istr = 65; /* Limit Exceeded*/ else istr = 0; /* "OK" LimitNotExceeded*/ break; case 0x07: /* transition */ b = bitnum(reading); switch(b) { case 0: istr = 0; break; /*no bits set, OK*/ case 1: istr = 87; break; /*transition up to Non-Critical*/ case 2: istr = 88; break; /*transition up to Critical */ case 3: istr = 89; break; /*transition up to Non-recoverable */ case 4: istr = 87; break; /*transition down to Non-Critical */ case 5: istr = 88; break; /*transition down to Critical */ case 6: istr = 89; break; /*transition to Non-recoverable */ case 7: istr = 90; break; /*Monitor*/ case 8: istr = 91; break; /*Informational*/ default: istr = 8; break; /*'OK*'*/ } break; case 0x08: if (reading & 0x01) istr = 9; /* Present */ else istr = 10; /*Absent*/ break; case 0x09: /* Availability event states */ if (reading & 0x01) istr = 17; /* Enabled */ else istr = 16; /*Disabled*/ break; case 0x0A: /* */ b = (reading & 0x7f); switch(b) { case 0x00: istr = 8; break; /* 00 'OK*'*/ case 0x01: istr = 92; break; /* transition to Running */ case 0x02: istr = 93; break; /* transition to In Test */ case 0x04: istr = 94; break; /* transition to Power Off */ case 0x08: istr = 95; break; /* transition to On Line */ case 0x10: istr = 96; break; /* transition to Off Line */ case 0x20: istr = 97; break; /* transition to Off Duty */ case 0x40: istr = 98; break; /* transition to Degraded */ case 0x80: istr = 99; break; /* transition to Power Save */ default: istr = 100; break; /* Install Error */ } break; case 0x0B: /* Redundancy */ b = (reading & 0x7f); switch(b) { case 0x00: istr = 8; break; /* 00 'OK*'*/ case 0x01: istr = 18; break; /* 01 Fully Redundant */ case 0x02: istr = 19; break; /* 02 Redundancy Lost */ case 0x04: istr = 20; break; /* 04 Redundancy Degraded */ case 0x08: istr = 82; break; /* 08 Non-Redundant/Sufficient down */ case 0x10: istr = 82; break; /* 10 Non-Redundant/Sufficient up*/ case 0x20: istr = 83; break; /* 20 Non-Redundant/Insufficient */ case 0x40: istr = 20; break; /* 40 Redundancy Degraded down */ default: istr = 20; break; /* Redundancy Degraded up */ } break; case 0x0C: /* ACPI Power States */ if (reading & 0x04) istr = 21; /* D3, Off */ else if (reading & 0x02) istr = 23; /* D2, Sleeping */ else if (reading & 0x01) istr = 22; /* D1, Working */ else istr = 24; /*D0, On*/ break; default: if (fdebug) printf("sensor[%x] et %02x type %02x not decoded, reading = %04x\n", num,evtype,type,reading); istr = STR_OTHER; /* other " - " */ break; } return(istr); } /* * decode_comp_reading * * Decodes the readings from compact SDR sensors. * Use sensor_dstatus array for sensor reading types and meaning strings. * Refer to IPMI Table 36-1 and 36-2 for this. * * Note that decoding should be based on sensor type and ev_type only, * except for end cases. * * Note reading1 = sens_reading[2], reading2 = sens_reading[3] */ int decode_comp_reading(uchar type, uchar evtype, uchar num, uchar reading1, uchar reading2) { int istr = 0; /*string index into sensor_dstatus[] */ uchar b; ushort reading; static char customstr[35]; /* usually reading2 has h.o. bit set (0x80). */ reading = reading1 | ((reading2 & 0x7f) << 8); switch(type) { case 0x01: /*Discrete Thermal, Temperature*/ if (fdebug) printf("Discrete Thermal snum %x evtype=%x reading=%x\n", num,evtype,reading); if (evtype == 0x07) { b = bitnum(reading); if (b == 0) istr = 8; /*no bits set, "OK*"*/ else if (b < 3) istr = 0; /*bits 1,2 "OK"*/ else istr = 65; /*transition to error, Limit Exceeded*/ } else if (evtype == 0x05) { /* see CPU1 VRD Temp on S5000, snum 0xc0 thru 0xcf */ if (reading & 0x01) istr = 65; /* Limit Exceeded*/ else istr = 0; /* "OK" LimitNotExceeded*/ } else if (evtype == 0x03) { if (reading & 0x01) istr = 13; /* Asserted */ else istr = 0; /* "OK" Deasserted */ } else { /* evtype == other 0x05 */ if (reading & 0x01) istr = 0; /* 8="OK*", 0="OK" */ else istr = 5; /*state asserted, Crit-hi */ } break; case 0x02: /*Discrete Voltage*/ { /* evtype == 0x05 for VBat, 0x03 for VR Watchdog */ if (reading & 0x01) istr = 65; /*LimitExceeded, was Crit-hi*/ else istr = 0; /* "OK" LimitNotExceeded*/ } break; case 0x04: /*Fan*/ if (evtype == 0x0b) { /*redundancy*/ b = reading & 0x3f; if (b == 0x00) istr = 16; /*sensor disabled*/ else if (b == 0x01) istr = 18; /*fully redundant*/ else if (b == 0x02) istr = 19; /*redundancy lost*/ else if (b == 0x0b) istr = STR_AC_LOST; /*ac lost*/ else istr = 20; /*redundancy degraded*/ } else if (evtype == 0x08) { /*presence*/ if (reading & 0x02) istr = 9; /*Present/Inserted*/ else if (reading & 0x01) istr = 10; /*Absent/Removed*/ else /*reading==00*/ istr = 47; /*Unused*/ } else if (evtype == 0x03) { /*PS Fan Fail*/ if (reading == 0) istr = 0; /*OK*/ else istr = 12; /*faulty*/ } else { /*other evtype*/ b = reading & 0x0f; if (b == 0) istr = 12; /*faulty*/ else if (b & 0x01) istr = 11; /*ready*/ else istr = 41; /*Unknown*/ } break; case 0x05: /*Physical Security, Chassis */ if (reading == 0) istr = 0; /*OK*/ else if (reading & 0x01) istr = 38; /*chassis intrusion*/ /* 0x02 Drive bay intrusion */ /* 0x04 IO area intrusion */ /* 0x08 Processor area intrusion */ else if (reading & 0x10) istr = 37; /*lan leash lost*/ /* 0x20 Dock/Undock */ /* 0x40 Fan area intrusion */ else istr = 41; /* Unknown, was bitnum(reading); */ break; case 0x07: /*Processor Status - 0x80 is OK/Present */ b = bitnum(reading); if (evtype == 0x03) { if (b <= 1) istr = 0; /*bit1 Deasserted, OK* */ else istr = 13; /*bit2 Asserted*/ } else { /*usu 0x6f*/ if (b > 10) istr = 41; /*Unknown*/ else if (b == 0) istr = 0; /*OK*/ else istr = 47 + b; /*Proc strings 48 thru 57*/ } break; case 0x08: /*Power Supply*/ b = reading & 0x7f; if (b == 0) istr = 10; /*absent*/ else if (b & 0x40) istr = STR_PS_CONFIG; /*Config Err*/ else if (b & 0x08) istr = STR_AC_LOST; /*AC Lost*/ else if (b & 0x04) istr = 15; /*Predictive Fail*/ else if (b & 0x02) istr = STR_PS_FAIL; /*PS Fail*/ else if (b & 0x01) istr = 9; /*present*/ break; case 0x09: /*Power Unit*/ b = reading & 0x3f; if (evtype == 0x0b) { /*Power Redundancy*/ if (b == 0x00) istr = 16; /*sensor disabled*/ else if (b == 0x01) istr = 18; /*fully redundant*/ else if (b == 0x02) istr = 19; /*redundancy lost*/ else if (b == 0x0b) istr = STR_AC_LOST; /*ac lost*/ else istr = 20; /*redundancy degraded*/ } else { /* Power Unit (evtype==0x6f or 0xef) */ if (b == 0) istr = 17; /*enabled*/ else if ((b & 0x01) == 1) istr = 16; /*disabled*/ } break; case 0x0C: /* Memory */ b = reading & 0x3f; if (b == 0) istr = 0; /*OK*/ else if (b & 0x01) istr = 8; /*Correctable ECC (OK*)*/ else if ((b & 0x02) || (b & 0x20)) istr = 39; /*ECC Error*/ else if (b & 0x04) istr = 40; /*Parity Error*/ else istr = bitnum(b); /* ECC or other error */ break; case 0x0D: /* drive slot - usually HSC sens_ownid == 0xc0 */ if (fRomley || fGrantley) { /* evtype==0x6f, has both status and presence */ if (reading & 0x02) istr = 12; /*Faulty*/ else if (reading & 0x80) istr = STR_REBUILDING; /*Rebuilding*/ else if (reading & 0x01) istr = 9; /*Present (OK)*/ else istr = 10; /*Absent*/ } else { if (evtype == 8) { /* HSC slot presence sensors (num > 8)*/ if (reading1 & 0x02) istr = 9; /*Present/Inserted*/ else if (reading1 & 0x01) istr = 10; /*Absent/Removed*/ else /*reading1==00*/ istr = 47; /*Unused*/ } else { /* HSC slot status sensors (evtype==0x6f)*/ /* usually reading2 == 0x82 or 0x8E if healthy */ if (reading2 & 0x01) istr = 12; /*state8=Rebuild stopped*/ else if (reading2 & 0x02) istr = 11; /*state9=Inserted/Ready */ else if (reading2 & 0x04) istr = 11; /*state10=Safe_to_Remove*/ else if (reading2 & 0x08) istr = 11; /*state11=Ready */ else if (reading2 == 0x80) istr = 47; /*no states, Unused*/ else istr = 12; /*faulty*/ b = 8; /*if no bits set, no raid state */ if (reading1 & 0x01) { b = 0; } /*state0=Faulty*/ else if (reading1 & 0x02) b = 1; /*state1=Rebuilding*/ else if (reading1 & 0x04) b = 2; /*state2=InFailedArray*/ else if (reading1 & 0x08) b = 3; /*state3=InCriticalArray*/ else if (reading1 & 0x10) b = 4; /*state4=ParityCheck*/ else if (reading1 & 0x20) b = 5; /*state5=PredictedFault*/ else if (reading1 & 0x40) b = 6; /*state6=Un-configured*/ else if (reading1 & 0x80) b = 7; /*state7=HotSpare*/ if (b < 8) { /* also include a raid_state, via custom string */ sprintf(customstr,"%s %s", sensor_dstatus[istr], raid_states[b]); istr = STR_CUSTOM; sensor_dstatus[istr] = customstr; if (fdebug) printf("dstatus=%s\n",sensor_dstatus[istr]); } } /*end-else-if HSC slot status (0x6f)*/ } break; case 0x10: /*Event Logging*/ /* usu evtype==0x6f*/ b = bitnum(reading & 0x3f); switch (b) { case 0x00: istr = 0; break; /*OK*/ case 0x01: istr = 59; break; /*MemLogDisabled*/ case 0x02: istr = 60; break; /*TypLogDisabled*/ case 0x03: istr = 61; break; /*LogCleared*/ case 0x04: istr = 62; break; /*AllLogDisabled*/ case 0x05: istr = 63; break; /*SelFull*/ case 0x06: istr = 64; break; /*SelNearFull*/ default: istr = 41; break; /*Unknown*/ } break; case 0x12: /*System Event*/ if (reading == 0) istr = 0; else istr = 13; /*Asserted*/ break; case 0x13: /*Critical Interrupt*/ /* valid bits: 0x03FF */ if (reading == 0) istr = 0; /*OK*/ else { b = bitnum(reading); /* ECC or other error */ if (b > 10) b = 10; istr = 24 + b; } break; case 0x14: /*Button*/ if (reading == 0) istr = 0; /*OK*/ else istr = 13; /*Asserted*/ break; case 0x15: /*Module/ Board */ if (evtype == 0x08) { /*presence*/ if (reading & 0x02) istr = 9; /*Present/Inserted*/ else if (reading & 0x01) istr = 10; /*Absent/Removed*/ else /*reading==00*/ istr = 47; /*Unused*/ } break; case 0x16: /* HSBP Status (esp. Romley) */ if (reading & 0x010) istr = STR_HSC_OFF; /*Offline*/ else istr = 0; /*OK*/ break; case 0x17: /* ATCA CDM, Air Filter, Filter Tray */ if (reading == 0) istr = 0; /*OK*/ else if (reading & 0x01) istr = 10; /*Absent*/ else istr = bitnum(reading); /* other error, TODO: fix this */ break; case 0x1C: /*Terminator (usu SCSI)*/ if (reading & 0x01) istr = 9; /*present*/ else istr = 10; /*missing,absent*/ break; case 0x21: /*DIMM memory slot*/ if ((reading & 0x04) != 0) istr = 9; /*present*/ else istr = 10; /*absent*/ sprintf(customstr,"%s", sensor_dstatus[istr]); if ((reading & 0x01) != 0) strcat(customstr,",Fault"); if ((reading & 0x0100) != 0) strcat(customstr,",Disabled"); istr = 58; /*use a custom string*/ sensor_dstatus[istr] = customstr; if (fdebug) printf("dstatus=%s\n",sensor_dstatus[istr]); break; case 0x22: /*ACPI Power State*/ b = bitnum(reading); switch(b) { case 0: istr = 0; break; /*OK*/ case 1: istr = 22; break; /*Working*/ case 2: case 3: case 4: case 5: case 9: case 10: istr = 23; break; /*Sleeping*/ case 6: case 7: case 8: case 11: case 12: istr = 24; break; /*On*/ case 13: istr = 21; break; /*Off*/ default: istr = 41; /*unknown*/ } break; case 0x23: /*Watchdog*/ if (reading == 0) istr = 0; else istr = 13; /*Asserted*/ break; case 0x24: /*Platform Alert*/ b = bitnum(reading); switch(b) { case 0: istr = 0; break; /*OK, no bits set*/ case 1: istr = 66; break; /*Page, bit 0 set*/ case 2: istr = 67; break; /*LAN, bit 1 set*/ case 3: istr = 68; break; /*PET*/ case 4: istr = 69; break; /*SNMP OEM*/ default: istr = 70; /*None*/ } break; case 0x25: /* Entity Presence */ if (reading & 0x01) istr = 8; /*Present*/ else if (reading & 0x02) istr = 9; /*Absent*/ else if (reading & 0x04) istr = 16; /*Disabled*/ else istr = 42; /* NotAvailable */ break; case 0x28: /* BMC FW Health */ if (evtype == 0x6F) { /*Sensor-specific*/ if (reading == 0) istr = 0; /*OK*/ else istr = 12; /*Faulty*/ } else { /*use event/reading type*/ istr = decode_comp_generic(type, evtype, num, reading); } break; case 0x29: /* Battery */ switch(reading & 0x7f) { case 0x00: istr = 0; break; /*OK*/ case 0x01: istr = 15; break; /*Predict Fail*/ case 0x04: istr = 9; break; /*Present*/ case 0x02: default: istr = 12; break; /*Failed/Faulty*/ } break; case 0x2A: /* Session Audit (IPMI 2.0) */ if (reading == 0x00) istr = 45; /*Activated*/ else istr = 46; /*Deactivated*/ break; case 0x2B: /* Version Change */ b = bitnum(reading1); switch(b) { case 0: istr = 0; break; /*OK, no bits set*/ case 1: istr = 72; break; /*HW Changed, bit 0 set*/ case 2: istr = 73; break; /*SW Changed, bit 1 set*/ case 3: istr = 74; break; /*HW incompatibility*/ default: istr = 75; break; /*Change error*/ } break; /* sensor types 0xC0 - 0xFF are OEM RESERVED */ case 0xF1: /* ATCA IPMB-0 Sensor */ if ((reading & 0x7fff) == 0x0008) istr = 0; /*OK*/ else istr = bitnum(reading1); /* other error, TODO: refine this */ break; case 0xC0: /* SMI State, NMI State */ case 0xD8: /* BIST */ case 0xF0: /* ATCA FRU HotSwap, TODO: refine this */ case 0xF2: /* ATCA Module HotSwap, TODO: refine this */ case 0xF3: /* SMI Timeout, etc. */ if (reading & 0x01) istr = 13; /* Asserted */ else istr = 0; /* "OK", Deasserted */ break; case 0x60: /* SCSI 1 Term Flt */ case 0x61: /* SCSI 2 Term Flt */ default: istr = decode_comp_generic(type, evtype, num, reading); break; } return(istr); } /* end decode_comp_reading */ #define STYPSZ 15 static char *get_stype_str(uchar stype) { /*return sensor type string, with fixed length */ static char stype_str[STYPSZ+1]; char *tmpstr; int i, n; tmpstr = get_sensor_type_desc(stype); n = strlen_(tmpstr); if (n > STYPSZ) n = STYPSZ; strncpy(stype_str,tmpstr,n); for (i = n; i < STYPSZ; i++) stype_str[i] = ' '; stype_str[i] = 0; tmpstr = stype_str; return(tmpstr); } void ShowSDR(char *tag, uchar *sdr) { SDR01REC *sdr01; SDR02REC *sdr02; SDR08REC *sdr08; SDR11REC *sdr11; SDR12REC *sdr12; SDR14REC *sdr14; SDRc0REC *sdrc0; char idstr[32]; char *typestr = NULL; int vend; int len, ilen, i, j; int ioff; uchar sens[4]; uchar sens_cap; uchar shar_cnt; int rc; double val; char brearm; uchar sep[4]; char rdgstr[50]; len = sdr[4] + 5; sens_cap = 0x80; /*ignore*/ if (fdebug) printf("ShowSDR: len=%d, type=%x\n",len,sdr[3]); memset(sens,0,4); if (frawsdr || fdebug) { /* raw is different than dump_buf */ printf("raw SDR: "); for (i = 0; i < len; i++) printf("%02x ",sdr[i]); printf("\n"); } strcpy(idstr,"INIT"); /*always set idstr to some initial string*/ switch(sdr[3]) { case 0x01: /* Full sensor record */ sdr01 = (SDR01REC *)sdr; ioff = 48; if (ioff > len) { if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n", sdr[3],len,ioff); fprintf(stderr,"Bad SDR Length %d, please apply the correct FRU/SDR diskette\n",len); return; } sens_cap = sdr[11]; /*sdr01->sens_capab*/ // ilen = (sdr[ioff] & 0x1f); /*sdr01->id_typelen*/ ilen = len - ioff; if (fdebug) printf("SDR[%x] Full ioff=%d idTypLen=0x%02x ilen=%d\n", sdr01->recid, ioff,sdr[ioff] ,ilen); if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; if (ilen <= 0) { /*bug if true*/ fprintf(stderr,"Bad SDR Length %d, omits ID string\n",len); ilen = 16; /*less than sizeof(idstr)*/ } memcpy(idstr,&sdr[ioff],ilen); for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; } idstr[ilen] = 0; /* stringify */ if ((sdr01->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/ else brearm = 'a'; /*automatic rearm*/ if (fdebug) printf("entity %d.%d, idlen=%d sizeof=%lu idstr0=%c s0=%x\n", sdr01->entity_id, sdr01->entity_inst, ilen,sizeof(SDR01REC),idstr[0],sdr[ioff]); rc = GetSensorReading(sdr01->sens_num,sdr01,sens); if (rc != 0) { /* if rc != 0, leave sens values zero */ i = 41; /* Unknown */ val = 0; if (rc == 0xCB) { /*sensor not present*/ i = 10; /* Absent */ typestr = "na"; } else typestr = decode_rv(rc); } else { j = (sens[2] & 0x3f); /*sensor reading state*/ i = bitnum((ushort)j); /*sensor_dstatus index*/ if (fdebug) printf("bitnum(%02x)=%d raw=%02x init=%x base/units=%x/%x\n", sens[2],i,sens[0],sens[1],sdr01->sens_base, sdr01->sens_units); if ((sens[1] & 0x20) != 0) { i = 7; val = 0; } /* Init state */ else if (sdr01->sens_units == 0xC0) i = 42; /*reading NotAvailable*/ else if (sens[2] == 0xc7) { i = 10; val = 0; /* Absent (Intel) */ if (fdebug) printf("sensor[%x] is absent (c7), no reading\n", sdr01->sens_num); } else val = RawToFloat(sens[0],sdr); typestr = get_unit_type(sdr01->sens_units, sdr01->sens_base, sdr01->sens_mod, fsimple); #ifdef WRONG if (is_romley(vend_id,prod_id) && (sdr01->sens_type == 0x0C) && (sdr01->sens_units & 0x01)) { /* Intel Memory Thermal Throttling %, raw 0x01 == 0.5 % */ val = (val / 2); /* handle MTT SDR errata */ } /*correct solution is to fix the SDR m-value instead */ #endif } rc = decode_oem_sensor(sdr,sens,oem_string,sizeof(oem_string)); if (rc == 0) { if (fsimple) strncpy(rdgstr,oem_string,sizeof(rdgstr)); else snprintf(rdgstr,sizeof(rdgstr),"%02x %s",sens[0],oem_string); } else { if (fsimple) snprintf(rdgstr,sizeof(rdgstr),"%s %c %.2f %s", sensor_dstatus[i],bdelim,val,typestr); else snprintf(rdgstr,sizeof(rdgstr),"%02x %s %.2f %s", sens[0], sensor_dstatus[i],val,typestr); } sep[0] = 0; /*null string*/ printf("%s", tag); if (fsimple) { sprintf(sep,"%c ",bdelim); printf("%04x %c Full %c %s %c %02x %c %s %c %s%c", sdr01->recid, bdelim, bdelim, get_stype_str(sdr01->sens_type), bdelim, sdr01->sens_num,bdelim, idstr, bdelim,rdgstr,chEol); } else printf("%04x SDR Full %02x %02x %02x %c %02x snum %02x %s = %s%c", sdr01->recid, sdr01->rectype, sdr01->ev_type, sdr01->sens_ownid, brearm, sdr01->sens_type, sdr01->sens_num, idstr, rdgstr, chEol); if (fdebug && fshowthr) printf("cap=%02x settable=%02x, readable=%02x\n", sens_cap,sdr[19],sdr[18]); if (sens_verbose) /* if -v, also show Entity ID */ printf("\t%sEntity ID %d.%d (%s), Capab: %s%c", sep, sdr01->entity_id, sdr01->entity_inst, decode_entity_id(sdr01->entity_id), // sens_cap, decode_capab(sens_cap),chEol); if (fshowthr && (sens_cap & 0x0f) != 0x03) { uchar thresh[7]; /* Thresholds, so show them */ /* Use settable bits to show thresholds, since the * readable values will be off for Full SDRs. * If cant set any thresholds, only show SDR thresholds */ if (sdr[19] == 0) rc = 1; else { /* Show volatile thresholds. */ rc = GetSensorThresholds(sdr01->sens_num,&thresh[0]); if (rc == 0) ShowThresh(2,thresh[0],&thresh[1],sdr); } /* Show SDR non-volatile thresholds. */ if (sens_verbose || rc !=0) ShowThresh(0,sdr[18],&sdr[36],sdr); // ShowThresh(0,0x3f,&sdr[36],sdr); /* to show all %%%% */ } if (fwrap) { /* (chEol != '\n') include time */ time_t ltime; time(<ime); if (fsimple) printf("%c %s",bdelim,ctime(<ime)); /*ctime has '\n' */ else printf("at %s",ctime(<ime)); /*ctime has '\n' */ } break; case 0x02: /* Compact sensor record */ sdr02 = (SDR02REC *)sdr; ioff = 32; if (ioff > len) { if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n", sdr[3],len,ioff); fprintf(stderr,"Bad SDR Length, please apply the correct FRU/SDR diskette\n"); return; } sens_cap = sdr[11]; /*sdr02->sens_capab*/ shar_cnt = sdr02->shar_cnt & 0x0f; /*sdr[23]*/ ilen = len - ioff; if ((ilen+1) >= sizeof(idstr)) ilen = sizeof(idstr) - 2; memcpy(idstr,&sdr[ioff],ilen); if ((shar_cnt > 1) && (sdr02->shar_off & 0x80) != 0) { /*do shared SDR*/ j = (sdr02->shar_off & 0x7f); /*sdr[24] = modifier offset*/ if (fdebug) printf("share count = %d, mod_offset = %d\n",shar_cnt,j); if ((sdr02->shar_cnt & 0x10) != 0) { /*alpha*/ idstr[ilen++] = 0x40 + j; /* j=1 -> 'A' */ idstr[ilen] = 0; /* stringify */ } else { /*numeric*/ sprintf(&idstr[ilen],"%d",j); ilen = strlen_(idstr); } } /* else normal idstr */ for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; } idstr[ilen] = 0; /* stringify */ if ((sdr02->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/ else brearm = 'a'; /*automatic rearm*/ if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%zu, s0=%x\n", ilen,idstr[0],sizeof(SDR02REC),sdr[ioff]); memset(sens,0,sizeof(sens)); rc = GetSensorReading(sdr02->sens_num,sdr02,sens); if (rc != 0) { /* if rc != 0, leave sens values zero */ i = 41; /* Unknown */ val = 0; if (rc == 0xCB) { /*sensor not present*/ i = 10; /* Absent */ typestr = "na"; } else typestr = decode_rv(rc); } else { if ((sens[1] & 0x20) != 0) i = 42; /*init state, NotAvailable*/ else { rc = decode_oem_sensor(sdr,sens,oem_string,sizeof(oem_string)); if (rc == 0) i = STR_OEM; else i = decode_comp_reading(sdr02->sens_type,sdr02->ev_type, sdr02->sens_num,sens[2],sens[3]); } } if (fdebug) printf("snum %x type %x evt %x reading %02x%02x i=%d rc=%d %s\n", sdr02->sens_num,sdr02->sens_type,sdr02->ev_type, sens[3],sens[2],i,rc, decode_rv(rc)); j = sens[2] | ((sens[3] & 0x7f) << 8); /*full reading, less h.o. bit*/ sep[0] = 0; /*null string*/ printf("%s", tag); if (fsimple) { sprintf(sep,"%c ",bdelim); printf("%04x %c Compact %c %s %c %02x %c %s %c %s %c%c", sdr02->recid, bdelim, bdelim, get_stype_str(sdr02->sens_type), bdelim, sdr02->sens_num, bdelim, idstr, bdelim, sensor_dstatus[i],bdelim,chEol); } else if (i == STR_OEM) { // idstr[ilen] = 0; /*cut out padding in idstr*/ printf("%04x SDR Comp %02x %02x %02x %c %02x snum %02x %s = %04x %s%c", sdr02->recid, sdr02->rectype, sdr02->ev_type, sdr02->sens_ownid, brearm, sdr02->sens_type, sdr02->sens_num, idstr, j, sensor_dstatus[i],chEol); // sensor_dstatus[i] == oem_string } else { printf("%04x SDR Comp %02x %02x %02x %c %02x snum %02x %s = %04x %s%c", sdr02->recid, sdr02->rectype, sdr02->ev_type, sdr02->sens_ownid, brearm, sdr02->sens_type, sdr02->sens_num, idstr, j, sensor_dstatus[i],chEol); /* idstr, sens[0], sens[1], sens[2], sens[3], */ } if (fdebug && fshowthr) printf("cap=%02x settable=%02x, readable=%02x\n", sens_cap,sdr[19],sdr[18]); if (fshowthr) /*also show Entity ID */ printf("\t%sEntity ID %d.%d (%s), Capab: %s%c", sep, sdr02->entity_id, sdr02->entity_inst, decode_entity_id(sdr02->entity_id), // sens_cap, decode_capab(sens_cap),chEol); if (fshowthr && ((sens_cap & 0x80) == 0) && (sens_cap & 0x0C) != 0) { uchar thresh[7]; /* Thresholds, show them */ /* Use readable bits to get & show thresholds */ if (sdr[20] != 0) { rc = GetSensorThresholds(sdr02->sens_num,&thresh[0]); if (rc == 0) ShowThresh(1,thresh[0],&thresh[1],sdr); } } if (fwrap) { /*include time and \n */ time_t ltime; time(<ime); if (fsimple) printf("%c %s",bdelim,ctime(<ime)); /*ctime has '\n' */ else printf("at %s",ctime(<ime)); /*ctime has '\n' */ } break; case 0x03: /* Event-only sensor record, treat like Compact SDR */ sdr02 = (SDR02REC *)sdr; ioff = 17; if (ioff > len) { fprintf(stderr,"Bad SDR %x Length %d. Please apply the correct FRU/SDR diskette\n", sdr02->recid, len); return; } if (!fsimple) { ilen = len - ioff; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[ioff],ilen); for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; } idstr[ilen] = 0; /* stringify */ sens_cap = sdr[11]; memset(sens,0,sizeof(sens)); if ((sdr02->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/ else brearm = 'a'; /*automatic rearm*/ // rc = GetSensorReading(sdr02->sens_num,sdr02,sens); /* EvtOnly SDRs do not support readings. * GetSensorReading would return ccode=0xCB (not present), * but this skips error msg */ rc = 0xCB; i = bitnum((ushort)sens[2]); j = sens[2] | ((sens[3] & 0x7f) << 8); printf("%s",tag); printf("%04x SDR EvtO %02x %02x %02x %c %02x snum %02x %s = %04x %s\n", sdr02->recid, sdr02->rectype, sdr02->reclen, sdr02->sens_ownid, 'a', sdr[10], sdr02->sens_num, idstr, j, sensor_dstatus[i]); // sens[0], sens[1], sens[2], sens[3], sensor_dstatus[i] } break; case 0x08: /* Entity Association record */ sdr08 = (SDR08REC *)sdr; if (!fsimple) { printf("%s",tag); printf("%04x SDR EntA %02x %02x %02x %02x %02x: ", sdr08->recid, sdr08->rectype, sdr08->reclen, sdr08->contid, sdr08->continst, sdr08->flags); for (i = 0; i < 8; i++) printf("%02x ",sdr08->edata[i]); printf("\n"); } break; case 0x09: /* Device-relative Entity Association record */ sdr08 = (SDR08REC *)sdr; /*but SDR09 is 26 bytes*/ if (!fsimple) { printf("%s",tag); printf("%04x SDR DEnt %02x %02x %02x %02x %02x %02x %02x: ", sdr08->recid, sdr08->rectype, sdr08->reclen, sdr08->contid, sdr08->continst, sdr08->flags, sdr08->edata[0], sdr08->edata[1]); /*display 2 of 4 contained entity devices edata[2-10] */ for (i = 2; i < 8; i++) printf("%02x ",sdr08->edata[i]); printf("\n"); } break; case 0x10: /* Generic Device Locator record */ sdr11 = (SDR11REC *)sdr; ioff = 16; if (ioff > len) { if (fdebug) printf("SDR %x bad length: type=%x, len=%d, ioff=%d\n", sdr11->recid, sdr[3],len,ioff); return; } if (!fsimple) { ilen = len - ioff; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[ioff],ilen); idstr[ilen] = 0; /* stringify */ printf("%s", tag); if (fsimple) printf("DevLocator record[%x]%c device %02x %c %s\n", sdr11->recid, bdelim,sdr11->dev_slave_adr,bdelim,idstr); else printf("%04x SDR DLoc %02x %02x dev: %02x %02x %02x %02x %02x %02x %s\n", sdr11->recid, sdr11->rectype, sdr11->reclen, sdr11->dev_access_adr, sdr11->dev_slave_adr, sdr11->access_lun, sdr[8], sdr[10], sdr[11], idstr); } break; case 0x11: /* FRU record */ sdr11 = (SDR11REC *)sdr; ioff = 16; if (ioff > len) { if (fdebug) printf("SDR %x bad length: type=%x len=%d ioff=%d\n", sdr11->recid, sdr[3],len,ioff); printf("Please apply the correct FRU/SDR diskette\n"); return; } if (!fsimple) { ilen = len - ioff; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[ioff],ilen); idstr[ilen] = 0; /* stringify */ if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%zu, s0=%x\n", ilen,idstr[0],sizeof(SDR11REC),sdr[ioff]); printf("%s", tag); if (fsimple) printf("FRU record[%x]: device %02x : %s\n", sdr11->recid, sdr11->dev_slave_adr,idstr); else printf("%04x SDR FRU %02x %02x dev: %02x %02x %02x %02x %02x %02x %s\n", sdr11->recid, sdr11->rectype, sdr11->reclen, sdr11->dev_access_adr, sdr11->dev_slave_adr /*fru_id*/, sdr11->access_lun, sdr11->chan_num, sdr11->entity_id, sdr11->entity_inst, idstr); } break; case 0x12: /* IPMB record */ sdr12 = (SDR12REC *)sdr; ioff = 16; if (ioff > len) { if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n", sdr[3],len,ioff); printf("Please apply the correct FRU/SDR diskette\n"); return; } if (!fsimple) { ilen = len - ioff; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[ioff],ilen); idstr[ilen] = 0; /* stringify */ if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%zu, s0=%x\n", ilen,idstr[0],sizeof(SDR12REC),sdr[ioff]); printf("%s", tag); if (fsimple) printf("IPMB record[%x]%c addr %02x %02x %c %s\n", sdr12->recid, bdelim,sdr12->dev_slave_adr, sdr12->chan_num,bdelim,idstr); else printf("%04x SDR IPMB %02x %02x dev: %02x %02x %02x %02x %02x %s\n", sdr12->recid, sdr12->rectype, sdr12->reclen, sdr12->dev_slave_adr, sdr12->chan_num, sdr12->dev_capab, sdr12->entity_id, sdr12->entity_inst, idstr); } break; case 0x14: /* BMC Message Channel Info record */ sdr14 = (SDR14REC *)sdr; if(!fsimple){ printf("%s", tag); printf("%04x SDR BMsg %02x %02x: ", sdr14->recid, sdr14->rectype, sdr14->reclen ); for (i = 0; i < 8; i++) printf("%02x ",sdr14->mdata[i]); printf("%s %s %02x\n",decode_itype(sdr14->mint), decode_itype(sdr14->eint), sdr14->rsvd); } break; case 0xc0: /* OEM SDR record (manuf_id 343. = Intel) */ sdrc0 = (SDRc0REC *)sdr; if(!fsimple) { vend = sdrc0->manuf_id[0] + (sdrc0->manuf_id[1] << 8) + (sdrc0->manuf_id[2] << 16); printf("%s",tag); printf("%04x SDR OEM %02x %02x ", sdrc0->recid, sdrc0->rectype, sdrc0->reclen); show_oemsdr(vend,sdr); } break; default: sdrc0 = (SDRc0REC *)sdr; /* also saw type = 0x08 & 0x14 on STL2s */ if (!fsimple){ printf("%s", tag); printf("%04x SDR type=%02x ", sdrc0->recid, sdr[3]); for (i = 0; i < len; i++) printf("%02x ",sdr[i]); printf("\n"); } } return; } static int ShowPowerOnHours(void) { uchar resp[MAX_BUFFER_SIZE]; int sresp = MAX_BUFFER_SIZE; uchar cc; int rc = -1; int i; unsigned int hrs; if (fmBMC) return(0); if (fsimple) return(0); sresp = MAX_BUFFER_SIZE; memset(resp,0,6); /* default response size is 5 */ rc = ipmi_cmd_mc(GET_POWERON_HOURS, NULL, 0, resp, &sresp, &cc, fdebug); if (rc == 0 && cc == 0) { /* show the hours (32-bits) */ hrs = resp[1] | (resp[2] << 8) | (resp[3] << 16) | (resp[4] << 24); /*60=normal, more is OOB, so avoid div-by-zero*/ if ((resp[0] <= 0) || (resp[0] >= 60)) i = 1; else { i = 60 / resp[0]; hrs = hrs / i; } printf(" SDR IPMI sensor: Power On Hours \t = %d hours\n", hrs); } if (fdebug) { printf("PowerOnHours (rc=%d cc=%x len=%d): ",rc,cc,sresp); if (rc == 0) for (i = 0; i < sresp; i++) printf("%02x ",resp[i]); printf("\n"); } return(rc); } int SaveThreshold(int id, int sensor_num, int sensor_lo, int sensor_hi, uchar *thr_set) { int rv = 0; char lostr[20]; char histr[20]; FILE *fd; /* persist the thresholds by re-applying with ipmiutil sensor commands.*/ if (thr_set != NULL) { sprintf(lostr,"-u 0x%02x%02x%02x%02x%02x%02x", sensor_thr[0], sensor_thr[1], sensor_thr[2], sensor_thr[3], sensor_thr[4], sensor_thr[5]); histr[0] = 0; /*empty string*/ } else { if (sensor_lo != 0xff) { sprintf(lostr,"-l 0x%02x",sensor_lo); } else lostr[0] = 0; if (sensor_hi != 0xff) { sprintf(histr,"-h 0x%02x",sensor_hi); } else histr[0] = 0; } fd = fopen(savefile,"a+"); if (fd == NULL) return(-1); fprintf(fd, "ipmiutil sensor -i 0x%04x -n 0x%02x %s %s\n", id, sensor_num, lostr,histr); fclose(fd); return(rv); } #ifdef NOT_USED #define PICMG_GET_ADDR_INFO 0x01 static int get_picmg_addrinfo(uchar a1, uchar a2, uchar *addrdata) { uchar idata[5]; uchar rdata[16]; int rlen; ushort icmd; uchar ilen, cc; int rv; idata[0] = 0x00; idata[1] = 0x00; idata[2] = 0x03; idata[3] = a1; /* 01 thru 0f */ idata[4] = a2; /* 00, 01 thru 09 */ ilen = 5; rlen = sizeof(rdata); icmd = PICMG_GET_ADDR_INFO | (NETFN_PICMG << 8); rv = ipmi_cmd_mc(icmd, idata, ilen, rdata, &rlen, &cc, fdebug); if (rv == 0 && cc != 0) rv = cc; if (rv == 0) { if (fdebug) { printf("picmg_addr(%02x,%02x)",a1,a2); dump_buf("picmg_addr",rdata,rlen,0); } memcpy(addrdata,rdata,rlen); } return(rv); } #endif #ifdef WIN32 static int get_filesize(char *fileName, ulong *psize) { int rv; WIN32_FILE_ATTRIBUTE_DATA fileInfo; if (fileName == NULL) return -1; if (psize == NULL) return -1; rv = GetFileAttributesEx(fileName, GetFileExInfoStandard, (void*)&fileInfo); if (!rv) return -1; *psize = (long)fileInfo.nFileSizeLow; return 0; } #endif int write_sdr_binfile(char *binfile) { uchar *pbuf = NULL; FILE *fp; int len, ret; ret = get_sdr_cache(&pbuf); /* sets nsdrs, sz_sdrs */ if (ret == 0) { fp = fopen(binfile,"wb"); if (fp == NULL) { ret = get_LastError(); printf("Cannot open file %s for writing, error %d\n",binfile,ret); } else { printf("Writing SDR size %d to %s ...\n",sz_sdrs,binfile); len = (int)fwrite(pbuf, 1, sz_sdrs, fp); fclose(fp); if (len <= 0) { ret = get_LastError(); printf("Error %d writing file %s\n",ret,binfile); } else ret = 0; } free_sdr_cache(pbuf); } return(ret); } int read_sdr_binfile(char *binfile, uchar **pbufret, int *buflen) { uchar *pbuf = NULL; FILE *fp; int len; int ret; #ifdef WIN32 { ulong flen; ret = get_filesize(binfile, &flen); if (ret == 0) len = flen; else { ret = get_LastError(); printf("Cannot get file size for %s, error %d\n",binfile,ret); return(ret); } } #endif fp = fopen(binfile,"rb"); if (fp == NULL) { ret = get_LastError(); printf("Cannot open file %s, error %d\n",binfile,ret); return(ret); } fseek(fp, 0L, SEEK_SET); #ifndef WIN32 { /*not windows but Linux, etc.*/ struct stat st; /* use fstat to get file size and allocate buffer */ ret = fstat(fileno(fp), &st); len = st.st_size; /*file size in bytes*/ if (ret != 0) { ret = get_LastError(); printf("Cannot stat file %s, error %d\n",binfile,ret); return(ret); } } #endif /* Could estimate size for nsdrs*SDR_SZ, but we don't yet know nsdrs. * It is better to use the real file size detected above. */ sz_sdrs = len; pbuf = malloc(len); if (fdebug) printf("sdr_binfile: malloc(%d) pbuf=%p\n",len,pbuf); if (pbuf == NULL) { ret = -2; fclose(fp); return(ret); } psdrcache = pbuf; /*ok, so proceed with restore*/ ret = 0; len = (int)fread(pbuf, 1, sz_sdrs, fp); if (len <= 0) { ret = get_LastError(); printf("Error %d reading file %s\n",ret,binfile); sz_sdrs = 0; /*for safety*/ } else if (len < sz_sdrs) { /* Show error if this happens in Windows */ ret = get_LastError(); printf("truncated fread(%s): attempted %d, got %d, error %d\n", binfile,sz_sdrs,len,ret); ret = 0; /*try to keep going*/ } fclose(fp); if (fdebug) { printf("SDR buffer from file (len=%d,sz=%d)\n",len,sz_sdrs); dump_buf("SDR buffer",pbuf,len,1); } *pbufret = pbuf; *buflen = len; return(ret); } #ifdef ALONE #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #else /* METACOMMAND or libipmiutil */ int i_sensor(int argc, char **argv) #endif { int ret, rv; int c; int recid, recnext; uchar sdrdata[MAX_BUFFER_SIZE]; uchar devrec[16]; int sz, i, j; int fsetfound = 0; int iloop, irec; int ipass, npass; uchar *pset; char *p; char *s1; printf("%s version %s\n",progname,progver); while ( (c = getopt( argc, argv,"a:bcd:ef:g:h:i:j:k:l:m:n:opqrstu:vwxT:V:J:L:EYF:P:N:R:U:Z:?")) != EOF ) switch(c) { case 'a': /* reArm sensor number N */ if (strncmp(optarg,"0x",2) == 0) frearm = htoi(&optarg[2]); else frearm = htoi(optarg); /*was atoi()*/ break; case 'c': fsimple = 1; break; /* Canonical/simple output*/ case 'd': fdump = 1; /* Dump SDRs to a file*/ binfile = optarg; break; case 'b': fchild = 1; break; /* Bladed, so get child SDRs */ case 'e': fchild = 1; break; /* Extra bladed child SDRs */ case 'f': frestore = 1; /* Restore SDRs from a file*/ binfile = optarg; break; case 's': fsimple = 1; break; /* Simple/canonical output */ /*fcanonical==fsimple*/ case 'g': rv = get_group_id(optarg); if (rv < 0) { printf("Unrecognized sensor type group (%s)\n",optarg); ret = ERR_BAD_PARAM; goto do_exit; } else fshowgrp = rv; if (fdebug) printf("num sensor type groups = %d\n",fshowgrp); break; case 'i': fshowidx = 1; get_idx_range(optarg); break; case 'j': fjumpstart = 1; /* Load SDR cache from a file*/ binfile = optarg; break; case 'k': loopsec = atoi(optarg); break; /*N sec between loops*/ case 'm': /* specific MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; printf("set MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'o': fgetmem = 1; break; case 'n': if (strncmp(optarg,"0x",2) == 0) i = htoi(&optarg[2]); else i = htoi(optarg); /*was atoi()*/ sensor_num = (uchar)i; printf("sensor_num = 0x%x\n",sensor_num); break; case 'h': /* highest threshold */ if (strncmp(optarg,"0x",2) == 0) { i = htoi(&optarg[2]); sensor_hi = (uchar)i; fsetthresh = 1; } else { sensor_hi_f = atof(optarg); fsetthresh = 2; /*indicates float conversion*/ } break; case 'l': /* lowest threshold */ if (strncmp(optarg,"0x",2) == 0) { i = htoi(&optarg[2]); sensor_lo = (uchar)i; fsetthresh = 1; } else { sensor_lo_f = atof(optarg); fsetthresh = 2; /*indicates float conversion*/ } break; case 'p': fsavethresh = 1; break; case 'q': fshowthr = 2; fwrap = 1; break; case 'r': frawsdr = 1; break; case 't': fshowthr = 1; break; case 'v': fshowthr = 1; sens_verbose = 1; break; case 'u': /* specify unique thresholds in hex or float */ /* raw hex format: 0xLNLCLUHNHCHU, all 6 required */ if (strncmp(optarg,"0x",2) == 0) { /*raw hex thresholds*/ sensor_thr[0] = htoi(&optarg[2]); /*lo noncrit*/ sensor_thr[1] = htoi(&optarg[4]); /*lo crit*/ sensor_thr[2] = htoi(&optarg[6]); /*lo unrec*/ sensor_thr[3] = htoi(&optarg[8]); /*hi noncrit*/ sensor_thr[4] = htoi(&optarg[10]); /*hi crit*/ sensor_thr[5] = htoi(&optarg[12]); /*hi unrec*/ /* validate sensor threshold ordering */ rv = validate_thresholds(&sensor_thr[0],0,NULL); if (rv == 0) { sensor_lo = sensor_thr[0]; sensor_hi = sensor_thr[3]; fsetthresh = 3; /*indicates unique raw thresholds */ } else { ret = ERR_BAD_PARAM; goto do_exit; } } else { /* assume float input thresholds, with ':' separator*/ /* format LN:LC:LU:HN:HC:HU */ sz = strlen_(optarg); p = &optarg[0]; for (i = 0; i < 6; i++) sensor_thrf[i] = THR_EMPTY; j = 0; for (i = 0; i <= sz; i++) { if (j >= 6) break; switch(optarg[i]) { case ':': case '\n': case '\0': optarg[i] = 0; if (p[0] == 0) sensor_thrf[j] = THR_EMPTY; else sensor_thrf[j] = atof(p); if (i+1 < sz) p = &optarg[i+1]; j++; break; default: break; } } /* validate sensor threshold ordering later */ // rv = validate_thresholds(&sensor_thrf[0],1,NULL); // if (rv == 0) { sensor_lo_f = sensor_thrf[0]; sensor_hi_f = sensor_thrf[3]; fsetthresh = 4; /*indicates unique float thresholds */ // } else { // ret = ERR_BAD_PARAM; // goto do_exit; // } } /*end-else -u float thresholds*/ break; case 'w': fwrap = 1; break; case 'x': fdebug = 1; break; case 'L': /* Loop */ nloops = atoi(optarg); fdoloop = 1; break; case 'V': /* priv level */ fprivset = 1; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: /*usage*/ printf("Usage: %s [-abcdefghijlmnprstuvwxL -NUPREFTVYZ]\n",progname); printf("where -x shows eXtra debug messages\n"); printf(" -a snum reArms the sensor (snum) for events\n"); printf(" -b show Bladed child MCs for PICMG (same as -e)\n"); printf(" -c displays a simpler, Canonical output fmt\n"); printf(" -d file Dump SDRs to a binary file\n"); printf(" -e show Every bladed child MC for PICMG\n"); // printf(" -f file Restore SDRs from a binary dump file\n"); printf(" -g fan show only this sensor type group\n"); printf(" -h tval specifies the Highest threshold to set\n"); printf(" -i id only show these sensor id numbers\n"); printf(" -j file Jump-start SDR cache from a binary file\n"); printf(" -k K If -L, wait K sec between loops (default=1)\n"); printf(" -l tval specifies the Lowest threshold to set\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -n snum specifies the sensor Number to set hi/lo\n"); printf(" -o output memory DIMM information\n"); printf(" -p persist the threshold being set\n"); printf(" -q shows threshold values in d:d:d format\n"); printf(" -r show Raw SDR bytes\n"); printf(" -s displays a Simpler output format\n"); printf(" -t shows Threshold values in text format\n"); printf(" -u thr set Unique threshold values (e.g. 3:2:1:48:49:50)\n"); printf(" -v Verbose: thresholds, max/min, hysteresis\n"); printf(" -w Wrap thresholds on sensor line\n"); printf(" -L n Loop n times every k seconds (default k=1)\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto do_exit; } if (fjumpstart && fchild) { printf("Cannot use -j jumpstart cache with -c child SDRs\n"); ret = ERR_BAD_PARAM; goto do_exit; } fremote = is_remote(); #ifndef WIN32 if (fremote == 0) { /* only run this as superuser for accessing IPMI devices. */ i = geteuid(); if (i > 1) { printf("Not superuser (%d)\n", i); /* Show warning, but could be ok if /dev/ipmi0 is accessible */ //ret = ERR_NOT_ALLOWED; //goto do_exit; } } #endif if (fremote) { if (!fprivset) { /* on many systems, getting the SDR Reservation ID requires admin */ /* if ((fsetthresh != 0) || (frearm != 0)) also require admin */ parse_lan_options('V',"4",0); } } ret = ipmi_getdeviceid(devrec,sizeof(devrec),fdebug); if (ret == 0) { uchar ipmi_maj; uchar ipmi_min; char *pstr; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; if ((devrec[1] & 0x80) == 0x80) fdevsdrs = 1; vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); if (vend_id == VENDOR_NSC) { /*NSC mBMC*/ pstr = "mBMC"; fmBMC = 1; fdevsdrs = 0; } else if (vend_id == VENDOR_INTEL) { /*Intel BMC*/ /*Intel Sahalee BMC */ pstr = "BMC"; fmBMC = 0; if (is_romley(vend_id,prod_id)) fRomley = 1; if (is_grantley(vend_id,prod_id)) fGrantley = 1; if (prod_id == 0x003E || fRomley || fGrantley) /*Urbanna,CG2100*/ set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/ } else if ((vend_id == VENDOR_SUPERMICRO) || (vend_id == VENDOR_SUPERMICROX)) { set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/ } else if (vend_id == 16394) { /*Pigeon Point*/ fbadsdr = 1; /* SDR has bad sa/mc value, so ignore it */ } else { /* Other products */ pstr = "BMC"; fmBMC = 0; if (vend_id == VENDOR_NEC) fdevsdrs = 0; } show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); // "-- %s version %x.%x, IPMI version %d.%d \n", pstr, } else { goto do_exit; } ret = ipmi_getpicmg( devrec, sizeof(devrec),fdebug); if (ret == 0) fpicmg = 1; /*if not PICMG, some vendors override to SDR Rep*/ fdevsdrs = use_devsdrs(fpicmg); if (fdevsdrs) printf("supports device sdrs\n"); npass = 1; if (g_sa != 0) { /* target a specific MC via IPMB (usu a picmg blade) */ ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); fchild = 0; /* no children, only the specified address */ } else { #ifdef PICMG_CHILD /* fchild set above if -b is specified to get Blade child SDRs */ /* npass = 2 will get both SdrRep & DevSdr passes on CMM */ if (fpicmg && fdevsdrs) { npass = 2; g_addrtype = ADDR_IPMB; } #endif g_sa = BMC_SA; } if (fgetmem) { if (fremote) printf("Cannot get memory DIMM information remotely.\n"); else { int msz; char desc[80]; char szstr[25]; ret = -1; for (j = 0; j < 1; j++) { for (i = 0; i < 16; i++) { rv = get_MemDesc(j, i, desc,&msz); if (rv == 0) { if (msz == 0) strcpy(szstr,"not present"); else if (msz & 0x8000) sprintf(szstr,"size=%dKB",(msz & 0x7FFF)); else sprintf(szstr,"size=%dMB",msz); printf("Memory Device (%d,%d): %s : %s\n", j,i,desc,szstr); ret = 0; } } } } /*end-else*/ goto do_exit; } if (fdump) { ret = write_sdr_binfile(binfile); goto do_exit; } /*endif fdump*/ if (frestore) { uchar sdr[MAX_BUFFER_SIZE]; ushort id; int slen; uchar *pbuf = NULL; ret = read_sdr_binfile(binfile,&pbuf,&slen); if (ret == 0) { /*successful, so write SDRs */ nsdrs = find_nsdrs(pbuf); printf("Ready to restore %d SDRs\n",nsdrs); set_reserve(1); ret = sdr_clear_repo(fdevsdrs); if (ret != 0) { printf("SDR Clear Repository error %d\n",ret); goto do_exit; } id = 0; while(find_sdr_next(sdr,pbuf,id) == 0) { id = sdr[0] + (sdr[1] << 8); if (fdebug) printf("adding SDR[%x]\n",id); set_reserve(1); ret = sdr_add_record(sdr,fdevsdrs); if (ret != 0) { printf("SDR[%x] add error %d\n",id,ret); break; } } /*end while sdr*/ } if (ret == 0) printf("Restored %d SDRs successfully.\n",nsdrs); free_sdr_cache(pbuf); /* does nothing if (pbuf == NULL) */ goto do_exit; } /*endif frestore*/ if (fjumpstart) { uchar *pbuf = NULL; int slen; ret = read_sdr_binfile(binfile,&pbuf,&slen); if (ret != 0) { /* Try to dump sdrs to this file if not there */ ret = write_sdr_binfile(binfile); if (ret == 0) ret = read_sdr_binfile(binfile,&pbuf,&slen); if (ret != 0) { fjumpstart = 0; /*cannot do jumpstart*/ } } else { /* set this as the SDR cache */ psdrcache = pbuf; sz_sdrs = slen; nsdrs = find_nsdrs(pbuf); if (fdebug) printf("jumpstart cache: nsdrs=%d size=%d\n",nsdrs,slen); } } /*endif fjumpstart*/ for (ipass = 0; ipass < npass; ipass++) { if (fjumpstart) ; /*already got this above*/ else { ret = GetSDRRepositoryInfo(&j,&fdevsdrs); if (fdebug) printf("GetSDRRepositoryInfo: ret=%x nSDRs=%d\n",ret,j); if (ret == 0 && j == 0) { printf("SDR Repository is empty\n"); goto do_exit; } nsdrs = j; } /* show header for SDR records */ if (fsimple) printf(" ID | SDRType | Type |SNum| Name |Status| Reading\n"); else printf("_ID_ SDR_Type_xx ET Own Typ S_Num Sens_Description Hex & Interp Reading\n"); if (fwrap) chEol = ' '; if (!fdoloop) nloops = 1; for (iloop = 0; iloop < nloops; iloop++) { if (fshowidx) recid = sensor_idx1; else recid = 0; irec = 0; /*first sdr record*/ while (recid != 0xffff) { if (fjumpstart) { if (irec == 0) /*need sdr_by_id if fshowid recid>0*/ ret = find_sdr_by_id(sdrdata,psdrcache,recid); else ret = find_sdr_next(sdrdata,psdrcache,recid); if (ret != 0) { /*end of sdrs*/ if (fdebug) printf("find_sdr_next(%04x): ret = %d\n", recid,ret); ret = 0; break; } recnext = sdrdata[0] + (sdrdata[1] << 8); /*same as recid*/ if (fdebug) printf("find_sdr_next(%04x): ret = %d, next=%04x\n", recid,ret,recnext); if (recid > 0 && recnext == 0) { if (fdebug) printf("Error recid=%04x recnext=%04x\n",recid,recnext); ret = 0; break; } sz = sdrdata[4] + 5; } else { int try; for (try = 0; try < 10; try++) { ret = GetSDR(recid,&recnext,sdrdata,sizeof(sdrdata),&sz); if (fdebug) printf("GetSDR[%04x]: ret = %x, next=%x\n",recid,ret,recnext); if (ret != 0) { if (ret == 0xC5) { /* lost Reservation ID, retry */ /*fprintf(stderr,"%04x lost reservation retrying to get, try: %d, %d, rlen = %d\n", recid,try,ret,sz);*/ os_usleep((rand() & 3000),0); fDoReserve = 1; } else { fprintf(stderr,"%04x GetSDR error %d, rlen = %d\n", recid,ret,sz); break; } } else { break; } if (try==9){ sz=0; fprintf(stderr,"%04x GetSDR error %d, rlen = %d\n", recid,ret,sz); } } if (sz < MIN_SDR_SZ) { /* don't have recnext, so abort */ break; } /* else fall through & continue */ } /*end-else*/ if (ret == 0) { /* (ret == 0) OK, got full SDR */ if (fdebug) { dump_buf("got SDR",sdrdata,sz,0); } if (sz < MIN_SDR_SZ) goto NextSdr; /* if recid == 0, get real record id */ if (recid == 0) recid = sdrdata[0] + (sdrdata[1] << 8); if (fshowgrp > 0) { for (i = 0; i < fshowgrp; i++) { uchar styp; if (sdrdata[3] == 0x03) styp = sdrdata[10]; /*EvtOnly*/ else styp = sdrdata[12]; if (fdebug) printf("sdrt=%02x styp=%02x sgrp[%d]=%02x\n", sdrdata[3],styp,i,sensor_grps[i]); if (sdrdata[3] == 0xc0) continue; /*skip OEM SDRs*/ if (styp == sensor_grps[i]) break; } if (i >= fshowgrp) goto NextSdr; } if ((sensor_num == INIT_SNUM) || (sdrdata[7] == sensor_num) || fsetthresh) { /* if -n not set or if -n matches, parse and show the SDR */ ShowSDR("",sdrdata); } /* else filter SDRs if not matching -n sensor_num */ #ifdef PICMG_CHILD /* * Special logic for blade child MCs in PICMG ATCA systems * if fchild, try all child MCs within the chassis. * SDR type 12 capabilities bits (sdrdata[8]): * 80 = Chassis Device * 40 = Bridge * 20 = IPMB Event Generator * 10 = IPMB Event Receiver * 08 = FRU Device * 04 = SEL Device * 02 = SDR Repository Device * 01 = Sensor Device * But all child MCs use Device SDRs anyway. */ if (fpicmg && fchild && (sdrdata[3] == 0x12)) { /* PICMG MC DLR */ int _recid, _recnext, _sz; uchar _sdrdata[MAX_SDR_SIZE]; int devsdrs_save; uchar cc; /* save the BMC globals, use IPMB MC */ devsdrs_save = fdevsdrs; fdevsdrs = 1; /* use Device SDRs for the children*/ if (fdebug) printf(" --- IPMB MC (sa=%02x cap=%02x id=%02x devsdrs=%d):\n", sdrdata[5],sdrdata[8],sdrdata[12],fdevsdrs); fDoReserve = 1; /* get a new SDR Reservation ID */ ipmi_set_mc(PICMG_SLAVE_BUS,sdrdata[5],sdrdata[6],g_addrtype); _sz = 16; ret = ipmi_cmd_mc(GET_DEVICE_ID,NULL,0,_sdrdata,&_sz,&cc,fdebug); if (ret == 0 && cc == 0) { /* Get the SDRs from the IPMB MC */ _recid = 0; while (_recid != 0xffff) { ret = GetSDR(_recid,&_recnext,_sdrdata,sizeof(_sdrdata),&_sz); if (ret != 0) { fprintf(stderr,"%04x GetSDR error %d, rlen = %d\n",_recid,ret,_sz); break; } else if (_sz >= MIN_SDR_SZ) ShowSDR(" ",_sdrdata); if (_recnext == _recid) _recid = 0xffff; else _recid = _recnext; } /*end while*/ } /*endif ret==0*/ /* restore BMC globals */ fdevsdrs = devsdrs_save; ipmi_restore_mc(); fDoReserve = 1; /* get a new SDR Reservation ID */ } /*endif fpicmg && fchild*/ #endif if (fdebug) printf("fsetthresh=%d snum=%02x(%02x) sa=%02x(%02x)\n", fsetthresh,sdrdata[7],sensor_num,sdrdata[5],g_sa); if (fsetthresh && (sdrdata[7] == sensor_num) && (sdrdata[5] == g_sa)) /*g_sa usu is BMC_SA*/ { /* setting threshold, compute threshold raw values */ if (fsetthresh == 2) { /*set from float*/ if (fdebug) printf("lof=%.2f hif=%.2f\n", sensor_lo_f,sensor_hi_f); if (sensor_lo_f != 0) sensor_lo = FloatToRaw(sensor_lo_f,sdrdata,0); if (sensor_hi_f != 0) sensor_hi = FloatToRaw(sensor_hi_f,sdrdata,0); } else if (fsetthresh == 1) { /*raw thresholds*/ if (sensor_hi != 0xff) sensor_hi_f = RawToFloat(sensor_hi,sdrdata); if (sensor_lo != 0xff) sensor_lo_f = RawToFloat(sensor_lo,sdrdata); } else if (fsetthresh == 3) { /*unique raw thresholds*/ if (sensor_hi != 0xff) sensor_hi_f = RawToFloat(sensor_hi,sdrdata); if (sensor_lo != 0xff) sensor_lo_f = RawToFloat(sensor_lo,sdrdata); } else if (fsetthresh == 4) { /*set unique from float*/ i = fill_thresholds(&sensor_thrf[0], sdrdata); /* if (i > 0) ; * filled in some thresholds */ { /* always set lo/hi if any are non-zero */ for (j = 0; j < 3; j++) { if (sensor_thrf[j] != 0) { sensor_lo_f = sensor_thrf[j]; break; } } for (j = 3; j < 6; j++) { if (sensor_thrf[j] != 0) { sensor_hi_f = sensor_thrf[j]; break; } } } if (fdebug) printf("lof=%.2f hif=%.2f\n", sensor_lo_f,sensor_hi_f); /* convert thrf (float) to thr (raw) */ if (sensor_lo_f != 0) { sensor_lo = FloatToRaw(sensor_lo_f,sdrdata,0); sensor_thr[0] = FloatToRaw(sensor_thrf[0],sdrdata,0); sensor_thr[1] = FloatToRaw(sensor_thrf[1],sdrdata,0); sensor_thr[2] = FloatToRaw(sensor_thrf[2],sdrdata,0); } if (sensor_hi_f != 0) { sensor_hi = FloatToRaw(sensor_hi_f,sdrdata,0); sensor_thr[3] = FloatToRaw(sensor_thrf[3],sdrdata,0); sensor_thr[4] = FloatToRaw(sensor_thrf[4],sdrdata,0); sensor_thr[5] = FloatToRaw(sensor_thrf[5],sdrdata,0); } /* validate threshold ordering */ if (validate_thresholds(sensor_thrf,1,sdrdata) != 0) { ret = ERR_BAD_PARAM; goto do_exit; } } { printf("\tSetting SDR %04x sensor %02x to lo=%02x hi=%02x\n", recid,sensor_num,sensor_lo,sensor_hi); if (recid == 0) fsetfound = 1; else fsetfound = recid; } } /*endif fsetthresh */ } /*endif ok, got full SDR */ NextSdr: if (ret == ERR_SDR_MALFORMED) break; if (fjumpstart) recid = recnext; else { if (recnext == recid) recid = 0xffff; /*break;*/ else recid = recnext; } if (fshowidx) { /* if we have already read the last in the range, done. */ if (recid >= sensor_idxN) break; // recnext = 0xffff; // break; } irec++; } /*end while recid*/ if (fdoloop && (nloops > 1)) { printf("\n"); /* output an empty separator line */ os_usleep(loopsec,0); /*delay 1 sec between loops*/ } } /*end for nloops*/ if (npass > 1) { /* npass==2 for PICMG */ /* Switch fdevsdrs from Device to Repository */ if (fdevsdrs == 0) fdevsdrs = 1; else fdevsdrs = 0; fDoReserve = 1; /* get a new SDR Reservation ID */ } } /*end for npass*/ if ((fshowidx == 0) && (fshowgrp == 0)) { /* use local rv, errors are ignored for POH */ rv = ShowPowerOnHours(); } if (frearm != 0) { ret = RearmSensor((uchar)frearm); printf("RearmSensor(0x%02x) ret = %d\n",frearm,ret); } if (fsetthresh != 0) { uchar tdata[7]; if (fsetfound == 0) { printf("Did not find sensor number %02x.\nPlease enter the sensor number parameter in hex, as it is displayed above.\n",sensor_num); } ret = GetSensorThresholds(sensor_num,tdata); if (ret != 0) goto do_exit; #ifdef TEST printf("thresh(%02x): %02x %02x %02x %02x %02x %02x %02x %02x\n", sensor_num, sensor_num, tdata[0], tdata[1], tdata[2], tdata[3], tdata[4], tdata[5], tdata[6]); printf(" set(%02x): %02x %02x \n", sensor_num,sensor_lo,sensor_hi); #endif if (fsetthresh == 3 || fsetthresh == 4) { /* apply unique sensor thresholds */ pset = &sensor_thr[0]; } else pset = NULL; /* use just hi/lo */ ret = SetSensorThresholds(sensor_num,sensor_hi,sensor_lo,tdata,pset); printf("SetSensorThreshold[%02x] to lo=%02x(%4.3f) hi=%02x(%4.3f), ret = %d\n", sensor_num,sensor_lo,sensor_lo_f,sensor_hi,sensor_hi_f,ret); if (fsavethresh && ret == 0) { recid = fsetfound; rv = SaveThreshold(recid,sensor_num,sensor_lo,sensor_hi,pset); if (rv == 0) printf("Saved thresholds for sensor %02x\n",sensor_num); } fsetthresh = 0; /*only set threshold once*/ } do_exit: // if (fjumpstart) free_sdr_cache(psdrcache); /* does nothing if ==NULL*/ /* show_outcome(progname,ret); *handled in ipmiutil.c*/ ipmi_close_(); return(ret); } /* end isensor.c */ ipmiutil-3.1.9/util/oem_lenovo.c0000644000000000000000000004057114144515623015355 0ustar rootroot/* * oem_lenovo.c * Handle Lenovo OEM command functions * * Author: Andy Cress arcress at users.sourceforge.net * Change history: * 11/21/2016 ARCress - created * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2016 Andy Cress All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of the copyright holder nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #ifdef WIN32 #include #include "getopt.h" #else #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #else #include #endif #endif #include #include #include #include #include "ipmicmd.h" #include "ievents.h" #include "oem_lenovo.h" extern uchar bitnum(ushort value); /*isensor.c*/ extern char fdebug; /*ipmicmd.c*/ void set_loglevel(int level); /*prototype */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil lenovooem"; #else static char * progver = "3.08"; static char * progname = "ilenovooem"; #endif static int verbose = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int vend_id = 0; static int prod_id = 0; /* See oem_ibm_sel_map from ipmitool contrib, interpretation not verified yet */ #define NIBMEVT 16 struct { uchar stype; uchar snum; uchar etype; uchar data1; uchar data2; uchar data3; uchar sev; char *desc; } oem_ibm_events[NIBMEVT] = { 0xC1, 0xFF, 0xFF, 0xFF, 0x01, 0x00, SEV_MIN, "CPU shutdown - Potential cause 'triple fault' a software address problem", 0xC1, 0xFF, 0xFF, 0xFF, 0x02, 0x01, SEV_INFO, "Memory Mirrored Failover Occurred - System running from mirrored memory image", 0xC1, 0xFF, 0xFF, 0xFF, 0x02, 0x04, SEV_INFO, "Memory hot replace event", 0xC1, 0xFF, 0xFF, 0xFF, 0x02, 0x05, SEV_INFO, "Memory hot add event", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x00, SEV_INFO, "Scalability link down", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x01, SEV_INFO, "Scalability link up", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x02, SEV_INFO, "Scalability link double wide down", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x03, SEV_INFO, "Scalability link double wide up", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x80, SEV_INFO, "Scalability link PFA", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x81, SEV_INFO, "Scalability link invalid port", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x82, SEV_INFO, "Scalability link invalid node", 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0x83, SEV_INFO, "Scalability link kill", 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, SEV_INFO, "Device OK", 0xE0, 0x00, 0x01, 0xFF, 0xFF, 0xFF, SEV_MAJ, "Required ROM space not available", 0xE0, 0x00, 0x02, 0xFF, 0xFF, 0xFF, SEV_MAJ, "Required I/O Space not available", 0xE0, 0x00, 0x03, 0xFF, 0xFF, 0xFF, SEV_MAJ, "Required memory not available" }; /*------------------------------------------------------------------------ * get_ibm_desc * Uses the oem_ibm_events to decode IBM events not otherwise handled. * Called by decode_sel_lenovo *------------------------------------------------------------------------*/ char * get_ibm_desc(uchar type, uchar num, uchar trig, uchar data1, uchar data2, uchar data3, uchar *sev) { int i; char *pstr = NULL; /* Use oem_ibm_events array for other misc descriptions */ data1 &= 0x0f; /*ignore top half of sensor offset for matching */ for (i = 0; i < NIBMEVT; i++) { if ((oem_ibm_events[i].stype == 0xff) || (oem_ibm_events[i].stype == type)) { if (oem_ibm_events[i].snum != 0xff && oem_ibm_events[i].snum != num) continue; if (oem_ibm_events[i].etype != 0xff && oem_ibm_events[i].etype != trig) continue; if (oem_ibm_events[i].data1 != 0xff && (oem_ibm_events[i].data1 & 0x0f) != (data1 & 0x0f)) continue; if (oem_ibm_events[i].data2 != 0xff && oem_ibm_events[i].data2 != data2) continue; if (oem_ibm_events[i].data3 != 0xff && oem_ibm_events[i].data3 != data3) continue; /* have a match, use description */ pstr = (char *)oem_ibm_events[i].desc; if (sev != NULL) *sev = oem_ibm_events[i].sev; break; } } /*end for*/ return(pstr); } /* end get_ibm_desc() */ /* * decode_sensor_lenovo * inputs: * sdr = the SDR buffer * reading = the 3 or 4 bytes of data from GetSensorReading * pstring = points to the output string buffer * slen = size of the output buffer * outputs: * rv = 0 if this sensor was successfully interpreted here, * non-zero otherwise, to use default interpretations. * pstring = contains the sensor reading interpretation string (if rv==0) */ int decode_sensor_lenovo(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; uchar stype, etype, entity; uchar bval; ushort rval; char *pstr = NULL; int b; int vend, prod; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); /* sdr[3] is 0x01 for Full, 0x02 for Compact */ bval = reading[2]; if (sdr[3] == 0x01) return(rv); /*skip if full sensor*/ entity = sdr[8]; stype = sdr[12]; etype = sdr[13]; rval = reading[2] | ((reading[3] & 0x7f) << 8); b = bitnum(rval); get_mfgid(&vend,&prod); /*saved from ipmi_getdeviceid */ if (fdebug) printf("oem_lenovo: mfg=%04x:%04x sensor type=%x evt=%x entity=%x rval=%04x\n", vend,prod,stype,etype,entity,rval); switch(stype) { case 0x07: /* CPU sensor type */ if ((etype == 0x6F) && (entity == 25)) { /*All CPUs*/ switch(b) { case 0x00: pstr = "OK"; break; case 0x02: pstr = "BIST_Fail"; break; case 0x05: pstr = "Config_Error"; break; case 0x06: pstr = "Uncorr_Error"; break; case 0x08: pstr = "Disabled"; break; default: pstr = "OK*"; break; } rv = 0; } else if ((etype == 0x6F) && (entity == 3)) { /*CPU status*/ /* Special CPU status reported on IBM/Lenovo */ switch(rval) { case 0x00: pstr = "Absent"; break; case 0x80: pstr = "Present"; break; default: pstr = "Error"; break; } rv = 0; } break; case 0x0C: /* DIMM slot status */ /* Special DIMM status reported on IBM/Lenovo */ /* IBM x3650 M2 (0x0002, 0x00dc) and * Lenovo x3650 M4 (0x4f4d, 0x0143) */ if (etype == 0x6F) { switch(rval) { case 0x00: pstr = "Absent"; break; case 0x40: pstr = "Present"; break; default: pstr = "Error"; break; } rv = 0; } break; case 0x0D: /* Disk Drive slots */ if (etype == 0x6F) { switch(bval) { case 0x00: pstr = "Absent"; break; case 0x01: pstr = "Present"; break; case 0x21: pstr = "NotRedundant"; break; case 0x40: pstr = "NotAvailable"; break; /*not initialized*/ default: pstr = "Faulty"; break; /*e.g. 0x03*/ } rv = 0; } break; case 0x0F: /* ABR Status, Firmware Error, Sys Boot Status, etc. */ if (etype == 0x6F) { /* should be entity 0x22 */ if (bval == 0x00) pstr = "OK"; else if (bval & 0x01) pstr = "FirmwareError"; /*bit 0*/ else if ((bval & 0x02) != 0) pstr = "FirmwareHang"; /*bit 1*/ else pstr = "OK*"; rv = 0; } break; case 0x17: /* RSA II Detect, Mem1 Detect (mfg=0002:0077) */ /* mfg=0002:0077 sensor type=17 evt=8 entity=b rval=0002, RSA II*/ /* mfg=0002:0077 sensor type=17 evt=8 entity=8 rval=0002, Mem1 */ switch(rval) { case 0x02: pstr = "OK"; break; default: pstr = "Unknown"; break; } rv = 0; break; case 0x1B: /* Front USB, nvDIMM Cable, etc. */ if (etype == 0x6F) { /* 0x01 = connected/OK, 0x02 = cable connect error */ switch(bval) { case 0x01: pstr = "OK"; break; case 0x02: pstr = "CableError"; break; default: pstr = "OK*"; break; } rv = 0; } break; case 0x1E: /* No Boot Device */ if (etype == 0x6F) { switch(b) { case 0x00: pstr = "OK"; break; /*No Media*/ default: pstr = "Asserted"; break; } rv = 0; } case 0x21: /*All PCI Error, PCI 1, Internal RAID, No Op ROM, etc.*/ if (etype == 0x6F) { if (bval == 0x00) pstr = "OK"; else pstr = "Fault"; rv = 0; } break; case 0x25: /* DASD Backplane*/ /*spec says 00 = Present, 01 = Absent, but not match results*/ /* 0066 SDR Comp 02 6f 20 a 25 snum 20 DASD Backplane 1 = 0001 OK* 0067 SDR Comp 02 6f 20 a 25 snum 21 DASD Backplane 2 = 0000 Absent 0068 SDR Comp 02 6f 20 a 25 snum 22 DASD Backplane 3 = 0000 Absent 0069 SDR Comp 02 6f 20 a 25 snum 23 DASD Backplane 4 = 0000 Absent 006a SDR Comp 02 6f 20 a 25 snum 24 DASD Backplane 5 = 0000 Absent 006b SDR Comp 02 6f 20 a 25 snum 25 DASD Backplane 6 = 0000 Absent */ rv = -1; break; case 0x2B: /* ROM Recovery, Bkup Auto Update, IMM*/ if (etype == 0x6F) { switch(bval) { case 0x00: pstr = "OK"; break; case 0x01: pstr = "Changed"; break; /*entity 0x22*/ case 0x05: pstr = "Invalid"; break; /*entity 0x21*/ case 0x07: pstr = "ChangedOK"; break; /*entity 21,22*/ default: pstr = "_"; break; } rv = 0; } break; case 0x02: /* SysBrd Vol Fault: et 07 8004=error */ if (etype == 0x07) { if ((bval & 0x04) != 0) pstr = "Faulty"; else pstr = "OK"; rv = 0; } break; case 0x28: /* Low Security Jmp et 08 8002=error*/ if (etype == 0x08) { if ((bval & 0x02) != 0) pstr = "Faulty"; else pstr = "OK"; rv = 0; } break; default: break; } if (rv == 0) snprintf(pstring,slen,"%s",pstr); // if (rv == 0) strncpy(pstring, pstr, slen); return(rv); } /* * decode_sel_lenovo * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) */ int decode_sel_lenovo(uchar *evt, char *outbuf, int outsz, char fdesc, char fdbg) { int rv = -1; ushort id; uchar rectype; ulong timestamp; char mybuf[64]; char *type_str = ""; char *pstr = NULL; uchar sevid; ushort genid; uchar snum, etype; uchar data1, data2, data3; fdebug = fdbg; sevid = SEV_INFO; id = evt[0] + (evt[1] << 8); rectype = evt[2]; snum = evt[11]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); etype = evt[12]; data1 = evt[13]; data2 = evt[14]; data3 = evt[15]; if (rectype == 0x02) { sprintf(mybuf,"%02x [%02x %02x %02x]", etype,data1,data2,data3); pstr = get_ibm_desc(evt[10], snum, etype, data1, data2, data3, &sevid); if (pstr != NULL) { type_str = "IBM_type"; rv = 0; } else { switch(evt[10]) { /*sensor type*/ case 0xC0: /* OEM type */ type_str = "OEM_type"; pstr = "OEM Sensor "; sevid = SEV_MAJ; rv = -1; break; default: /*other sensor types*/ break; } } } if (rv == 0) { format_event(id,timestamp, sevid, genid, type_str, snum,NULL,pstr,mybuf,outbuf,outsz); } return(rv); } static void usage(void) { printf("Usage: %s [arg]\n",progname); printf("These commands may not work on all Lenovo systems\n"); } static int ipmi_oemlenovo_main(int argc, char **argv) { int rv = 0; if (strncmp(argv[0],"other",9) == 0) { usage(); rv = ERR_USAGE; } else { usage(); rv = ERR_USAGE; } return(rv); } #ifdef METACOMMAND int i_oemlenovo(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rv = 0; uchar devrec[16]; int c, i; char *s1; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); parse_lan_options('V',"4",0); /*default to admin priv*/ while ( (c = getopt( argc, argv,"m:xzEF:J:N:P:R:T:U:V:YZ:?")) != EOF ) switch(c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 2; /* normal (dbglog if isol) */ verbose = 1; break; case 'z': fdebug = 3; /*full debug (for isol)*/ verbose = 1; break; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: usage(); return(ERR_USAGE); break; } for (i = 0; i < optind; i++) { argv++; argc--; } if (argc == 0) { usage(); return(ERR_USAGE); } rv = ipmi_getdeviceid(devrec,16,fdebug); if (rv == 0) { char ipmi_maj, ipmi_min; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); } rv = ipmi_oemlenovo_main(argc, argv); ipmi_close_(); return(rv); } /* end oem_lenovo.c */ ipmiutil-3.1.9/util/ievents.h0000644000000000000000000000567714144515623014705 0ustar rootroot/* * ievents.h * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2011 Kontron America, Inc. * * 12/12/11 Andy Cress - created */ /*M* Copyright (c) 2011 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Kontron nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ /* Public routines from ievents.c */ int decode_sel_entry( uchar *psel, char *outbuf, int sz); char *decode_entity_id(int id); char *get_sensor_type_desc(uchar stype); char *get_sev_str(int val); void fmt_time(time_t etime, char *buf, int bufsz); int get_sensor_tag(int isdr, int genid, uchar snum, char *tag, uchar *sdr, int szsdr); void format_event(ushort id, time_t timestamp, int sevid, ushort genid, char *ptype, uchar snum, char *psens, char *pstr, char *more, char *outbuf, int outsz); #define DIMM_UNKNOWN "DIMM_unknown" #define DIMM_NUM "DIMM(%d)" /* * set_sel_opts is used to specify options for showing/decoding SEL events. * sensdesc : 0 = simple, no sensor descriptions * 1 = get sensor descriptions from sdr cache * 2 = get sensor descriptions from sensor file (-s) * canon : 0 = normal output * 1 = canonical, delimited output * sdrs : NULL = no sdr cache, dynamically get sdr cache if sensdesc==1 * ptr = use this pointer as existing sdr cache if sensdesc==1 * fdbg : 0 = normal mode * 1 = debug mode * futc : 0 = normal mode * 1 = show raw UTC time */ void set_sel_opts(int sensdsc, int canon, void *sdrs, char fdbg, char futc); /*end ievents.h*/ ipmiutil-3.1.9/util/ifru_picmg.c0000644000000000000000000003702414144515623015336 0ustar rootroot/* * ifru_picmg.c * These are helper routines for FRU PICMG decoding. * * Author: Andy Cress arcress at users.sourceforge.net * * Copyright (c) 2009 Kontron America, Inc. * * 09/08/10 Andy Cress - created */ /*M* Copyright (c) 2010 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Kontron nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #ifdef WIN32 #include #include #include "getopt.h" #else #include #include #include #include #endif #include #include "ipmicmd.h" #include "ipicmg.h" extern int verbose; extern void show_guid(uchar *pguid); /*from ifru.c*/ static char *picmg_link_type(uchar b) { char *s; if (b >= 0xf0 && b <= 0xf3) s = "OEM GUID Definition"; else switch(b) { case 0x01: s = "PICMG 3.0 Base Interface 10/100/1000"; break; case 0x02: s = "PICMG 3.1 Ethernet Fabric Interface"; break; case 0x03: s = "PICMG 3.2 Infiniband Fabric Interface"; break; case 0x04: s = "PICMG 3.3 Star Fabric Interface"; break; case 0x05: s = "PICMG 3.4 PCI Express Fabric Interface"; break; default: s = "Reserved"; break; } return(s); } static char *picmg_if_type(uchar b) { char *s; switch(b) { case 0x00: s = "Base Interface"; break; case 0x01: s = "Fabric Interface"; break; case 0x02: s = "Update Channel"; break; case 0x03: default: s = "Reserved"; break; } return(s); } static char *picmg_chan_type(uchar b) { char *s; switch(b) { case 0x00: case 0x07: s = "PICMG 2.9"; break; case 0x08: s = "Single Port Fabric IF"; break; case 0x09: s = "Double Port Fabric IF"; break; case 0x0a: s = "Full Port Fabric IF"; break; case 0x0b: s = "Base IF"; break; case 0x0c: s = "Update Channel IF"; break; default: s = "Unknown IF"; break; } return(s); } void show_fru_picmg(uchar *pdata, int dlen) { int id, i, j, k, m, n; float f; uchar *p; uchar b0, b1, b2, b3, b4, b5, b6, b7, b8; char *s1, *s2; long l1, l2, l3; id = pdata[3]; i = 5; switch(id) { case FRU_PICMG_BACKPLANE_P2P: printf("\tFRU_PICMG_BACKPLANE_P2P\n"); while (i <= dlen) { b1 = pdata[i]; b2 = pdata[i+1]; b3 = pdata[i+2]; printf("\t Channel Type : %02x - %s\n",b1, picmg_chan_type(b1)); printf("\t Slot Address : %02x\n",b2); printf("\t Channel Count : %02x\n",b3); i += 3; for (j = 0; j < b3; j++) { if (i > dlen) break; if (verbose) printf("\t Channel[%d] : %02x -> %02x in slot %02x\n", j,pdata[i],pdata[i+1],pdata[i+2]); i += 3; } } break; case FRU_PICMG_ADDRESS_TABLE: printf("\tFRU_PICMG_ADDRESS_TABLE\n"); printf("\t Type/Len : %02x\n", pdata[i++]); printf("\t Shelf Addr : "); for (j = 0; j < 20; j++) printf("%02x ",pdata[i++]); printf("\n"); n = pdata[i++]; printf("\t AddrTable Entries: %02x\n",n); for (j = 0; j < n; j++) { if (i >= dlen) break; printf("\t HWAddr %02x, SiteNum %02x, SiteType %02x\n", pdata[i], pdata[i+1], pdata[i+2]); i += 3; } break; case FRU_PICMG_SHELF_POWER_DIST: printf("\tFRU_PICMG_SHELF_POWER_DIST\n"); n = pdata[i++]; printf("\t Num Power Feeds : %02x\n",n); for (j = 0; j < n; j++) { if (i >= dlen) break; printf("\t Max Ext Current : %04x\n", (pdata[i] | (pdata[i+1] << 8))); i += 2; printf("\t Max Int Current : %04x\n", (pdata[i] | (pdata[i+1] << 8))); i += 2; printf("\t Min Exp Voltage : %02x\n", pdata[i++]); m = pdata[i++]; /*num entries*/ printf("\t Feed to FRU count: %02x\n", m); for (k = 0; k < m; k++) { if (i >= dlen) break; printf("\t HW: %02x",pdata[i++]); printf(" FRU ID: %02x\n",pdata[i++]); } } break; case FRU_PICMG_SHELF_ACTIVATION: printf("\tFRU_PICMG_SHELF_ACTIVATION\n"); printf("\t Allowance for FRU Act Readiness : %02x\n", pdata[i++]); n = pdata[i++]; printf("\t FRU activation and Power desc Cnt: %02x\n",n); for (j = 0; j < n; j++) { if (i >= dlen) break; printf("\t HW Addr: %02x, ", pdata[i++]); printf(" FRU ID: %02x, ", pdata[i++]); printf(" Max FRU Power: %04x, ", pdata[i] | (pdata[i+1]<<8)); i += 2; printf(" Config: %02x\n", pdata[i++]); } break; case FRU_PICMG_SHMC_IP_CONN: printf("\tFRU_PICMG_SHMC_IP_CONN\n"); printf("\t Conn Data: "); for ( ; i < dlen; i++) { printf("%02x ",pdata[i]); } printf("\n"); break; case FRU_PICMG_BOARD_P2P: /*0x14*/ printf("\tFRU_PICMG_BOARD_P2P\n"); n = pdata[i++]; /*guid count*/ printf("\t GUID count : %d\n",n); for (j = 0; j < n; j++) { printf("\t GUID[%d] : ",j); show_guid(&pdata[i]); printf("\n"); i += 16; } for (j = 1; i < dlen; i += 4) { p = &pdata[i]; b1 = (p[0] & 0x3f); /*chan*/ b2 = (p[0] & 0xc0) >> 6; /*if*/ b3 = (p[1] & 0x0f); /*port*/ b4 = ((p[1] & 0xf0) >> 4) + (p[2] & 0xf0); /*type*/ b5 = (p[2] & 0x0f); /*ext*/ b6 = p[3]; /*grouping*/ printf("\t Link%d Grouping : %02x\n",j,b6); printf("\t Link%d Extension : %02x\n",j,b5); printf("\t Link%d Type : %02x - %s\n", j,b4,picmg_link_type(b4)); printf("\t Link%d Port : %02x\n",j,b3); printf("\t Link%d Interface : %02x - %s\n", j,b2,picmg_if_type(b2)); printf("\t Link%d Channel : %02x\n",j,b1); j++; } break; case FRU_AMC_CURRENT: printf("\tFRU_AMC_CURRENT\n"); b1 = pdata[i]; /*current*/ f = (float)(b1/10.0); printf("\t Current draw: %.1f A @ 12V => %.2f Watt\n", f, (f*12.0)); break; case FRU_AMC_ACTIVATION: printf("\tFRU_AMC_ACTIVATION\n"); b1 = pdata[i] | (pdata[i+1]<<8); /*max current*/ i += 2; f = (float)b1 / 10; printf("\t Max Internal Current(@12V) : %.2f A [ %.2f Watt ]\n", f, f*12); printf("\t Module Activation Readiness: %i sec.\n",pdata[i++]); n = pdata[i++]; printf("\t Descriptor Count: %i\n",n); for (j = 0; i < dlen; i += 3) { if (j >= n) break; printf("\t IPMB Address : %02x\n",pdata[i]); printf("\t Max Module Current: %.2f A\n", (float)(pdata[i+1]/10)); j++; } break; case FRU_AMC_CARRIER_P2P: printf("\tFRU_AMC_CARRIER_P2P\n"); for ( ; i < dlen; ) { b1 = pdata[i]; /*resource id*/ n = pdata[i+1]; /*desc count*/ i += 2; b2 = (b1 >> 7); printf("\t Resource ID: %i, Type: %s\n", (b1 & 0x07), (b2 == 1 ? "AMC" : "Local")); printf("\t Descriptor Count: %i\n",n); for (j = 0; j < n; j++) { if (i >= dlen) break; p = &pdata[i]; b3 = p[0]; /*remote resource id*/ b4 = (p[1] & 0x1f); /*remote port*/ b5 = (p[1] & 0xe0 >> 5) + (p[2] & 0x03 << 3); /*local*/ printf("\t Port %02d -> Remote Port %02d " "[ %s ID: %02d ]\n", b5, b4, ((b3 >> 7) == 1)? "AMC " : "local", b3 & 0x0f); i += 3; } } break; case FRU_AMC_P2P: printf("\tFRU_AMC_P2P\n"); n = pdata[i++]; /*guid count*/ printf("\t GUID count : %d\n",n); for (j = 0; j < n; j++) { printf("\t GUID[%d] : ",j); show_guid(&pdata[i]); printf("\n"); i += 16; } b1 = pdata[i] & 0x0f; /*resource id*/ b2 = (pdata[i] & 0x80) >> 7; /*resource type*/ i++; printf("\t Resource ID: %i - %s\n",b1, b2 ? "AMC Module" : "On-Carrier Device"); n = pdata[i++]; /*descriptor count*/ printf("\t Descriptor Count: %i\n",n); for (j = 0; j < n; j++) { /*channel desc loop*/ if (i >= dlen) break; p = &pdata[i]; b0 = p[0] & 0x1f; b1 = ((p[0] & 0xe0) >> 5) + ((p[1] & 0x03) << 3); b2 = ((p[1] & 0x7c) >> 2); b3 = ((p[1] & 0x80) >> 7) + ((p[2] & 0x0f) << 1); printf("\t Lane 0 Port: %i\n",b0); printf("\t Lane 1 Port: %i\n",b1); printf("\t Lane 2 Port: %i\n",b2); printf("\t Lane 3 Port: %i\n",b3); i += 3; } for ( ; i < dlen; i += 5) { /*ext descriptor loop*/ p = &pdata[i]; b0 = p[0]; /*channel id*/ b1 = p[1] & 0x01; /*port flag 0*/ b2 = (p[1] & 0x02) >> 1; /*port flag 1*/ b3 = (p[1] & 0x04) >> 2; /*port flag 2*/ b4 = (p[1] & 0x08) >> 3; /*port flag 3*/ b5 = ((p[1] & 0xf0) >> 4) + ((p[2] & 0x0f) << 4); /*type*/ b6 = (p[2] & 0xf0) >> 4; /*type ext*/ b7 = p[3]; /*group id*/ b8 = (p[4] & 0x03); /*asym match*/ printf("\t Link Designator: Channel ID: %i, " "Port Flag 0: %s%s%s%s\n",b0, b1 ? "o" : "-", b2 ? "o" : "-", b3 ? "o" : "-", b4 ? "o" : "-" ); switch(b5) { /*link type*/ case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE: printf("\t Link Type: %02x - %s\n", b5, "AMC.1 PCI Express"); switch(b6) { /*link type ext*/ case AMC_LINK_TYPE_EXT_PCIE_G1_NSSC: s2 = "Gen 1 capable - non SSC"; break; case AMC_LINK_TYPE_EXT_PCIE_G1_SSC: s2 = "Gen 1 capable - SSC"; break; case AMC_LINK_TYPE_EXT_PCIE_G2_NSSC: s2 = "Gen 2 capable - non SSC"; break; case AMC_LINK_TYPE_EXT_PCIE_G2_SSC: s2 = "Gen 2 capable - SSC"; break; default: s2 = "Invalid"; break; } printf("\t Link Type Ext: %02x - %s\n", b6,s2); break; case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS1: case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS2: printf("\t Link Type: %02x - %s\n", b5, "AMC.1 PCI Express Advanced Switching"); printf("\t Link Type Ext: %02x\n", b6); break; case FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET: s1 = "AMC.2 Ethernet"; printf("\t Link Type: %02x - %s\n", b5,s1); switch(b6) { /*link type ext*/ case AMC_LINK_TYPE_EXT_ETH_1000_BX: s2 = "1000Base-Bx (SerDES Gigabit) Ethernet Link"; break; case AMC_LINK_TYPE_EXT_ETH_10G_XAUI: s2 = "10Gbit XAUI Ethernet Link"; break; default: s2 = "Invalid"; break; } printf("\t Link Type Ext: %02x - %s\n", b6,s2); break; case FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE: printf("\t Link Type: %02x - %s\n", b5, "AMC.3 Storage"); switch(b6) { /*link type ext*/ case AMC_LINK_TYPE_EXT_STORAGE_FC: s2 = "Fibre Channel"; break; case AMC_LINK_TYPE_EXT_STORAGE_SATA: s2 = "Serial ATA"; break; case AMC_LINK_TYPE_EXT_STORAGE_SAS: s2 = "Serial Attached SCSI"; break; default: s2 = "Invalid"; break; } printf("\t Link Type Ext: %02x - %s\n", b6,s2); break; case FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO: printf("\t Link Type: %02x - %s\n", b5, "AMC.4 Serial Rapid IO"); printf("\t Link Type Ext: %02x\n", b6); break; default: printf("\t Link Type: %02x - %s\n", b5, "reserved or OEM GUID"); printf("\t Link Type Ext: %02x\n", b6); break; } /*end switch(link_type)*/ printf("\t Link group Id: %i\n", b7); printf("\t Link Asym Match: %i\n", b8); } /*end ext descriptor loop*/ break; case FRU_AMC_CARRIER_INFO: printf("\tFRU_AMC_CARRIER_INFO\n"); b1 = pdata[i++]; /*extVersion*/ n = pdata[i++]; /*siteCount*/ printf("\t AMC.0 extension version: R%d.%d\n", b1 & 0x0f, (b1 >> 4) & 0x0f); printf("\t Carrier Site Count: %d\n",n); for (j = 0; j < n; j++) { if (i >= dlen) break; printf("\t Site ID: %i\n", pdata[i++]); } break; case FRU_PICMG_CLK_CARRIER_P2P: printf("\tFRU_PICMG_CLK_CARRIER_P2P\n"); b0 = pdata[i++]; n = pdata[i++]; k = (b0 & 0xC0) >> 6; switch(k) { case 0: s1 = "On-Carrier-Device"; break; case 1: s1 = "AMC slot"; break; case 2: s1 = "Backplane"; break; default: s1 = "reserved"; break; } printf("\t Clock Resource ID: %02x, Type: %s\n",b0,s1 ); printf("\t Channel Count : %02x\n",n); for (j = 0; j < n; j++) { b1 = pdata[i++]; /*local channel*/ b2 = pdata[i++]; /*remote channel*/ b3 = pdata[i++]; /*remote resource*/ k = (b3 & 0xC0) >> 6; switch(k) { case 0: s1 = "Carrier-Dev"; break; case 1: s1 = "AMC slot "; break; case 2: s1 = "Backplane "; break; default: s1 = "reserved "; break; } printf("\t CLK-ID: %02x -> %02x [ %s %02x ]\n",b1,b2,s1,b3); } break; case FRU_PICMG_CLK_CONFIG: printf("\tFRU_PICMG_CLK_CONFIG\n"); b0 = pdata[i++]; n = pdata[i++]; printf("\t Clock Resource ID: %02x\n",b0); printf("\t Descriptor Count : %02x\n",n); for (j = 0; j < n; j++) { b1 = pdata[i++]; /*channel id*/ b2 = pdata[i++]; /*control*/ printf("\t CLK-ID: %02x - CTRL %02x [ %12s ]\n", b1, b2, (b2 & 0x01) == 0 ? "Carrier IPMC":"Application"); b3 = pdata[i++]; /*indirect_cnt*/ b4 = pdata[i++]; /*direct_cnt*/ printf("\t Cnt: Indirect %02x / Direct %02x\n",b3,b4); for (k = 0; k < b3; k++) { b5 = pdata[i++]; /*feature*/ b6 = pdata[i++]; /*dep_chn_id*/ printf("\t Feature: %02x [%8s] - ", b5, (b5 & 0x01)==1 ? "Source":"Receiver"); printf("Dep. CLK-ID: %02x\n",b6); } for (k = 0; k < b4; k++) { b5 = pdata[i++]; /*feature*/ b6 = pdata[i++]; /*family*/ b7 = pdata[i++]; /*accuracy*/ l1 = pdata[i] | (pdata[i+1] << 8) | /*frequency*/ (pdata[i+2] << 8) | (pdata[i+3] << 8); i += 4; l2 = pdata[i] | (pdata[i+1] << 8) | /*min frequency*/ (pdata[i+2] << 8) | (pdata[i+3] << 8); i += 4; l3 = pdata[i] | (pdata[i+1] << 8) | /*max frequency*/ (pdata[i+2] << 8) | (pdata[i+3] << 8); i += 4; printf("\t Feature: %02x - PLL: %x / Asym: %s\n", b5, (b5 >> 1) & 0x01, (b5 & 1) ? "Source":"Receiver"); printf("\t Family : %02x - AccLVL: %02x\n", b6, b7); printf("\t FRQ : %-9d, min: %-9d, max: %-9d\n", (int)l1, (int)l2, (int)l3); } } break; case FRU_UTCA_FRU_INFO_TABLE: case FRU_UTCA_CARRIER_MNG_IP: case FRU_UTCA_CARRIER_INFO: case FRU_UTCA_CARRIER_LOCATION: case FRU_UTCA_SHMC_IP_LINK: case FRU_UTCA_POWER_POLICY: case FRU_UTCA_ACTIVATION: case FRU_UTCA_PM_CAPABILTY: case FRU_UTCA_FAN_GEOGRAPHY: case FRU_UTCA_CLOCK_MAPPING: case FRU_UTCA_MSG_BRIDGE_POLICY: case FRU_UTCA_OEM_MODULE_DESC: printf("\tNot yet implemented uTCA record %x\n",id); break; default: printf("\tUnknown PICMG Extension %x\n",id); break; } } /*end show_fru_picmg*/ /*end ifru_picmg.c */ ipmiutil-3.1.9/util/ipmibmc.c0000644000000000000000000001446314144515623014634 0ustar rootroot/*M* // $Workfile: ipmibmc.c $ // $Revision: 1.0 $ // $Modtime: 12 Nov 2008 15:20:14 $ // $Author: arcress at users.sourceforge.net $ // // This implements support for the /dev/bmc interface from // the Solaris 10 IPMI driver. // // 11/12/08 ARC - created *M*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2008, Intel Corporation Copyright (c) 2009 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------*/ #ifdef SOLARIS #include #include #include #include #include #include #include #include #include #include #include #include #include "ipmicmd.h" /* for uchar, NCMDS */ #define MAX_SEND_SIZE 34 #define MAX_RECV_SIZE 33 #define MIN_RQ_SIZE 2 #define MIN_RS_SIZE 3 #define MAX_BUF_SIZE 256 #define MSG_BUF_SIZE 1024 // #define IOCTL_IPMI_KCS_ACTION 0x01 // #define IOCTL_IPMI_INTERFACE_METHOD 0x02 #define BMC_MSG_REQ 1 #define BMC_MSG_RSP 2 #define BMC_MSG_ERR 3 extern ipmi_cmd_t ipmi_cmds[NCMDS]; static int ipmi_fd = -1; typedef struct bmc_rq { uchar netfn; uchar lun; uchar cmd; uchar dlen; uchar data[MAX_SEND_SIZE]; } bmc_rq_t; typedef struct bmc_rs { uchar netfn; uchar lun; uchar cmd; uchar ccode; uchar dlen; uchar data[MAX_RECV_SIZE]; } bmc_rs_t; typedef struct bmc_ioctl_t { bmc_rq_t req; bmc_rs_t rsp; } bmc_ioctl_t; typedef struct bmc_msg { uchar m_type; /* Message type (1=req, 2=resp, 3=error)*/ uint32 m_id; /* Message ID */ uchar reserved[32]; uchar msg[1]; /* Variable length message data */ } bmc_msg_t; int ipmi_open_bmc(char fdebugcmd) { int rc = -1; char *pdev; if (ipmi_fd != -1) return(0); pdev = "/dev/bmc"; ipmi_fd = open(pdev, O_RDWR); if (ipmi_fd == -1) { if (fdebugcmd) printf("ipmi_open_bmc: cannot open %s, errno=%d\n",pdev,errno); return(rc); } /* dont bother to check for ioctl method, just use putmsg method */ rc = 0; if (fdebugcmd) printf("ipmi_open_bmc: successfully opened bmc\n"); return(rc); } int ipmi_close_bmc(void) { int rc = 0; if (ipmi_fd != -1) { close(ipmi_fd); ipmi_fd = -1; } return(rc); } int ipmi_cmdraw_bmc( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rv = -1; static uint32 msg_seq = 0; int flags = 0; struct strbuf sendbuf; struct strbuf recvbuf; bmc_msg_t *msg; bmc_rq_t *rq; bmc_rs_t *rs; int sz, i; if (sdata > MAX_SEND_SIZE) i = sdata - MAX_SEND_SIZE; else i = 0; sz = (sizeof(bmc_msg_t) - 1) + sizeof(bmc_rq_t) + i; msg = malloc(sz); if (msg == NULL) return(rv); rq = (bmc_rq_t *)&msg->msg[0]; msg->m_type = BMC_MSG_REQ; msg->m_id = msg_seq++; rq->netfn = netfn; rq->lun = lun; rq->cmd = cmd; rq->dlen = sdata; memcpy(rq->data, pdata, sdata); sendbuf.len = sz; sendbuf.buf = (uchar *)msg; if (fdebugcmd) { dump_buf("ipmi_cmdraw_bmc sendbuf",sendbuf.buf,sendbuf.len,0); } rv = putmsg(ipmi_fd, NULL, &sendbuf, 0); if (rv < 0) { perror("BMC putmsg: "); free(msg); return(rv); } free(msg); recvbuf.buf = malloc(MSG_BUF_SIZE); recvbuf.maxlen = MSG_BUF_SIZE; rv = getmsg(ipmi_fd, NULL, &recvbuf, &flags); if (rv < 0) { perror("BMC getmsg: "); free(recvbuf.buf); return(rv); } msg = (bmc_msg_t *)recvbuf.buf; if (fdebugcmd) { dump_buf("ipmi_cmdraw_bmc recvbuf",recvbuf.buf,recvbuf.len,0); } switch (msg->m_type) { case BMC_MSG_RSP: rs = (bmc_rs_t *)&msg->msg[0]; *pcc = rs->ccode; i = rs->dlen; if (i < 0) i = 0; *sresp = i; if (*pcc == 0 && i > 0) memcpy(presp,rs->data,i); rv = 0; break; case BMC_MSG_ERR: default: rv = msg->msg[0]; printf("ipmi_cmdraw_bmc: %s\n", strerror(rv)); break; } free(recvbuf.buf); return(rv); } int ipmi_cmd_bmc(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, i; for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == cmd) break; } if (i >= NCMDS) { printf("ipmi_cmd_bmc: Unknown command %x\n",cmd); return(-1); } if (cmd >= CMDMASK) cmd = cmd & CMDMASK; /* unmask it */ rc = ipmi_cmdraw_bmc(cmd, ipmi_cmds[i].netfn, ipmi_cmds[i].lun, ipmi_cmds[i].sa, ipmi_cmds[i].bus, pdata,sdata,presp,sresp,pcc,fdebugcmd); return(rc); } #endif /* end of ipmibmc.c */ ipmiutil-3.1.9/util/ifruset.c0000644000000000000000000015075714144515623014704 0ustar rootroot/* * ifruset (copy of ifru.c with extended FRU writing) * * This tool reads the FRU configuration, and optionally sets the asset * tag field in the FRU data. See IPMI v1.5 spec section 28. * It can use either the Intel /dev/imb driver or VALinux /dev/ipmikcs. * * Author: Andy Cress arcress at users.sourceforge.net * * Copyright (c) 2009 Kontron America, Inc. * * 04/01/10 Andy Cress - created from ifru.c 2.6.1 */ /*M* Copyright (c) 2009 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Kontron nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #ifdef WIN32 #include #include #include #include #include "getopt.h" #elif defined(DOS) #include #include #include #include #include "getopt.h" #else #include #include #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include "ipmicmd.h" #include "ipicmg.h" // #define OEM_PICMG 12634 extern int get_LastError( void ); /* ipmilan.c */ extern int get_BiosVersion(char *str); extern int get_SystemGuid(uchar *str); extern void fmt_time(time_t etime, char *buf, int bufsz); /*see ievents.c*/ #define FIELD_LEN 24 #define NUM_BOARD_FIELDS 6 #define NUM_PRODUCT_FIELDS 8 #define NUM_CHASSIS_FIELDS 3 #define ERR_LENMAX -7 /*same as LAN_ERR_BADLENGTH */ #define ERR_LENMIN -10 /*same as LAN_ERR_TOO_SHORT */ #define ERR_OTHER -13 /*same as LAN_ERR_OTHER */ #define STRING_DATA_TYPE_BINARY 0x00 #define STRING_DATA_TYPE_BCD_PLUS 0x01 #define STRING_DATA_TYPE_SIX_BIT_ASCII 0x02 #define STRING_DATA_TYPE_LANG_DEPENDENT 0x03 #define FRUCHUNK_SZ 16 #define FRU_END 0xC1 #define FRU_EMPTY_FIELD 0xC0 #define FRU_TYPE_MASK 0xC0 #define FRU_LEN_MASK 0x3F #define IPROD_MANUF 0 #define IPROD_NAME 1 #define IPROD_PART 2 #define IPROD_VERS 3 #define IPROD_SERNUM 4 #define IPROD_ASSET 5 #define IPROD_FRUID 6 #define IPROD_OEM 7 #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char *progname = "ipmiutil fruset"; #else static char * progver = "3.12"; static char *progname = "ifruset"; #endif static char fdebug = 0; static char fpicmg = 0; static char fonlybase = 0; static char fonlyhsc = 0; static char fdevsdrs = 0; static char fshowlen = 0; static char fgetfru = 0; static char fdoanyway = 0; static char fset_mc = 0; static char fcanonical = 0; static char fdump = 0; static char frestore = 0; static int fwritefru = 0; static int prod_id, vend_id = 0; static char bdelim = ':'; static char *binfile = NULL; static uchar bmc_sa = BMC_SA; /*defaults to 0x20*/ static uchar guid[17] = ""; static uchar *frubuf = NULL; static uchar *newdata = NULL; /* new FRU data, including the product area */ /* usually 4*64 + 3 = 259 bytes */ static int sfru = 0; static int chassis_offset = -1; static int chassis_len = 0; static char chassis_name[FIELD_LEN] = {0}; static int product_num = NUM_PRODUCT_FIELDS; typedef struct { int offset; int len; char tag[FIELD_LEN]; } FIELDTYPE; static FIELDTYPE prodarea[NUM_PRODUCT_FIELDS] = { -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0} }; static FIELDTYPE prodnew[NUM_PRODUCT_FIELDS] = { -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0}, -1, 0, {0} }; static int maxprod = 0; static int ctype; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = 0; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static uchar g_fruid = 0; /* default to fruid 0 */ static uchar g_frutype = 0; /* g_frutype values (detected), see also FruTypeString * --TAG---- FRU IPMB * Baseboard = 0x0c 0x07 * PowerSply = 0x0a * PowerCage = 0x15 * DIMM = 0x20 * HotSwapCt = 0x0f * ME = 0x2e * Component = * * (all others) */ #define MAX_CTYPE 26 char *ctypes[MAX_CTYPE] = { "", "Other", "Unknown", "Desktop", "Low Profile Desktop", "Pizza Box", "Mini-Tower", "Tower", "Portable", "Laptop", "Notebook", "Handheld", "Docking Station", "All-in-One", "Sub-Notebook", "Space-saving", "Lunch Box", "Main Server Chassis", "Expansion Chassis", "SubChassis", "Bus Expansion Chassis", "Peripheral Chassis", "RAID Chassis", /*0x17=23.*/ "Rack-Mount Chassis", "New24" , "New25"}; /* what about bladed chassies? */ char *ctype_hdr = "Chassis Type "; char *chassis[NUM_CHASSIS_FIELDS] = { "Chassis Part Number ", "Chassis Serial Num ", "Chassis OEM Field " }; char *board[NUM_BOARD_FIELDS] = { "Board Manufacturer ", "Board Product Name ", "Board Serial Number ", "Board Part Number ", "Board FRU File ID ", "Board OEM Field " }; char *product[NUM_PRODUCT_FIELDS] = { "Product Manufacturer", "Product Name ", "Product Part Number ", "Product Version ", "Product Serial Num ", "Product Asset Tag ", "Product FRU File ID ", "Product OEM Field " }; char *asset_hdr = " Asset Tag Length "; #if 0 typedef struct { uchar len :6; uchar type:2; } TYPE_LEN; /*old, assumes lo-hi byte order*/ #else typedef struct { uchar len; uchar type; } TYPE_LEN; #endif void free_fru(void) { if (frubuf != NULL) { free(frubuf); frubuf = NULL; } if (newdata != NULL) { free(newdata); newdata = NULL; } return; } int load_fru(uchar sa, uchar frudev, uchar frutype) { int ret = 0; uchar indata[FRUCHUNK_SZ]; uchar resp[18]; int sresp; uchar cc; int sz; char fwords; ushort fruoff = 0; int i; int chunk; memset(indata, 0, sizeof(indata)); indata[0] = frudev; sresp = sizeof(resp); if (fdebug) printf("load_fru: sa = %02x, frudev = %02x\n",sa,frudev); ret = ipmi_cmd_mc(GET_FRU_INV_AREA,indata,1,resp,&sresp,&cc,fdebug); if (fdebug) printf("load_fru: inv ret = %d, cc = %x\n",ret,cc); if (ret != 0) return(ret); if (cc != 0) { ret = (cc & 0x00ff); return(ret); } sz = resp[0] + (resp[1] << 8); if (resp[2] & 0x01) { fwords = 1; sz = sz * 2; } else fwords = 0; frubuf = malloc(sz); if (frubuf == NULL) return(get_errno()); sfru = sz; /* Loop on READ_FRU_DATA */ for (i = 0, chunk=FRUCHUNK_SZ; i < sz; i+=chunk) { if ((i+chunk) >= sz) chunk = sz - i; indata[0] = frudev; /* FRU Device ID */ if (fwords) { indata[3] = chunk / 2; fruoff = (i/2); } else { indata[3] = chunk; fruoff = i; } indata[1] = fruoff & 0x00FF; indata[2] = (fruoff & 0xFF00) >> 8; sresp = sizeof(resp); ret = ipmi_cmd_mc(READ_FRU_DATA,indata,4,resp,&sresp,&cc,fdebug); if (ret != 0) break; else if (cc != 0) { if (i == 0) ret = cc & 0x00ff; if (fdebug) printf("read_fru[%d]: ret = %d cc = %x\n",i,ret,cc); break; } memcpy(&frubuf[i],&resp[1],chunk); } if ((frudev == 0) && (sa == bmc_sa)) { /*main system fru*/ sresp = sizeof(resp); ret = ipmi_cmd_mc(GET_SYSTEM_GUID,indata,0,resp,&sresp,&cc,fdebug); if ((ret != 0) && !is_remote()) { /* get UUID from SMBIOS */ cc = 0; sresp = 16; ret = get_SystemGuid(resp); } if (fdebug) printf("system_guid: ret = %d, cc = %x\n",ret,cc); if (ret == 0 && cc == 0) { if (fdebug) { printf("system guid (%d): ",sresp); for (i=0; i<16; i++) printf("%02x ",resp[i]); printf("\n"); } memcpy(&guid,&resp,16); guid[16] = 0; } } /*endif*/ return(ret); } static void decode_string(unsigned char type, unsigned char language_code, unsigned char *source, int slen, char *target, int tsize) { static const char bcd_plus[] = "0123456789 -.:,_"; unsigned char *s = &source[0]; unsigned char *d = &target[0]; int len, i, j, k; union { uint32_t bits; char chars[4]; } u; if (slen == 0 || slen == 1) return; switch(type) { case STRING_DATA_TYPE_BINARY: /* 00: binary/unspecified */ len = (slen*2); break; /* hex dump -> 2x length */ case STRING_DATA_TYPE_SIX_BIT_ASCII: /*type 2 6-bit ASCII*/ /* 4 chars per group of 1-3 bytes */ len = ((((slen+2)*4)/3) & ~3); break; case STRING_DATA_TYPE_LANG_DEPENDENT: /* 03 language dependent */ case STRING_DATA_TYPE_BCD_PLUS: /* 01b: BCD plus */ default: len = slen; break; } if (len >= tsize) len = tsize - 1; memset(target, 0, len); if (type == STRING_DATA_TYPE_BCD_PLUS) { /*type 1 BCD plus*/ for (k=0; k 1 ? s[i+1] : 0); u.chars[1] = (k > 2 ? s[i+2] : 0); #define CHAR_IDX 3 #else memcpy((void *)&u.bits, &s[i], k); #define CHAR_IDX 0 #endif for (k=0; k<4; k++) { target[j++] = ((u.chars[CHAR_IDX] & 0x3f) + 0x20); u.bits >>= 6; } } target[j] = '\0'; } else if (type == STRING_DATA_TYPE_LANG_DEPENDENT) { /*type 3*/ if ((language_code == 0x00) || (language_code == 0x25) || (language_code == 0x19)) { memcpy(target, source, len); target[len] = 0x0; } else { printf("Language 0x%x dependent decode not supported\n",language_code); } } else if (type == STRING_DATA_TYPE_BINARY) { /* 00: binary/unspecified */ strncpy(target, buf2str(s, slen), len); } else { /* other */ printf("Unable to decode type 0x%.2x\n",type); } return; } uchar calc_cksum(uchar *pbuf,int len) { int i; uchar cksum; uchar sum = 0; for (i = 0; i < len; i++) sum += pbuf[i]; cksum = 0 - sum; return(cksum); } static void dumpbuf(uchar *pbuf,int sz) { uchar line[17]; uchar a; int i, j; line[0] = 0; line[16] = 0; j = 0; for (i = 0; i < sz; i++) { if (i % 16 == 0) { j = 0; printf("%s\n %04d: ",line,i); } a = pbuf[i]; if (a < 0x20 || a > 0x7f) a = '.'; line[j++] = a; printf("%02x ",pbuf[i]); } line[j] = 0; printf("%s\n",line); return; } #define NSPDMFG 7 static struct { uchar id; char *str; } spd_mfg[NSPDMFG] = { /* see JEDEC JEP106 doc */ { 0x2c, "Micron" }, { 0x15, "Philips Semi" }, { 0x1c, "Mitsubishi" }, { 0xce, "Samsung" }, { 0xc1, "Infineon" }, { 0x98, "Kingston" }, { 0x89, "Intel" } }; int ValidTL(uchar typelen) { if (vend_id != VENDOR_INTEL) return 1; if ((typelen & 0xC0) == 0xC0) return 1; else return 0; } char * FruTypeString(uchar frutype) { char *pstr; switch (frutype) { case 0x07: pstr = "Baseboard"; break; /*IPMB*/ case 0x0c: pstr = "Baseboard"; break; /*FRU*/ case 0x0a: pstr = "PowerSply"; break; /*FRU*/ case 0x15: pstr = "PowerCage"; break; /*FRU*/ case 0x20: pstr = "DIMM "; break; /*FRU*/ case 0x0f: pstr = "HotSwapCt"; break; /*IPMB*/ case 0x2e: pstr = "ME "; break; /*IPMB*/ default: pstr = "Component"; break; } return(pstr); } static void show_spd(uchar *spd, int lenspd, uchar frudev, uchar frutype) { int sz; char *pstr; uchar mrev; int i; char devstr[20]; sz = spd[0]; /* sz should == lenspd */ if (fcanonical) devstr[0] = 0; /*default is empty string*/ else sprintf(devstr,"[%s,%02x] ",FruTypeString(frutype),frudev); printf("%sMemory SPD Size %c %d\n", devstr,bdelim,lenspd); if (spd[2] == 0x07) pstr = "DDR"; else /* usu 0x04 */ pstr = "SDRAM"; printf("%sMemory Type %c %s\n", devstr,bdelim,pstr); printf("%sModule Density %c %d MB per bank\n", devstr,bdelim, (spd[31] * 4)); printf("%sModule Banks %c %d banks\n", devstr,bdelim,spd[5]); printf("%sModule Rows, Cols %c %d rows, %d cols\n", devstr,bdelim, spd[3], spd[4]); if (spd[11] == 0x00) pstr = "Non-parity"; else /* usu 0x02 */ pstr = "ECC"; printf("%sDIMM Config Type %c %s\n",devstr,bdelim,pstr); for (i = 0; i < NSPDMFG; i++) if (spd_mfg[i].id == spd[64]) break; if (i == NSPDMFG) pstr = ""; /* not found, use null string */ else pstr = spd_mfg[i].str; printf("%sManufacturer ID %c %s (0x%02x)\n", devstr,bdelim, pstr, spd[64]); mrev = spd[91]; /* save this byte for later */ spd[91] = 0; /*stringify part number */ printf("%sManufacturer Part# %c %s\n", devstr,bdelim,&spd[73]); printf("%sManufacturer Rev %c %02x %02x\n", devstr,bdelim,mrev,spd[92]); printf("%sManufacturer Date %c year=%02d week=%02d\n", devstr,bdelim,spd[93],spd[94]); printf("%sAssembly Serial Num %c %02x%02x%02x%02x\n", devstr,bdelim,spd[95], spd[96], spd[97], spd[98]); spd[91] = mrev; /* restore byte, so ok to repeat later */ return; } void show_guid(uchar *pguid) { char *s; int i; for (i=0; i<16; i++) { if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) s = "-"; else s = ""; printf("%s%02x",s,pguid[i]); } } static char *volt_desc(uchar b) { char *s; switch(b) { case 0x03: s = "5V"; break; case 0x02: s = "3.3V"; break; case 0x01: s = "-12V"; break; case 0x00: default: s = "12V"; break; } return(s); } static char *mgt_type(uchar b) { char *s; switch(b) { case 0x01: s = "SysMgt_URL"; break; case 0x02: s = "SystemName"; break; case 0x03: s = "SysPingAddr"; break; case 0x04: s = "Compon_URL"; break; case 0x05: s = "ComponName"; break; case 0x06: s = "ComponPing"; break; case 0x07: default: s = "SysGUID"; break; } return(s); } static void show_fru_multi(char *tag, int midx, uchar mtype, uchar *pdata, int dlen) { int vend, i; char mystr[256]; char *s1, *s2; int v1, v2, v3, v4, v5, v6, v7, v8; uchar b1, b2; if (fdebug) dumpbuf(pdata,dlen); /*multi-record area dump*/ sprintf(mystr,"%sMulti[%d] ",tag,midx); i = strlen(mystr); switch(mtype) { case 0x00: /*Power Supply*/ printf("%sPower Supply Record %c \n",mystr,bdelim); v1 = pdata[0] + ((pdata[1] & 0x0f) << 8); printf("\t Capacity \t%c %d W\n",bdelim, v1); v2 = pdata[2] + (pdata[3] << 8); printf("\t Peak VA \t%c %d VA\n",bdelim, v2); printf("\t Inrush Current\t%c %d A\n",bdelim, pdata[4]); printf("\t Inrush Interval\t%c %d ms\n",bdelim, pdata[5]); v3 = pdata[6] + (pdata[7] << 8); v4 = pdata[8] + (pdata[9] << 8); printf("\t Input Voltage Range1\t%c %d-%d V\n", bdelim,v3/100,v4/100); v3 = pdata[10] + (pdata[11] << 8); v4 = pdata[12] + (pdata[13] << 8); printf("\t Input Voltage Range2\t%c %d-%d V\n", bdelim,v3/100,v4/100); printf("\t Input Frequency Range\t%c %d-%d Hz\n", bdelim,pdata[14],pdata[15]); printf("\t AC Dropout Tolerance\t%c %d ms\n",bdelim, pdata[16]); b1 = pdata[17]; b2 = (b1 & 0x01); if (b2) { /*predictive fail*/ if (b1 & 0x10 != 0) s1 = "DeassertFail "; else s1 = "AssertFail "; } else { if (b1 & 0x10 != 0) s1 = "2pulses/rot "; else s1 = "1pulse/rot "; } printf("\t Flags \t%c %s%s%s%s%s\n",bdelim, (b2 ? "PredictFail " : ""), ((b1 & 0x02 == 0) ? "" : "PowerFactorCorrect "), ((b1 & 0x04 == 0) ? "" : "AutoswitchVolt "), ((b1 & 0x08 == 0) ? "" : "Hotswap "), s1); v5 = pdata[18] + ((pdata[19] & 0x0f) << 8); v6 = (pdata[19] & 0xf0) >> 4; printf("\t Peak Capacity \t%c %d W for %d s\n",bdelim, v5,v6); if (pdata[20] == 0) { printf("\t Combined Capacity\t%c not specified\n",bdelim); } else { b1 = pdata[20] & 0x0f; b2 = (pdata[20] & 0xf0) >> 4; v7 = pdata[21] + (pdata[22] << 8); printf("\t Combined Capacity\t%c %d W (%s and %s)\n", bdelim, v7,volt_desc(b1),volt_desc(b2)); } if (b2) /*predictive fail*/ printf("\t Fan low threshold\t%c %d RPS\n",bdelim,pdata[23]); break; case 0x01: /*DC Output*/ b1 = pdata[0] & 0x0f; b2 = (pdata[0] & 0x80 != 0); printf("%sDC Output %c number %d\n",mystr,bdelim,b1); printf("\t Standby power \t%c %s\n", bdelim, (b2 ? "Yes" : "No")); v1 = pdata[1] + (pdata[2] << 8); printf("\t Nominal voltage \t%c %.2f V\n", bdelim, v1 / 100); v2 = pdata[3] + (pdata[4] << 8); v3 = pdata[5] + (pdata[6] << 8); printf("\t Voltage deviation \t%c + %.2f V / - %.2f V\n", bdelim, v3/100, v2/100); v4 = pdata[7] + (pdata[8] << 8); printf("\t Ripple and noise pk-pk \t%c %d mV\n", bdelim, v4); v5 = pdata[9] + (pdata[10] << 8); printf("\t Min current draw \t%c %.3f A\n", bdelim, v5/1000); v6 = pdata[11] + (pdata[12] << 8); printf("\t Max current draw \t%c %.3f A\n", bdelim, v6/1000); break; case 0x02: /*DC Load*/ b1 = pdata[0] & 0x0f; printf("%sDC Load %c number %d\n",mystr,bdelim,b1); v1 = pdata[1] + (pdata[2] << 8); printf("\t Nominal voltage \t%c %.2f V\n", bdelim, v1 / 100); v2 = pdata[3] + (pdata[4] << 8); v3 = pdata[5] + (pdata[6] << 8); printf("\t Min voltage allowed \t%c %.2f A\n", bdelim, v2); printf("\t Max voltage allowed \t%c %.2f A\n", bdelim, v3); v4 = pdata[7] + (pdata[8] << 8); printf("\t Ripple and noise pk-pk \t%c %d mV\n", bdelim, v4); v5 = pdata[9] + (pdata[10] << 8); printf("\t Min current load \t%c %.3f A\n", bdelim, v5/1000); v6 = pdata[11] + (pdata[12] << 8); printf("\t Max current load \t%c %.3f A\n", bdelim, v6/1000); break; case 0x03: /*Management Access*/ b1 = pdata[0]; printf("%sManagemt Access %c %s ",mystr,bdelim,mgt_type(b1)); memcpy(mystr,&pdata[1],dlen-1); mystr[dlen-1] = 0; printf("%s\n",mystr); break; case 0x04: /*Base Compatibility*/ vend = pdata[0] + (pdata[1] << 8) + (pdata[2] << 16); printf("%sBasic Compat %c %06x\n",mystr,bdelim,vend); break; case 0x05: /*Extended Compatibility*/ vend = pdata[0] + (pdata[1] << 8) + (pdata[2] << 16); printf("%sExtended Compat %c %06x\n",mystr,bdelim,vend); break; case 0xC0: /*OEM Extension*/ vend = pdata[0] + (pdata[1] << 8) + (pdata[2] << 16); if (vend == OEM_PICMG) { printf("%sOEM PICMG %c \n", mystr,bdelim); show_fru_picmg(pdata,dlen); } else printf("%sOEM Ext %c %06x %02x\n", mystr,bdelim, vend, pdata[3]); break; default: printf("%s %02x %c %02x\n", mystr,mtype,bdelim, pdata[0]); break; } } int show_fru(uchar sa, uchar frudev, uchar frutype) { int ret = 0; int i, j, n, sz; uchar *pfru; uchar lang; TYPE_LEN tl; char newstr[64]; int iaoff, ialen, bdoff, bdlen; int proff, prlen, choff, chlen; int moff, mlen; char devstr[24]; char *pstr; int extra = 0; if (frubuf[0] == 0x80) { /* 0x80 = type for DIMMs (SPD) */ /* FRU Header: 80 08 07 0c 0a 01 48 00 (DIMM) */ sz = frubuf[0]; if (fdebug) { printf("DIMM SPD Body (size=%d/%d): ",sz,sfru); dumpbuf(frubuf,sfru); } show_spd(frubuf,sfru, frudev,frutype); return(ret); } pstr = FruTypeString(frutype); if (fcanonical) devstr[0] = 0; /*default is empty string*/ else sprintf(devstr,"[%s,%02x] ",pstr,frudev); printf("%s%s FRU Size %c %d\n",devstr,pstr,bdelim,sfru); /* * FRU header: * 0 = format_ver (01 is std, usu 0x80 if DIMM) * 1 = internal_use offset * 2 = chassis_info offset * 3 = board_info offset (usu 6 fields) * 4 = product_info offset (usu 8 fields) * 5 = multirecord offset * 6 = pad (00) * 7 = header checksum (zero checksum) * FRU Header: 01 01 02 09 13 00 00 e0 (BMC) * FRU Header: 01 00 00 00 01 07 00 f7 (Power Cage) */ pfru = &frubuf[0]; sz = 8; /*minimum for common header*/ for (i = 1; i < 6; i++) { /* walk thru offsets */ if (frubuf[i] != 0) sz = frubuf[i] * 8; } if (sz > 8) { /* if have at least one section */ if (frubuf[5] != 0) j = 5 + frubuf[sz+2]; /*if multi-record area*/ else j = frubuf[sz+1] * 8; /* else add length of last section */ sz += j; } /* Now, sz = size used, sfru = total available size */ if (sz > sfru) { if (fdebug) { printf("FRU Header: "); for (i = 0; i < 8; i++) printf("%02x ",frubuf[i]); printf("\n"); } printf("FRU size out of bounds: available=%d used=%d\n",sfru,sz); printf("Please apply the correct FRU/SDR diskette\n"); if (fdoanyway) { extra = sz - sfru; sz = sfru; } else return(ERR_OTHER); } /* internal area offset, length */ iaoff = frubuf[1] * 8; ialen = frubuf[iaoff + 1] * 8; /* chassis area offset, length */ choff = frubuf[2] * 8; chlen = frubuf[choff + 1] * 8; /* board area offset, length */ bdoff = frubuf[3] * 8; bdlen = frubuf[bdoff + 1] * 8; /* product area offset, length */ proff = frubuf[4] * 8; prlen = frubuf[proff + 1] * 8; if (extra > 0) { /*do fixup of extra in product area*/ prlen -= extra; j = prlen / 8; prlen = j * 8; /*resolve to 8-byte bound*/ frubuf[proff + 1] = j; } /* multi-record area offset, length */ moff = frubuf[5] * 8; mlen = 0; if (moff > 0) { for (i = moff; i < sfru; ) { if (frubuf[i] == 0 && frubuf[i+2] == 0) break; /*type/len invalid*/ j = 5 + frubuf[i+2]; mlen += j; if (frubuf[i+1] & 0x80) break; i += j; } } if (fdebug) { printf("FRU Header: "); for (i = 0; i < 8; i++) printf("%02x ",frubuf[i]); printf("\n"); printf("FRU Body (size=%d/%d): ",sz,sfru); dumpbuf(frubuf,sfru); printf("header, len=%d, cksum0 = %02x, cksum1 = %02x\n", 8,frubuf[7],calc_cksum(&frubuf[0],7)); printf("internal off=%d, len=%d, cksum = %02x\n", iaoff,ialen,calc_cksum(&frubuf[iaoff],ialen-1)); printf("chassis off=%d, len=%d, cksum = %02x\n", choff,chlen,calc_cksum(&frubuf[choff],chlen-1)); printf("board off=%d, len=%d, cksum = %02x\n", bdoff,bdlen,calc_cksum(&frubuf[bdoff],bdlen-1)); printf("prod off=%d, len=%d, cksum = %02x\n", proff,prlen,calc_cksum(&frubuf[proff],prlen-1)); /* Multi-record area */ printf("multi off=%d, len=%d, fru sz=%d\n", moff,mlen,sz); } /*endif fdebug, show header*/ if (choff != 0) { /* show Chassis area fields */ pfru = &frubuf[choff]; lang = 25; /* English */ ctype = pfru[2]; /*chassis type*/ if (fdebug) printf("ctype=%x\n",ctype); if (ctype >= MAX_CTYPE) ctype = MAX_CTYPE - 1; printf("%s%s%c %s\n",devstr, ctype_hdr,bdelim,ctypes[ctype]); pfru += 3; /* skip chassis header */ for (i = 0; i < NUM_CHASSIS_FIELDS; i++) { if (pfru[0] == FRU_END) break; /*0xC1 = end of FRU area*/ if (!ValidTL(pfru[0])) printf(" ERROR - Invalid Type/Length %02x for %s\n", pfru[0],chassis[i]); tl.type = (pfru[0] & FRU_TYPE_MASK) >> 6; tl.len = pfru[0] & FRU_LEN_MASK; if (i == 2) { /* OEM field for chassis_name */ chassis_offset = (int)(pfru - frubuf); chassis_len = tl.len; if (fdebug) printf("chassis oem dtype=%d lang=%d len=%d\n", tl.type,lang,tl.len); } pfru++; { newstr[0] = 0; decode_string(tl.type,lang,pfru,tl.len,newstr,sizeof(newstr)); printf("%s%s%c %s\n",devstr, chassis[i],bdelim,newstr); } pfru += tl.len; } if (fdebug) printf("num Chassis fields = %d\n",i); } if (bdoff != 0) { long nMin, nSec; time_t tsec; /* show Board area fields */ pfru = &frubuf[bdoff]; lang = pfru[2]; /* Decode board mfg date-time (num minutes since 1/1/96) */ nMin = pfru[3] + (pfru[4] << 8) + (pfru[5] << 16); /* 13674540 min from 1/1/70 to 1/1/96 */ nSec = (nMin + 13674540) * 60; tsec = (time_t)(nSec & 0x0ffffffff); // fmt_time(tsec,newstr,sizeof(newstr)); printf("%sBoard Mfg DateTime %c %s",devstr,bdelim,ctime(&tsec)); pfru += 6; /* skip board header */ for (i = 0; i < NUM_BOARD_FIELDS; i++) { if (pfru[0] == FRU_END) break; /*0xC1 = end*/ if (!ValidTL(pfru[0])) printf(" ERROR - Invalid Type/Length %02x for %s\n", pfru[0],board[i]); tl.type = (pfru[0] & FRU_TYPE_MASK) >> 6; tl.len = pfru[0] & FRU_LEN_MASK; pfru++; { newstr[0] = 0; decode_string(tl.type,lang,pfru,tl.len,newstr,sizeof(newstr)); printf("%s%s%c %s\n",devstr, board[i],bdelim,newstr); } pfru += tl.len; } if (fdebug) printf("num Board fields = %d\n",i); } if (proff != 0) { /* show Product area fields */ pfru = &frubuf[proff]; maxprod = pfru[1] * 8; lang = pfru[2]; pfru += 3; /* skip product header */ for (i = 0; i < NUM_PRODUCT_FIELDS; i++) { if (*pfru == FRU_END) { /*0xC1 = end*/ /* Wart for known Kontron 1-byte Product Version anomaly. */ if ((vend_id == VENDOR_KONTRON) && (i == 3)) ; else break; } if (*pfru == 0) *pfru = FRU_EMPTY_FIELD; /* fix a broken table */ if (!ValidTL(pfru[0])) printf(" ERROR - Invalid Type/Length %02x for %s\n", pfru[0],product[i]); tl.type = (pfru[0] & FRU_TYPE_MASK) >> 6; tl.len = pfru[0] & FRU_LEN_MASK; n = (int)(pfru - frubuf); prodarea[i].offset = n; prodarea[i].len = tl.len; memcpy(prodarea[i].tag, &frubuf[n+1] ,tl.len); pfru++; { newstr[0] = 0; decode_string(tl.type,lang,pfru,tl.len,newstr,sizeof(newstr)); printf("%s%s%c %s\n",devstr, product[i],bdelim,newstr); } pfru += tl.len; } if (fdebug) printf("num Product fields = %d, last=%x, max = %d\n", i,*pfru,maxprod ); product_num = i; /*save number of existing product fields*/ if (*pfru == 0x00) *pfru = FRU_END; /* insert end char if broken */ } if (moff != 0) { /* multi-record area may contain several record headers * 0 = record type id * 1 = 0x02 or 0x80 if End-of-List * 2 = record len * 3 = record chksum * 4 = header chksum */ pfru = &frubuf[moff]; j = moff; for (i = 0; j < sz; i++) { if (pfru[0] == 0 && pfru[2] == 0) break; /*type/len invalid*/ n = pfru[2]; /* len of this record */ show_fru_multi(devstr,i,pfru[0],&pfru[5],n); j += (5 + n); if (pfru[1] & 0x80) j = sz; /*0x80 = end of list*/ pfru += (5 + n); } } if ((frudev == 0) && (sa == bmc_sa)) { char *s; printf("%sSystem GUID %c ",devstr,bdelim); for (i=0; i<16; i++) { if ((i == 4) || (i == 6) || (i == 8) || (i == 10)) s = "-"; else s = ""; printf("%s%02x",s,guid[i]); } printf("\n"); } return(ret); } static int write_fru_data(uchar id, ushort offset, uchar *data, int dlen, char fdebug) { int ret = -1; int chunk; ushort fruoff; uchar req[FRUCHUNK_SZ+9]; uchar resp[16]; int sresp; uchar cc; int i, j; /* Write the buffer in small 16-byte (FRUCHUNK_SZ) chunks */ req[0] = id; /* FRU Device ID (fruid) */ fruoff = offset; chunk = FRUCHUNK_SZ; for (i = 0; i < dlen; i += chunk) { req[1] = fruoff & 0x00ff; req[2] = (fruoff & 0xff00) >> 8; if ((i + chunk) > dlen) chunk = dlen - i; memcpy(&req[3],&data[i],chunk); if (fdebug) { printf("write_fru_data[%d] (len=%d): ",i,chunk+3); for (j = 0; j < chunk+3; j++) printf("%02x ",req[j]); printf("\n"); } sresp = sizeof(resp); ret = ipmi_cmd_mc(WRITE_FRU_DATA,req,(uchar)(chunk+3),resp,&sresp, &cc,fdebug); if ((ret == 0) && (cc != 0)) ret = cc & 0x00ff; if (fdebug && ret == 0) printf("write_fru_data[%d]: %d bytes written\n",i,resp[0]); if (ret != 0) break; fruoff += chunk; } return(ret); } /* * write_product * Updates the FRU Product area only. * Note that this function will always provide >=8 product fields, * even if the original had less than 8. * inputs: prodnew = array of new strings to write * frubuf = contains existing FRU data * newdata = new product area buffer, malloc'd * outputs: returns 0 if successful */ int write_product(void) { int ret = -1; uchar req[25]; uchar resp[16]; int sresp; uchar cc; ushort fruoff; int alen, clen; int snlen, verlen; uchar *pfru0; uchar *pfru; uchar *pnew; int i, j, k, n, plen, newlen, max, plimit; int chas_offset; int prod_offset; int mult_offset, mult_len; uchar chksum; int chunk; chas_offset = frubuf[2] * 8; // offset of chassis data prod_offset = frubuf[4] * 8; // offset of product data plen = frubuf[prod_offset+1] * 8; // length of product data mult_offset = frubuf[5] * 8; mult_len = 0; if (mult_offset > 0) { for (i = mult_offset; i < sfru; ) { mult_len += (5 + frubuf[i+2]); if (frubuf[i+1] & 0x80) break; i = mult_len; } } /* Check if asset tag will fit in product data area of FRU. */ if (fdebug) printf("write_product: fru[4,p]=[%02x,%02x] prod_off=%d, plen=%d\n", frubuf[4],frubuf[prod_offset+1],prod_offset,plen); if (plen > sfru) return ERR_LENMAX; // product bigger than buffer if (prodnew[IPROD_ASSET].len > plen) return ERR_LENMAX; /* if asset bigger than product data, error. */ /* asset comes after sernum, so this check works for both */ newdata = malloc(sfru); /* but should not need more than plen bytes */ if (newdata == NULL) return(get_errno()); memset(newdata,0,sfru); pnew = &newdata[0]; /* Set pointer to start of chassis area */ pfru = &frubuf[chas_offset]; /* Product Area Header (3 bytes): [0] = 0x01; * format ver 1 * [1] = 0x0a; *product area size (in 8-byte mult)* [2] = 0x00; *lang=english * Usually max product area is 3 + 8*32 = 259 mod 8 = 264. */ pfru0 = &frubuf[prod_offset]; pfru = &frubuf[prod_offset]; j = 3; memcpy(pnew,pfru,j); pfru += j; pnew += j; n = j; if (mult_offset > 0) plimit = plen; else plimit = sfru - prod_offset; /*plen can expand*/ for (i = 0; i < NUM_PRODUCT_FIELDS; i++) { j = prodarea[i].len; /*new len*/ k = pfru[0] & FRU_LEN_MASK; /*old len*/ if (k == 1) { /*was 0xC1 FRU_END*/ if ((vend_id == VENDOR_KONTRON) && (i == 3) && (j == 1)) { /* fix Kontron 1-byte Version */ prodarea[i].tag[1] = ' '; j++; } else k = 0; } /* check for product area overflow */ if (n + 2 >= plimit) { if (fdebug) printf("Field %d is at %d, beyond product area size %d\n", i+1,n+2,plimit); break; } else if ((n + 1 + j) >= plimit) { if (fdebug) printf("Field %d at %d + %d, truncated, product size %d\n", i+1,n+1,j,plimit); j = 0; } pnew[0] = (j | FRU_TYPE_MASK); /*add type=3 to len*/ memcpy(&pnew[1],prodarea[i].tag,j); if (fdebug) { printf("i=%d frubuf[%d]: %02x %02x %02x, j=%d k=%d n=%d\n", i,(pfru-frubuf),pfru[0],pfru[1],pfru[2],j,k,n); if (i >= product_num) printf("Field %d is beyond existing %d fields\n",i+1,product_num); } pnew += j + 1; pfru += k + 1; n += j + 1; } // n = (int)(pnew - newdata); /*new product area index*/ k = (int)(pfru - pfru0); /*old product area index*/ if (mult_offset > 0) /* do not expand if multi-record area there */ max = plen - k; else /* nothing else, can expand product area, up to sfru */ max = sfru - (k + prod_offset); if (fdebug) printf("frubuf[%d]: %02x %02x %02x, j=%d k=%d n=%d remainder=%d\n", (pfru-frubuf),pfru[0],pfru[1],pfru[2],j,k,n,max); if (max < 0) max = 0; /* copy trailing fru data from saved copy */ for (i = 0; i < max; i++) { pnew[i] = pfru[i]; if (pfru[i] == FRU_END) { i++; break; } /*0xC1*/ } if (i == max) { /*never found 0xC1 FRU_END*/ pnew[0] = FRU_END; /*mark this trailing field as empty*/ i = 1; } newlen = n + i; if (fdebug) printf("newbuf[%d]: %02x %02x %02x, j=%d newlen=%d plen=%d\n", n,pnew[0],pnew[1],pnew[2],j,newlen,plen); /* round up to next 8-byte boundary */ /* need one more byte for checksum, so if j=0, add 8 anyway */ j = 8 - (newlen % 8); for (i = 0; i < j; i++) newdata[newlen++] = 0; if (newlen < plen) newlen = plen; /* don't shrink the product area */ newdata[1] = newlen / 8; // set length of product data /* include new checksum (calc over Product area) */ chksum = calc_cksum(&newdata[0],newlen-1); newdata[newlen-1] = chksum; if (fdebug) { printf("old prod_area buffer (%d):",plen); dumpbuf(&frubuf[prod_offset],plen); printf("new prod_area buffer (%d):",newlen); dumpbuf(newdata,newlen); } if (prod_offset + newlen >= sfru) return ERR_LENMAX; if ((mult_offset > 0) && (newlen > plen)) return ERR_LENMAX; #ifdef TEST newlen = 0; /*don't actually write the new data, if testing*/ #endif ret = write_fru_data(g_fruid, prod_offset, newdata, newlen, fdebug); return(ret); } #define CHUNKSZ 16 #define LAST_REC 0xffff #define STR_OFF 16 int get_sdr(ushort recid, ushort resid, ushort *recnext, uchar *sdr, int *slen, uchar *pcc) { uchar idata[6]; uchar rdata[64]; int sresp; ushort cmd; uchar cc = 0; int len = 0; int rc; idata[0] = resid & 0x00ff; idata[1] = (resid & 0xff00) >> 8; idata[2] = recid & 0x00ff; idata[3] = (recid & 0xff00) >> 8; idata[4] = 0; /*offset*/ idata[5] = CHUNKSZ; /*bytes to read*/ if (fdevsdrs) cmd = GET_DEVICE_SDR; else cmd = GET_SDR; sresp = sizeof(rdata); rc = ipmi_cmd_mc(cmd, idata, 6, rdata, &sresp,&cc, fdebug); if (fdebug) printf("get_sdr[%x] ret = %d cc = %x sresp = %d\n", recid,rc,cc,sresp); if (rc == 0 && cc == 0xCA) { idata[5] = 8; /*bytes to read*/ sresp = sizeof(rdata); rc = ipmi_cmd_mc(cmd, idata, 6, rdata, &sresp,&cc, fdebug); if (fdebug) printf("get_sdr[%x] ret = %d cc = %x sresp = %d\n", recid,rc,cc,sresp); } *pcc = cc; if (rc == 0 && cc == 0) { *recnext = rdata[0] + (rdata[1] << 8); memcpy(sdr,&rdata[2],sresp-2); *slen = sdr[6] + 5; /*get actual SDR size*/ len = sresp-2; /* if an SDR locator record, get the rest of it. */ if (sdr [3] == 0x11 || sdr[3] == 0x12) if (*slen > CHUNKSZ) { idata[0] = resid & 0x00ff; idata[1] = (resid & 0xff00) >> 8; idata[2] = recid & 0x00ff; idata[3] = (recid & 0xff00) >> 8; idata[4] = CHUNKSZ; /*offset*/ idata[5] = *slen - CHUNKSZ; /*bytes to read*/ sresp = sizeof(rdata); rc = ipmi_cmd_mc(cmd, idata, 6, rdata, &sresp,&cc, fdebug); if (fdebug) printf("get_sdr[%x] 2nd ret=%d cc=%x sresp=%d\n", recid,rc,cc,sresp); if (rc == 0 && cc == 0) { sresp -= 2; memcpy(&sdr[len],&rdata[2],sresp); len += sresp; } } *slen = len; } return(rc); } void show_loadfru_error(uchar sa, uchar fruid, int ret) { if (ret == 0) return; switch(ret) { case 0x081: printf("\tFRU(%x,%x) device busy\n",sa,fruid); break; case 0x0C3: printf("\tFRU(%x,%x) timeout, not found\n",sa,fruid); break; case 0x0CB: printf("\tFRU(%x,%x) not present\n",sa,fruid); break; default: printf("load_fru(%x,%x) error = %d (0x%x)\n", sa,fruid,ret,ret); break; } return; } #ifdef METACOMMAND int i_ifruset(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret; int c; char DevRecord[16]; ushort recid; ushort nextid; ushort rsvid; uchar sdr[40]; char biosver[80]; uchar cc; uchar sa; uchar fruid = 0; uchar frutype = 0; int len, i; char *s1; FILE *fp; printf("%s version %s\n",progname,progver); parse_lan_options('V',"4",0); /*request admin priv by default*/ while ( (c = getopt( argc, argv,"a:bcd:h:i:f:m:n:o:p:r:s:u:v:xyz:T:V:J:EYF:P:N:R:U:Z:?")) != EOF ) switch(c) { case 'x': fdebug = 1; break; case 'y': fdoanyway = 1; break; case 'b': fonlybase = 1; g_frutype = 0x07; break; case 'c': fcanonical = 1; bdelim = BDELIM; break; #ifdef TEST case 'h': if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; strncpy(chassis_name,optarg,len); if (len == 1) { /* add a space */ chassis_name[1] = ' '; chassis_name[2] = 0; } } break; #else case 'h': fonlyhsc = 1; /* can use -m00c000s instead */ g_frutype = 0x0f; break; #endif case 'a': fwritefru |= 0x01; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_ASSET].tag,optarg,len); prodnew[IPROD_ASSET].len = len; } break; case 'f': fwritefru |= 0x04; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_FRUID].tag,optarg,len); prodnew[IPROD_FRUID].len = len; } break; case 'n': fwritefru |= 0x20; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_NAME].tag,optarg,len); prodnew[IPROD_NAME].len = len; } break; case 'o': fwritefru |= 0x10; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_OEM].tag,optarg,len); prodnew[IPROD_OEM].len = len; } break; case 'p': fwritefru |= 0x40; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_PART].tag,optarg,len); prodnew[IPROD_PART].len = len; } break; case 'u': fwritefru |= 0x80; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_MANUF].tag,optarg,len); prodnew[IPROD_MANUF].len = len; } break; case 's': fwritefru |= 0x02; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_SERNUM].tag,optarg,len); prodnew[IPROD_SERNUM].len = len; } break; case 'v': fwritefru |= 0x08; if (optarg) { len = strlen(optarg); if (len >= FIELD_LEN) len = FIELD_LEN - 1; /* if (len == 1), handle it in write_product() */ strncpy(prodnew[IPROD_VERS].tag,optarg,len); prodnew[IPROD_VERS].len = len; } break; case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; printf("set MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'z': /* set local IPMB MC sa */ sa = htoi(&optarg[0]); /*device slave address*/ ipmi_set_mymc(g_bus, sa, g_lun,ADDR_IPMB); bmc_sa = sa; case 'i': fonlybase = 1; /*specify a fru id*/ if (strncmp(optarg,"0x",2) == 0) g_fruid = htoi(&optarg[2]); else g_fruid = htoi(optarg); printf("Using FRU ID 0x%02x\n",g_fruid); break; case 'd': fdump = 1; /*dump fru to a file*/ binfile = optarg; break; case 'r': frestore = 1; /*restore fru from a file*/ fwritefru = 0x100; binfile = optarg; break; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-bcimxy -unpvsafo -NUPREFTVY]\n",progname); printf(" -u manu Sets Product Manufacturer (0)\n"); printf(" -n name Sets Product Name (1)\n"); printf(" -p part Sets Product Part Number (2)\n"); printf(" -v vers Sets Product Version (3)\n"); printf(" -s snum Sets Product Serial Num (4)\n"); printf(" -a tag Sets Product Asset Tag (5)\n"); printf(" -f fru Sets Product FRU File ID (6)\n"); printf(" -o oem Sets Product OEM Field (7)\n"); // printf(" -h chname Sets the Chassis Name \n"); printf(" -b Only show Baseboard FRU data\n"); printf(" -c show Canonical, delimited output\n"); printf(" -d Dump FRU to a file\n"); printf(" -r Restore FRU from a file\n"); printf(" -i 00 Get/Set a specific FRU ID\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -x Display extra debug messages\n"); printf(" -y Ignore the check for FRU size overflow\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto do_exit; } // if (is_remote() && fwritefru) parse_lan_options('V',"4",0); ret = ipmi_getdeviceid( DevRecord, sizeof(DevRecord),fdebug); if (ret == 0) { uchar ipmi_maj, ipmi_min; ipmi_maj = DevRecord[4] & 0x0f; ipmi_min = DevRecord[4] >> 4; vend_id = DevRecord[6] + (DevRecord[7] << 8) + (DevRecord[8] << 16); prod_id = DevRecord[9] + (DevRecord[10] << 8); show_devid( DevRecord[2], DevRecord[3], ipmi_maj, ipmi_min); if ((DevRecord[1] & 0x80) == 0x80) fdevsdrs = 1; if (vend_id == VENDOR_NEC) fdevsdrs = 0; else if (vend_id == VENDOR_INTEL) { if (prod_id == 0x003E) { set_max_kcs_loops(URNLOOPS); /*longer for cmds (default 300)*/ } } } else { goto do_exit; } ret = ipmi_getpicmg( DevRecord, sizeof(DevRecord),fdebug); if (ret == 0) fpicmg = 1; if ((vend_id == VENDOR_INTEL) && (!fpicmg)) fdevsdrs = 0; /* override, use SDR repository*/ if (fdebug) printf("bmc_sa = %02x fdevsdrs = %d\n",bmc_sa,fdevsdrs); if (fset_mc) { /* target a specific MC via IPMB (usu a picmg blade) */ if (fdebug) printf("set_mc: %02x:%02x:%02x type=%d\n", g_bus,g_sa,g_lun,g_addrtype); ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); fonlybase = 1; /*only show this MC*/ } else { g_sa = bmc_sa; /* BMC_SA = 0x20 */ } if (g_frutype == 0) { g_frutype = 0x01; /* other = "Component" */ } if (!fonlybase && !fonlyhsc) { /* loop thru SDRs to find FRU devices */ #ifdef NOT_YET { /* get SDR Repository Info (needs to be copied here)*/ ret = GetSDRRepositoryInfo(&j,&fdevsdrs); if (fdebug) printf("GetSDRRepositoryInfo: ret=%x nSDRs=%d\n",ret,j); } #endif { /* reserve the SDR repository */ uchar resp[16]; int sresp; uchar cc; ushort cmd; sresp = sizeof(resp); if (fdevsdrs) cmd = RESERVE_DEVSDR_REP; else cmd = RESERVE_SDR_REP; ret = ipmi_cmd_mc(cmd, NULL, 0, resp, &sresp, &cc, 0); if (fdebug) printf("ipmi_cmd RESERVE status = %d, cc = %x\n",ret,cc); rsvid = resp[0] + (resp[1] << 8); } recid = 0; while (recid != LAST_REC) { char idstr[32]; int ilen; len = sizeof(sdr); /*sizeof(sdr); get 32 sdr bytes*/ ret = get_sdr(recid,rsvid,&nextid,sdr,&len,&cc); if ((ret != 0) || (cc != 0)) { printf("SDR[%04x] error %d ccode = %x\n",recid,ret,cc); break; } fgetfru = 0; if ((sdr[3] == 0x11) || (sdr[3] == 0x12)) /* SDR FRU or IPMB type */ { if (len > STR_OFF) { ilen = len - STR_OFF; if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1; memcpy(idstr,&sdr[STR_OFF],ilen); idstr[ilen] = 0; } else idstr[0] = 0; sa = sdr[5]; /* usu 0x20 for bmc_sa */ /* Get its FRU data */ if ((sdr[3] == 0x11) && (sdr[7] & 0x80)) { /* FRU SDRs */ /* It is a logical FRU device */ if (fcanonical) printf("SDR[%04x] FRU %c %s\n", recid, bdelim, idstr); else printf("SDR[%04x] FRU %02x %02x %02x %02x %s\n", recid, sdr[5],sdr[6],sdr[12],sdr[13],idstr); fruid = sdr[6]; frutype = sdr[12]; if (sa == bmc_sa && fruid == 0) /*do this below*/; else switch(sdr[12]) /*FRU entity id*/ { case 0x0a: /*Power Supply*/ case 0x20: /*DIMM*/ case 0x15: /*Power Cage*/ default: fgetfru = 1; break; } } else if (sdr[3] == 0x12) { /* IPMB SDRs (DLRs for MCs) */ if (fcanonical) printf("SDR[%04x] IPMB %c %s\n", recid, bdelim, idstr); else printf("SDR[%04x] IPMB %02x %02x %02x %02x %s\n", recid, sdr[5],sdr[6],sdr[12],sdr[13],idstr); fruid = 0; /*every MC must have fruid 0*/ frutype = sdr[12]; if (sa == bmc_sa && fruid == 0) { /*do bmc_sa,0 below*/ if (fdebug) printf("do bmc_sa %02x below\n",sa); g_frutype = frutype; } else if (frutype == 0x2e) { /*skip ME*/ if (fdebug) printf("skipping ME sa %02x, %02x\n",sa,fruid); } else if (sa == 0x28) { /*do nothing for Bridge Ctlr sa=0x28*/ if (fdebug) printf("skipping IPMB sa %02x, %02x\n",sa,fruid); } else if (sa == 0xC0) { /* HotSwap Backplane (sa=0xC0) */ /* Note: Loading sa 0xC0 over ipmi lan gives a timeout * error, but it works locally. */ fgetfru = 1; } else { /* other misc sa,fruid */ fgetfru = 1; } } if (fgetfru) { uchar adrtype; adrtype = g_addrtype; if (fdebug) printf("set_mc %02x:%02x:%02x type=%d fruid=%02x\n", g_bus,sa,g_lun,adrtype,fruid); ipmi_set_mc(g_bus, sa, g_lun,adrtype); ret = load_fru(sa,fruid,frutype); if (ret != 0) { show_loadfru_error(sa,fruid,ret); free_fru(); } else { ret = show_fru(sa,fruid,frutype); if (ret != 0) printf("show_fru error = %d\n",ret); free_fru(); } ipmi_restore_mc(); } } /*endif FRU/IPMB SDR */ recid = nextid; } /*end while sdrs*/ } /*endif not fonlybase*/ /* load the FRU data for Baseboard (address 0x20) */ printf("\n"); sa = g_sa; /* bmc_sa = BMC_SA = 0x20 */ if (fonlyhsc) { sa = 0xC0; g_addrtype = ADDR_SMI; ipmi_set_mc(g_bus,sa,g_lun,g_addrtype); } if (g_addrtype == ADDR_IPMB) ipmi_set_mc(g_bus,sa,g_lun,g_addrtype); ret = load_fru(sa,g_fruid,g_frutype); if (ret != 0) { show_loadfru_error(sa,g_fruid,ret); free_fru(); goto do_exit; } /* display the Baseboard FRU data */ ret = show_fru(sa,g_fruid,g_frutype); if (ret != 0) printf("show_fru error = %d\n",ret); if (!is_remote()) { char devstr[24]; if (fcanonical) devstr[0] = 0; /*default is empty string*/ else sprintf(devstr,"[%s,%02x] ",FruTypeString(g_frutype),g_fruid); i = get_BiosVersion(biosver); if (i == 0) printf("%sBIOS Version %c %s\n",devstr,bdelim,biosver); } if (fdump && ret == 0) { /* Dump FRU to a binary file */ #ifdef WIN32 fp = fopen(binfile,"wb"); #else fp = fopen(binfile,"w"); #endif if (fp == NULL) { ret = get_LastError(); printf("Cannot open file %s, error %d\n",binfile,ret); } else { printf("Writing FRU size %d to %s ...\n",sfru,binfile); len = fwrite(frubuf, 1, sfru, fp); fclose(fp); if (len <= 0) { ret = get_LastError(); printf("Error %d writing file %s\n",ret,binfile); } else ret = 0; } } else if (frestore) { uchar cksum; /* Restore FRU from a binary file */ #ifdef WIN32 fp = fopen(binfile,"rb"); #else fp = fopen(binfile,"r"); #endif if (fp == NULL) { ret = get_LastError(); printf("Cannot open file %s, error %d\n",binfile,ret); } else { ret = 0; /* sfru and frubuf were set from load_fru above. */ len = fread(frubuf, 1, sfru, fp); if (len <= 0) { ret = get_LastError(); printf("Error %d reading file %s\n",ret,binfile); sfru = 0; /*for safety*/ } fclose(fp); if (fdebug) { printf("FRU buffer from file (%d):",sfru); dumpbuf(frubuf,sfru); } /* Do some validation of the FRU buffer header */ cksum = calc_cksum(&frubuf[0],7); if (fdebug) printf("header, len=8, cksum0 = %02x, cksum1 = %02x\n", frubuf[7],cksum); if (frubuf[7] != cksum) { printf("Not a valid FRU file\n"); ret = ERR_BAD_FORMAT; free_fru(); } if (ret == 0) { /*successfully read data*/ printf("Writing FRU size %d from %s ...\n",sfru,binfile); ret = write_fru_data(g_fruid, 0, frubuf, sfru, fdebug); free_fru(); if (ret != 0) printf("write_fru error %d (0x%02x)\n",ret,ret); else { /* successful, show new data */ ret = load_fru(sa,g_fruid,g_frutype); if (ret != 0) show_loadfru_error(sa,g_fruid,ret); else ret = show_fru(sa,g_fruid,g_frutype); free_fru(); } } } } /*end-else frestore */ else if ((fwritefru != 0) && ret == 0) { printf("\nWriting new product data (%s,%s,%s,%s,%s,%s,%s,%s) ...\n", prodnew[0].tag, prodnew[1].tag, prodnew[2].tag, prodnew[3].tag, prodnew[4].tag, prodnew[5].tag, prodnew[6].tag, prodnew[7].tag); for (i = 0; i < NUM_PRODUCT_FIELDS; i++) { len = prodnew[i].len; if (len > 0) { if (len >= FIELD_LEN) len = FIELD_LEN - 1; if (len == 1) { prodnew[i].tag[1] = ' '; len++; } prodarea[i].len = len; memcpy(prodarea[i].tag,prodnew[i].tag,len); } } ret = write_product(); free_fru(); if (ret != 0) printf("write_product error %d (0x%02x)\n",ret,ret); else { /* successful, show new data */ ret = load_fru(sa,g_fruid,g_frutype); if (ret != 0) show_loadfru_error(sa,g_fruid,ret); else ret = show_fru(sa,g_fruid,g_frutype); free_fru(); } } else free_fru(); do_exit: ipmi_close_(); show_outcome(progname,ret); return(ret); } /* end ifruset.c */ ipmiutil-3.1.9/util/oem_intel.h0000644000000000000000000000676714144515623015204 0ustar rootroot/* * oem_intel.h * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2010 Kontron America, Inc. * * 09/02/10 Andy Cress - separated from ialaems.c */ /*M* Copyright (c) 2010 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Kontron nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #define PRIVATE_BUS_ID 0x03 // w Sahalee, the 8574 is on Private Bus 1 #define PRIVATE_BUS_ID5 0x05 // for Intel TIGI2U #define PRIVATE_BUS_ID7 0x07 // for Intel S5000 #define PERIPHERAL_BUS_ID 0x24 // w mBMC, the 8574 is on the Peripheral Bus #define ALARMS_PANEL_WRITE 0x40 #define ALARMS_PANEL_READ 0x41 #define DISK_LED_WRITE 0x44 // only used for Chesnee mBMC #define DISK_LED_READ 0x45 // only used for Chesnee mBMC #define HAS_ALARMS_MASK 0x0001 #define HAS_BMCTAM_MASK 0x0002 #define HAS_ENCL_MASK 0x0004 #define HAS_PICMG_MASK 0x0008 #define HAS_NSC_MASK 0x0010 #define HAS_ROMLEY_MASK 0x0020 #define HAS_GRANTLEY_MASK 0x0040 uchar get_nsc_diskleds(uchar busid); int set_nsc_diskleds(uchar val, uchar busid); void show_nsc_diskleds(uchar val); uchar get_alarms_intel(uchar busid); int set_alarms_intel(uchar val, uchar busid); void show_alarms_intel(uchar val); int check_bmctam_intel(void); int detect_capab_intel(int vend_id,int prod_id, int *cap, int *ndsk,char fdbg); int get_led_status_intel(uchar *pstate); int is_lan2intel(int vend, int prod); int decode_sensor_intel(uchar *sdr,uchar *reading,char *pstring, int slen); int decode_sensor_intel_nm(uchar *sdr,uchar *reading,char *pstring, int slen); void show_oemsdr_intel(uchar *sdr); void show_oemsdr_nm(uchar *sdr); int is_romley(int vend, int prod); int is_thurley(int vend, int prod); int get_enc_leds_intel(uchar *val); int set_enc_leds_intel(uchar val); void show_enc_leds_intel(uchar val, int numd); int lan_failover_intel(uchar func, uchar *mode); int intel_romley_desc(int vend, int prod, char **pdesc); int get_power_restore_delay_intel(int *delay); int get_hsbp_version_intel(uchar *maj, uchar *min); int is_grantley(int vend, int prod); int intel_grantley_desc(int vend, int prod, char **pdesc); /* end oem_intel.h */ ipmiutil-3.1.9/util/oem_supermicro.h0000644000000000000000000000514214144515623016243 0ustar rootroot/* * oem_supermicro.h * SuperMicro OEM command functions * *--------------------------------------------------------------------- */ /*M* Copyright (c) 2013 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Kontron nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #define SUPER_NETFN_OEM 0x30 #define SUPER_CMD_BMCSTATUS 0x70 #define SUPER_CMD_RESET_INTRUSION 0x03 #define SUPER_NETFN_OEMFW 0x3C /*for SuperMicro/Peppercon*/ #define SUPER_CMD_OEMFWINFO 0x20 int oem_supermicro_get_bmc_status(uchar *sts); int oem_supermicro_set_bmc_status(uchar sts); int oem_supermicro_get_health(char *pstr, int sz); int oem_supermicro_get_firmware_info(uchar *info); int oem_supermicro_get_firmware_str(char *pstr, int sz); int oem_supermicro_reset_intrusion(void); int oem_supermicro_get_lan_port(uchar *val); int oem_supermicro_set_lan_port(uchar val); char *oem_supermicro_lan_port_string(uchar val); int decode_sensor_supermicro(uchar *sdr,uchar *reading,char *pstring, int slen, int fsimple, char fdbg); int decode_mem_supermicro(int prod, uchar b2, uchar b3, char *desc, int *psz); int decode_sel_supermicro(uchar *evt, char *outbuf, int outsz, char fdesc, char fdebug); /* end oem_supermicro.h */ ipmiutil-3.1.9/util/isensor.h0000644000000000000000000001100714144515623014672 0ustar rootroot/* * isensor.h * common routines from isensor.c */ #define SDR_SZ 80 /*max SDR size*/ typedef struct { ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar sens_ownid; uchar sens_ownlun; uchar sens_num; /*sdr[7]*/ uchar entity_id; uchar entity_inst; uchar sens_init; uchar sens_capab; uchar sens_type; /*sdr[12]*/ uchar ev_type; /*sdr[13]*/ uchar data1[6]; /*masks*/ uchar sens_units; /*sdr[20]*/ uchar sens_base; uchar sens_mod; uchar linear; uchar m; uchar m_t; uchar b; uchar b_a; uchar a_ax; uchar rx_bx; uchar flags; uchar nom_reading; uchar norm_max; uchar norm_min; uchar sens_max_reading; uchar sens_min_reading; uchar unr_threshold; uchar ucr_threshold; uchar unc_threshold; uchar lnr_threshold; uchar lcr_threshold; uchar lnc_threshold; uchar pos_hysteresis; uchar neg_hysteresis; uchar data3[3]; uchar id_strlen; uchar id_string[16]; } SDR01REC; typedef struct { ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar sens_ownid; uchar sens_ownlun; uchar sens_num; uchar entity_id; uchar entity_inst; uchar sens_init; uchar sens_capab; uchar sens_type; uchar ev_type; uchar data1[6]; uchar sens_units; uchar sens_base; uchar sens_mod; uchar shar_cnt; uchar shar_off; uchar pos_hysteresis; uchar neg_hysteresis; uchar data2[4]; uchar id_strlen; uchar id_string[16]; } SDR02REC; typedef struct { /* 0x08 = Entity Association record */ ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar contid; uchar continst; uchar flags; uchar edata[8]; } SDR08REC; typedef struct { /*0x14 = BMC Message Channel Info record */ ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar mdata[8]; uchar mint; uchar eint; uchar rsvd; } SDR14REC; typedef struct { /*0x11 = FRU Locator*/ ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar dev_access_adr; /*usu sa*/ uchar dev_slave_adr; /*usu fru_id*/ uchar access_lun; uchar chan_num; uchar reserved; uchar dev_type; uchar dev_typemod; uchar entity_id; uchar entity_inst; uchar oem; uchar id_strlen; uchar id_string[16]; } SDR11REC; typedef struct { /*0x12 = IPMB Locator, for MCs*/ ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar dev_slave_adr; uchar chan_num; uchar power_state; uchar dev_capab; uchar reserved[3]; uchar entity_id; uchar entity_inst; uchar oem; uchar id_strlen; uchar id_string[16]; } SDR12REC; typedef struct { /*0xc0 = OEM Record*/ ushort recid; uchar sdrver; /*usu. 0x51 = v1.5*/ uchar rectype; /* 01, 02, 11, 12, c0 */ uchar reclen; uchar manuf_id[3]; /*Intel = 0x57,0x01,0x00 = 343.*/ uchar oem_data[60]; /* (reclen-3 bytes)*/ } SDRc0REC; int get_sdr_cache(uchar **pcache); void free_sdr_cache(uchar *pcache); int get_sdr_file(char *sdrfile, uchar **sdrlist); int find_nsdrs(uchar *pcache); int find_sdr_next(uchar *psdr, uchar *pcache, ushort id); int find_sdr_by_snum(uchar *psdr, uchar *pcache, uchar snum, uchar sa); int find_sdr_by_tag(uchar *psdr, uchar *pcache, char *tag, uchar dbg); int find_sdr_by_id(uchar *psdr, uchar *pcache, ushort id); void ShowSDR(char *tag, uchar *sdr); int GetSDRRepositoryInfo(int *nret, int *fdev); int GetSensorThresholds(uchar sens_num, uchar *data); int GetSensorReading(uchar sens_num, void *psdr, uchar *sens_data); int GetSensorReadingFactors(uchar snum, uchar raw, int *m, int *b, int * b_exp, int *r, int *a); double RawToFloat(uchar raw, uchar *psdr); char *decode_entity_id(int id); char *get_unit_type(int iunits, int ibase, int imod, int fshort); /* * decode_comp_reading * * Decodes the readings from compact SDR sensors. * Use sensor_dstatus array for sensor reading types and meaning strings. * Refer to IPMI Table 36-1 and 36-2 for this. * Note that decoding should be based on sensor type and ev_type only, * except for end cases. * * reading1 = sens_reading[2], reading2 = sens_reading[3] */ int decode_comp_reading(uchar type, uchar evtype, uchar num, uchar reading1, uchar reading2); /* end isensor.h */ ipmiutil-3.1.9/util/ifwum.c0000644000000000000000000014567414144515623014354 0ustar rootroot/* * 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 #include "getopt.h" #elif defined(HPUX) /* getopt defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #include #include #include #include #ifdef LINUX #include #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, ¬Used); } 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, ¬Used); } 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;qtyprotocolRevision); 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; } ipmiutil-3.1.9/util/ihpm.c0000644000000000000000000040205714144515623014151 0ustar rootroot/* * ihpm.c * Hardware Platform Management, IPM Controller Firmware Upgrade Procedure * * Change history: * 08/25/2010 ARCress - ported from ipmitool/lib/ipmi_hpmfwupg.c * 08/24/2011 ARcress - updated to Kontron 1.08 (K17) version, * added hpm_decode_cc(), etc. * *--------------------------------------------------------------------- */ /* * Copyright (c) 2006 Kontron Canada, Inc. All Rights Reserved. * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifdef WIN32 #include #include #include #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int typedef uint32_t socklen_t; #include "getopt.h" #else #include #include #include #include #include /*for toupper*/ #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include #include #include #include "ipmicmd.h" #include "ihpm.h" /**************************************************************************** * * Copyright (c) 2006 Kontron Canada, Inc. All Rights Reserved. * * HPM.1 * Hardware Platform Management * IPM Controller Firmware Upgrade Procedure * * This module implements an Upgrade Agent for the IPM Controller * Firmware Upgrade Procedure (HPM.1) specification version 1.0. * * author: * Frederic.Lelievre@ca.kontron.com * Francois.Isabelle@ca.kontron.com * Jean-Michel.Audet@ca.kontron.com * MarieJosee.Blais@ca.kontron.com * ***************************************************************************** * * HISTORY * =========================================================================== * 2007-01-11 * * - Incremented to version 0.2 * - Added lan packet size reduction mechanism to workaround fact * that lan iface will not return C7 on excessive length * - Fixed some typos * - now uses lprintf() * * - Incremented to version 0.3 * - added patch for openipmi si driver V39 (send message in driver does not * retry on 82/83 completion code and return 82/83 as response from target * [conditionnaly built with ENABLE_OPENIPMI_V39_PATCH] * * see: ipmi-fix-send-msg-retry.pacth in openipmi-developer mailing list * * 2007-01-16 * * - Incremented to version 0.4 * - Fixed lan iface inaccesiblity timeout handling. Waiting for firmware * activation completion (fixed sleep) before re-opening a session and * get the final firmware upgrade status. * - Fixed some user interface stuff. * * 2007-05-09 * * - Incremented to version 1.0 * - Modifications for compliancy with HPM.1 specification version 1.0 * * 2007-06-05 * * - Modified the display of upgrade of Firmware version. * - Added new options like "check" and "component" and "all" to hpm commands. * - By default we skip the upgrade if we have the same firmware version * as compared to the Image file (*.hpm).This will ensure that user does * not update the target incase its already been updated * * 2008-01-25 * - Reduce buffer length more aggressively when no response from iol. * - Incremented version to 1.02 * * 2009-02-11 * - With multi-component HPM file, if one component need to be skipped because * the component is already up-to-date, ipmitool sends "Initiate upgrade * action / Upload for upgrade" anyway. * * If the component needs to be skipped, ipmitool will not send "Initiate * upgrade action / Upload for upgrade" * * - Incremented version to 1.03 * * 2009-02-11 * - Fixed side effect introduced by last version, "forced" update didn't * work anymore * - Incremented version to 1.04 * * 2009-03-25 * - Fix the case where ipmitool loses the iol connection during the upload * block process. Once IPMITool was successfully sent the first byte, * IPMITool will not resize the block size. * * 2009-03-26 * - Fix the problem when we try to upgrade specific component and the component * is already updated, IPMITool sends a "prepare action" but IPMITool skips * the upload firmware block process. * So, if we specify a specific component, we want to force to upload this * specific component. * - Incremented version to 1.05 * * 2009-04-20 * - Reworked previous update, when 'component' is specified, the other * components are now skipped. * - Incremented version to 1.06 * * =========================================================================== * TODO * =========================================================================== * 2007-01-11 * - Add interpretation of GetSelftestResults * - Add interpretation of component ID string * *****************************************************************************/ extern int verbose; /* * Agent version */ #define HPMFWUPG_VERSION_MAJOR 1 #define HPMFWUPG_VERSION_MINOR 0 #define HPMFWUPG_VERSION_SUBMINOR 9 static char * progname = "ihpm"; static char * progver = "1.09"; /* HPMFWUPG_VERSION */ extern char fdebug; /*from ipmicmd.c*/ static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int g_channel_buf_size = 0; /* * HPM.1 FIRMWARE UPGRADE COMMANDS (part of PICMG) */ #define HPMFWUPG_GET_TARGET_UPG_CAPABILITIES 0x2E #define HPMFWUPG_GET_COMPONENT_PROPERTIES 0x2F #define HPMFWUPG_ABORT_UPGRADE 0x30 #define HPMFWUPG_INITIATE_UPGRADE_ACTION 0x31 #define HPMFWUPG_UPLOAD_FIRMWARE_BLOCK 0x32 #define HPMFWUPG_FINISH_FIRMWARE_UPLOAD 0x33 #define HPMFWUPG_GET_UPGRADE_STATUS 0x34 #define HPMFWUPG_ACTIVATE_FIRMWARE 0x35 #define HPMFWUPG_QUERY_SELFTEST_RESULT 0x36 #define HPMFWUPG_QUERY_ROLLBACK_STATUS 0x37 #define HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK 0x38 /* * HPM.1 SPECIFIC COMPLETION CODES */ #define HPMFWUPG_ROLLBACK_COMPLETED 0x00 #define HPMFWUPG_COMMAND_IN_PROGRESS 0x80 #define HPMFWUPG_NOT_SUPPORTED 0x81 #define HPMFWUPG_SIZE_MISMATCH 0x81 #define HPMFWUPG_ROLLBACK_FAILURE 0x81 #define HPMFWUPG_INV_COMP_MASK 0x81 #define HPMFWUPG__ABORT_FAILURE 0x81 #define HPMFWUPG_INV_COMP_ID 0x82 #define HPMFWUPG_INT_CHECKSUM_ERROR 0x82 #define HPMFWUPG_INV_UPLOAD_MODE 0x82 #define HPMFWUPG_ROLLBACK_OVERRIDE 0x82 #define HPMFWUPG_INV_COMP_PROP 0x83 #define HPMFWUPG_FW_MISMATCH 0x83 #define HPMFWUPG_ROLLBACK_DENIED 0x83 #define HPMFWUPG_NOT_SUPPORTED_NOW 0xd5 /* * This error code is used as a temporary PATCH to * the latest Open ipmi driver. This PATCH * will be removed once a new Open IPMI driver is released. * (Buggy version = 39) */ #define ENABLE_OPENIPMI_V39_PATCH #ifdef ENABLE_OPENIPMI_V39_PATCH #define RETRY_COUNT_MAX 3 static int errorCount; #define HPMFWUPG_IS_RETRYABLE(error) \ ((((error==0x83)||(error==0x82)||(error==0x80)) && (errorCount++descString,11); /* * If the cold reset is required then we can display * on it * so that user is aware that he needs to do payload power * cycle after upgrade */ printf("|%c%-2d|%-11s|",pVersion->coldResetRequired?'*':' ',pVersion->componentId,descString); if (mode & TARGET_VER) { if (pVersion->targetMajor == 0xFF && pVersion->targetMinor == 0xFF) printf(" ---.-- -------- |"); else printf(" %3d.%02x %02X%02X%02X%02X |", pVersion->targetMajor, pVersion->targetMinor, pVersion->targetAux[0], pVersion->targetAux[1], pVersion->targetAux[2], pVersion->targetAux[3] ); if (mode & ROLLBACK_VER) { if (pVersion->rollbackMajor == 0xFF && pVersion->rollbackMinor == 0xFF) printf(" ---.-- -------- |"); else printf(" %3d.%02x %02X%02X%02X%02X |", pVersion->rollbackMajor, pVersion->rollbackMinor, pVersion->rollbackAux[0], pVersion->rollbackAux[1], pVersion->rollbackAux[2], pVersion->rollbackAux[3]); } else { printf(" ---.-- -------- |"); } } if (mode & IMAGE_VER) { if (pVersion->imageMajor == 0xFF && pVersion->imageMinor == 0xFF) printf(" ---.-- |"); else printf(" %3d.%02x %02X%02X%02X%02X |", pVersion->imageMajor, pVersion->imageMinor, pVersion->imageAux[0], pVersion->imageAux[1], pVersion->imageAux[2], pVersion->imageAux[3]); } return 0; } /**************************************************************************** * * Function Name: HpmfwupgTargerCheck * * Description: This function gets the target information and displays it on the * screen * *****************************************************************************/ int HpmfwupgTargetCheck(void * intf, int option) { // struct HpmfwupgUpgradeCtx fwupgCtx; struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; int rc = HPMFWUPG_SUCCESS; int componentId = 0; int flagColdReset = FALSE; struct ipm_devid_rsp devIdrsp; struct HpmfwupgGetComponentPropertiesCtx getCompProp; int mode = 0; rc = HpmfwupgGetDeviceId(intf, &devIdrsp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Verify whether the Target board is present \n"); return rc; } rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); if (rc != HPMFWUPG_SUCCESS) { /* * That indicates the target is not responding to the command * May be that there is no HPM support */ lprintf(LOG_NOTICE,"Board might not be supporting the HPM.1 Standards\n"); return rc; } if (option & VIEW_MODE) { lprintf(LOG_NOTICE,"-------Target Information-------"); lprintf(LOG_NOTICE,"Device Id : 0x%x", devIdrsp.device_id); lprintf(LOG_NOTICE,"Device Revision : 0x%x", devIdrsp.device_revision); lprintf(LOG_NOTICE,"Product Id : 0x%04x", buf2short(devIdrsp.product_id)); lprintf(LOG_NOTICE,"Manufacturer Id : 0x%04x (%s)\n\n", buf2short(devIdrsp.manufacturer_id), get_mfg_str(devIdrsp.manufacturer_id,NULL)); HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER); } for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX; componentId++ ) { /* If the component is supported */ if ( ((1 << componentId) & targetCapCmd.resp.componentsPresent.ComponentBits.byte) ) { memset((PVERSIONINFO)&gVersionInfo[componentId],0x00,sizeof(VERSIONINFO)); getCompProp.req.componentId = componentId; getCompProp.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompGenProp Failed for component Id %d\n",componentId); return rc; } gVersionInfo[componentId].rollbackSupported = getCompProp.resp.Response. generalPropResp.GeneralCompProperties.bitfield.rollbackBackup; gVersionInfo[componentId].coldResetRequired = getCompProp.resp.Response. generalPropResp.GeneralCompProperties.bitfield.payloadColdReset; getCompProp.req.selector = HPMFWUPG_COMP_DESCRIPTION_STRING; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompDescString Failed for component Id %d\n",componentId); return rc; } strcpy((char *)&gVersionInfo[componentId].descString, getCompProp.resp.Response.descStringResp.descString); getCompProp.req.selector = HPMFWUPG_COMP_CURRENT_VERSION; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompCurrentVersion Failed for component Id %d\n",componentId); return rc; } gVersionInfo[componentId].componentId = componentId; gVersionInfo[componentId].targetMajor = getCompProp.resp.Response. currentVersionResp.currentVersion[0]; gVersionInfo[componentId].targetMinor = getCompProp.resp.Response. currentVersionResp.currentVersion[1]; gVersionInfo[componentId].targetAux[0] = getCompProp.resp.Response. currentVersionResp.currentVersion[2]; gVersionInfo[componentId].targetAux[1] = getCompProp.resp.Response. currentVersionResp.currentVersion[3]; gVersionInfo[componentId].targetAux[2] = getCompProp.resp.Response. currentVersionResp.currentVersion[4]; gVersionInfo[componentId].targetAux[3] = getCompProp.resp.Response. currentVersionResp.currentVersion[5]; mode = TARGET_VER; if (gVersionInfo[componentId].rollbackSupported) { getCompProp.req.selector = HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompRollbackVersion Failed for component Id %d\n",componentId); } else { gVersionInfo[componentId].rollbackMajor = getCompProp.resp .Response.rollbackFwVersionResp.rollbackFwVersion[0]; gVersionInfo[componentId].rollbackMinor = getCompProp.resp .Response.rollbackFwVersionResp.rollbackFwVersion[1]; gVersionInfo[componentId].rollbackAux[0] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[2]; gVersionInfo[componentId].rollbackAux[1] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[3]; gVersionInfo[componentId].rollbackAux[2] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[4]; gVersionInfo[componentId].rollbackAux[3] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[5]; } mode |= ROLLBACK_VER; } if (gVersionInfo[componentId].coldResetRequired) { /* * If any of the component indicates that the Payload Cold reset is required * then set the flag */ flagColdReset = TRUE; } if (option & VIEW_MODE) { HpmDisplayVersion(mode,&gVersionInfo[componentId]); printf("\n"); } } } if (option & VIEW_MODE) { HpmDisplayLine("-",53 ); if (flagColdReset) { fflush(stdout); lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset"); } printf("\n\n"); } return HPMFWUPG_SUCCESS; } /***************************************************************************** * Function Name: HpmfwupgUpgrade * * Description: This function performs the HPM.1 firmware upgrade procedure as * defined the IPM Controller Firmware Upgrade Specification * version 1.0 * *****************************************************************************/ int HpmfwupgUpgrade(void *intf, char* imageFilename, int activate,int componentToUpload, int option) { int rc = HPMFWUPG_SUCCESS; // struct HpmfwupgImageHeader imageHeader; struct HpmfwupgUpgradeCtx fwupgCtx; /* * GET IMAGE BUFFER FROM FILE */ rc = HpmfwupgGetBufferFromFile(imageFilename, &fwupgCtx); /* * VALIDATE IMAGE INTEGRITY */ if ( rc == HPMFWUPG_SUCCESS ) { printf("Validating firmware image integrity..."); fflush(stdout); rc = HpmfwupgValidateImageIntegrity(&fwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { printf("OK\n"); fflush(stdout); } else { free(fwupgCtx.pImageData); } } /* * PREPARATION STAGE */ if ( rc == HPMFWUPG_SUCCESS ) { printf("Performing preparation stage..."); fflush(stdout); rc = HpmfwupgPreparationStage(intf, &fwupgCtx, option); if ( rc == HPMFWUPG_SUCCESS ) { printf("OK\n"); fflush(stdout); } else { free(fwupgCtx.pImageData); } } /* * UPGRADE STAGE */ if ( rc == HPMFWUPG_SUCCESS ) { if (option & VIEW_MODE) { lprintf(LOG_NOTICE,"\nComparing Target & Image File version"); } else { lprintf(LOG_NOTICE,"\nPerforming upgrade stage:"); } if (option & VIEW_MODE) { rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,componentToUpload,VIEW_MODE); } else { rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,componentToUpload,option); if (rc == HPMFWUPG_SUCCESS ) { if( verbose ) { printf("Component update mask : 0x%02x\n", fwupgCtx.compUpdateMask.ComponentBits.byte); } rc = HpmfwupgUpgradeStage(intf, &fwupgCtx,componentToUpload,option); } } if ( rc != HPMFWUPG_SUCCESS ) { if (verbose) printf("HPM Upgrade error %d\n",rc); free(fwupgCtx.pImageData); } } /* * ACTIVATION STAGE */ if ( rc == HPMFWUPG_SUCCESS && activate ) { lprintf(LOG_NOTICE,"Performing activation stage: "); rc = HpmfwupgActivationStage(intf, &fwupgCtx); if ( rc != HPMFWUPG_SUCCESS ) { if (verbose) printf("HPM Activation error %d\n",rc); free(fwupgCtx.pImageData); } } if ( rc == HPMFWUPG_SUCCESS ) { if (option & VIEW_MODE) { // Dont display anything here in case we are just viewing it lprintf(LOG_NOTICE," "); } else { lprintf(LOG_NOTICE,"\nFirmware upgrade procedure successful\n"); } free(fwupgCtx.pImageData); } else { lprintf(LOG_NOTICE,"Firmware upgrade procedure failed\n"); } return rc; } /**************************************************************************** * * Function Name: HpmfwupgValidateImageIntegrity * * Description: This function validates a HPM.1 firmware image file as defined * in section 4 of the IPM Controller Firmware Upgrade * Specification version 1.0 * *****************************************************************************/ int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; md5_state_t ctx; static unsigned char md[HPMFWUPG_MD5_SIGNATURE_LENGTH]; unsigned char* pMd5Sig = pFwupgCtx->pImageData + (pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH); /* Validate MD5 checksum */ memset(md, 0, HPMFWUPG_MD5_SIGNATURE_LENGTH); memset(&ctx, 0, sizeof(md5_state_t)); md5_init(&ctx); md5_append(&ctx, pFwupgCtx->pImageData, pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH); md5_finish(&ctx, md); if ( memcmp(md, pMd5Sig,HPMFWUPG_MD5_SIGNATURE_LENGTH) != 0 ) { lprintf(LOG_NOTICE,"\n Invalid MD5 signature"); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { /* Validate Header signature */ if( strncmp(pImageHeader->signature, HPMFWUPG_IMAGE_SIGNATURE, HPMFWUPG_HEADER_SIGNATURE_LENGTH) == 0 ) { /* Validate Header image format version */ if ( pImageHeader->formatVersion == HPMFWUPG_IMAGE_HEADER_VERSION ) { /* Validate header checksum */ if ( HpmfwupgCalculateChecksum((unsigned char*)pImageHeader, sizeof(struct HpmfwupgImageHeader) + pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/) != 0 ) { lprintf(LOG_NOTICE,"\n Invalid header checksum"); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Unrecognized image version"); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Invalid image signature"); rc = HPMFWUPG_ERROR; } } return rc; } /**************************************************************************** * * Function Name: HpmfwupgPreparationStage * * Description: This function the preperation stage of a firmware upgrade * procedure as defined in section 3.2 of the IPM Controller * Firmware Upgrade Specification version 1.0 * *****************************************************************************/ int HpmfwupgPreparationStage(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx, int option) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; /* Get device ID */ rc = HpmfwupgGetDeviceId(intf, &pFwupgCtx->devId); /* Match current IPMC IDs with upgrade image */ if ( rc == HPMFWUPG_SUCCESS ) { /* Validate device ID */ if ( pImageHeader->deviceId == pFwupgCtx->devId.device_id ) { /* Validate product ID */ if ( memcmp(pImageHeader->prodId, pFwupgCtx->devId.product_id, HPMFWUPG_PRODUCT_ID_LENGTH ) == 0 ) { /* Validate man ID */ if ( memcmp(pImageHeader->manId, pFwupgCtx->devId.manufacturer_id, HPMFWUPG_MANUFATURER_ID_LENGTH ) != 0 ) { lprintf(LOG_NOTICE,"\n Invalid image file for manufacturer %u", buf2short(pFwupgCtx->devId.manufacturer_id)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Invalid image file for product %u", buf2short(pFwupgCtx->devId.product_id)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Invalid device ID %x", pFwupgCtx->devId.device_id); rc = HPMFWUPG_ERROR; } if (rc != HPMFWUPG_SUCCESS) { /* * Giving one more chance to user to check whether its OK to continue even if the * product ID does not match. This is helpful as sometimes we just want to update * and dont care whether we have a different product Id. If the user says NO then * we need to just bail out from here */ if ( (option & FORCE_MODE) || (option & VIEW_MODE) ) { printf("\n Image Information"); printf("\n Device Id : 0x%x",pImageHeader->deviceId); printf("\n Prod Id : 0x%02x%02x",pImageHeader->prodId[1], pImageHeader->prodId[0]); printf("\n Manuf Id : 0x%02x%02x%02x",pImageHeader->manId[2], pImageHeader->manId[1],pImageHeader->manId[0]); printf("\n Board Information"); printf("\n Device Id : 0x%x", pFwupgCtx->devId.device_id); printf("\n Prod Id : 0x%02x%02x",pFwupgCtx->devId.product_id[1], pFwupgCtx->devId.product_id[0]); printf("\n Manuf Id : 0x%02x%02x%02x",pFwupgCtx->devId.manufacturer_id[2], pFwupgCtx->devId.manufacturer_id[1],pFwupgCtx->devId.manufacturer_id[0]); if (HpmGetUserInput("\n Continue ignoring DeviceID/ProductID/ManufacturingID (Y/N) :")) rc = HPMFWUPG_SUCCESS; } else { /* * If you use all option its kind of FORCE command where we need to upgrade all the components */ printf("\n\n Use \"all\" option for uploading all the components\n"); } } } /* Validate earliest compatible revision */ if ( rc == HPMFWUPG_SUCCESS ) { /* Validate major & minor revision */ if ( pImageHeader->compRevision[0] < pFwupgCtx->devId.fw_rev1 ) { /* Do nothing, upgrade accepted */ } else if ( pImageHeader->compRevision[0] == pFwupgCtx->devId.fw_rev1 ) { /* Must validate minor revision */ if ( pImageHeader->compRevision[1] > pFwupgCtx->devId.fw_rev2 ) { /* Version not compatible for upgrade */ lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]); lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]); lprintf(LOG_NOTICE," Not compatible with "); lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1); lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2); rc = HPMFWUPG_ERROR; } } else { /* Version not compatible for upgrade */ lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]); lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]); lprintf(LOG_NOTICE," Not compatible with "); lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1); lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2); rc = HPMFWUPG_ERROR; } if (rc != HPMFWUPG_SUCCESS) { /* Confirming it once again */ if ( (option & FORCE_MODE) || (option & VIEW_MODE) ) { if( HpmGetUserInput("\n Continue IGNORING Earliest compatibility (Y/N) :")) rc = HPMFWUPG_SUCCESS; } } } /* Get target upgrade capabilities */ if ( rc == HPMFWUPG_SUCCESS ) { struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); if ( rc == HPMFWUPG_SUCCESS ) { /* Copy response to context */ memcpy(&pFwupgCtx->targetCap, &targetCapCmd.resp, sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp)); if (option & VIEW_MODE) { return rc; } else { /* Make sure all component IDs defined in the upgrade image are supported by the IPMC */ if ( (pImageHeader->components.ComponentBits.byte & pFwupgCtx->targetCap.componentsPresent.ComponentBits.byte ) != pImageHeader->components.ComponentBits.byte ) { lprintf(LOG_NOTICE,"\n Some components present in the image file are not supported by the IPMC"); rc = HPMFWUPG_ERROR; } /* Make sure the upgrade is desirable rigth now */ if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.fwUpgUndesirable == 1 ) { lprintf(LOG_NOTICE,"\n Upgrade undesirable at this moment"); rc = HPMFWUPG_ERROR; } /* Get confimation from the user if he wants to continue when service affected during upgrade */ if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.servAffectDuringUpg == 1 || pImageHeader->imageCapabilities.bitField.servAffected == 1 ) { if (HpmGetUserInput("\nServices may be affected during upgrade. Do you wish to continue? y/n ")) { rc = HPMFWUPG_SUCCESS; } else { rc = HPMFWUPG_ERROR; } } } } } /* Get the general properties of each component present in image */ if ( rc == HPMFWUPG_SUCCESS ) { int componentId; for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX; componentId++ ) { /* Reset component properties */ memset(&pFwupgCtx->genCompProp[componentId], 0, sizeof (struct HpmfwupgGetGeneralPropResp)); if ( (1 << componentId & pImageHeader->components.ComponentBits.byte) ) { struct HpmfwupgGetComponentPropertiesCtx getCompPropCmd; /* Get general component properties */ getCompPropCmd.req.componentId = componentId; getCompPropCmd.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES; rc = HpmfwupgGetComponentProperties(intf, &getCompPropCmd); if ( rc == HPMFWUPG_SUCCESS ) { /* Copy response to context */ memcpy(&pFwupgCtx->genCompProp[componentId], &getCompPropCmd.resp, sizeof(struct HpmfwupgGetGeneralPropResp)); } } } } return rc; } /**************************************************************************** * * Function Name: HpmfwupgPreUpgradeCheck * * Description: This function the pre Upgrade check, this mainly helps in checking * which all version upgrade is skippable because the image version * is same as target version. * *****************************************************************************/ int HpmfwupgPreUpgradeCheck(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx, int componentToUpload,int option) { int rc = HPMFWUPG_SUCCESS; unsigned char* pImagePtr; struct HpmfwupgActionRecord* pActionRecord; unsigned int actionsSize; int flagColdReset = FALSE; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; /* Put pointer after image header */ pImagePtr = (unsigned char*) (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) + pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/); /* Deternime actions size */ actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader); if (option & VIEW_MODE) { HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER|IMAGE_VER); } /* Perform actions defined in the image */ while( ( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH)) && ( rc == HPMFWUPG_SUCCESS) ) { /* Get action record */ pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr; /* Validate action record checksum */ if ( HpmfwupgCalculateChecksum((unsigned char*)pActionRecord, sizeof(struct HpmfwupgActionRecord)) != 0 ) { lprintf(LOG_NOTICE," Invalid Action record."); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { switch( pActionRecord->actionType ) { case HPMFWUPG_ACTION_BACKUP_COMPONENTS: { pImagePtr += sizeof(struct HpmfwupgActionRecord); } break; case HPMFWUPG_ACTION_PREPARE_COMPONENTS: { if (componentToUpload != DEFAULT_COMPONENT_UPLOAD) { if (!(1<components.ComponentBits.byte)) { lprintf(LOG_NOTICE,"\nComponent Id given is not supported\n"); return HPMFWUPG_ERROR; } } pImagePtr += sizeof(struct HpmfwupgActionRecord); } break; case HPMFWUPG_ACTION_UPLOAD_FIRMWARE: /* Upload all firmware blocks */ { struct HpmfwupgFirmwareImage* pFwImage; unsigned char* pData; unsigned int firmwareLength = 0; unsigned char mode = 0; unsigned char componentId = 0x00; unsigned char componentIdByte = 0x00; VERSIONINFO *pVersionInfo; // struct HpmfwupgGetComponentPropertiesCtx getCompProp; /* Save component ID on which the upload is done */ componentIdByte = pActionRecord->components.ComponentBits.byte; while ((componentIdByte>>=1)!=0) { componentId++; } pFwupgCtx->componentId = componentId; pFwImage = (struct HpmfwupgFirmwareImage*)(pImagePtr + sizeof(struct HpmfwupgActionRecord)); pData = ((unsigned char*)pFwImage + sizeof(struct HpmfwupgFirmwareImage)); /* Get firmware length */ firmwareLength = pFwImage->length[0]; firmwareLength |= (pFwImage->length[1] << 8) & 0xff00; firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000; firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000; pVersionInfo = &gVersionInfo[componentId]; pVersionInfo->imageMajor = pFwImage->version[0]; pVersionInfo->imageMinor = pFwImage->version[1]; pVersionInfo->imageAux[0] = pFwImage->version[2]; pVersionInfo->imageAux[1] = pFwImage->version[3]; pVersionInfo->imageAux[2] = pFwImage->version[4]; pVersionInfo->imageAux[3] = pFwImage->version[5]; mode = TARGET_VER | IMAGE_VER; if (pVersionInfo->coldResetRequired) { flagColdReset = TRUE; } pVersionInfo->skipUpgrade = FALSE; if (option & FORCE_MODE_ALL) { /* user has given all to upload all the components on the command line */ if(verbose) { lprintf(LOG_NOTICE,"Forcing ALL components"); } } else if( option & FORCE_MODE_COMPONENT ) { if( componentToUpload != componentId ) { if(verbose) { lprintf(LOG_NOTICE,"Forcing component %d skip", componentId); } /* user has given the component Id to upload on the command line */ pVersionInfo->skipUpgrade = TRUE; } else if(verbose) { lprintf(LOG_NOTICE,"Forcing component %d update", componentId); /* user has given the component Id to upload on the command line */ } } else { if ( (pVersionInfo->imageMajor == pVersionInfo->targetMajor) && (pVersionInfo->imageMinor == pVersionInfo->targetMinor)) { if (pVersionInfo->rollbackSupported) { /*If the Image Versions are same as Target Versions then check for the * rollback version*/ if ( (pVersionInfo->imageMajor == pVersionInfo->rollbackMajor) && (pVersionInfo->imageMinor == pVersionInfo->rollbackMinor) ) { /* This indicates that the Rollback version is also same as * Image version -- So now we must skip it */ pVersionInfo->skipUpgrade = TRUE; } mode |= ROLLBACK_VER; } else { pVersionInfo->skipUpgrade = TRUE; } } if ( verbose ) { lprintf(LOG_NOTICE,"Component %d: %s", componentId , (pVersionInfo->skipUpgrade?"skipped":"to update")); } } if( pVersionInfo->skipUpgrade == FALSE ) { pFwupgCtx->compUpdateMask.ComponentBits.byte |= 1<pImageData; struct HpmfwupgActionRecord* pActionRecord; int rc = HPMFWUPG_SUCCESS; unsigned char* pImagePtr; unsigned int actionsSize; int flagColdReset = FALSE; // time_t start,end; /* Put pointer after image header */ pImagePtr = (unsigned char*) (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) + pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/); /* Deternime actions size */ actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader); if (option & VERSIONCHECK_MODE || option & FORCE_MODE) { HpmDisplayUpgradeHeader(0); } /* Perform actions defined in the image */ while( ( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH)) && ( rc == HPMFWUPG_SUCCESS) ) { /* Get action record */ pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr; /* Validate action record checksum */ if ( HpmfwupgCalculateChecksum((unsigned char*)pActionRecord, sizeof(struct HpmfwupgActionRecord)) != 0 ) { lprintf(LOG_NOTICE," Invalid Action record."); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { switch( pActionRecord->actionType ) { case HPMFWUPG_ACTION_BACKUP_COMPONENTS: { /* Send prepare components command */ struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; initUpgActionCmd.req.componentsMask = pFwupgCtx->compUpdateMask; /* Action is prepare components */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_BACKUP; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); pImagePtr += sizeof(struct HpmfwupgActionRecord); } break; case HPMFWUPG_ACTION_PREPARE_COMPONENTS: { int componentId; /* Make sure every components specified by this action supports the prepare components */ /* Component 'filtering' is done in PreUpdateCheck() and pFwupgCtx is set accordiongly */ for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX; componentId++ ) { if ( (1 << componentId & pFwupgCtx->compUpdateMask.ComponentBits.byte) ) { if ( pFwupgCtx->genCompProp[componentId].GeneralCompProperties.bitfield.preparationSupport == 0 ) { lprintf(LOG_NOTICE," Prepare component not supported by component ID %d", componentId); rc = HPMFWUPG_ERROR; break; } } } if ( rc == HPMFWUPG_SUCCESS ) { if ( pFwupgCtx->compUpdateMask.ComponentBits.byte != 0x00 ) { /* Send prepare components command */ struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; initUpgActionCmd.req.componentsMask = pFwupgCtx->compUpdateMask; /* Action is prepare components */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_PREPARE; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); } pImagePtr += sizeof(struct HpmfwupgActionRecord); } } break; case HPMFWUPG_ACTION_UPLOAD_FIRMWARE: /* Upload all firmware blocks */ rc = HpmFwupgActionUploadFirmware ( pActionRecord->components, pFwupgCtx, &pImagePtr, componentToUpload, intf, option, &flagColdReset ); break; default: lprintf(LOG_NOTICE," Invalid Action type. Cannot continue"); rc = HPMFWUPG_ERROR; break; } } } HpmDisplayLine("-",78); if (flagColdReset) { fflush(stdout); lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset"); } return rc; } static int HpmFwupgActionUploadFirmware ( struct HpmfwupgComponentBitMask components, struct HpmfwupgUpgradeCtx* pFwupgCtx, unsigned char** pImagePtr, int componentToUpload, void *intf, int option, int *pFlagColdReset ) { struct HpmfwupgFirmwareImage* pFwImage; struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; struct HpmfwupgUploadFirmwareBlockCtx uploadCmd; struct HpmfwupgFinishFirmwareUploadCtx finishCmd; // struct HpmfwupgGetComponentPropertiesCtx getCompProp; VERSIONINFO *pVersionInfo; time_t start,end; int rc = HPMFWUPG_SUCCESS; int skip = TRUE; unsigned char* pData, *pDataInitial; unsigned char count; unsigned int totalSent = 0; unsigned char bufLength = 0; unsigned int firmwareLength = 0; unsigned int displayFWLength = 0; unsigned char *pDataTemp; unsigned int imageOffset = 0x00; unsigned int blockLength = 0x00; unsigned int lengthOfBlock = 0x00; unsigned int numTxPkts = 0; unsigned int numRxPkts = 0; unsigned char mode = 0; unsigned char componentId = 0x00; unsigned char componentIdByte = 0x00; /* Save component ID on which the upload is done */ componentIdByte = components.ComponentBits.byte; while ((componentIdByte>>=1)!=0) { componentId++; } pFwupgCtx->componentId = componentId; pVersionInfo = (VERSIONINFO*) &gVersionInfo[componentId]; pFwImage = (struct HpmfwupgFirmwareImage*)((*pImagePtr) + sizeof(struct HpmfwupgActionRecord)); pDataInitial = ((unsigned char*)pFwImage + sizeof(struct HpmfwupgFirmwareImage)); pData = pDataInitial; /* Get firmware length */ firmwareLength = pFwImage->length[0]; firmwareLength |= (pFwImage->length[1] << 8) & 0xff00; firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000; firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000; mode = TARGET_VER | IMAGE_VER; if (pVersionInfo->rollbackSupported) { mode |= ROLLBACK_VER; } if ((option & DEBUG_MODE)) { printf("\n\n Comp ID : %d [%-20s]\n",pVersionInfo->componentId,pFwImage->desc); } else { HpmDisplayVersion(mode,pVersionInfo); } if( (1 << componentId) & pFwupgCtx->compUpdateMask.ComponentBits.byte) { if( verbose ) { lprintf(LOG_NOTICE,"Do not skip %d" , componentId); } skip = FALSE; } if(!skip) { /* Initialize parameters */ uploadCmd.req.blockNumber = 0; /* Check if we receive size in parameters */ if(g_channel_buf_size != 0) { if (g_sa == BMC_SA) { bufLength = g_channel_buf_size - 9; /* Plan for overhead */ } else { bufLength = g_channel_buf_size - 11; /* Plan for overhead */ } } else { /* Find max buffer length according the connection parameters */ if ( is_remote() ) /*IPMI LAN*/ { bufLength = HPMFWUPG_SEND_DATA_COUNT_LAN - 2; if (g_sa != BMC_SA) bufLength -= 8; } else { int i; i = get_driver_type(); if ((i == DRV_MV || i == DRV_KCS) && /*open driver*/ (g_sa == BMC_SA) ) { bufLength = HPMFWUPG_SEND_DATA_COUNT_KCS - 2; } else { if ( g_bus == 7 ) { bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMBL; } else { bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMB; } } } } if (verbose) printf("Upgrade buffer size = %d (%d)\n",bufLength,g_channel_buf_size); /* Send Initiate Upgrade Action */ initUpgActionCmd.req.componentsMask = components; /* Action is upgrade */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_UPGRADE; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); if (rc != HPMFWUPG_SUCCESS) { skip = TRUE; } if ( (pVersionInfo->coldResetRequired) && (!skip)) { *pFlagColdReset = TRUE; } /* pDataInitial is the starting pointer of the image data */ /* pDataTemp is one which we will move across */ pData = pDataInitial; pDataTemp = pDataInitial; lengthOfBlock = firmwareLength; totalSent = 0x00; displayFWLength= firmwareLength; time(&start); while ( (pData < (pDataTemp+lengthOfBlock)) && (rc == HPMFWUPG_SUCCESS) ) { if ( (pData+bufLength) <= (pDataTemp+lengthOfBlock) ) { count = bufLength; } else { count = (unsigned char)((pDataTemp+lengthOfBlock) - pData); } memcpy(&uploadCmd.req.data, pData, bufLength); imageOffset = 0x00; blockLength = 0x00; numTxPkts++; rc = HpmfwupgUploadFirmwareBlock(intf, &uploadCmd, pFwupgCtx, count, &imageOffset,&blockLength); numRxPkts++; if ( rc != HPMFWUPG_SUCCESS) { if ( rc == HPMFWUPG_UPLOAD_BLOCK_LENGTH ) { /* Retry with a smaller buffer length */ if ( is_remote() ) // strstr(intf->name,"lan") != NULL { bufLength -= (unsigned char)8; lprintf(LOG_INFO,"Trying reduced buffer length: %d", bufLength); } else { bufLength -= (unsigned char)1; lprintf(LOG_INFO,"Trying reduced buffer length: %d", bufLength); } rc = HPMFWUPG_SUCCESS; } else if ( rc == HPMFWUPG_UPLOAD_RETRY ) { rc = HPMFWUPG_SUCCESS; } else { fflush(stdout); lprintf(LOG_NOTICE,"\n Error in Upload FIRMWARE command [rc=%d]\n",rc); lprintf(LOG_NOTICE,"\n TotalSent:0x%x ",totalSent); /* Exiting from the function */ rc = HPMFWUPG_ERROR; } } else { if (blockLength > firmwareLength) { /* * blockLength is the remaining length of the firmware to upload so * if its greater than the firmware length then its kind of error */ lprintf(LOG_NOTICE,"\n Error in Upload FIRMWARE command [rc=%d]\n",rc); lprintf(LOG_NOTICE,"\n TotalSent:0x%x Img offset:0x%x Blk length:0x%x Fwlen:0x%x\n", totalSent,imageOffset,blockLength,firmwareLength); rc = HPMFWUPG_ERROR; } totalSent += count; if (imageOffset != 0x00) { /* block Length is valid */ lengthOfBlock = blockLength; pDataTemp = pDataInitial + imageOffset; pData = pDataTemp; if ( displayFWLength == firmwareLength) { /* This is basically used only to make sure that we display uptil 100% */ displayFWLength = blockLength + totalSent; } } else { pData += count; } time(&end); /* * Just added debug mode in case we need to see exactly how many bytes have * gone through - Its a hidden option used mainly should be used for debugging */ if ( option & DEBUG_MODE) { fflush(stdout); printf(" Blk Num : %02x Bytes : %05x \r\n", uploadCmd.req.blockNumber,totalSent); if (imageOffset || blockLength) { printf("\r--> ImgOff : %x BlkLen : %x\n",imageOffset,blockLength); } if (displayFWLength == totalSent) { printf(" Time Taken %02d:%02d\n",(end-start)/60, (end-start)%60); printf("\n"); } } else { HpmDisplayUpgrade(0,totalSent,displayFWLength,(end-start)); } uploadCmd.req.blockNumber++; } } } if (skip) { HpmDisplayUpgrade(1,0,0,0); *pImagePtr = pDataInitial + firmwareLength; } if ( (rc == HPMFWUPG_SUCCESS) && (!skip) ) { /* Send finish component */ /* Set image length */ finishCmd.req.componentId = componentId; /* We need to send the actual data that is sent * not the comlete firmware image length */ finishCmd.req.imageLength[0] = totalSent & 0xFF; finishCmd.req.imageLength[1] = (totalSent >> 8) & 0xFF; finishCmd.req.imageLength[2] = (totalSent >> 16) & 0xFF; finishCmd.req.imageLength[3] = (totalSent >> 24) & 0xFF; rc = HpmfwupgFinishFirmwareUpload(intf, &finishCmd, pFwupgCtx); if ( option & DEBUG_MODE) printf("HpmfwupgFinishFirmwareUpload rc = %d sent = %d\n",rc,totalSent); *pImagePtr = pDataInitial + firmwareLength; } return rc; } /**************************************************************************** * * Function Name: HpmfwupgActivationStage * * Description: This function the validation stage of a firmware upgrade * procedure as defined in section 3.4 of the IPM Controller * Firmware Upgrade Specification version 1.0 * *****************************************************************************/ static int HpmfwupgActivationStage(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgActivateFirmwareCtx activateCmd; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; /* Print out stuf...*/ printf(" "); fflush(stdout); /* Activate new firmware */ rc = HpmfwupgActivateFirmware(intf, &activateCmd, pFwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { /* Query self test result if supported by target and new image */ if ( (pFwupgCtx->targetCap.GlobalCapabilities.bitField.ipmcSelftestCap == 1) || (pImageHeader->imageCapabilities.bitField.imageSelfTest == 1) ) { struct HpmfwupgQuerySelftestResultCtx selfTestCmd; rc = HpmfwupgQuerySelftestResult(intf, &selfTestCmd, pFwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { /* Get the self test result */ if ( selfTestCmd.resp.result1 != 0x55 ) { /* Perform manual rollback if necessary */ /* BACKUP/ MANUAL ROLLBACK not supported by this UA */ lprintf(LOG_NOTICE," Self test failed:"); lprintf(LOG_NOTICE," Result1 = %x", selfTestCmd.resp.result1); lprintf(LOG_NOTICE," Result2 = %x", selfTestCmd.resp.result2); rc = HPMFWUPG_ERROR; } } else { /* Perform manual rollback if necessary */ /* BACKUP / MANUAL ROLLBACK not supported by this UA */ lprintf(LOG_NOTICE," Self test failed."); } } } /* If activation / self test failed, query rollback status if automatic rollback supported */ if ( rc == HPMFWUPG_ERROR ) { if ( (pFwupgCtx->targetCap.GlobalCapabilities.bitField.autRollback == 1) && (pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.rollbackBackup != 0x00) ) { struct HpmfwupgQueryRollbackStatusCtx rollCmd; lprintf(LOG_NOTICE," Getting rollback status..."); fflush(stdout); rc = HpmfwupgQueryRollbackStatus(intf, &rollCmd, pFwupgCtx); } } return rc; } int HpmfwupgGetBufferFromFile(char* imageFilename, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; FILE* pImageFile = fopen(imageFilename, "rb"); if ( pImageFile == NULL ) { lprintf(LOG_NOTICE,"Cannot open image file %s", imageFilename); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { /* Get the raw data in file */ fseek(pImageFile, 0, SEEK_END); pFwupgCtx->imageSize = ftell(pImageFile); pFwupgCtx->pImageData = malloc(sizeof(unsigned char)*pFwupgCtx->imageSize); pFwupgCtx->compUpdateMask.ComponentBits.byte = 0; rewind(pImageFile); if ( pFwupgCtx->pImageData != NULL ) { fread(pFwupgCtx->pImageData, sizeof(unsigned char), pFwupgCtx->imageSize, pImageFile); } else { rc = HPMFWUPG_ERROR; } fclose(pImageFile); } return rc; } int HpmfwupgGetDeviceId(void *intf, struct ipm_devid_rsp* pGetDevId) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_DEVICE_ID; req.msg.data_len = 0; rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(pGetDevId, rsp->data, sizeof(struct ipm_devid_rsp)); } else { lprintf(LOG_NOTICE,"Error getting device ID, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting device ID\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgGetTargetUpgCapabilities(void *intf, struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_GET_TARGET_UPG_CAPABILITIES; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgGetTargetUpgCapabilitiesReq); rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp)); if ( verbose ) { lprintf(LOG_NOTICE,"TARGET UPGRADE CAPABILITIES"); lprintf(LOG_NOTICE,"-------------------------------"); lprintf(LOG_NOTICE,"HPM.1 version............%d ", pCtx->resp.hpmVersion); lprintf(LOG_NOTICE,"Component 0 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component0 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 1 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component1 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 2 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component2 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 3 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component3 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 4 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component4 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 5 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component5 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 6 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component6 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 7 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component7 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Upgrade undesirable.....[%c] ", pCtx->resp.GlobalCapabilities. bitField.fwUpgUndesirable ? 'y' : 'n'); lprintf(LOG_NOTICE,"Aut rollback override...[%c] ", pCtx->resp.GlobalCapabilities. bitField.autRollbackOverride ? 'y' : 'n'); lprintf(LOG_NOTICE,"IPMC degraded...........[%c] ", pCtx->resp.GlobalCapabilities. bitField.ipmcDegradedDurinUpg ? 'y' : 'n'); lprintf(LOG_NOTICE,"Defered activation......[%c] ", pCtx->resp.GlobalCapabilities. bitField.deferActivation ? 'y' : 'n'); lprintf(LOG_NOTICE,"Service affected........[%c] ", pCtx->resp.GlobalCapabilities. bitField.servAffectDuringUpg ? 'y' : 'n'); lprintf(LOG_NOTICE,"Manual rollback.........[%c] ", pCtx->resp.GlobalCapabilities. bitField.manualRollback ? 'y' : 'n'); lprintf(LOG_NOTICE,"Automatic rollback......[%c] ", pCtx->resp.GlobalCapabilities. bitField.autRollback ? 'y' : 'n'); lprintf(LOG_NOTICE,"Self test...............[%c] ", pCtx->resp.GlobalCapabilities. bitField.ipmcSelftestCap ? 'y' : 'n'); lprintf(LOG_NOTICE,"Upgrade timeout.........[%d sec] ", pCtx->resp.upgradeTimeout*5); lprintf(LOG_NOTICE,"Self test timeout.......[%d sec] ", pCtx->resp.selftestTimeout*5); lprintf(LOG_NOTICE,"Rollback timeout........[%d sec] ", pCtx->resp.rollbackTimeout*5); lprintf(LOG_NOTICE,"Inaccessibility timeout.[%d sec] \n", pCtx->resp.inaccessTimeout*5); } } else { lprintf(LOG_NOTICE,"Error getting target upgrade capabilities\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting target upgrade capabilities\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgGetComponentProperties(void *intf, struct HpmfwupgGetComponentPropertiesCtx* pCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_GET_COMPONENT_PROPERTIES; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgGetComponentPropertiesReq); rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode == 0x00 ) { switch ( pCtx->req.selector ) { case HPMFWUPG_COMP_GEN_PROPERTIES: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetGeneralPropResp)); if ( verbose ) { lprintf(LOG_NOTICE,"GENERAL PROPERTIES"); lprintf(LOG_NOTICE,"-------------------------------"); lprintf(LOG_NOTICE,"Payload cold reset req....[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.payloadColdReset ? 'y' : 'n'); lprintf(LOG_NOTICE,"Def. activation supported.[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.deferredActivation ? 'y' : 'n'); lprintf(LOG_NOTICE,"Comparison supported......[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.comparisonSupport ? 'y' : 'n'); lprintf(LOG_NOTICE,"Preparation supported.....[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.preparationSupport ? 'y' : 'n'); lprintf(LOG_NOTICE,"Rollback supported........[%c] \n", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.rollbackBackup ? 'y' : 'n'); } break; case HPMFWUPG_COMP_CURRENT_VERSION: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetCurrentVersionResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Current Version: "); lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.currentVersionResp.currentVersion[0]); lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.currentVersionResp.currentVersion[1]); lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.currentVersionResp.currentVersion[2], pCtx->resp.Response.currentVersionResp.currentVersion[3], pCtx->resp.Response.currentVersionResp.currentVersion[4], pCtx->resp.Response.currentVersionResp.currentVersion[5]); } break; case HPMFWUPG_COMP_DESCRIPTION_STRING: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDescStringResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Description string: %s\n", pCtx->resp.Response.descStringResp.descString); } break; case HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetRollbackFwVersionResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Rollback FW Version: "); lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[0]); lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[1]); lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[2], pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[3], pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[4], pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[5]); } break; case HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDeferredFwVersionResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Deferred FW Version: "); lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[0]); lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[1]); lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[2], pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[3], pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[4], pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[5]); } break; // OEM Properties command case HPMFWUPG_COMP_OEM_PROPERTIES: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetOemProperties)); if ( verbose ) { unsigned char i = 0; lprintf(LOG_NOTICE,"OEM Properties: "); for (i=0; i < HPMFWUPG_OEM_LENGTH; i++) { lprintf(LOG_NOTICE," 0x%x ", pCtx->resp.Response.oemProperties.oemRspData[i]); } } break; default: lprintf(LOG_NOTICE,"Unsupported component selector"); rc = HPMFWUPG_ERROR; break; } } else { lprintf(LOG_NOTICE,"Error getting component properties, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting component properties\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgAbortUpgrade(void *intf, struct HpmfwupgAbortUpgradeCtx* pCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_ABORT_UPGRADE; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgAbortUpgradeReq); rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode != 0x00 ) { lprintf(LOG_NOTICE,"Error aborting upgrade, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error aborting upgrade\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgInitiateUpgradeAction(void *intf, struct HpmfwupgInitiateUpgradeActionCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_INITIATE_UPGRADE_ACTION; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgInitiateUpgradeActionReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ) { rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); } else if ( rsp->ccode != 0x00 ) { lprintf(LOG_NOTICE,"Error initiating upgrade action, compcode = %x %s\n", rsp->ccode, hpm_decode_cc(req.msg.cmd,rsp->ccode)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error initiating upgrade action\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgUploadFirmwareBlock(void *intf, struct HpmfwupgUploadFirmwareBlockCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx, int count ,unsigned int *imageOffset, unsigned int *blockLength ) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_UPLOAD_FIRMWARE_BLOCK; req.msg.data = (unsigned char*)&pCtx->req; /* 2 is the size of the upload struct - data */ req.msg.data_len = 2 + count; rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS || rsp->ccode == 0x00 ) { /* * We need to check if the response also contains the next upload firmware offset * and the firmware length in its response - These are optional but very vital */ if ( rsp->data_len > 1 ) { /* * If the response data length is greater than 1 it should contain both the * the Section offset and section length. Because we cannot just have * Section offset without section length so the length should be 9 */ if ( rsp->data_len == 9 ) { /* rsp->data[1] - LSB rsp->data[2] - rsp->data[3] = MSB */ *imageOffset = (rsp->data[4] << 24) + (rsp->data[3] << 16) + (rsp->data[2] << 8) + rsp->data[1]; *blockLength = (rsp->data[8] << 24) + (rsp->data[7] << 16) + (rsp->data[6] << 8) + rsp->data[5]; } else { /* * The Spec does not say much for this kind of errors where the * firmware returned only offset and length so currently returning it * as 0x82 - Internal CheckSum Error */ lprintf(LOG_NOTICE,"Error wrong rsp->datalen %d for Upload Firmware block command\n",rsp->data_len); rsp->ccode = HPMFWUPG_INT_CHECKSUM_ERROR; } } } /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ) { rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); } else if (rsp->ccode != 0x00) { /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); rc = HPMFWUPG_UPLOAD_RETRY; } /* * If completion code = 0xc7, we will retry with a reduced buffer length. * Do not print error. */ else if ( rsp->ccode == IPMI_CC_REQ_DATA_INV_LENGTH ) { rc = HPMFWUPG_UPLOAD_BLOCK_LENGTH; } else { lprintf(LOG_NOTICE,"Error uploading firmware block, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } } else { lprintf(LOG_NOTICE,"Error uploading firmware block\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgFinishFirmwareUpload(void *intf, struct HpmfwupgFinishFirmwareUploadCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_FINISH_FIRMWARE_UPLOAD; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgFinishFirmwareUploadReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); } else if ( rsp->ccode != IPMI_CC_OK ) { lprintf(LOG_NOTICE,"Error finishing firmware upload, compcode = %x %s\n", rsp->ccode, hpm_decode_cc(req.msg.cmd,rsp->ccode)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error finishing firmware upload\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgActivateFirmware(void *intf, struct HpmfwupgActivateFirmwareCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_ACTIVATE_FIRMWARE; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgActivateFirmwareReq) - (!pCtx->req.rollback_override ? 1 : 0); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { printf("Waiting firmware activation..."); fflush(stdout); rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { lprintf(LOG_NOTICE,"OK"); } else { lprintf(LOG_NOTICE,"Failed"); } } else if (rsp->ccode == HPMFWUPG_NOT_SUPPORTED_NOW) /*0xd5*/ { printf("Activation already completed.\n"); rc = HPMFWUPG_SUCCESS; } else if ( rsp->ccode != IPMI_CC_OK ) { lprintf(LOG_NOTICE,"Error activating firmware, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error activating firmware\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgGetUpgradeStatus(void *intf, struct HpmfwupgGetUpgradeStatusCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_GET_UPGRADE_STATUS; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgGetUpgradeStatusReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetUpgradeStatusResp)); if ( verbose > 1 ) { lprintf(LOG_NOTICE,"Upgrade status:"); lprintf(LOG_NOTICE," Command in progress: %x", pCtx->resp.cmdInProcess); lprintf(LOG_NOTICE," Last command completion code: %x", pCtx->resp.lastCmdCompCode); } } /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ else if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); pCtx->resp.lastCmdCompCode = HPMFWUPG_COMMAND_IN_PROGRESS; } else { if ( verbose ) { lprintf(LOG_NOTICE,"Error getting upgrade status, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } } else { if ( verbose ) { lprintf(LOG_NOTICE,"Error getting upgrade status"); rc = HPMFWUPG_ERROR; } } return rc; } int HpmfwupgManualFirmwareRollback(void *intf, struct HpmfwupgManualFirmwareRollbackCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgManualFirmwareRollbackReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ) { struct HpmfwupgQueryRollbackStatusCtx resCmd; printf("Waiting firmware rollback..."); fflush(stdout); rc = HpmfwupgQueryRollbackStatus(intf, &resCmd, pFwupgCtx); } else if ( rsp->ccode != 0x00 ) { lprintf(LOG_NOTICE,"Error sending manual rollback, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error sending manual rollback\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgQueryRollbackStatus(void *intf, struct HpmfwupgQueryRollbackStatusCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; unsigned int rollbackTimeout = 0; unsigned int timeoutSec1, timeoutSec2; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_QUERY_ROLLBACK_STATUS; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgQueryRollbackStatusReq); /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { rollbackTimeout = pFwupgCtx->targetCap.rollbackTimeout*5; } else { struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; verbose--; rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); verbose++; if ( rc == HPMFWUPG_SUCCESS ) { rollbackTimeout = targetCapCmd.resp.rollbackTimeout *5; } else { rollbackTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; } } /* Poll rollback status until completion or timeout */ timeoutSec1 = (uint32_t)time(NULL); timeoutSec2 = (uint32_t)time(NULL); do { /* Must wait at least 100 ms between status requests */ os_usleep(0,100000); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ if ( rsp ) { if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS; } } timeoutSec2 = (uint32_t)time(NULL); }while( rsp && (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) && (timeoutSec2 - timeoutSec1 < rollbackTimeout ) ); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgQueryRollbackStatusResp)); if ( pCtx->resp.rollbackComp.ComponentBits.byte != 0 ) { /* Rollback occured */ lprintf(LOG_NOTICE,"Rollback occured on component mask: 0x%02x", pCtx->resp.rollbackComp.ComponentBits.byte); } else { lprintf(LOG_NOTICE,"No Firmware rollback occured"); } } else if ( rsp->ccode == 0x81 ) { lprintf(LOG_NOTICE,"Rollback failed on component mask: 0x%02x", pCtx->resp.rollbackComp.ComponentBits.byte); rc = HPMFWUPG_ERROR; } else { lprintf(LOG_NOTICE,"Error getting rollback status, compcode = %x", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting upgrade status\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgQuerySelftestResult(void *intf, struct HpmfwupgQuerySelftestResultCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; unsigned char selfTestTimeout = 0; unsigned int timeoutSec1, timeoutSec2; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { /* Getting selftest timeout from new image */ struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; selfTestTimeout = pImageHeader->selfTestTimeout; } else { selfTestTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_QUERY_SELFTEST_RESULT; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgQuerySelftestResultReq); /* Poll rollback status until completion or timeout */ timeoutSec1 = (uint32_t)time(NULL); timeoutSec2 = (uint32_t)time(NULL); do { /* Must wait at least 100 ms between status requests */ os_usleep(0,100000); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ if ( rsp ) { if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS; } } timeoutSec2 = (uint32_t)time(NULL); }while( rsp && (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) && (timeoutSec2 - timeoutSec1 < selfTestTimeout ) ); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgQuerySelftestResultResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Self test results:"); lprintf(LOG_NOTICE,"Result1 = %x", pCtx->resp.result1); lprintf(LOG_NOTICE,"Result2 = %x", pCtx->resp.result2); } } else { lprintf(LOG_NOTICE,"Error getting self test results, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting upgrade status\n"); rc = HPMFWUPG_ERROR; } return rc; } struct ipmi_rs * HpmfwupgSendCmd(void *intf, struct ipmi_rq req, struct HpmfwupgUpgradeCtx* pFwupgCtx ) { struct ipmi_rs * rsp; unsigned int inaccessTimeout = 0, inaccessTimeoutCounter = 0; unsigned int upgradeTimeout = 0, upgradeTimeoutCounter = 0; unsigned int timeoutSec1, timeoutSec2; unsigned char retry = 0; static struct ipmi_rs fakeRsp; int rv, rsp_len; /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { inaccessTimeout = pFwupgCtx->targetCap.inaccessTimeout*5; upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5; } else { /* keeping the inaccessTimeout to 60 seconds results in almost 2900 retries * So if the target is not available it will be retrying the command for 2900 * times which is not effecient -So reducing the Timout to 5 seconds which is * almost 200 retries if it continuously recieves 0xC3 as completion code. */ inaccessTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; } timeoutSec1 = (uint32_t)time(NULL); do { static unsigned char isValidSize = FALSE; rv = ipmi_sendrecv(&req, fakeRsp.data, &rsp_len); if( rv < 0) { #define HPM_LAN_PACKET_RESIZE_LIMIT 6 if(is_remote()) /* also covers lanplus */ { static int errorCount=0; lprintf(LOG_DEBUG,"HPM: no response available"); lprintf(LOG_DEBUG,"HPM: the command may be rejected for " \ "security reasons"); if ( req.msg.netfn == IPMI_NETFN_PICMG && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK && errorCount < HPM_LAN_PACKET_RESIZE_LIMIT && (!isValidSize) ) { lprintf(LOG_DEBUG,"HPM: upload firmware block API called"); lprintf(LOG_DEBUG,"HPM: returning length error to force resize"); fakeRsp.ccode = IPMI_CC_REQ_DATA_INV_LENGTH; rv = fakeRsp.ccode; rsp = &fakeRsp; errorCount++; } else if ( req.msg.netfn == IPMI_NETFN_PICMG && ( req.msg.cmd == HPMFWUPG_ACTIVATE_FIRMWARE || req.msg.cmd == HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK ) ) { /* * rsp == NULL and command activate firmware or manual firmware * rollback most likely occurs when we have sent a firmware activation * request. Fake a command in progress response. */ lprintf(LOG_DEBUG,"HPM: activate/rollback firmware API called"); lprintf(LOG_DEBUG,"HPM: returning in progress to handle IOL session lost"); fakeRsp.ccode = HPMFWUPG_COMMAND_IN_PROGRESS; rv = fakeRsp.ccode; rsp = &fakeRsp; } else if ( req.msg.netfn == IPMI_NETFN_PICMG && ( req.msg.cmd == HPMFWUPG_QUERY_ROLLBACK_STATUS || req.msg.cmd == HPMFWUPG_GET_UPGRADE_STATUS ) ) { /* * rsp == NULL and command get upgrade status or query rollback * status most likely occurs when we are waiting for firmware * activation. Try to re-open the IOL session (re-open will work * once the IPMC recovers from firmware activation. */ lprintf(LOG_DEBUG,"HPM: upg/rollback status firmware API called"); lprintf(LOG_DEBUG,"HPM: try to re-open IOL session"); { /* force session re-open */ ipmi_close_(); os_usleep(inaccessTimeout,0); /* Fake timeout to retry command */ fakeRsp.ccode = 0xc3; rv = fakeRsp.ccode; rsp = &fakeRsp; } } } } /* Handle inaccessibility timeout (rsp = NULL if IOL) */ if ( rv < 0 || rv == 0xff || rv == 0xc3 || rv == 0xd3 ) { if ( inaccessTimeoutCounter < inaccessTimeout ) { timeoutSec2 = (uint32_t)time(NULL); if ( timeoutSec2 > timeoutSec1 ) { inaccessTimeoutCounter += timeoutSec2 - timeoutSec1; timeoutSec1 = (uint32_t)time(NULL); } os_usleep(0,100000); retry = 1; } else { retry = 0; } } /* Handle node busy timeout */ else if ( rv == 0xc0 ) { if ( upgradeTimeoutCounter < upgradeTimeout ) { timeoutSec2 = (uint32_t)time(NULL); if ( timeoutSec2 > timeoutSec1 ) { timeoutSec1 = (uint32_t)time(NULL); // upgradeTimeoutCounter += timeoutSec2 - timeoutSec1; upgradeTimeoutCounter += 1; } os_usleep(0,100000); retry = 1; } else { retry = 0; } } else { #ifdef ENABLE_OPENIPMI_V39_PATCH if( rv == IPMI_CC_OK ) { errorCount = 0 ; } #endif retry = 0; if ( req.msg.netfn == IPMI_NETFN_PICMG && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK && (!isValidSize) ) { lprintf(LOG_INFO,"Buffer length is now considered valid" ); isValidSize = TRUE; } } }while( retry ); if (rv < 0) rsp = NULL; else { rsp = &fakeRsp; /*has data already*/ rsp->ccode = (uchar)rv; rsp->session.payloadtype = 0; /*IPMI_PAYLOAD_TYPE_IPMI*/ rsp->data_len = rsp_len; } return rsp; } int HpmfwupgWaitLongDurationCmd(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; unsigned int upgradeTimeout = 0; unsigned int timeoutSec1, timeoutSec2; struct HpmfwupgGetUpgradeStatusCtx upgStatusCmd; /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5; if ( verbose ) printf("Use File Upgrade Capabilities: %i seconds\n", upgradeTimeout); } else { /* Try to retreive from Caps */ struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; if(HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd) != HPMFWUPG_SUCCESS) { upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; if ( verbose ) printf("Use default timeout: %i seconds\n", upgradeTimeout); } else { upgradeTimeout = (targetCapCmd.resp.upgradeTimeout * 5); if ( verbose ) printf("Use Command Upgrade Capabilities Timeout: %i seconds\n", upgradeTimeout); } } if(rc == HPMFWUPG_SUCCESS) { /* Poll upgrade status until completion or timeout*/ timeoutSec1 = (uint32_t)time(NULL); timeoutSec2 = (uint32_t)time(NULL); rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx); } while( (upgStatusCmd.resp.lastCmdCompCode == HPMFWUPG_COMMAND_IN_PROGRESS ) && (timeoutSec2 - timeoutSec1 < upgradeTimeout ) && (rc == HPMFWUPG_SUCCESS) ) { /* Must wait at least 1000 ms between status requests */ os_usleep(0,1000000); rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx); //printf("Get Status: %x - %x = %x _ %x [%x]\n", timeoutSec2, timeoutSec1,(timeoutSec2 - timeoutSec1),upgradeTimeout, rc); } if ( upgStatusCmd.resp.lastCmdCompCode != 0x00 ) { if ( verbose ) { lprintf(LOG_NOTICE,"Error waiting for command %x, compcode = %x", upgStatusCmd.resp.cmdInProcess, upgStatusCmd.resp.lastCmdCompCode, hpm_decode_cc(upgStatusCmd.resp.cmdInProcess, upgStatusCmd.resp.lastCmdCompCode)); } rc = HPMFWUPG_ERROR; } return rc; } unsigned char HpmfwupgCalculateChecksum(unsigned char* pData, unsigned int length) { unsigned char checksum = 0; int dataIdx = 0; for ( dataIdx = 0; dataIdx < (int)length; dataIdx++ ) { checksum += pData[dataIdx]; } return checksum; } static void HpmfwupgPrintUsage(void) { lprintf(LOG_NOTICE,"help - This help menu"); lprintf(LOG_NOTICE,"check - Check the target information"); lprintf(LOG_NOTICE,"check - If the user is unsure of what update is going to be "); lprintf(LOG_NOTICE," This will display the existing target version and image "); lprintf(LOG_NOTICE," version on the screen"); lprintf(LOG_NOTICE,"upgrade - Upgrade the firmware using a valid HPM.1 image "); lprintf(LOG_NOTICE," This checks the version from the file and image and "); lprintf(LOG_NOTICE," if it differs then only updates else skips"); lprintf(LOG_NOTICE,"upgrade all - Updates all the components present in the file on the target board"); lprintf(LOG_NOTICE," without skipping (use this only after using \"check\" command"); lprintf(LOG_NOTICE,"upgrade component x - Upgrade only component from the given "); lprintf(LOG_NOTICE," component 0 - BOOT"); lprintf(LOG_NOTICE," component 1 - RTK"); lprintf(LOG_NOTICE,"upgrade activate - Upgrade the firmware using a valid HPM.1 image "); lprintf(LOG_NOTICE," If activate is specified, activate new firmware rigth"); lprintf(LOG_NOTICE," away"); lprintf(LOG_NOTICE,"activate [norollback] - Activate the newly uploaded firmware"); lprintf(LOG_NOTICE,"targetcap - Get the target upgrade capabilities"); lprintf(LOG_NOTICE,"compprop can be one of the following: "); lprintf(LOG_NOTICE," 0- General properties"); lprintf(LOG_NOTICE," 1- Current firmware version"); lprintf(LOG_NOTICE," 2- Description string"); lprintf(LOG_NOTICE," 3- Rollback firmware version"); lprintf(LOG_NOTICE," 4- Deferred firmware version"); lprintf(LOG_NOTICE,"abort - Abort the on-going firmware upgrade"); lprintf(LOG_NOTICE,"upgstatus - Returns the status of the last long duration command"); lprintf(LOG_NOTICE,"rollback - Performs a manual rollback on the IPM Controller"); lprintf(LOG_NOTICE," firmware"); lprintf(LOG_NOTICE,"rollbackstatus - Query the rollback status"); lprintf(LOG_NOTICE,"selftestresult - Query the self test results\n"); } int ipmi_hpmfwupg_main(void * intf, int argc, char ** argv) { int rc = HPMFWUPG_SUCCESS; int activateFlag = 0x00; int componentId = DEFAULT_COMPONENT_UPLOAD; int option = VERSIONCHECK_MODE; lprintf(LOG_DEBUG,"ipmi_hpmfwupg_main()"); lprintf(LOG_NOTICE,"\nPICMG HPM.1 Upgrade Agent %d.%d.%d: \n", HPMFWUPG_VERSION_MAJOR, HPMFWUPG_VERSION_MINOR, HPMFWUPG_VERSION_SUBMINOR); if ( (argc == 0) || (strcmp(argv[0], "help") == 0) ) { HpmfwupgPrintUsage(); return ERR_USAGE; } if ( (strcmp(argv[0], "check") == 0) ) { /* hpm check */ if (argv[1] == NULL) { rc = HpmfwupgTargetCheck(intf,VIEW_MODE); } else { /* hpm check */ rc = HpmfwupgTargetCheck(intf,0); if (rc == HPMFWUPG_SUCCESS) { rc = HpmfwupgUpgrade(intf, argv[1],0,DEFAULT_COMPONENT_UPLOAD,VIEW_MODE); } } } else if ( strcmp(argv[0], "upgrade") == 0) { int i =0; if (fdebug) option |= DEBUG_MODE; if (g_channel_buf_size > 0) printf("Large buffer size %d specified\n", g_channel_buf_size ); for (i=1; i< argc ; i++) { if (strcmp(argv[i],"activate") == 0) { activateFlag = 1; } /* hpm upgrade all */ if (strcmp(argv[i],"all") == 0) { option &= ~(VERSIONCHECK_MODE); option &= ~(VIEW_MODE); option |= FORCE_MODE_ALL; } /* hpm upgrade component */ if (strcmp(argv[i],"component") == 0) { if (i+1 < argc) { componentId = atoi(argv[i+1]); option &= ~(VERSIONCHECK_MODE); option &= ~(VIEW_MODE); option |= FORCE_MODE_COMPONENT; if( verbose ) { lprintf(LOG_NOTICE,"Component Id %d provided",componentId ); } /* Error Checking */ if (componentId >= HPMFWUPG_COMPONENT_ID_MAX) { lprintf(LOG_NOTICE,"Given component ID %d exceeds Max Comp ID %d\n", componentId, HPMFWUPG_COMPONENT_ID_MAX-1); return HPMFWUPG_ERROR; } } if (componentId == DEFAULT_COMPONENT_UPLOAD) { /* That indicates the user has given component on console but not * given any ID */ lprintf(LOG_NOTICE,"No component Id provided\n"); return HPMFWUPG_ERROR; } } if (strcmp(argv[i],"debug") == 0) { option |= DEBUG_MODE; } } rc = HpmfwupgTargetCheck(intf,0); if (rc == HPMFWUPG_SUCCESS) { /* Call the Upgrade function to start the upgrade */ rc = HpmfwupgUpgrade(intf, argv[1],activateFlag,componentId,option); } } else if ( (argc >= 1) && (strcmp(argv[0], "activate") == 0) ) { struct HpmfwupgActivateFirmwareCtx cmdCtx; if ( (argc == 2) && (strcmp(argv[1], "norollback") == 0) ) cmdCtx.req.rollback_override = 1; else cmdCtx.req.rollback_override = 0; rc = HpmfwupgActivateFirmware(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "targetcap") == 0) ) { struct HpmfwupgGetTargetUpgCapabilitiesCtx cmdCtx; verbose++; rc = HpmfwupgGetTargetUpgCapabilities(intf, &cmdCtx); } else if ( (argc == 3) && (strcmp(argv[0], "compprop") == 0) ) { struct HpmfwupgGetComponentPropertiesCtx cmdCtx; cmdCtx.req.componentId = atob(argv[1]); cmdCtx.req.selector = atob(argv[2]); verbose++; rc = HpmfwupgGetComponentProperties(intf, &cmdCtx); } else if ( (argc == 1) && (strcmp(argv[0], "abort") == 0) ) { struct HpmfwupgAbortUpgradeCtx cmdCtx; verbose++; rc = HpmfwupgAbortUpgrade(intf, &cmdCtx); } else if ( (argc == 1) && (strcmp(argv[0], "upgstatus") == 0) ) { struct HpmfwupgGetUpgradeStatusCtx cmdCtx; verbose++; rc = HpmfwupgGetUpgradeStatus(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "rollback") == 0) ) { struct HpmfwupgManualFirmwareRollbackCtx cmdCtx; verbose++; rc = HpmfwupgManualFirmwareRollback(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "rollbackstatus") == 0) ) { struct HpmfwupgQueryRollbackStatusCtx cmdCtx; verbose++; rc = HpmfwupgQueryRollbackStatus(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "selftestresult") == 0) ) { struct HpmfwupgQuerySelftestResultCtx cmdCtx; verbose++; rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL); } else { HpmfwupgPrintUsage(); } return rc; } #ifdef METACOMMAND int i_hpm(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { void *intf = NULL; int rc = 0; int c, i; char *s1; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); while ( (c = getopt( argc, argv,"m:z:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'z': g_channel_buf_size = atoi(optarg); if (g_channel_buf_size < HPMFWUPG_SEND_DATA_COUNT_LAN) rc = ERR_BAD_LENGTH; else if (g_channel_buf_size > IPMI_REQBUF_SIZE) rc = LAN_ERR_BADLENGTH; if (rc != 0) { printf("Invalid buffer size %d\n",g_channel_buf_size); return rc; } break; case 'x': fdebug = 1; verbose = 1; set_loglevel(LOG_DEBUG); break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': HpmfwupgPrintUsage(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } rc = ipmi_hpmfwupg_main(intf, argc, argv); ipmi_close_(); // show_outcome(progname,rc); return rc; } /* end ihpm.c */ ipmiutil-3.1.9/util/md2.h0000644000000000000000000003336714144515623013707 0ustar rootroot/* * md2.h * Used in ipmilan.c * * 05/26/2006 ARCress - copied from freeipmi ipmi-md2.c, * added md2_sum() subroutine, added WIN32 flag * 08/14/2008 ARCress - moved md2 routines from md2.c to md2.h */ /* * (c) (C) 2003 FreeIPMI Core Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and * NON-INFRINGEMENT. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you * do not wish to do so, delete this exception statement from your * version. If you delete this exception statement from all source * files in the program, then also delete it here. */ /* ==================================================================== * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ /* only include this file if MD2OK was defined */ #ifdef WIN32 #define u_int32_t unsigned int #define u_int8_t unsigned char #endif /* start ipmi-md2.h */ #define IPMI_MD2_BLOCK_LEN 16 #define IPMI_MD2_BUFFER_LEN 48 #define IPMI_MD2_CHKSUM_LEN 16 #define IPMI_MD2_DIGEST_LEN 16 #define IPMI_MD2_PADDING_LEN 16 #define IPMI_MD2_ROUNDS_LEN 18 typedef struct __md2 { u_int32_t magic; u_int8_t l; unsigned int mlen; u_int8_t x[IPMI_MD2_BUFFER_LEN]; u_int8_t c[IPMI_MD2_CHKSUM_LEN]; u_int8_t m[IPMI_MD2_BLOCK_LEN]; } ipmi_md2_t; int ipmi_md2_init(ipmi_md2_t *ctx); int ipmi_md2_update_data(ipmi_md2_t *ctx, u_int8_t *buf, unsigned int buflen); int ipmi_md2_finish(ipmi_md2_t *ctx, u_int8_t *digest, unsigned int digestlen); /* end ipmi-md2.h */ static char padding[16][16] = { {0x01}, {0x02,0x02}, {0x03,0x03,0x03}, {0x04,0x04,0x04,0x04}, {0x05,0x05,0x05,0x05,0x05}, {0x06,0x06,0x06,0x06,0x06,0x06}, {0x07,0x07,0x07,0x07,0x07,0x07,0x07}, {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08}, {0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09}, {0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A}, {0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B}, {0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C}, {0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D}, {0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E}, {0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F}, {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10} }; static unsigned char S[256] = { 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 }; #define L ctx->l #define X ctx->x #define C ctx->c #define M ctx->m #define Mlen ctx->mlen #define IPMI_MD2_MAGIC 0xf00fd00d int ipmi_md2_init(ipmi_md2_t *ctx) { if (ctx == NULL) { errno = EINVAL; return -1; } ctx->magic = IPMI_MD2_MAGIC; L = 0; Mlen = 0; memset(X, '\0', IPMI_MD2_BUFFER_LEN); memset(C, '\0', IPMI_MD2_CHKSUM_LEN); memset(M, '\0', IPMI_MD2_BLOCK_LEN); return 0; } static void _ipmi_md2_update_digest_and_checksum(ipmi_md2_t *ctx) { int j, k; u_int8_t c, t; /* Update X */ for (j = 0; j < IPMI_MD2_BLOCK_LEN; j++) { X[16+j] = M[j]; X[32+j] = (X[16+j] ^ X[j]); } t = 0; for (j = 0; j < IPMI_MD2_ROUNDS_LEN; j++) { for (k = 0; k < IPMI_MD2_BUFFER_LEN; k++) { t = X[k] = (X[k] ^ S[t]); } t = (t + j) % 256; } /* Update C and L */ /* achu: Note that there is a typo in the RFC 1319 specification. * In section 3.2, the line: * * Set C[j] to S[c xor L] * * should read: * * Set C[j] to C[j] xor S[c xor L]. */ for (j = 0; j < IPMI_MD2_BLOCK_LEN; j++) { c = M[j]; C[j] = C[j] ^ S[c ^ L]; L = C[j]; } } int ipmi_md2_update_data(ipmi_md2_t *ctx, u_int8_t *buf, unsigned int buflen) { if (ctx == NULL || ctx->magic != IPMI_MD2_MAGIC || buf == NULL) { errno = EINVAL; return -1; } if (buflen == 0) return 0; if ((Mlen + buflen) >= IPMI_MD2_BLOCK_LEN) { unsigned int bufcount; bufcount = (IPMI_MD2_BLOCK_LEN - Mlen); memcpy(M + Mlen, buf, bufcount); _ipmi_md2_update_digest_and_checksum(ctx); while ((buflen - bufcount) >= IPMI_MD2_BLOCK_LEN) { memcpy(M, buf + bufcount, IPMI_MD2_BLOCK_LEN); bufcount += IPMI_MD2_BLOCK_LEN; _ipmi_md2_update_digest_and_checksum(ctx); } Mlen = buflen - bufcount; if (Mlen > 0) memcpy(M, buf + bufcount, Mlen); } else { /* Not enough data to update X and C, just copy in data */ memcpy(M + Mlen, buf, buflen); Mlen += buflen; } return buflen; } static void _ipmi_md2_append_padding_and_checksum(ipmi_md2_t *ctx) { unsigned int padlen; int padindex; padlen = IPMI_MD2_PADDING_LEN - Mlen; padindex = padlen - 1; ipmi_md2_update_data(ctx, padding[padindex], padlen); ipmi_md2_update_data(ctx, C, IPMI_MD2_CHKSUM_LEN); } int ipmi_md2_finish(ipmi_md2_t *ctx, u_int8_t *digest, unsigned int digestlen) { if (ctx == NULL || ctx->magic != IPMI_MD2_MAGIC || digest == NULL || digestlen < IPMI_MD2_DIGEST_LEN) { errno = EINVAL; return -1; } _ipmi_md2_append_padding_and_checksum(ctx); memcpy(digest, X, IPMI_MD2_DIGEST_LEN); return IPMI_MD2_DIGEST_LEN; } /* added - ARCress */ void md2_sum(unsigned char *pdata, int sdata, unsigned char *digest) { ipmi_md2_t ctx; ipmi_md2_init(&ctx); ipmi_md2_update_data(&ctx, pdata, sdata); ipmi_md2_finish(&ctx, digest, 16); } /*end md2.h */ ipmiutil-3.1.9/util/idiscover.c0000644000000000000000000007454614144515623015213 0ustar rootroot/* * idiscover.c * Discover all IPMI-LAN-enabled nodes on this network or subnet. * This program is not completely reliable yet, not all IPMI-LAN-enabled * nodes respond. * Currently this utility is compiled with NO_THREADS, but threads can * be enabled by commenting out this flag. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2006 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 10/27/06 Andy Cress - created * 05/01/07 Andy Cress - added -g for GetChannelAuthCap method, * added -a logic for broadcast ping, * updated WIN32 logic * 09/20/07 Andy Cress - fixed send/receive thread order * 07/15/08 Andy Cress - added -r for ping repeats * 11/21/08 Andy Cress - detect eth intf and broadcast ip addr * 01/04/16 Andy Cress - v1.11, allow 0 if fBroadcastOk (-a) */ /*M* Copyright (c) 2006, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #if defined(HAVE_CONFIG_H) #include "config.h" #endif #ifdef WIN32 #include #include #include #include #include #include #include "getopt.h" #define NO_THREADS 1 typedef unsigned int socklen_t; WSADATA lan_ws; /*global for WSA*/ #elif defined(DOS) #include #include #include #include #include "getopt.h" #define NO_THREADS 1 #else /* Linux, BSD, Solaris */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #ifndef HAVE_CONFIG_H typedef unsigned int socklen_t; #endif #else #include #endif /* comment out NO_THREADS to use this utility in Linux with threads */ #define NO_THREADS 1 #endif #ifndef ETH_P_IP #define ETH_P_IP 0x0800 /* Internet Protocol packet, see linux/if_ether.h */ #endif /* TODO: fix RAW for -m in Solaris, FreeBSD, Windows (works in Linux) */ #ifdef SOLARIS #include #define RAW_DOMAIN AF_INET #define RAW_PROTO IPPROTO_RAW static char frawok = 0; /*raw not working in Solaris*/ #elif BSD #define RAW_DOMAIN AF_INET #define RAW_PROTO IPPROTO_RAW static char frawok = 0; /*raw not working in FreeBSD*/ #elif HPUX #define RAW_DOMAIN AF_INET #define RAW_PROTO IPPROTO_RAW static char frawok = 0; /*raw not working in HPUX*/ #elif MACOS #define RAW_DOMAIN AF_INET #define RAW_PROTO IPPROTO_RAW static char frawok = 0; /*raw not working in MacOS*/ #elif WIN32 #define RAW_DOMAIN AF_INET #define RAW_PROTO IPPROTO_ICMP static char frawok = 0; /*raw not working in Windows*/ #else #define RAW_DOMAIN AF_PACKET #define RAW_PROTO htons(ETH_P_IP) static char frawok = 1; /*raw works in Linux*/ #endif #include #include "ipmicmd.h" #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 #endif #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif #define RMCP_PRI_RMCP_PORT 0x26F #define SZ_PING 12 #define IPMI_PING_MAX_LEN 50 /* usu 28 */ #define CMD_GET_CHAN_AUTH_CAP 0x38 #ifdef WIN32 int GetFirstIP(uchar *ipaddr, uchar *macadr, char *ipname, char fdb); /*ilan.c*/ #endif /* * Global variables */ static char * progver = "1.11"; static char * progname = "idiscover"; static char fdebug = 0; static char fping = 1; static char fraw = 0; static char fBroadcastOk = 0; static char fcanonical = 0; static int broadcast_pings = 1; //static uchar ipmi_maj = 0; //static uchar ipmi_min = 0; //static uchar netfn; static ushort g_port = RMCP_PRI_RMCP_PORT; static SockType g_sockfd = 0; static SockType g_sockraw = 0; static int g_limit = 30; /* after this many 'other' packets, stop. */ static struct sockaddr_in _srcaddr; // static struct sockaddr_in _destaddrlist[255]; static struct in_addr _startAddr, _endAddr; static char g_startDest[MAXHOSTNAMELEN+1] = {'\0'}; static char g_endDest[MAXHOSTNAMELEN+1] = {'\0'}; static char g_interface[INET_ADDRSTRLEN+1] = {""}; /*e.g. "eth0"*/ static int g_num_packets = 0; static int g_npings = 0; static int g_npongs = 0; static int g_recv_status = 0; static int g_wait = 1; /* num sec to wait */ static int g_delay = 0; /* num usec between sends */ static int g_repeat = 1; /* number of times to repeat ping to each node */ static char bdelim = BDELIM; /* '|' */ #ifdef METACOMMAND extern FILE *fpdbg; /*from ipmicmd.c*/ extern char *strlasterr(int rv); /*from ipmilan.c*/ #else void dump_buf(char *tag, uchar *pbuf, int sz, char fshowascii) { uchar line[17]; uchar a; int i, j; FILE *fpdbg; fpdbg = stdout; line[0] = 0; line[16] = 0; j = 0; fprintf(fpdbg,"%s (len=%d): ", tag,sz); for (i = 0; i < sz; i++) { if (i % 16 == 0) { j = 0; fprintf(fpdbg,"%s\n %04x: ",line,i); } if (fshowascii) { a = pbuf[i]; if (a < 0x20 || a > 0x7f) a = '.'; line[j++] = a; } fprintf(fpdbg,"%02x ",pbuf[i]); } if (j < 16) { line[j] = 0; for (i = 0; i < (16-j); i++) fprintf(fpdbg," "); } fprintf(fpdbg,"%s\n",line); return; } #endif void printerr( const char *pattn, ...) { va_list arglist; FILE *fderr; // fderr = fopen("/tmp/idiscover.log","a+"); // if (fderr == NULL) return; fderr = stderr; va_start(arglist, pattn); vfprintf(fderr, pattn, arglist); va_end(arglist); // fclose(fderr); } static char *showlasterr(void) { char *str; #ifdef WIN32 static char strbuf[80]; int rv; char *desc; rv = WSAGetLastError(); #ifdef METACOMMAND /* get descriptions from strlasterr in ipmilan.c */ desc = strlasterr(rv); #else if (rv == WSAECONNRESET) desc = "Connection reset"; /*10054*/ else if (rv == WSAECONNREFUSED) desc = "Connection refused"; /*10061*/ else if (rv == WSAEHOSTUNREACH) desc = "No route to host"; /*10065*/ else desc = ""; #endif sprintf(strbuf,"LastError = %d %s",rv,desc); str = strbuf; #else str = strerror(errno); #endif return(str); } static void cleanup(void) { SockType *pfd; int i; for (i = 0; i < 2; i++) { if (i == 0) pfd = &g_sockfd; else pfd = &g_sockraw; if (*pfd > 0) { #ifdef WIN32 closesocket(*pfd); WSACleanup(); #else close(*pfd); #endif } *pfd = 0; } } void show_usage(void) { printf("Usage: %s [-abegix] \n",progname); printf(" -a all nodes, enables broadcast ping\n"); printf(" -b beginning IP address (x.x.x.x), required\n"); printf(" -e ending IP address (x.x.x.x), default is begin IP\n"); printf(" -g use GetChanAuthCap instead of RMCP ping\n"); printf(" -i interface name, default is eth0\n"); printf(" -m get MAC addresses with a raw broadcast ping\n"); printf(" -p N specific Port (IPMI LAN port=623)\n"); printf(" -r N number of Repeat pings to each node (default=1)\n"); // printf(" -s specific subnet\n"); printf(" -x show eXtra debug messages\n"); } static int os_sleep(unsigned int s, unsigned int u) { #ifdef WIN32 if (s == 0) { if (u >= 1000) Sleep(u/1000); } else { Sleep(s * 1000); } #else /*Linux*/ #ifdef SELECT_TIMER struct timeval tv; tv.tv_sec = s; tv.tv_usec = u; if (select(1, NULL, NULL, NULL, &tv) < 0) printerr("select: %s\n", showlasterr()); #else if (s == 0) { usleep(u); } else { sleep(s); } #endif #endif return 0; } void split_ip(uint addr, uchar *ip) { ip[3] = (addr & 0x000000ff); ip[2] = (addr & 0x0000ff00) >> 8; ip[1] = (addr & 0x00ff0000) >> 16; ip[0] = (addr & 0xff000000) >> 24; } int ntoi(int addr) { return(addr); } void show_ip(int saddr) { uchar ip[4]; split_ip(saddr,ip); printerr("%d.%d.%d.%d\n",ip[0],ip[1],ip[2],ip[3]); } static int ipmilan_sendto(SockType s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { int n; #ifdef NEED_PAD int fusepad = 0; /* Never need a pad byte for ping/pong packets */ if (len == 56 || len == 84 || len == 112 || len == 128 || len == 156) { fusepad = 1; len += 1; } #endif n = (int)sendto(s,msg,len,flags,to,tolen); // if (fusepad && (n > 0)) n--; return(n); } static int ipmilan_recvfrom(SockType s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { int rv; rv = (int)recvfrom(s,buf,len,flags,from,fromlen); /* Sometimes the OS sends an ECONNREFUSED error, but * retrying will catch the BMC's reply packet. */ #ifdef WIN32 if (rv < 0) { int err; err = WSAGetLastError(); if (err == WSAECONNREFUSED) /*10061*/ rv = (int)recvfrom(s,buf,len,flags,from,fromlen); } #else if ((rv < 0) && (errno == ECONNREFUSED)) rv = (int)recvfrom(s,buf,len,flags,from,fromlen); #endif return(rv); } #if defined(WIN32) int inet_aton(const char *cp, struct in_addr *inp) { int rv; int adr; inp->s_addr = inet_addr(cp); adr = (int)inp->s_addr; if (adr == INADDR_NONE) rv = 0; else rv = 1; /*success*/ return(rv); } #elif defined(SOLARIS) || defined(HPUX) int find_ifname(char *ifname) { return(-1); } #else #include int find_ifname(char *ifname) { struct ifaddrs *ifaddr, *ifa; int rv = -1; if (getifaddrs(&ifaddr) == -1) return(rv); for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) continue; if (strcmp(ifa->ifa_name,"lo") == 0) continue; /* if here, we have a valid ifname */ strcpy(ifname,ifa->ifa_name); if (fdebug) printf("find_ifname: found %s\n",ifname); rv = 0; break; } freeifaddrs(ifaddr); return(rv); } #endif int sock_init( char *_interface, char *_startIP, char *_endIP) { int rv; uchar *pb; uchar val; #ifdef WIN32 DWORD rvl; rvl = WSAStartup(0x0101,&lan_ws); if (rvl != 0) { printerr("init: WSAStartup(1.1) error %ld\n", rvl); return((int)rvl); } #else char findif; #endif if ((g_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SockInvalid) { printerr("socket: %s\n", showlasterr()); return(-1); } memset(&_srcaddr, 0, sizeof(_srcaddr)); _srcaddr.sin_family = AF_INET; _srcaddr.sin_port = htons(0); _srcaddr.sin_addr.s_addr = htonl(INADDR_ANY); #ifdef WIN32 { int ret; uchar osip[4]; uchar osmac[6]; uchar osname[64]; char ipstr[20]; char *temp_start; if (fBroadcastOk && (g_startDest[0] == 0)) { ret = GetFirstIP(osip,osmac,osname,fdebug); /*ilan.c*/ if (ret == 0) { // osip[3] = 0xFF; /*255 for broadcast*/ sprintf(ipstr,"%d.%d.%d.255",osip[0],osip[1],osip[2]); temp_start = ipstr; strcpy(g_startDest,temp_start); strcpy(g_endDest,temp_start); } else { /*use some defaults*/ strcpy(g_startDest,"255.255.255.255"); strcpy(g_endDest,"255.255.255.255"); } } } #elif defined(HPUX) { /*find the OS eth interface to use*/ char devname[INET_ADDRSTRLEN+1]; int i, n; n = 0; sprintf(devname,"lan%d",n); } #else { /*find the OS eth interface to use*/ struct sockaddr_in temp_sockaddr; char *temp_start; struct ifreq ifr; char devname[INET_ADDRSTRLEN+1]; int i, n; if (_interface == NULL) findif = 1; else if (_interface[0] == 0) findif = 1; else findif = 0; if (findif) { n = find_ifname(devname); if (n >= 0) { _interface = devname; findif = 0; /*found, do not find again below */ } } if (findif) { /* try again to find the first active ethN interface */ n = -1; for (i = 0; (i < 16) && (n == -1); i++) { #ifdef SOLARIS sprintf(devname,"e1000g%d",i); #elif BSD sprintf(devname,"em%d",i); #else sprintf(devname,"eth%d",i); #endif strcpy(ifr.ifr_name, devname); ifr.ifr_addr.sa_family = AF_INET; if (ioctl(g_sockfd, SIOCGIFADDR, &ifr) >= 0) { /* valid IP address, so active interface, use it */ temp_sockaddr = *((struct sockaddr_in *)&ifr.ifr_addr); memcpy(&_srcaddr.sin_addr.s_addr, &temp_sockaddr.sin_addr.s_addr, sizeof(_srcaddr.sin_addr.s_addr)); strcpy(g_interface, devname); temp_start = inet_ntoa(temp_sockaddr.sin_addr); if (temp_start == NULL) temp_start = ""; else if (fBroadcastOk && (g_startDest[0] == 0)) { pb = (uchar *)&temp_sockaddr.sin_addr.s_addr; pb[3] = 0xFF; /*255 for broadcast*/ temp_start = inet_ntoa(temp_sockaddr.sin_addr); strcpy(g_startDest,temp_start); strcpy(g_endDest,temp_start); } printf("sock_init: found %s with %s\n",devname,temp_start); n = i; break; } } if (n < 0) rv = LAN_ERR_OTHER; /*-13*/ } else { /* valid _interface string */ if (strchr(_interface, '.') != NULL) { /* assume it is an IP address*/ if ((rv = inet_pton(AF_INET, _interface, &_srcaddr.sin_addr)) < 0) printerr("inet_pton: %s\n", showlasterr()); if (rv == 0) printerr("invalid interface address\n"); return(rv); } else { /* assume interface name, like eth0 */ strncpy(ifr.ifr_name, _interface, IFNAMSIZ); ifr.ifr_addr.sa_family = AF_INET; if (ioctl(g_sockfd, SIOCGIFADDR, &ifr) < 0) { printerr("ioctl(%s): %s\n", _interface, showlasterr()); return(-1); } temp_sockaddr = *((struct sockaddr_in *)&ifr.ifr_addr); memcpy(&_srcaddr.sin_addr.s_addr, &temp_sockaddr.sin_addr.s_addr, sizeof(_srcaddr.sin_addr.s_addr)); if (fBroadcastOk && (g_startDest[0] == 0)) { pb = (uchar *)&temp_sockaddr.sin_addr.s_addr; pb[3] = 0xFF; /*255 for broadcast*/ temp_start = inet_ntoa(temp_sockaddr.sin_addr); strcpy(g_startDest,temp_start); strcpy(g_endDest,temp_start); } } } } #endif if (fBroadcastOk) { rv = setsockopt(g_sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast_pings, sizeof(broadcast_pings)); if (rv) { printerr("setsockopt: %s\n", showlasterr()); return(-1); } } if (bind(g_sockfd, (struct sockaddr *)&_srcaddr, sizeof(_srcaddr)) < 0) { printerr("bind: %s\n", showlasterr()); return(-1); } rv = inet_aton(_startIP, &_startAddr); if (rv ) { _startAddr.s_addr = ntohl(_startAddr.s_addr); if (fdebug) show_ip(_startAddr.s_addr); pb = (unsigned char*)&_startAddr.s_addr; if (!fBroadcastOk && (pb[0] < 1) ) printerr("Malformed begin IP: %s\n", _startIP); else if (!fBroadcastOk && (pb[0] >254) ) printerr("Malformed begin IP: %s\n", _startIP); else if (fBroadcastOk) { val = pb[0] & 0x0f; if (val == 0x0f) rv = 0; else if (val == 0x00) rv = 0; else printerr("Malformed begin broadcast IP: %s\n", _startIP); } else rv = 0; } else { printerr("Invalid begin IP: %s\n", _startIP); } if (rv) return(rv); rv = inet_aton(_endIP, &_endAddr); if (rv ) { _endAddr.s_addr = ntohl(_endAddr.s_addr); if (fdebug) show_ip(_endAddr.s_addr); pb = (unsigned char*)&_endAddr.s_addr; if (!fBroadcastOk && (pb[0] < 1) ) printerr("Malformed end IP: %s\n", _endIP); else if (!fBroadcastOk && (pb[0] >254) ) printerr("Malformed end IP: %s\n", _endIP); else rv = 0; } else { printerr("Invalid end IP: %s\n", _endIP); } /* calculate g_num_packets */ g_num_packets = ntoi(_endAddr.s_addr) - ntoi(_startAddr.s_addr) + 1; if (fdebug) printerr("g_num_packets = %d\n",g_num_packets); if (g_num_packets < 1) g_num_packets = 0; return(rv); } /*end sock_init*/ void *receiveThread(void *p) { uchar buffer[IPMI_PING_MAX_LEN]; struct timeval tv; fd_set rset; int rv, len; static int needlf = 0; char host[200]; SockType sockrecv; int nothers = 0; int addr_type = AF_INET; /*or AF_INET6*/ #ifndef WIN32 struct hostent *h_ent = NULL; char serv[200]; int r; #endif sockrecv = g_sockfd; if (fraw) { /* opening SOCK_RAW requires admin/root privilege. */ if ((g_sockraw = socket(RAW_DOMAIN, SOCK_RAW,RAW_PROTO)) == SockInvalid) { printerr("raw socket: %s\n", showlasterr()); fraw = 0; } else { sockrecv = g_sockraw; if (fdebug) printf("g_sockraw = %d\n",g_sockraw); } } /* receive while loop */ do { tv.tv_sec = g_wait; tv.tv_usec = 0; FD_ZERO(&rset); FD_SET(sockrecv, &rset); g_recv_status = 0; if (fdebug) printerr("waiting for ping %d response\n",g_npings); if ((rv = select((int)(sockrecv+1), &rset, NULL, NULL, &tv)) < 0) { printerr("select: %s\n", showlasterr()); cleanup(); exit(rv); // error, exit idiscover recv thread } if (fdebug) printerr("select rv = %d\n",rv); if (rv > 0) { struct sockaddr_in from; socklen_t fromlen; char rstr[40]; char macstr[20]; struct in_addr from_ip; char estr[40]; if (needlf) { printf("\n"); needlf = 0; } g_recv_status = 1; fromlen = sizeof(from); len = ipmilan_recvfrom(sockrecv, buffer, IPMI_PING_MAX_LEN, 0, (struct sockaddr *)&from, &fromlen); if (fdebug) printerr("recvfrom rv = %d\n",rv); if (len < 0) { printerr("ipmilan_recvfrom: %s\n", showlasterr()); continue; } if (fdebug) { /* can we get the MAC addr of the responder also? */ // dump_buf("from_addr",(uchar *)&from,fromlen,0); dump_buf("recvfrom",buffer,len,0); } g_recv_status = 2; g_npongs++; macstr[0] = 0; if (fraw) { /* Raw packet, include MAC address string */ /* * Sample raw packet for UDP ping response * dst_mac src_mac eth_p iphdr * 0000: 00 07 e9 06 15 31 00 0e 0c 2b b5 81 08 00 45 00 * udp src_ip dst_ip * 0010: 00 38 00 00 40 00 40 11 b6 01 c0 a8 01 c2 c0 a8 * rmcp * 0020: 01 a1 02 6f 80 1e 00 24 0e d1 06 00 ff 06 00 00 * 0030: 11 be */ if ((buffer[23] != 0x11) || (buffer[42] != 0x06)) { /* [23]: 0x11==UDP, 0x06==TCP ; [42]: 0x06 ==RMCP */ if (nothers > g_limit) { if (fdebug) printf("got %d other packets, stop.\n",nothers); break; } nothers++; continue; } if (buffer[6] == 0xFF || buffer[26] == 0xFF) /*broadcast*/ continue; sprintf(macstr,"%02x:%02x:%02x:%02x:%02x:%02x %c", buffer[6], buffer[7], buffer[8], /*06=src_mac*/ buffer[9], buffer[10], buffer[11], bdelim); memcpy(&from_ip,&buffer[26],4); /*26=src_ip*/ } else { memcpy(&from_ip,&from.sin_addr,4); } host[0] = 0; #ifndef WIN32 /* Linux, BSD, Solaris, MacOS */ #if !defined(CROSS_COMPILE) h_ent = gethostbyaddr((void *)&from_ip,4,addr_type); if (h_ent != NULL) { strncpy(host,h_ent->h_name,sizeof(host)); } else if (!fraw) #endif { r = getnameinfo((struct sockaddr *)&from, fromlen, host, sizeof(host), serv, sizeof(serv), 0); if (r) host[0] = 0; else if (host[0] >= '0' && host[0] <= '9') host[0] = 0; } #endif // parse the received pong rstr[0] = 0; if (fping == 0 && len > 0) { /* -g and got rsp data */ /* parse GetChanAuthcap response into rstr */ /* 4 bytes RMCP, 10 bytes IPMI session, then msg */ /* 6 bytes msg hdr, then rsp data */ /* 20 = ccode, 21 = chan, 22 = auth type support */ if (buffer[20] != 0) /*ccode error*/ sprintf(rstr,"%c (ccode=0x%02x)",bdelim,buffer[20]); else /*ccode is ok*/ sprintf(rstr,"%c (channel %d)",bdelim,buffer[21]); } if (fcanonical) { estr[0] = 0; rstr[0] = 0; } else { sprintf(estr,"response from %c ",bdelim); } /* &buffer[0] = source MAC, &buffer[6] = destination MAC */ printf("%.2d%c %s%s %s \t%c %s %s\n", g_npongs,bdelim,estr,macstr,inet_ntoa(from_ip), bdelim,host,rstr); } else { /*ping, no answer*/ if (!fBroadcastOk) { printf("."); fflush(stdout); /*show progress*/ needlf = 1; } } } #ifdef NO_THREADS while(fBroadcastOk && rv > 0); #else while(1); #endif return(p); } /* * send_ping_pkt: * RMCP Ping buffer, sent as a UDP packet to port 0x026f. * rmcp.ver = 0x06 // RMCP Version 1.0 * rmcp.resvd = 0x00 // RESERVED * rmcp.seq = 0xff // no RMCP ACK * rmcp.class = 0x06 // RMCP_CLASS_ASF * asf.iana = 0x000011BE // ASF_RMCP_IANA (hi-lo) * asf.type = 0x80 // ASF_TYPE_PING * asf.tag = 0x00 // ASF sequence number * asf.resvd = 0x00 // RESERVED * asf.len = 0x00 */ int send_ping_pkt(struct sockaddr_in *_daddr, uchar seq) { uchar pingbuf[SZ_PING] = {06,0,0xFF,06,0x00,0x00,0x11,0xBE,0x80,0,0,0 }; int rv, len; pingbuf[9] = seq; len = sizeof(pingbuf); if (fdebug) dump_buf("send_ping",pingbuf,len,0); rv = ipmilan_sendto(g_sockfd, pingbuf, len, 0, (struct sockaddr *)_daddr, sizeof(struct sockaddr_in)); return(rv); } static int send_poke1(struct sockaddr_in *_daddr) { int rv; uchar asfpkt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x18, 0xc8, 0xc2, 0x01, 0x01, 0x3c }; if (fdebug) dump_buf("send_poke1",asfpkt,16,0); rv = ipmilan_sendto(g_sockfd, asfpkt, 16, 0, (struct sockaddr *)_daddr, sizeof(struct sockaddr_in)); return rv; } static uchar cksum(const uchar *buf, register int len) { register uchar csum; register int i; /* 8-bit 2s compliment checksum */ csum = 0; for (i = 0; i < len; i++) csum = (csum + buf[i]) % 256; csum = -csum; return(csum); } static int send_getauth(struct sockaddr_in *_daddr, uchar seq) { int rv, len; // static uchar swseq = 0; uchar getauthpkt[23] = { 0x06, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x20, 0x18, 0xc8, 0x81, 0x04, 0x38, 0x0e, 0x04, 0x31 }; /* * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 * 06 00 ff 07 00 00 00 00 00 00 00 00 00 09 20 18 c8 81 04 38 0e 04 31 * [RMCP hdr ] [IPMI session hdr (len)] [IPMI msg ] [data] */ // getauthpkt[8] = 0x00; /* seq always 00 for GetChanAuthCap */ getauthpkt[21] = 0x02; /*requested priv_level: 2=user, 4=admin*/ getauthpkt[22] = cksum(&getauthpkt[17],5); len = sizeof(getauthpkt); if (fdebug) dump_buf("send_getauth",getauthpkt,len,0); rv = ipmilan_sendto(g_sockfd, getauthpkt, len, 0, (struct sockaddr *)_daddr, sizeof(struct sockaddr_in)); if (fdebug) printf("send_getauth: rv = %d\n",rv); return rv; } int send_probe(struct sockaddr_in *_daddr, uchar seq) { int rv; if (fBroadcastOk) { rv = setsockopt(g_sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast_pings, sizeof(broadcast_pings)); if (fdebug) { char *estr; if (rv) estr = showlasterr(); else estr = ""; printerr("setsockopt(broadcast): rv=%d %s\n", rv,estr); } } if (fping) rv = send_ping_pkt( _daddr, seq); else rv = send_getauth( _daddr, seq); return(rv); } void *sendThread(void *p) { int i, j, n; // char _dest[MAXHOSTNAMELEN+1]; char _dest_ip[INET_ADDRSTRLEN+1]; struct sockaddr_in _destaddr; uchar o[4]; uint ip; uchar _seq; int rv; n = g_num_packets; /*num*/ ip = _startAddr.s_addr; for (i = 0; i < n; i++) { split_ip(ip,o); if (o[3] == 0) continue; if (!fBroadcastOk && (o[3] == 255)) continue; sprintf(_dest_ip,"%d.%d.%d.%d",o[0],o[1],o[2],o[3]); /* set _destaddr */ _destaddr.sin_family = AF_INET; _destaddr.sin_port = htons(g_port); if ( !inet_aton( _dest_ip, &_destaddr.sin_addr)) { printerr("inet_aton error %s\n",_dest_ip); continue; } for (j=0; j= 0) { receiveThread(NULL); } } #endif /* sleep an interval (g_delay usec) */ if (g_delay > 0) os_sleep(0,g_delay); } /*end-for g_repeat*/ ip++; /* increment to next IP */ } return(p); } #ifdef METACOMMAND int i_discover(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rv = 0; int c; #ifndef NO_THREADS char message[32]; pthread_t thread[2]; int iret[2]; #endif #ifdef METACOMMAND fpdbg = stdout; #endif printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"ab:ce:gi:l:mp:r:s:x?")) != EOF ) switch(c) { case 'a': fBroadcastOk = 1; fping = 1; break; /*all (broadcast ping)*/ case 'c': /*canonical, CSV*/ fcanonical = 1; bdelim = BCOMMA; break; case 'm': /* show MAC address, use raw, requires root priv */ fBroadcastOk = 1; fping = 1; fraw = 1; break; /*all (broadcast ping)*/ case 'l': g_limit = atoi(optarg); break; case 'g': fping = 0; break; /*use get chan auth cap method */ case 'b': /*begin*/ strncpy(g_startDest,optarg,MAXHOSTNAMELEN); break; case 'e': /*end*/ strncpy(g_endDest,optarg,MAXHOSTNAMELEN); break; case 'i': /*interface*/ strncpy(g_interface,optarg,sizeof(g_interface)); break; case 'p': /*port/socket*/ g_port = (ushort)atoi(optarg); break; case 'r': /*repeat N times*/ g_repeat = atoi(optarg); break; case 's': /*subnet*/ /* copy optarg from 10.243.42.0 or similar, to * begin/end range. */ break; case 'x': fdebug = 1; break; /* debug messages */ default: if (fdebug) printerr("getopt(%c) default\n",c); show_usage(); rv = ERR_USAGE; goto do_exit; } #ifdef WIN32 /* Winsock inet_aton() does not like 255.255.255.255 */ if (!fBroadcastOk && (g_startDest[0] == 0) ) { show_usage(); printerr("A beginning IP is required, using -b\n"); goto do_exit; } #else if (g_startDest[0] == 0) { strcpy(g_startDest,"255.255.255.255"); /* INADDR_BROADCAST */ fBroadcastOk = 1; } #endif if (fraw == 1) { if (frawok == 0) { printf("Warning: SOCK_RAW not yet implemented on this OS\n"); } #ifdef LINUX else { c = geteuid(); if (c > 1) printf("Must be root/superuser to use SOCK_RAW\n"); } #endif } if (g_endDest[0] == 0 || fBroadcastOk) strcpy(g_endDest,g_startDest); /*only one IP address*/ if (fdebug) printerr("intf=%s begin=%s end=%s port=%d\n", g_interface,g_startDest,g_endDest,g_port); rv = sock_init(g_interface, g_startDest, g_endDest); if (fdebug) printerr("sock_init rv = %d, sockfd = %d\n",rv,g_sockfd); if (rv != 0) { show_usage(); printerr("sock_init error %d\n",rv); goto do_exit; } printf("Discovering IPMI Devices:\n"); #ifdef NO_THREADS sendThread(NULL); #else iret[1] = pthread_create( &thread[1], NULL, receiveThread, (void*) message); iret[0] = pthread_create( &thread[0], NULL, sendThread, (void*) message); pthread_join( thread[0], NULL); pthread_join( thread[1], NULL); #endif // if (fdebug) printf("\n%s: %d pings sent, %d responses\n",progname,g_npings,g_npongs); do_exit: cleanup(); return(rv); } /* end main()*/ /* end idiscover.c */ ipmiutil-3.1.9/util/ipmicmd.c0000644000000000000000000014130114144515623014626 0ustar rootroot/*M* // PVCS: // $Workfile: ipmicmd.c $ // $Revision: 1.12 $ // $Modtime: 23 Feb 2005 11:24:14 $ // $Author: arcress at users.sourceforge.net $ // // Define the ipmi_cmd routine and supporting logic to execute IPMI // commands via one of the supported IPMI drivers: // /dev/ipmi0 /dev/ipmi/0 = MontaVista OpenIPMI driver // /dev/imb = Intel IMB ipmidrvr (comes with ISM) // /dev/ipmikcs /dev/ipmi/kcs = valinux driver by San Mehat // libfreeipmi.so = GNU FreeIPMI user-space library // ldipmidaemon = LanDesk IPMI daemon (user-space process) // // 08/05/02 ARC - created // 08/15/02 ARC - added decode_cc // 10/24/02 ARC - made cmd param ushort to be more unique // 01/29/03 ARC - added MontaVista OpenIPMI driver support // 07/25/03 ARC - added serial-over-lan commands // 07/30/03 ARC - added GetThresholds, fix for ipmi_cmd_raw, // changed some error messages // 09/04/03 ARC - added debug messages for fDriverTyp first time // 05/05/04 ARC - leave _mv device open, rely on each app calling ipmi_close, // helps performance. // 08/10/04 ARC - fix typo in ipmi_cmd_raw/mv: cmd->icmd (thanks Kevin Gao) // 08/26/04 ARC - fix out-of-bounds error in decode_cc // 10/27/04 ARC - added gnu FreeIPMI library support // 11/11/04 ARC - added fdebug to ipmi_getdeviceid & ipmi_open_gnu // 02/23/05 ARC - added routines for LanDesk, fDriverTyp=5 // 07/15/05 ARC - test for ldipmi first, since it hangs KCS if another // driver tries to coexist. // 07/06/06 ARC - better separate driver implementations, cleaner now *M*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2002-2006, Intel Corporation Copyright (c) 2009 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------*/ #ifdef WIN32 #include #include #include #include #include #include #elif defined(EFI) // defined (EFI32) || defined (EFI64) || defined(EFIX64) #include #include #else /* Linux, Solaris, BSD */ #include #include #include #include #include #include #ifndef DOS #include #include #endif #include #include #endif #include "ipmicmd.h" /* has NCMDS, ipmi_cmd_t */ #include "ipmilan2.h" /*includes ipmilan.h also*/ ipmi_cmd_t ipmi_cmds[NCMDS] = { /*if add here, also change NCMDS in ipmicmd.h*/ {/*empty,temp*/ 0, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 20}, {GET_SEL_INFO, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 0, 14}, {GET_SEL_ALLOCATION_INFO,BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 0, 9}, {GET_SEL_ENTRY, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 6, 18}, {RESERVE_SEL, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 0, 2}, {CLEAR_SEL, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 6, 1}, {GET_SEL_TIME, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 6, 4}, {GET_LAN_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 4, 19}, {SET_LAN_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 21, 0}, {GET_LAN_STATS, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 2, 18}, {GET_SER_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 4, 19}, {SET_SER_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 21, 0}, {SET_SER_MUX, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 2, 0}, {GET_PEF_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 3, 22}, {SET_PEF_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 22, 0}, // {SET_PEF_ENABLE, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 4, 0}, /*old*/ {GET_DEVSDR_INFO, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 0, 6}, {GET_DEVICE_SDR, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 6, 18}, {RESERVE_DEVSDR_REP,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 0, 2}, {GET_SENSOR_READING,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 1, 4}, {GET_SENSOR_READING_FACTORS,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 2, 7}, {GET_SENSOR_TYPE, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 1, 2}, {GET_SENSOR_THRESHOLD,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 1, 7}, {SET_SENSOR_THRESHOLD,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 8, 0}, {GET_SENSOR_HYSTERESIS,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 2, 2}, {SET_SENSOR_HYSTERESIS,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 4, 0}, {GET_SDR, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 6, 18},/*full=63*/ {GET_SDR_REPINFO, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 0, 14}, {RESERVE_SDR_REP, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 0, 2}, {GET_FRU_INV_AREA, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 1, 3}, {READ_FRU_DATA, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN, 4, 18}, {WRITE_FRU_DATA, BMC_SA, PUBLIC_BUS, NETFN_STOR, BMC_LUN,20 /*3+N(17)*/, 1}, {GET_DEVICE_ID, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 15}, {SET_USER_ACCESS, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 4, 0}, {GET_USER_ACCESS, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 2, 4}, {GET_USER_NAME, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 1, 16}, {SET_USER_NAME, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 17, 0}, {SET_USER_PASSWORD,BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 18, 0}, {MASTER_WRITE_READ,BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 4 /*or 3*/, 1}, {GET_SYSTEM_GUID, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 16}, {WATCHDOG_GET, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 8}, {WATCHDOG_SET, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 6, 0}, {WATCHDOG_RESET, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 0}, {CHASSIS_STATUS, BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 0, 2}, {CHASSIS_CTL, BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 1, 0}, {CHASSIS_IDENTIFY, BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 1, 0}, {GET_POWERON_HOURS,BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 0, 0}, {SET_BOOT_OPTIONS, BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 19, 0}, {GET_BOOT_OPTIONS, BMC_SA, PUBLIC_BUS, NETFN_CHAS, BMC_LUN, 3, 18}, {ACTIVATE_SOL1, BMC_SA, PUBLIC_BUS, NETFN_SOL, BMC_LUN, 0, 0}, {SET_SOL_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_SOL, BMC_LUN, 3, 0}, {GET_SOL_CONFIG, BMC_SA, PUBLIC_BUS, NETFN_SOL, BMC_LUN, 4, 2}, {ACTIVATE_SOL2, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 0, 0}, {SET_SOL_CONFIG2, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 3, 0}, {GET_SOL_CONFIG2, BMC_SA, PUBLIC_BUS, NETFN_TRANS, BMC_LUN, 4, 2}, {GET_SEVT_ENABLE, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 1, 5}, {SET_SEVT_ENABLE, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 6, 0}, {REARM_SENSOR, BMC_SA, PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 6, 0}, {READ_EVENT_MSGBUF,BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 0, 16}, {GET_EVENT_RECEIVER,BMC_SA,PUBLIC_BUS, NETFN_SEVT, BMC_LUN, 0, 2}, {GET_CHANNEL_INFO, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 1, 9}, {SET_CHANNEL_ACC, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 3, 0}, {GET_CHANNEL_ACC, BMC_SA, PUBLIC_BUS, NETFN_APP, BMC_LUN, 2, 1} }; /* Subroutine definitions for each driver */ #ifdef EFI int ipmi_open_efi(char fdebug); int ipmi_cmdraw_efi( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); #else #ifdef WIN32 extern int ipmi_cmdraw_ia( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_ia(char fdebug); extern int ipmi_close_ia(void); extern int ipmi_cmdraw_ms(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_ms(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_ms(char fdebug); extern int ipmi_close_ms(void); #elif defined(SOLARIS) extern int ipmi_cmdraw_bmc(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_bmc(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_bmc(char fdebug); extern int ipmi_close_bmc(void); extern int ipmi_cmdraw_lipmi(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_lipmi(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_lipmi(char fdebug); extern int ipmi_close_lipmi(void); #elif defined(LINUX) extern int ipmi_cmdraw_ia( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_ia(char fdebug); extern int ipmi_close_ia(void); extern int ipmi_cmdraw_mv(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_mv(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_mv(char fdebug); extern int ipmi_close_mv(void); extern int ipmi_open_ld(char fdebug); extern int ipmi_close_ld(void); extern int ipmi_cmdraw_ld(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_ld(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_direct(char fdebug); extern int ipmi_close_direct(void); extern int ipmi_cmdraw_direct( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_direct(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_set_max_kcs_loops(int ms); #elif defined(DOS) extern int ipmi_open_direct(char fdebug); extern int ipmi_close_direct(void); extern int ipmi_cmdraw_direct( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_direct(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_set_max_kcs_loops(int ms); #else /* BSD */ extern int ipmi_open_direct(char fdebug); extern int ipmi_close_direct(void); extern int ipmi_cmdraw_direct( uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_direct(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_set_max_kcs_loops(int ms); extern int ipmi_cmdraw_mv(uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_cmd_mv(ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd); extern int ipmi_open_mv(char fdebug); extern int ipmi_close_mv(void); #endif extern int fd_wait(int fd, int nsec, int usec); #endif /* Global Data */ int fDriverTyp = DRV_UNKNOWN; /* 1=IMB driver, 2=VA driver, 3=MV open driver */ /* 4= GNU FreeIPMI, 5= LanDesk, 6= builtin IPMI LAN */ /* 7= direct KCS, 8= direct SMB, 9= IPMI LAN v2.0 */ int fipmi_lan = 0; int fjustpass = 0; FILE *fperr = NULL; FILE *fpdbg = NULL; FILE *fplog = NULL; int fauth_type_set = 0; char fdebug = 0; char log_name[60] = {'\0'}; /*log_name global*/ uchar my_devid[20] = {0,0,0,0,0,0,0,0}; /*saved devid, only needs 16 bytes*/ int gshutdown = 0; /* see ipmilan.c ipmilanplus.c */ LAN_OPT lanp = { "localhost","","", IPMI_SESSION_AUTHTYPE_MD5, IPMI_PRIV_LEVEL_USER, 3, "", 0, RMCP_PRI_RMCP_PORT }; static char *gnode = lanp.node; //char *guser = lanp.user; //char *gpswd = lanp.pswd; //uchar *gaddr = lanp.addr; //int gaddr_len = 0; //int gcipher_suite = 3; /*used in ipmilanplus.c*/ //int gauth_type = IPMI_SESSION_AUTHTYPE_MD5; /*if 0, use any: MD5, MD2, etc.*/ //int gpriv_level = IPMI_PRIV_LEVEL_USER; typedef struct { uchar adrtype; uchar sa; uchar bus; uchar lun; uchar capab; } mc_info; mc_info bmc = { ADDR_SMI, BMC_SA, PUBLIC_BUS, BMC_LUN, 0x8F }; /*BMC via SMI*/ mc_info mc2 = { ADDR_IPMB, BMC_SA, PUBLIC_BUS, BMC_LUN, 0x4F }; /*IPMB target*/ mc_info mymc = { ADDR_IPMB, BMC_SA, PUBLIC_BUS, BMC_LUN, 0x4F }; /*IPMB */ static char bcomma = ','; static mc_info *mc = &bmc; #ifdef WIN32 static char msg_no_drv[] = { /*no Windows driver*/ "Cannot open an IPMI driver: imbdrv.sys or ipmidrv.sys\n"}; #elif defined(SOLARIS) static char msg_no_drv[] = { /*no Solaris driver*/ "Cannot open an IPMI driver: /dev/bmc or /dev/lipmi\n"}; #elif defined(LINUX) static char msg_no_drv[] = { /*no Linux driver*/ "Cannot open an IPMI driver: /dev/imb, /dev/ipmi0, " "/dev/ipmi/0, \n\t " /* "/dev/ipmikcs, /dev/ipmi/kcs, " *no longer support valinux */ #ifdef LINK_LANDESK "ldipmi, " #endif "or direct driverless.\n" }; #elif defined(DOS) static char msg_no_drv[] = { /*no DOS IPMI driver*/ "Cannot open an IPMI direct KCS interface.\n"}; #else static char msg_no_drv[] = { /*no BSD IPMI driver*/ "Cannot open an IPMI driver: /dev/ipmi0 or direct.\n"}; #endif /* From IPMI v1.5/v2.0 spec, Table 5-2 Completion Codes */ #define NUMCC 32 struct { uchar code; char *mesg; } cc_mesg[NUMCC] = { /* Note: completion codes 0x80-0x9f may vary depending on the command. * 0x80 = Invalid Session Handle or Empty Buffer or Unsupported Feature */ {0x00, "Command completed successfully"}, {0x80, "Invalid Session Handle or Empty Buffer"}, {0x81, "Lost Arbitration"}, {0x82, "Bus Error"}, {0x83, "NAK on Write - busy"}, {0x84, "Truncated Read"}, {0x85, "Invalid session ID in request"}, /*for ActivateSession*/ {0x86, "Requested privilege level exceeds limit"}, /*for ActivateSession*/ {0xC0, "Node Busy"}, {0xC1, "Invalid Command"}, {0xC2, "Command invalid for given LUN"}, {0xC3, "Timeout while processing command"}, {0xC4, "Out of space"}, {0xC5, "Reservation ID cancelled or invalid"}, {0xC6, "Request data truncated"}, {0xC7, "Request data length invalid"}, {0xC8, "Request data field length limit exceeded"}, {0xC9, "Parameter out of range"}, {0xCA, "Cannot return requested number of data bytes"}, {0xCB, "Requested sensor, data, or record not present"}, {0xCC, "Invalid data field in request"}, {0xCD, "Command illegal for this sensor/record type"}, {0xCE, "Command response could not be provided"}, {0xCF, "Cannot execute duplicated request"}, {0xD0, "SDR Repository in update mode, no response"}, {0xD1, "Device in firmware update mode, no response"}, {0xD2, "BMC initialization in progress, no response"}, {0xD3, "Destination unavailable"}, {0xD4, "Cannot execute command. Insufficient privilege level"}, {0xD5, "Cannot execute command. Request parameters not supported"}, {0xD6, "Cannot execute command. Subfunction unavailable"}, {0xFF, "Unspecified error"} }; char * decode_cc(ushort icmd, int cc) { static char other_msg[25]; char *pmsg; int i; for (i = 0; i < NUMCC; i++) { if (cc == cc_mesg[i].code) break; } if (i == NUMCC) { /* if not found, show other_msg */ sprintf(other_msg,"Other error 0x%02x",cc); pmsg = other_msg; } else { if ((icmd == READ_EVENT_MSGBUF) && (cc == 0x80)) pmsg = "no data available (queue/buffer empty)"; else pmsg = cc_mesg[i].mesg; } return(pmsg); } char *decode_rv(int rv) { char *msg; static char msgbuf[80]; if (rv == 0x6F) msg = "License not supported"; /*for Dell*/ else if (rv > 0) msg = decode_cc((ushort)0,rv); else switch(rv) { case 0: msg = "completed successfully"; break; case -1: msg = "error -1"; break; case LAN_ERR_SEND_FAIL: msg = "send to BMC failed"; break; case LAN_ERR_RECV_FAIL: msg = "receive from BMC failed"; break; case LAN_ERR_CONNECT: msg = "cannot connect to BMC"; break; case LAN_ERR_ABORT: msg = "abort signal caught"; break; case LAN_ERR_TIMEOUT: msg = "timeout occurred"; break; case LAN_ERR_BADLENGTH: msg = "length greater than max"; break; case LAN_ERR_INVPARAM: msg = "invalid lan parameter"; break; case LAN_ERR_NOTSUPPORT: msg = "request not supported"; break; case LAN_ERR_TOO_SHORT: msg = "receive too short"; break; case LAN_ERR_HOSTNAME: msg = "error resolving hostname"; break; case LAN_ERR_PING: msg = "error during ping"; break; case LAN_ERR_V1: msg = "BMC only supports lan v1"; break; case LAN_ERR_V2: msg = "BMC only supports lan v2"; break; case LAN_ERR_OTHER: msg = "other error"; break; case ERR_NO_DRV: msg = "cannot open IPMI driver"; break; case ERR_BAD_PARAM: msg = "invalid parameter"; break; case ERR_NOT_ALLOWED: msg = "access not allowed"; break; case ERR_USAGE: msg = "usage or help requested"; break; case LAN_ERR_DROPPED: msg = "session dropped by BMC"; break; case ERR_FILE_OPEN: msg = "cannot open file"; break; case ERR_NOT_FOUND: msg = "item not found"; break; case ERR_BMC_MSG: msg = "error getting msg from BMC"; break; /* ipmidir.h: ERGETTINGIPMIMESSAGE -504 */ case ERR_BAD_FORMAT: msg = "bad format"; break; case ERR_BAD_LENGTH: msg = "length less than min"; break; case ERR_SDR_MALFORMED: msg = "an SDR is malformed"; break; default: sprintf(msgbuf,"error %d",rv); msg = msgbuf; break; } return(msg); } int get_cmd_rslen(uchar cmd, uchar netfn) { /* used by ipmicmd_gnu */ int rslen = 0; int i; ushort cmdkey; cmdkey = cmd | (netfn << 8); for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == cmdkey) { rslen = ipmi_cmds[i].rslen; break; } } return(rslen); } /*end get_cmd_rslen()*/ static int ndrivers = NDRIVERS; static struct { int idx; char *tag; } drv_types[NDRIVERS] = { { DRV_IMB, "imb" }, { DRV_MV, "open" }, { DRV_LD, "landesk" }, { DRV_LAN2, "lan2" }, { DRV_LAN2I,"lan2i" }, { DRV_LAN, "lan" }, { DRV_KCS, "kcs" }, { DRV_SMB, "smb" }, { DRV_MS, "ms" }, { DRV_BMC, "sun_bmc" }, { DRV_LIPMI,"sun_lipmi" }, { DRV_SMC, "supermicro" }, { DRV_IBM, "ibm" }, { DRV_HP, "hp" }, /*++++*/ #ifdef EFI { DRV_EFI, "efi" } #else { 0, "" } /*DRV_UNKNOWN*/ #endif }; // { DRV_VA, "va" }, // { DRV_GNU, "free" }, void set_iana(int iana) { my_devid[6] = (iana & 0x0000ff); my_devid[7] = ((iana & 0x00ff00) >> 8); my_devid[8] = ((iana & 0xff0000) >> 16); } void set_mfgid(uchar *devid, int len) { if (devid == NULL) return; if (len > sizeof(my_devid)) len = sizeof(my_devid); memcpy(my_devid,devid,len); } void get_mfgid(int *pvend, int *pprod) { if (pvend != NULL) *pvend = my_devid[6] + (my_devid[7] << 8) + (my_devid[8] << 16); if (pprod != NULL) *pprod = my_devid[9] + (my_devid[10] << 8); } char *show_driver_type(int idx) { int i; char *tag; for (i = 0; i < ndrivers; i++) { if (drv_types[i].idx == idx) { tag = drv_types[i].tag; break; } } if (i >= ndrivers) { /*not found*/ tag = "unknown"; } return(tag); } int get_driver_type(void) { return(fDriverTyp); } int set_driver_type(char *tag) { int rv = 0; int i; /* else if (str_icmp(tag,"lan2") == 0) * leave vendor id as is. */ for (i = 0; i < ndrivers; i++) { if (str_icmp(drv_types[i].tag, tag) == 0) { fDriverTyp = drv_types[i].idx; if (fDriverTyp == DRV_LAN2I) { /*LAN2 Intel*/ set_iana(VENDOR_INTEL); /*VENDOR_INTEL = 0x000157*/ } else if (fDriverTyp == DRV_SMC) { /*supermicro*/ set_iana(VENDOR_SUPERMICRO); /*VENDOR_SUPERMICRO = 0x002A7C*/ fDriverTyp = DRV_LAN; } if (fDriverTyp == DRV_IBM) { /*LAN IBM*/ set_iana(VENDOR_IBM); fDriverTyp = DRV_LAN; } if (fDriverTyp == DRV_HP) { /*LAN2 HP ++++*/ set_iana(VENDOR_HP); fDriverTyp = DRV_LAN2; lanp.auth_type = IPMI_SESSION_AUTHTYPE_NONE; /*HP default*/ } break; } } if (i >= ndrivers) { /*not found*/ fDriverTyp = DRV_UNKNOWN; /*not set yet, so detect*/ rv = 1; // if (fdebugcmd) { printf("Invalid -F argument (%s), valid driver types are:\n",tag); for (i = 0; i < ndrivers; i++) printf("\t%s\n",drv_types[i].tag); } } return(rv); } /* * use_devsdrs * detect whether to use SDR repository or Device SDRs from * the saved GetDeviceID response. * ipmi_getdeviceid saves it into my_devid. */ int use_devsdrs(int picmg) { int fdev, vend, prod; /* set Device SDRs flag as specified in the GetDeviceID */ if ((my_devid[1] & 0x80) == 0x80) fdev = 1; else fdev = 0; if (picmg) return(fdev); /* check for vendor/products that can report the flag wrong */ vend = my_devid[6] + (my_devid[7] << 8) + (my_devid[8] << 16); prod = my_devid[9] + (my_devid[10] << 8); switch(vend) { case VENDOR_INTEL: if ((prod != 0x800) && (prod != 0x808) && (prod != 0x841)) fdev = 0; break; case VENDOR_NSC: fdev = 0; break; case VENDOR_NEC: fdev = 0; break; case VENDOR_DELL: fdev = 0; break; case VENDOR_HP: fdev = 0; break; case VENDOR_SUN: fdev = 0; break; default: break; } return(fdev); } /* get_lan_channel returns the next lan channel starting with chfirst. */ int get_lan_channel(uchar chfirst, uchar *chan) { int ret, j; uchar iData[4]; uchar rData[9]; int rlen; uchar cc; int found = 0; for (j = chfirst; j < 12; j++) { rlen = sizeof(rData); iData[0] = (uchar)j; /*channel #*/ memset(rData,0,9); /*initialize recv data*/ ret = ipmi_cmd(GET_CHANNEL_INFO, iData, 1, rData, &rlen, &cc, fdebug); if (ret == 0xcc || cc == 0xcc) /* special case for ipmi_lan */ continue; if (ret != 0) { if (fdebug) printf("get_chan_info rc = %x\n",ret); break; } /* rData[1] == channel medium type */ if (rData[1] == 4) { /* medium type 4 = 802.3 LAN type*/ if (fdebug) printf("chan[%d] = lan\n",j); found = 1; *chan = (uchar)j; break; } } if (found == 0) ret = -1; return(ret); } int nodeislocal(char *nodename) { if (nodename == NULL) return 1; if (nodename[0] == 0) return 1; if (strcmp(nodename,"localhost") == 0) return 1; return 0; } int set_max_kcs_loops(int ms) { int rv = 0; #if defined(LINUX) rv = ipmi_set_max_kcs_loops(ms); #elif defined(BSD) rv = ipmi_set_max_kcs_loops(ms); #elif defined(DOS) rv = ipmi_set_max_kcs_loops(ms); #endif return(rv); } /* * ipmi_open * This is called by ipmi_cmd and ipmicmd_raw if a session has not * yet been opened (fDriverTyp == DRV_UNKNOWN). * The order to try these drivers could be customized for specific * environments by modifying this routine. * * ipmi_cmd[raw] would call a specific open routine if set_driver_type(). */ int ipmi_open(char fdebugcmd) { int rc = 0; fperr = stderr; fpdbg = stdout; fdebug = fdebugcmd; #ifdef EFI rc = ipmi_open_efi(fdebugcmd); #else if (!nodeislocal(gnode)) { fipmi_lan = 1; } if (fdebugcmd) printf("ipmi_open: driver type = %s\n", show_driver_type(fDriverTyp)); /* first time, so try each */ if (fipmi_lan) { /* Try IPMI LAN 1.5 first */ rc = ipmi_open_lan(gnode,lanp.port,lanp.user,lanp.pswd,fdebugcmd); fDriverTyp = DRV_LAN; if (rc == LAN_ERR_V2) { /* Use IPMI LAN 2.0 if BMC said it only supports LAN2 */ /* This is a violation of IPMI 2.0 Spec section 13.4, * but some HP firmware behaves this way, so handle it. */ fDriverTyp = DRV_LAN2; rc = ipmi_open_lan2(gnode,lanp.user,lanp.pswd,fdebugcmd); if (rc != 0) fDriverTyp = DRV_UNKNOWN; } } else { /* local, not lan */ #ifdef WIN32 rc = ipmi_open_ia(fdebugcmd); if (rc == ACCESS_OK) fDriverTyp = DRV_IMB; else if ((rc = ipmi_open_ms(fdebugcmd)) == ACCESS_OK) fDriverTyp = DRV_MS; else rc = ERR_NO_DRV; #elif defined(SOLARIS) rc = ipmi_open_bmc(fdebugcmd); if (rc == ACCESS_OK) fDriverTyp = DRV_BMC; else if ((rc = ipmi_open_lipmi(fdebugcmd)) == ACCESS_OK) fDriverTyp = DRV_LIPMI; else rc = ERR_NO_DRV; #elif defined(LINUX) if ((rc = ipmi_open_ld(fdebugcmd)) == ACCESS_OK) { fDriverTyp = DRV_LD; ipmi_close_ld(); } else if ((rc = ipmi_open_mv(fdebugcmd)) == ACCESS_OK) { fDriverTyp = DRV_MV; /* ipmi_close_mv(); * leave it open until explicit close */ } else if ((rc = ipmi_open_ia(fdebugcmd)) == ACCESS_OK) { fDriverTyp = DRV_IMB; } else if ((rc = ipmi_open_direct(fdebugcmd)) == ACCESS_OK) { /* set to either DRV_KCS or DRV_SMB */ } else rc = ERR_NO_DRV; #elif defined(DOS) rc = ipmi_open_direct(fdebugcmd); /* sets fDriverTyp to either DRV_KCS or DRV_SMB */ if (rc != ACCESS_OK) rc = ERR_NO_DRV; #else /* BSD or MACOS */ if ((rc = ipmi_open_mv(fdebugcmd)) == ACCESS_OK) { /* FreeBSD "kldload ipmi" has /dev/ipmi0 */ fDriverTyp = DRV_MV; /* ipmi_close_mv(); * leave it open until explicit close */ } else if ((rc = ipmi_open_direct(fdebugcmd)) == ACCESS_OK) { /* sets fDriverTyp to either DRV_KCS or DRV_SMB */ } else rc = ERR_NO_DRV; #endif } /*endelse local, not lan*/ #endif if (fdebugcmd) printf("ipmi_open rc = %d type = %s\n",rc, show_driver_type(fDriverTyp)); return (rc); } int ipmi_close_(void) { int rc = 0; #ifndef EFI switch (fDriverTyp) { #ifdef WIN32 case DRV_IMB: rc = ipmi_close_ia(); break; case DRV_MS: rc = ipmi_close_ms(); break; #elif defined(SOLARIS) case DRV_BMC: rc = ipmi_close_bmc(); break; case DRV_LIPMI: rc = ipmi_close_lipmi(); break; #elif defined(LINUX) case DRV_IMB: rc = ipmi_close_ia(); break; case DRV_MV: rc = ipmi_close_mv(); break; case DRV_LD: rc = ipmi_close_ld(); break; case DRV_SMB: case DRV_KCS: rc = ipmi_close_direct(); break; #elif defined(DOS) case DRV_SMB: case DRV_KCS: rc = ipmi_close_direct(); break; #else /* BSD or MACOS */ case DRV_MV: rc = ipmi_close_mv(); break; case DRV_SMB: case DRV_KCS: rc = ipmi_close_direct(); break; #endif case DRV_LAN: rc = ipmi_close_lan(gnode); break; case DRV_LAN2I: case DRV_LAN2: rc = ipmi_close_lan2(gnode); break; default: break; } /*end switch*/ #endif fDriverTyp = DRV_UNKNOWN; return (rc); } /* don't worry about conflict with other ipmi libs any longer */ int ipmi_close(void) { return(ipmi_close_()); } #if defined(EFI) int ipmi_open_efi(int fdebugcmd) { int rc = 0; static bool BmcLibInitialized = false; if (BmcLibInitialized == false ) { rc = BmcLibInitialize(); if (rc == 0) { BmcLibInitialized = true; fDriverTyp = DRV_EFI; } } return rc; } #define TIMEOUT_EFI (1000*1000) /*see ipmi_timeout_ia*/ int ipmi_cmdraw_efi(uchar cmd, uchar netfn, uchar sa, uchar bus, uchar lun, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { BMC_MESSAGE ReqMsg; BMC_MESSAGE RespMsg; int status = 0; uchar * pc; int sz, i; ReqMsg.DevAdd = sa; ReqMsg.NetFn = netfn; ReqMsg.LUN = lun; ReqMsg.Cmd = cmd; ReqMsg.Len = sdata; for( sz=0; (sz 255) return(LAN_ERR_BADLENGTH); if (fDriverTyp == DRV_UNKNOWN) { /*first time, so find which one */ rc = ipmi_open(fdebugcmd); if (fdebugcmd) fprintf(fpdbg,"Driver type %s, open rc = %d\n", show_driver_type(fDriverTyp),rc); if (rc == ERR_NO_DRV && !fipmi_lan) fprintf(fperr, "%s", msg_no_drv); else if (rc != 0) fprintf(fperr,"ipmi_open error = %d %s\n", rc,decode_rv(rc)); if (rc != 0) return(rc); } /*endif first time*/ icmd = (cmd & 0x00ff) | (netfn << 8); *pcc = 0; /* Check for the size of the response buffer being zero. */ /* This may be valid for some commands, but print a debug warning. */ if (fdebugcmd && (*sresp == 0)) printf("ipmi_cmdraw: warning, sresp==0\n"); #ifdef EFI rc = ipmi_cmdraw_efi(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); #else switch (fDriverTyp) { #ifdef WIN32 case DRV_IMB: rc = ipmi_cmdraw_ia(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_MS: rc = ipmi_cmdraw_ms(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; #elif defined(SOLARIS) case DRV_BMC: rc = ipmi_cmdraw_bmc(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_LIPMI: rc = ipmi_cmdraw_lipmi(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; #elif defined(LINUX) case DRV_IMB: rc = ipmi_cmdraw_ia(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_MV: rc = ipmi_cmdraw_mv(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_LD: rc = ipmi_cmdraw_ld( cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_SMB: case DRV_KCS: rc = ipmi_cmdraw_direct(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; #elif defined(DOS) case DRV_SMB: case DRV_KCS: rc = ipmi_cmdraw_direct(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; #else /* BSD or MACOS */ case DRV_MV: rc = ipmi_cmdraw_mv(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_SMB: case DRV_KCS: rc = ipmi_cmdraw_direct(cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; #endif case DRV_LAN: rc = ipmi_cmdraw_lan(gnode, cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; case DRV_LAN2I: case DRV_LAN2: rc = ipmi_cmdraw_lan2(gnode, cmd, netfn, lun, sa, bus, pdata,sdata, presp,sresp, pcc, fdebugcmd); break; default: /* no ipmi driver */ rc = ERR_NO_DRV; break; } /*end switch*/ #endif if ((rc >= 0) && (*pcc != 0) && fdebugcmd) { fprintf(fpdbg,"ccode %x: %s\n",*pcc,decode_cc(icmd,(int)*pcc)); } /* clear the temp cmd (OLD) */ // ipmi_cmds[0].cmdtyp = 0; // ipmi_cmds[0].sa = BMC_SA; return(rc); } /* * ipmi_cmd_mc() * This uses the mc pointer to route commands via either the SMI or * IPMB method to the designated mc. * See also ipmi_set_mc and ipmi_restore_mc. */ int ipmi_cmd_mc(ushort icmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { uchar cmd, netfn; int rv; cmd = icmd & CMDMASK; netfn = (icmd & 0xFF00) >> 8; if (sdata > 255) return(LAN_ERR_BADLENGTH); if ((fDriverTyp != DRV_MV) && (mc->adrtype == ADDR_IPMB) && !fipmi_lan) { rv = ipmi_cmd_ipmb(cmd, netfn, mc->sa, mc->bus, mc->lun, pdata, sdata, presp, sresp, pcc, fdebugcmd); } else { /* use ADDR_SMI */ rv = ipmi_cmdraw(cmd, netfn, mc->sa, mc->bus, mc->lun, pdata, sdata, presp, sresp, pcc, fdebugcmd); } return(rv); } int ipmi_cmdraw_mc(uchar cmd, uchar netfn, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rv; if (sdata > 255) return(LAN_ERR_BADLENGTH); if ((fDriverTyp != DRV_MV) && (mc->adrtype == ADDR_IPMB) && !fipmi_lan) { rv = ipmi_cmd_ipmb(cmd, netfn, mc->sa, mc->bus, mc->lun, pdata, sdata, presp, sresp, pcc, fdebugcmd); } else { /* use ADDR_SMI */ rv = ipmi_cmdraw(cmd, netfn, mc->sa, mc->bus, mc->lun, pdata, sdata, presp, sresp, pcc, fdebugcmd); } return(rv); } /* * ipmi_cmd() * * This is the externally exposed subroutine for commands that * are defined in the ipmi_cmds array above. * It calls the ipmi_cmdraw routine for further processing. */ int ipmi_cmd(ushort icmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, i; uchar bcmd; uchar netfn, sa, bus, lun; fperr = stderr; fpdbg = stdout; if (sdata > 255) return(LAN_ERR_BADLENGTH); if (fDriverTyp == DRV_UNKNOWN) { /*first time, so find which one */ rc = ipmi_open(fdebugcmd); if (fdebugcmd) fprintf(fpdbg,"Driver type %s, open rc = %d\n", show_driver_type(fDriverTyp),rc); if (rc != 0) { if (rc == ERR_NO_DRV && !fipmi_lan) fprintf(fperr, "%s", msg_no_drv); else fprintf(fperr,"ipmi_open error = %d %s\n", rc,decode_rv(rc)); return(rc); } } /*endif first time*/ for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == icmd) break; } if (i >= NCMDS) { fprintf(fperr, "ipmi_cmd: Unknown command %x\n",icmd); return(-1); } bcmd = icmd & CMDMASK; /* unmask it */ netfn = ipmi_cmds[i].netfn; lun = ipmi_cmds[i].lun; sa = ipmi_cmds[i].sa; bus = ipmi_cmds[i].bus; rc = ipmi_cmdraw(bcmd, netfn, sa, bus, lun, pdata,sdata, presp,sresp, pcc, fdebugcmd); return(rc); } /* MOVED ipmi_cmd_ipmb() to ipmilan.c */ int ipmi_getpicmg(uchar *presp, int sresp, char fdebug) { uchar idata[2]; int rc; uchar cc; /* check that sresp is big enough */ if (sresp < 4) return(-3); idata[0] = PICMG_ID; rc = ipmi_cmdraw(PICMG_GET_PROPERTIES, NETFN_PICMG, BMC_SA, PUBLIC_BUS, BMC_LUN, idata, 1, presp,&sresp, &cc, fdebug); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); return(ACCESS_OK); /* success */ } int ipmi_getdeviceid(uchar *presp, int sresp, char fdebug) { int rc, i; uchar cc; /* check that sresp is big enough (default is 15 bytes for Langley)*/ if (sresp < 15) return(ERR_BAD_LENGTH); rc = ipmi_cmd_mc(GET_DEVICE_ID, NULL, 0, presp,&sresp, &cc, fdebug); if (rc != ACCESS_OK) return(rc); if (cc != 0) return(cc); i = sresp; if (i > sizeof(my_devid)) i = sizeof(my_devid); memcpy(my_devid,presp,i); /* save device id for later use */ if (fdebug) { uchar maj,min,iver; int vend, prod; get_devid_ver(&maj,&min,&iver); get_mfgid(&vend, &prod); printf("devid: firmware ver %x.%02x, IPMI v%02x, vendor=%d prod=%d\n", maj,min,iver,vend,prod); } return(ACCESS_OK); /* success */ } void get_devid_ver(uchar *bmaj, uchar *bmin, uchar *iver) { if (bmaj != NULL) *bmaj = my_devid[2]; if (bmin != NULL) *bmin = my_devid[3]; if (iver != NULL) *iver = my_devid[4]; } void show_devid(uchar b1, uchar b2, uchar i1, uchar i2) { /* b1 = devid[2]; b2 = devid[3]; i2|i1 = devid[4]; */ printf("-- BMC version %x.%02x%c IPMI version %d.%d \n",b1,b2,bcomma,i1,i2); } void ipmi_set_mc(uchar bus, uchar sa, uchar lun, uchar atype) { mc = &mc2; mc->bus = bus; mc->sa = sa; mc->lun = lun; mc->adrtype = atype; /* ADDR_SMI or ADDR_IPMB */ if (fdebug) printf("ipmi_set_mc(%02x,%02x,%02x,%02x)\n",bus,sa,lun,atype); return; } void ipmi_restore_mc(void) { mc = &bmc; return; } void ipmi_get_mc(uchar *bus, uchar *sa, uchar *lun, uchar *type) { /* mc = &bmc or &mc2; */ if (bus != NULL) *bus = mc->bus; if (sa != NULL) *sa = mc->sa; if (lun != NULL) *lun = mc->lun; if (type != NULL) *type = mc->adrtype; /* ADDR_SMI or ADDR_IPMB */ return; } void ipmi_set_mymc(uchar bus, uchar sa, uchar lun, uchar type) { mymc.bus = bus; mymc.sa = sa; mymc.lun = lun; mymc.adrtype = type; /* ADDR_SMI or ADDR_IPMB */ return; } void ipmi_get_mymc(uchar *bus, uchar *sa, uchar *lun, uchar *type) { if (bus != NULL) *bus = mymc.bus; if (sa != NULL) *sa = mymc.sa; if (lun != NULL) *lun = mymc.lun; if (type != NULL) *type = mymc.adrtype; /* ADDR_SMI or ADDR_IPMB */ return; } int ipmi_sendrecv(struct ipmi_rq * req, uchar *rsp, int *rsp_len) { /* compatible with intf->sendrecv() */ int rv; uchar ccode; int rlen; rlen = IPMI_RSPBUF_SIZE; *rsp_len = 0; if ((fDriverTyp != DRV_MV) && (mc->adrtype == ADDR_IPMB) && !fipmi_lan) { rv = ipmi_cmd_ipmb( req->msg.cmd, req->msg.netfn, mc->sa,mc->bus, req->msg.lun, req->msg.data, (uchar)req->msg.data_len, rsp, &rlen, &ccode, fdebug); } else { /* use ADDR_SMI */ rv = ipmi_cmdraw(req->msg.cmd, req->msg.netfn, mc->sa,mc->bus, req->msg.lun, req->msg.data, (uchar)req->msg.data_len, rsp, &rlen, &ccode, fdebug); } if (rv == 0 && ccode != 0) rv = ccode; if (rv == 0) { /*success*/ *rsp_len = rlen; } return (rv); } #ifdef WIN32 static HANDLE con_in = INVALID_HANDLE_VALUE; static DWORD cmodein; static DWORD cmodeold; void tty_setraw(int mode) { // system("@echo off"); con_in = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(con_in, &cmodein); cmodeold = cmodein; if (mode == 2) { cmodein &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT); } else { /* (mode==1) just suppress ECHO */ cmodein &= ~ENABLE_ECHO_INPUT; } SetConsoleMode(con_in, cmodein); } void tty_setnormal(int mode) { // system("echo on"); if (mode == 1) cmodein |= ENABLE_ECHO_INPUT; else cmodein = cmodeold; SetConsoleMode(con_in, cmodein); } int tty_getattr(int *lflag, int *oflag, int *iflag) { *lflag = (int)cmodein; *oflag = 0; *iflag = 0; return(0); } #elif defined(DOS) void tty_setraw(int mode) { return; } void tty_setnormal(int mode) { return; } int tty_getattr(int *lflag, int *oflag, int *iflag) { return(-1); } #else /*LINUX, SOLARIS, BSD*/ // #include static struct termios mytty; static struct termios ttyold; static ulong tty_oldflags; int tty_getattr(int *lflag, int *oflag, int *iflag) { int rv; static struct termios outtty; rv = tcgetattr(STDOUT_FILENO, &outtty); if (rv == 0) { *lflag = outtty.c_lflag; *oflag = outtty.c_oflag; *iflag = outtty.c_iflag; } return(rv); } void tty_setraw(int mode) { int i; // system("stty -echo"); i = tcgetattr(STDIN_FILENO, &mytty); if (i == 0) { tty_oldflags = mytty.c_lflag; ttyold = mytty; #ifdef SOLARIS mytty.c_iflag |= IGNPAR; mytty.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); mytty.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); mytty.c_lflag &= ~IEXTEN; /* mytty.c_oflag &= ~OPOST; // this causes NL but no CR on output */ mytty.c_cc[VMIN] = 1; mytty.c_cc[VTIME] = 0; i = tcsetattr(STDIN_FILENO, TCSADRAIN, &mytty); #else if (mode == 2) { /*raw mode*/ mytty.c_lflag &= ~(ICANON | ISIG | ECHO); // mytty.c_oflag &= ~ONLCR; /* do not map NL to CR-NL on output */ } else /* (mode==1) just suppress ECHO */ mytty.c_lflag &= ~ECHO; i = tcsetattr(STDIN_FILENO, TCSANOW, &mytty); #endif } } void tty_setnormal(int mode) { // system("stty echo"); if (mode == 1) mytty.c_lflag |= ECHO; else { /*(mode==2)*/ mytty.c_lflag = tty_oldflags; mytty = ttyold; } tcsetattr(STDIN_FILENO, TCSANOW, &mytty); #ifdef SOLARIS tcsetattr(fileno(stdin), TCSADRAIN, &mytty); #endif } #endif static char *my_getline(char *prompt, char fwipe) { /* getline is the same format as readline, but much simpler, and portable. */ static char linebuf[128]; int c, i; if (prompt != NULL) printf("%s\n",prompt); if (fwipe) tty_setraw(1); for (i = 0; i < (sizeof(linebuf)-1); i++) { c = getc(stdin); if (c == EOF) break; if (c == '\n') break; if ((c < 0x20) || (c > 0x7F)) break; /*out of bounds for ASCII */ linebuf[i] = c & 0xff; } linebuf[i] = 0; if (fwipe) { for (c = 0; c < i; c++) putc('*',stdout); putc('\n',stdout); tty_setnormal(1); } if (i == 0) return NULL; return(linebuf); } static char *getline_wipe(char *prompt) { return(my_getline(prompt,1)); } void set_debug(void) { fdebug = 1; } char is_remote(void) { return((char)fipmi_lan); } int get_lan_options(char *node, char *user, char *pswd, int *auth, int *priv, int *cipher, void *addr, int *addr_len) { if (fipmi_lan == 0) return(-1); if (node != NULL) strcpy(node,lanp.node); if (user != NULL) strcpy(user,lanp.user); if (pswd != NULL) strcpy(pswd,lanp.pswd); if (auth != NULL) *auth = lanp.auth_type; if (priv != NULL) *priv = lanp.priv; if (cipher != NULL) *cipher = lanp.cipher; if (addr != NULL && lanp.addr_len != 0) memcpy(addr,lanp.addr,lanp.addr_len); if (addr_len != NULL) *addr_len = lanp.addr_len; return(0); } int set_lan_options(char *node, char *user, char *pswd, int auth, int priv, int cipher, void *addr, int addr_len) { int rv = 0; if (node != NULL) { strncpy(lanp.node,node,SZGNODE); lanp.node[SZGNODE] = '\0'; gnode = lanp.node; fipmi_lan = 1; } if (user != NULL) { strncpy(lanp.user,user,SZGNODE); lanp.user[SZGNODE] = '\0'; } if (pswd != NULL) { strncpy(lanp.pswd,pswd,PSW_MAX); lanp.pswd[PSW_MAX] = '\0'; } if (auth > 0 && auth <= 5) { lanp.auth_type = auth; } else rv = ERR_BAD_PARAM; if (priv > 0 && priv <= 5) { lanp.priv = priv; } else rv = ERR_BAD_PARAM; if (cipher >= 0 && cipher <= 17) { lanp.cipher = cipher; } else rv = ERR_BAD_PARAM; if ((addr != NULL) && (addr_len > 15) && (addr_len <= sizeof(lanp.addr))) { memcpy(lanp.addr,addr,addr_len); lanp.addr_len = addr_len; } ipmi_flush_lan(gnode); return(rv); } void parse_lan_options(int c, char *popt, char fdebugcmd) { #if defined(EFI) | defined(DOS) return; #else int i; static int fset_dtype = 0; uchar sa; char *p = NULL; switch(c) { case 'p': i = atoi(popt); if (i > 0) lanp.port = i; else printf("-p port %d < 0, defaults to %d\n", i,RMCP_PRI_RMCP_PORT); break; case 'F': /* force driver type */ i = set_driver_type(popt); if (i == 0) fset_dtype = 1; break; case 'T': /* auth type */ i = atoi(popt); if (i >= 0 && i <= 5) lanp.auth_type = i; fauth_type_set = 1; break; case 'V': /* priv level */ i = atoi(popt); if (i > 0 && i <= 5) lanp.priv = i; break; case 'J': i = atoi(popt); if (i >= 0 && i <= 17) lanp.cipher = i; else printf("-J cipher suite %d > 17, defaults to %d\n", i,lanp.cipher); if (fset_dtype == 0) i = set_driver_type("lan2"); break; case 'N': strncpy(lanp.node,popt,SZGNODE); /*remote nodename */ lanp.node[SZGNODE] = '\0'; fipmi_lan = 1; break; case 'U': strncpy(lanp.user,popt,SZGNODE); /*remote username */ lanp.user[SZGNODE] = '\0'; /* Hide username from 'ps' */ memset(popt, ' ', strlen(popt)); break; case 'R': case 'P': strncpy(lanp.pswd,popt,PSW_MAX); /*remote password */ lanp.pswd[PSW_MAX] = '\0'; /* Hide password from 'ps' */ memset(popt, ' ', strlen(popt)); break; case 'E': /* get password from IPMI_PASSWORD environment var */ p = getenv("IPMI_PASSWORD"); if (p == NULL) perror("getenv(IPMI_PASSWORD)"); else { strncpy(lanp.pswd,p,PSW_MAX); /*remote password */ if (strlen(p) > PSW_MAX) lanp.pswd[PSW_MAX] = '\0'; if (fdebugcmd) printf("using IPMI_PASSWORD\n"); } break; case 'Y': /* prompt for remote password */ p = getline_wipe("Enter IPMI LAN Password: "); if (p != NULL) { strncpy(lanp.pswd,p,PSW_MAX); /*remote password */ if (strlen(p) > PSW_MAX) lanp.pswd[PSW_MAX] = '\0'; } break; case 'Z': /* set local MC address */ sa = htoi(&popt[0]); /*device slave address*/ ipmi_set_mymc(mc->bus, sa, mc->lun, ADDR_IPMB); break; default: if (fdebugcmd) printf("unrecognized option %c\n",c); break; } ipmi_flush_lan(gnode); #endif } /*end parse_lan_options*/ void print_lan_opt_usage(int opt) { #if defined(EFI) | defined(DOS) return; #else if (opt == 1) /*port ok*/ printf(" -p port UDP Port of target system\n"); printf(" -N node Nodename or IP address of target system\n"); printf(" -U user Username for remote node\n"); printf(" -P/-R pswd Remote Password\n"); printf(" -E use password from Environment IPMI_PASSWORD\n"); printf(" -F force driver type (e.g. imb, lan2)\n"); printf(" -J 0 use lanplus cipher suite 0: 0 thru 14, 3=default\n"); printf(" -T 1 use auth Type: 1=MD2, 2=MD5(default), 4=Pswd\n"); printf(" -V 2 use priVilege level: 2=user(default), 4=admin\n"); printf(" -Y prompt for remote password\n"); printf(" -Z set slave address of local MC\n"); #endif } /*end parse_lan_options*/ char *get_nodename(void) { return(gnode); } void show_outcome(char *prog, int ret) { int err = 0; if (prog == NULL) prog = ""; err = get_LastError(); if (ret == -1 && err != 0) show_LastError(prog,err); printf("%s%c %s\n",prog,bcomma,decode_rv(ret)); } /* end ipmicmd.c */ ipmiutil-3.1.9/util/ipmiutil.c0000644000000000000000000001757014351572427015057 0ustar rootroot/*********************************************** * ipmiutil.c * * This is a meta-command utility to invoke each of the * other sub-commands in a consolidated interface. * To build this, compile with -DMETACOMMAND. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2006-2007 Intel Corporation. * Copyright (c) 2009 Kontron America, Inc. * * 01/03/07 ARCress - created * 01/05/07 ARCress - version 1.0 * 01/10/07 ARCress - version 1.1 * 02/07/07 ARCress - version 1.3 adding isolconsole * 02/26/07 ARCress - updated sub-command names * 08/31/07 ARCress - added "leds" subcommand * ***********************************************/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2007, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------*/ #include #include #include #include #include #include #include "ipmicmd.h" #include "ipmiutil.h" static char *progname = "ipmiutil"; char *progver = "3.19"; // static char fdebug = 0; /*int ipmiutil(int argc, char **argv); */ #define NSUBCMDS 29 static struct { int idx; char tag[16]; int (*rtn)(int argc, char **argv); char desc[64]; } subcmds[NSUBCMDS] = { { 0, "alarms", i_alarms, "show/set the front panel alarm LEDs and relays" }, { 1, "leds", i_alarms, "show/set the front panel alarm LEDs and relays" }, { 2, "discover", i_discover, "discover all IPMI servers on this LAN" }, { 3, "cmd", i_cmd , "send a specified raw IPMI command to the BMC" }, { 4, "config", i_config, "list/save/restore BMC configuration parameters" }, { 26, "dcmi", i_dcmi, "get/set DCMI parameters" }, { 5, "ekanalyzer", i_ekanalyzer, "run EKeying analyzer on FRU files (deprecated, see fru)" }, { 6, "events", i_events, "decode IPMI events and display them" }, { 7, "firewall", i_firewall, "show/set firmware firewall functions" }, { 8, "fru", i_fru, "show decoded FRU inventory data, write asset tag"}, { 9, "fwum", i_fwum, "OEM firmware update manager extensions" }, { 10, "getevt", i_getevt, "get IPMI events and display them, event daemon" }, { 11, "getevent", i_getevt, "get IPMI events and display them, event daemon" }, { 12, "health", i_health, "check and show the basic health of the IPMI BMC"}, { 13, "hpm", i_hpm, "HPM firmware update manager extensions" }, { 14, "lan", i_lan, "show/set IPMI LAN parameters, users, PEF rules"}, { 15, "picmg", i_picmg, "show/set picmg extended functions" }, { 25, "power", i_reset, "issue IPMI reset or power control to the system"}, { 16, "reset", i_reset, "issue IPMI reset or power control to the system"}, { 17, "sel", i_sel, "show/clear firmware System Event Log records" }, { 18, "sensor", i_sensor, "show Sensor Data Records, readings, thresholds" }, { 19, "serial", i_serial, "show/set IPMI Serial & Terminal Mode parameters"}, { 20, "sol", i_sol, "start/stop an SOL console session" }, { 21, "smcoem", i_smcoem, "SuperMicro OEM functions" }, { 22, "sunoem", i_sunoem, "Sun OEM functions" }, { 23, "delloem",i_delloem, "Dell OEM functions" }, { 24, "tsol", i_tsol, "Tyan SOL console start/stop session" }, { 28, "user", i_user, "list or modify IPMI LAN users" }, { 27, "wdt", i_wdt, "show/set/reset the watchdog timer" } }; static char usagemsg[] = "Usage: ipmiutil [other options]\n" " where is one of the following:\n"; static char helpmsg[] = "For help on each command (e.g. 'sel'), enter:\n" " ipmiutil sel -?\n"; static void show_usage() { int i; printf("%s", usagemsg); for (i=0; i= NSUBCMDS) { #ifdef LINUX if ((strcmp(argv[1],"svc") == 0) && (argc >= 3)) { char mycmd[80]; char *pfunc; char *psvc; char fchkok; /* undocumented: start a given service, only works locally */ psvc = "ipmi_port"; if (argc > 2) pfunc = argv[2]; else pfunc = "on"; ret = system("ls /sbin/chkconfig >/dev/null 2>&1"); if (ret == 0) fchkok = 1; else fchkok = 0; if (strcmp(pfunc,"off") == 0) { sprintf(mycmd,"service %s stop\n",psvc); printf("%s\n",mycmd); ret = system(mycmd); if (fchkok) { sprintf(mycmd,"/sbin/chkconfig --del %s\n",psvc); printf("%s\n",mycmd); ret = system(mycmd); } } else { if (fchkok) { sprintf(mycmd,"/sbin/chkconfig --add %s\n",psvc); printf("%s\n",mycmd); ret = system(mycmd); sprintf(mycmd,"/sbin/chkconfig --level 345 %s on\n",psvc); // printf("%s\n",mycmd); ret = system(mycmd); } sprintf(mycmd,"service %s start\n",psvc); printf("%s\n",mycmd); ret = system(mycmd); } } else #endif { printf("%s ver %s\n", progname,progver); show_usage(); ret = ERR_USAGE; } } do_exit: { char tag[30]; sprintf(tag,"%s %s",progname,psubcmd); show_outcome(tag,ret); } return(ret); } #endif /*end ipmiutil.c*/ ipmiutil-3.1.9/util/iserial.c0000644000000000000000000016134114144515623014642 0ustar rootroot/* * tmconfig.c * * This tool sets up the serial EMP port for the Terminal Mode settings. * * Author: Andy Cress arcress at users.sourceforge.net * Copyright (c) 2002-2006 Intel Corporation. * * Options: * -b Set serial port up for Basic Mode (fBMode) * -B Set baud rate for serial port * -d Disable serial port for IPMI use * -f Flow Control setting, default=1 (RTS/CTS) * -r Read-only, view serial port parameters * -s configure serial port for Shared Basic Mode & Remote Console * -t Configure serial port for shared Terminal Mode (TMode) & Console * -u username Set username for EMP TMode login (default is null user 1) * -p password Set password for EMP TMode login * -l show LAN parameters also * -m0 switch MUX to Normal baseboard operation * -m1 switch MUX to BMC operation (BMode or TMode) * -x eXtra debug messages * -f special boot Flags * * Change Log: * 02/12/02 Andy Cress - created from pefconfig.c * 03/08/02 Andy Cress - added GET_USER_ACCESS to serial parameters shown * 03/11/02 Andy Cress - changed MUX param 8 value for -b * 03/13/02 Andy Cress - changed default behavior to be like -r, * added -c option to configure TMode * 03/15/02 Andy Cress v1.3 added bootflags * 04/12/02 Andy Cress v1.4 use always avail instead of shared mode * also, don't do boot flags if not specified * 07/02/02 Andy Cress v1.5 add more Usage, add -d option. * 07/25/02 Andy Cress v1.6 fixed passwd offset for fSetTMode (-c) * 08/02/02 Andy Cress v1.7 moved common ipmi_cmd() code to ipmicmd.c * 12/09/02 Andy Cress v1.8 make sure -d sets user1 to admin again, * combine -n/-t into -m for MUX, * fix -c to drop thru to SetTMode logic, * param 8 values changed, * Dont SetUser for TMode unless -u, * use DCD & RTS/CTS for TMode. * 12/12/02 Andy Cress v1.9 change access from 0x23 to 0x2b * 01/23/03 Andy Cress v1.10 decode UserAccess meanings * 01/29/03 Andy Cress v1.11 added MV OpenIPMI support * 07/31/03 Andy Cress v1.12 added -F to try force it * 09/10/03 Andy Cress v1.13 isolate ser_ch, add -n option to specify chan#, * abort if no serial channels * 05/05/04 Andy Cress v1.14 call ipmi_close before exit, added WIN32 * 06/29/04 Andy Cress v1.15 added fSetPsw even if not fSetUser3 * 11/01/04 Andy Cress v1.16 add -N / -R for remote nodes * 11/23/04 Andy Cress v1.17 recompile with ipmignu.c changes * 01/31/05 Andy Cress v1.18 allow IPMI 2.0 versions * 03/18/05 Andy Cress v1.19 fix for -n, show the ser_ch it is using. * 05/19/05 Andy Cress v1.20 show 4 users if IPMI20 * 06/13/05 Andy Cress v1.21 show multiple alert destinations * 08/10/05 Andy Cress v1.22 truncate extra string chars * 05/02/06 Andy Cress v1.23 add -B option for baud rate * 09/12/06 Andy Cress v1.26 use authmask to set Serial Param(2) * 09/29/06 Andy Cress v1.27 add -q for user number, add -f for Flow Control, * adjust Mode if known, clear SerialParam(3) if -d, * added ShowAccess if -r. */ /*M* Copyright (c) 2002-2006, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #ifdef WIN32 #include #include #include #include #include "getopt.h" #elif defined(DOS) #include #include #include #include #include "getopt.h" #else #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #include #endif #include "ipmicmd.h" #define SELprintf printf #define SER_CH 4 #define LAN_CH 1 #define MAXCHAN 16 #define PSW_LEN 16 /*see also PSW_MAX=20 in ipmicmd.h*/ /* Note: The optional IPMI 2.0 20-byte passwords are not supported here, * due to back-compatibility issues. */ /* serial channel access values */ #define ALWAYS_AUTH 0x22 #define ALWAYS_NOAUTH 0x2A #define SHARED_AUTH 0x23 #define SHARED_NOAUTH 0x2B typedef struct { unsigned short record_id; uchar record_type; int timestamp; unsigned short generator_id; uchar evm_rev; //event message revision uchar sensor_type; uchar sensor_number; uchar event_trigger; uchar event_data1; uchar event_data2; uchar event_data3; } SEL_RECORD; typedef struct { /* See IPMI Table 19-3 */ uchar data[30]; } SER_RECORD; /* * Global variables */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil serial"; #else static char * progver = "3.08"; static char * progname = "iserial"; #endif static int vend_id = 0; static int prod_id = 0; static char fdebug = 0; static char fpicmg = 0; static char freadonly = 0; static char fdoanyway = 0; static char fSetUser3 = 0; /* =1 set User3->admin and User1->user access*/ static char fSetPsw = 0; /* =1 set Password to user parameter */ static char fSetTMode = 0; /* =1 configure for TMode */ static char fBasebdOn = 0; /* =1 only do MUX switch BMC -> Baseboard */ static char fTModeOn = 0; /* =1 only do MUX switch Baseboard -> BMC */ static char fBMode = 0; /* =1 do Basic mode config stuff */ static char fShared = 0; /* =1 shared Basic mode & Remote console */ static char fDisable = 0; /* =1 to disable serial port IPMI */ static char fKnownMode = 0; /* =0 if unknown, =1 if TMode, =2 if BMode */ static char fgetlan = 0; static char fnotshared = 0; /* =1 if IPMI serial shared with OS/BIOS*/ static char fconsoleonly = 0; /* =1 BIOS console only, no serial mux */ static char fIPMI20 = 0; /* =1 IPMI v2.0 or greater */ static char fcanonical = 0; /* =1 IPMI v2.0 or greater */ static char fuser1admin = 0; /* =1 if default user 1 should be admin */ static char bdelim = ':'; static char bFlow = 1; /* Flow Control: 1=RTS/CTS, 0=none */ static char inactivity = 0; /* Inactivity Timeout (30 sec increments) */ static char newbaud = 0x07; /* default = 19.2K */ static uchar bootflags = 16; /* if < 16 use these bootflags */ static uchar ser_ch = SER_CH; static uchar lan_ch = LAN_CH; /* usu LAN 1 = 7 */ static uchar ser_user = 0x03; /* if -u specified, configure user 3 */ static uchar ser_access = 0x04; /* user priv 4=Admin, 3=Operator, 2=User */ static uchar usernum = 0; /* set non-zero to specify user number */ static uchar useridx = 0; /* user number index for get/show*/ static uchar max_users = 5; /* set in GetUserAccess() if unum==1 */ static uchar enabled_users = 0; /* set in GetUserAccess() if unum==1 */ static uchar show_users = 5; /* set in GetUserAccess() if unum==1 */ static char rguser[16] = "root"; /* default, settable via user param */ static char rgpasswd[PSW_LEN+1] = "password"; /* default, set via user param */ #define NLAN 27 static struct { int cmd; int sz; char desc[28]; } lanparams[NLAN] = { /* see IPMI Table 19-4 */ /* 0 */ { 0, 1, "Set in progress"}, /* 1 */ { 1, 1, "Auth type support"}, /* 2 */ { 2, 5, "Auth type enables"}, /* 3 */ { 3, 4, "IP address"}, /* 4 */ { 4, 1, "IP addr src"}, /* (DHCP/Static) */ /* 5 */ { 5, 6, "MAC addr"}, /* 6 */ { 6, 4, "Subnet mask"}, /* 7 */ { 7, 3, "IPv4 header"}, /* 8 */ { 8, 2, "Prim RMCP port "}, /* 9 */ { 9, 2, "Sec RMCP port "}, /* 10 */ {10, 1, "BMC grat ARP "}, /* 11 */ {11, 1, "grat ARP interval"}, /* 12 */ {12, 4, "Def gateway IP"}, /* 13 */ {13, 6, "Def gateway MAC"}, /* 14 */ {14, 4, "Sec gateway IP"}, /* 15 */ {15, 6, "Sec gateway MAC"}, /* 16 */ {16,18, "Community string"}, /* 17 */ {17, 1, "Num dest"}, /* 18 */ {18, 5, "Dest type"}, /* 19 */ {19, 13, "Dest address"}, /* 20 */ {96, 28, "OEM Alert String"}, /* 21 */ {97, 1, "Alert Retry Algorithm"}, /* 22 */ {98, 3, "UTC Offset"}, /* 23 */ {192, 4, "DHCP Server IP"}, /* 24 */ {193, 6, "DHCP MAC Address"}, /* 25 */ {194, 1, "DHCP Enable"}, /* 26 */ {201, 2, "Channel Access Mode (Lan)"} }; /* Special temp ids for other serial commands that aren't serial params */ #define CMDID_CA1 201 /*this is the first temp id*/ #define CMDID_UA1 202 #define CMDID_UA2 203 #define CMDID_UA3 204 #define CMDID_UA4 205 #define CMDID_MUX 210 #define CMDID_BOOT 211 #define NSER 28 /* was 32 */ static struct { int cmd; int sz; char desc[28]; } serparams[NSER] = { /* see IPMI Table 20-4 */ /* 0 */ { 0, 1, "Set in progress"}, /* 1 */ { 1, 1, "Auth type support"}, /* 2 */ { 2, 5, "Auth type enables"}, /* 3 */ { 3, 1, "Connection Mode"}, /* 4 */ { 4, 1, "Sess Inactiv Timeout"}, /* 5 */ { 5, 5, "Channel Callback"}, /* 6 */ { 6, 1, "Session Termination"}, /* 7 */ { 7, 2, "IPMI Msg Comm"}, /* 8 */ { 8, 2, "Mux Switch"}, /* 9 */ { 9, 2, "Modem Ring Time"}, /* 10 */ {10,17, "Modem Init String"}, /* 11 */ {11, 5, "Modem Escape Seq"}, /* 12 */ {12, 8, "Modem Hangup Seq"}, /* 13 */ {13, 8, "Modem Dial Command"}, /* 14 */ {14, 1, "Page Blackout Interval"}, /* 15 */ {15,18, "Community String"}, /* 16 */ {16, 1, "Num of Alert Dest"}, /* 17 */ {17, 5, "Destination Info"}, /* 18 */ {18, 1, "Call Retry Interval"}, /* 19 */ {19, 3, "Destination Comm Settings"}, /* 20 */ {20, 1, "Number Dial Strings"}, /* 21 */ {21,33, "Dest Dial String"}, /* 22 */ {22, 1, "Number Dest IP Addrs"}, /* 23 */ {23, 5, "Dest IP Address"}, /* 24 */ {29, 2, "Terminal Mode Config"}, /* 25 */ {CMDID_MUX, 1,"Get Serial MUX Status"}, /* 26 */ {CMDID_BOOT, 3,"Get Boot Options(3)"}, /* 27 */ {CMDID_CA1, 2,"Channel Access Mode (Ser)"} /* 28 *% {CMDID_UA1, 4,""}, //"Get User Access (1)", */ /* 29 *% {CMDID_UA2, 4,""}, //"Get User Access (2)", */ /* 30 *% {CMDID_UA3, 4,""}, //"Get User Access (3)", */ /* 31 *% {CMDID_UA4, 4,""} //"Get User Access (4)" */ }; static int GetDeviceID(SER_RECORD *pSerRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; if (pSerRecord == NULL) return(-1); status = ipmi_cmd(GET_DEVICE_ID, inputData, 0, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("GetDeviceID: completion code=%x\n", completionCode); } else { // dont copy first byte (Parameter revision, usu 0x11) memcpy(pSerRecord,&responseData[0],responseLength); set_mfgid(&responseData[0],responseLength); return(0); // successful, done } } /* endif */ /* if get here, error */ return(-1); } /*end GetDeviceID() */ static int GetChanAcc(uchar chan, uchar parm, SER_RECORD *pSerRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; if (pSerRecord == NULL) return(-1); responseLength = 3; inputData[0] = chan; inputData[1] = parm; /* 0x80 = active, 0x40 = non-volatile */ status = ipmi_cmd(GET_CHANNEL_ACC, inputData, 2, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("GetChanAcc: completion code=%x\n", completionCode); } else { memcpy(pSerRecord,&responseData[0],responseLength); return(0); // successful, done } } /* endif */ /* if get here, error */ return(-1); } /*GetChanAcc()*/ static int SetChanAcc(uchar chan, uchar parm, uchar val) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; int status; uchar inputData[24]; uchar completionCode; /* parm: 0x80 = active, 0x40 = set non-vol*/ responseLength = 1; inputData[0] = chan; /* channel */ inputData[1] = (parm & 0xc0) | (val & 0x3F); if (chan == lan_ch) inputData[2] = 0x04; /* LAN, don't set priv level*/ else inputData[2] = (parm & 0xc0) | 0x04; /* set Admin priv level */ /* serial defaults to 0x02 = User priv level */ status = ipmi_cmd(SET_CHANNEL_ACC, inputData, 3, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("SetChanAcc: completion code=%x\n", completionCode); } else { return(0); // successful, done } } /* endif */ /* if get here, error */ return(-1); } /*SetChanAcc()*/ static int GetSerEntry(uchar subfunc, uchar bset, SER_RECORD *pSerRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; uchar chan; if (pSerRecord == NULL) { if (fdebug) printf("GetSerEntry: error, output buffer is NULL\n"); return (-1); } chan = ser_ch; /* sample: 0=IPMB, 1=EMP/serial, 6=LAN2, 7=LAN1 */ inputData[0] = chan; // flags, channel 3:0 (1=EMP) inputData[1] = subfunc; // Param selector inputData[2] = bset; // Set selector inputData[3] = 0; // Block selector if (subfunc == 10) { /*modem init string*/ inputData[3] = 1; /*blocks start with 1*/ } else if (subfunc == 21) { inputData[3] = 1; /*blocks start with 1*/ } status = ipmi_cmd(GET_SER_CONFIG, inputData, 4, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (completionCode == 0x80) SELprintf("GetSerEntry(%d): Parameter not supported\n", subfunc); else SELprintf("GetSerEntry(%d): completion code=%x\n", subfunc,completionCode); // responseData[0]); } else { // dont copy first byte (Parameter revision, usu 0x11) memcpy(pSerRecord,&responseData[1],responseLength-1); pSerRecord->data[responseLength-1] = 0; //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) printf("GetSerEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); return -1; } static int SetSerEntry(uchar subfunc, SER_RECORD *pSerRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pSerRecord == NULL) { if (fdebug) printf("SetSerEntry(%d): error, input buffer is NULL\n", subfunc); return (-1); } inputData[0] = ser_ch; // flags, channel 3:0 (EMP) inputData[1] = subfunc; // Param selector memcpy(&inputData[2],pSerRecord,reqlen); status = ipmi_cmd(SET_SER_CONFIG, inputData, (uchar)(reqlen+2), responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (completionCode == 0x80) SELprintf("SetSerEntry(%d): Parameter not supported\n", subfunc); else SELprintf("SetSerEntry(%d): completion code=%x\n", subfunc, completionCode); } else { //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) printf("SetSerEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); return -1; } /* end SetSerEntry() */ #ifdef NEEDED int SerialIsOptional(uchar bparam) { /* These Serial Parameters are for optional Modem/Callback functions. */ uchar optvals[9] = { 5, 9, 10, 11, 12, 13, 14, 20, 21 }; int rv = 0; int i; for (i = 0; i < sizeof(optvals); i++) { if (optvals[i] == bparam) { rv = 1; break; } } return(rv); } #endif int SetMiscEntry(ushort icmd, SER_RECORD *pSerRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pSerRecord == NULL) { if (fdebug) printf("SetMiscEntry: error, input buffer is NULL\n"); return (-1); } memcpy(&inputData[0],pSerRecord,reqlen); status = ipmi_cmd(icmd, inputData, (uchar)reqlen, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { printf("SetMiscEntry(%04x): completion code=%x\n", icmd,completionCode); } else { //successful if (responseLength > 1) { // skip first byte (Parameter revision, usu 0x11) memcpy(pSerRecord,&responseData[1],responseLength-1); } return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) printf("SetMiscEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); return -1; } /* end SetMiscEntry() */ int GetMiscEntry(ushort icmd, SER_RECORD *pSerRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pSerRecord == NULL) { if (fdebug) printf("GetMiscEntry: error, output buffer is NULL\n"); return (-1); } memcpy(&inputData[0],pSerRecord,reqlen); status = ipmi_cmd(icmd, inputData, (uchar)reqlen, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { if (completionCode == 0x80) printf("GetMiscEntry(%d): Parameter not supported\n", icmd); else printf("GetMiscEntry(%d): completion code=%x\n", icmd,completionCode); } else { //successful if (responseLength > 1) memcpy(pSerRecord,&responseData[0],responseLength); return(0); } } if (fdebug) printf("GetMiscEntry(%d): ipmi_cmd status=%d, completion code=%x\n", icmd,status,completionCode); return -1; } /* end GetMiscEntry() */ void ShowUserAccess(uchar unum, uchar c0, uchar c1, uchar c2, uchar c, char *name) { /* channel is always ser_ch */ if (unum == 1 && !fcanonical) { printf("Users: showing %d of max %d users (%d enabled)\n", show_users,max_users,enabled_users); } printf("Get User Access(%d)%c %02x %02x %02x %02x%c ", unum,bdelim,c0,c1,c2,c,bdelim); if (c & 0x10) printf("IPMI, "); c = (c & 0x0f); switch(c) { case 1: printf("Callback"); break; case 2: printf("User "); break; case 3: printf("Operator"); break; case 4: printf("Admin"); break; case 5: printf("OEM "); break; case 0x0f: printf("No access"); break; default: printf("Reserved"); } printf(" (%s)\n",name); } int GetUserAccess(uchar unum, uchar *rdata, char *name) { int rv; /* rdata must be at least 2 bytes, and name must be at least 16 bytes */ rdata[0] = ser_ch; /* channel# */ rdata[1] = unum; /* user# */ rv = GetMiscEntry(GET_USER_ACCESS, (SER_RECORD *)rdata, 2); if (rv == 0 && name != NULL) { name[0] = unum; /* user# */ rv = GetMiscEntry(GET_USER_NAME, (SER_RECORD *)name, 1); if (rv != 0) name[0] = 0; rv = 0; } if (unum == 1) { /*get max_users and enabled_users*/ max_users = rdata[0] & 0x3f; enabled_users = rdata[1] & 0x3f; // if (enabled_users > show_users) show_users = enabled_users; if (show_users > max_users) show_users = max_users; } if (rv == 0) ShowUserAccess(unum,rdata[0],rdata[1],rdata[2],rdata[3],name); else printf("Get User Access(%d): error %d\n",unum,rv); return(rv); } static int GetLanEntry(uchar subfunc, SER_RECORD *pSerRecord) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; uchar chan; uchar bset; if (pSerRecord == NULL) { if (fdebug) printf("GetLanEntry: error, output buffer is NULL\n"); return (-1); } chan = lan_ch; if (subfunc == 18 || subfunc == 19) bset = 1; /* dest id = 1 */ else bset = 0; inputData[0] = chan; // flags, channel 3:0 (LAN 1) inputData[1] = subfunc; // Param selector (3 = ip addr) inputData[2] = bset; // Set selector inputData[3] = 0; // Block selector status = ipmi_cmd(GET_LAN_CONFIG, inputData, 4, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("GetLanEntry: completion code=%x\n", completionCode); // responseData[0]); } else { // dont copy first byte (Parameter revision, usu 0x11) memcpy(pSerRecord,&responseData[1],responseLength-1); pSerRecord->data[responseLength-1] = 0; //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) printf("GetLanEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); return -1; } /* end GetLanEntry() */ #ifdef NOT static int SetLanEntry(uchar subfunc, SER_RECORD *pSerRecord, int reqlen) { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar inputData[24]; int status; uchar completionCode; if (pSerRecord == NULL) { if (fdebug) printf("SetLanEntry: error, input buffer is NULL\n"); return (-1); } inputData[0] = lan_ch; // flags, channel 3:0 (LAN 1) inputData[1] = subfunc; // Param selector (3 = ip addr) memcpy(&inputData[2],pSerRecord,reqlen); status = ipmi_cmd(SET_LAN_CONFIG,inputData,(uchar)(reqlen+2),responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if( completionCode ) { SELprintf("SetLanEntry: completion code=%x\n", completionCode); // responseData[0]); } else { //successful, done return(0); } } // we are here because completionCode is not COMPLETION_CODE_OK if (fdebug) printf("SetLanEntry: ipmi_cmd status=%d, completion code=%d\n", status,completionCode); return -1; } /* end SetLanEntry() */ #endif static int ReadSELinfo() { uchar responseData[MAX_BUFFER_SIZE]; int responseLength = MAX_BUFFER_SIZE; uchar completionCode; uchar inputData[6]; int status; status = ipmi_cmd(GET_SEL_INFO, inputData, 0, responseData, &responseLength, &completionCode, fdebug); if (status == ACCESS_OK) { if (fdebug) SELprintf("Code %d SEL Ver %d Support %d\n", completionCode, responseData[0], responseData[13] ); //successful, done return(0); } else return(1); } /*end ReadSELinfo()*/ #define NBAUDS 10 static struct { unsigned char val; char str[8]; } mapbaud[NBAUDS] = { { 6, "9600" }, { 6, "9.6K" }, { 7, "19.2K" }, { 7, "19200" }, { 8, "38.4K" }, { 8, "38400" }, { 9, "57.6K" }, { 9, "57600" }, { 10, "115.2K" }, { 10, "115200" } }; static unsigned char Str2Baud(char * str) { unsigned char baud = 0; int i, n, len; len = (int)strlen(str); for (i = 0; i < len; i++) /*toupper*/ if (str[i] >= 'a' && str[i] <= 'z') str[i] &= 0x5F; for (i = 0; i < NBAUDS; i++) { n = (int)strlen(mapbaud[i].str); if (strncmp(str,mapbaud[i].str,n) == 0) { baud = mapbaud[i].val; break; } } if (i == NBAUDS || baud == 0) { printf("Invalid -B parameter value (%s), using 19.2K.\n",str); i = 1; /* default is 19.2K */ baud = mapbaud[i].val; /* =7 */ } if (fdebug) printf("new baud = %02x (%s)\n",baud,mapbaud[i].str); return(baud); } static char *Baud2Str(unsigned char bin) { char *baudstr; unsigned char b; b = bin & 0x0f; switch(b) { case 6: baudstr = "9600 "; break; case 7: baudstr = "19.2k"; break; case 8: baudstr = "38.4k"; break; case 9: baudstr = "57.6k"; break; case 10: baudstr = "115.2k"; break; default: baudstr = "nobaud"; } return(baudstr); } void ShowChanAccess(uchar chan, char *tag, uchar access, uchar access2) { printf("Channel Access Mode(%d=%s)%c %02x %02x %c ", chan,tag,bdelim,access,access2,bdelim); switch (access & 0x03) { case 0: printf("Access = Disabled, "); break; case 1: printf("Access = Pre-Boot, "); break; case 2: printf("Access = Always Avail, "); break; case 3: printf("Access = Shared, "); break; default: break; } if (access & 0x20) printf("PEF Alerts Disabled\n"); /*0*/ else printf("PEF Alerts Enabled\n"); /*1*/ } static int valid_priv(int c) { int rv; switch(c) { case 1: case 2: case 3: case 4: case 5: case 0x0f: rv = 1; break; default: rv = 0; break; } return(rv); } #ifdef METACOMMAND int i_serial(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int ret; SER_RECORD SerRecord; char uname[16]; int i, idx; int c; int rlen; uchar iData[2]; uchar rData[10]; uchar cc; int j; uchar bset; uchar nalert, ndial, ndest; uchar ialert, idial, idest; uchar authmask = 0; char mystr[80]; // progname = argv[0]; printf("%s ver %s \n",progname,progver); if (argc <= 1) freadonly = 1; /* default to readonly if no options */ while ( (c = getopt( argc, argv,"abcdef:gi:lm:n:p:#:q:rstu:v:xB:F:T:V:J:EYP:N:R:U:X:Z:?")) != EOF ) switch(c) { case 'x': fdebug = 1; break; case 'r': freadonly = 1; break; case 'l': fgetlan = 1; break; case 'd': fDisable = 1; freadonly = 0; break; case 'a': fcanonical = 1; /* canonical mode with delimeter */ bdelim = BDELIM; break; case 'c': /* configure Terminal Mode & Console */ case 't': fSetTMode = 1; /* set Terminal Mode & Console */ freadonly = 0; break; case 'e': fSetTMode = 1; /* set Terminal Mode not shared*/ fnotshared = 1; /* no BIOS console, not shared */ freadonly = 0; break; case 'g': fSetTMode = 1; /* set Terminal Mode, but BCR only */ fconsoleonly = 1; /* BIOS console only, disable mux */ freadonly = 0; break; case 'b': fBMode = 1; /* set Basic Mode only */ freadonly = 0; break; case 's': fBMode = 1; /* set Basic Mode & Console */ fShared = 1; freadonly = 0; break; case 'f': i = atoi(optarg); /*flow control*/ if (i >= 0 && i < 2) bFlow = (uchar)i; break; case 'i': i = atoi(optarg); /*inactivity timeout*/ if (i > 0 && i < 30) inactivity = 1; else inactivity = i / 30; break; case 'B': newbaud = Str2Baud(optarg); break; case 'm': /* set MUX to specific value */ i = atoi(optarg); if (fdebug) printf("MUX Mode %d\n",i); switch(i) { case 0: fBasebdOn = 1; break; case 1: fTModeOn = 1; break; default: fBasebdOn = 1; } break; case 'u': strncpy(rguser,optarg,16); rguser[15] = 0; /* Use specified user #3, and set user 1 to not admin */ fSetUser3 = 1; break; case 'p': strncpy(rgpasswd,optarg,PSW_LEN); rgpasswd[PSW_LEN] = 0; fSetPsw = 1; /* Hide password from 'ps' */ memset(optarg, ' ', strlen(optarg)); break; case 'q': case '#': usernum = atob(optarg); if (usernum > 15) usernum = 0; /*MAX_IPMI_USERS = 4*/ break; case 'n': ser_ch = atob(optarg); if (ser_ch > MAXCHAN) ser_ch = SER_CH; /*default=1*/ break; case 'v': /*user privilege level access */ i = atoi(optarg); if (valid_priv(i)) ser_access = i & 0x0f; else printf("Invalid privilege -v %d, using Admin\n",i); break; case 'X': bootflags = atob(optarg); fdoanyway = 1; /* undocumented, for test only */ break; case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-bcdefglmnq#rstxB -u user -p passwd -NUPREFTVY]\n",progname); printf(" -b configure serial port for Basic Mode\n"); printf(" -c Configure serial port for shared Terminal Mode & Console\n"); printf(" -d Disable serial port for IPMI use.\n"); printf(" -e configure serial port for Terminal Mode only\n"); printf(" -f0 Flow control: 0=none, 1=RTS/CTS(default)\n"); printf(" -g configure serial port for console only, with BMode CTS\n"); printf(" -s configure serial port for Shared Basic Mode & Remote Console\n"); printf(" -l show some LAN parameters also\n"); printf(" -m0 switch MUX to Normal baseboard operation\n"); printf(" -m1 switch MUX to BMC operation (BMode or TMode)\n"); printf(" -B bval set Baud to bval for serial port\n"); printf(" -n ser_chan serial channel Number (default=1)\n"); printf(" -p password set Password for EMP TMode login\n"); printf(" -u username set Username for EMP TMode login\n"); printf(" -q/-# User number of Username for EMP\n"); printf(" -r Read-only, view serial port parameters (default)\n"); printf(" -t Configure serial port for shared Terminal Mode & Console (same as -c)\n"); printf(" -v4 access priVilege: 4=Admin, 3=Operator, 2=User\n"); printf(" -x eXtra debug messages\n"); print_lan_opt_usage(0); ret = ERR_USAGE; goto do_exit; } if (is_remote() && !freadonly) parse_lan_options('V',"4",0); ret = GetDeviceID( &SerRecord); if (ret != 0) { goto do_exit; } else { uchar ipmi_maj, ipmi_min; uchar *devrec; devrec = &SerRecord.data[0]; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; vend_id = devrec[6] + (devrec[7] << 8) + (int)(devrec[8] << 16); prod_id = devrec[9] + (devrec[10] << 8); show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); if ((ipmi_maj == 0) || (ipmi_maj == 1 && ipmi_min < 5)) { /* IPMI 0.9 and 1.0 dont support this. */ printf("This system does not support EMP Terminal Mode.\n"); if (!fdoanyway) { ret = LAN_ERR_NOTSUPPORT; goto do_exit; } } if (ipmi_maj >= 2) fIPMI20 = 1; /* Determine if Basic or Terminal Mode is supported by product id */ if (vend_id == VENDOR_INTEL) { /*Intel*/ switch(prod_id) { case 0x4311: fKnownMode = 1; break; /*NSI2U, BMode*/ case 0x000C: fKnownMode = 1; break; /*TSRLT2, BMode*/ case 0x0100: fKnownMode = 1; break; /*Tiger2, BMode*/ case 0x001B: fKnownMode = 2; break; /*TIGPR2U, TMode*/ case 0x0022: fKnownMode = 2; break; /*TIGI2U, TMode*/ case 0x0026: fKnownMode = 2; break; /*Alcolu, TMode*/ case 0x0028: fKnownMode = 2; break; /*Alcolu, TMode*/ case 0x0811: fKnownMode = 2; break; /*TIGW1U, TMode*/ case 0x003E: fKnownMode = 2; /*NSN2U/CG2100, TMode*/ set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/ break; default: break; } } else if (vend_id == VENDOR_NSC) { /*NSC*/ if (prod_id == 0x4311) fKnownMode = 1; /*TIGPT1U, No EMP*/ } /* else * other vend_id, leave defaults */ if (fKnownMode > 0) { /* Adjust if we know that the user set the wrong one. */ if (fKnownMode == 1 && fSetTMode == 1) { printf("Adjusting from Terminal Mode to Basic Mode\n"); fSetTMode = 0; fBMode = 1; fShared = 1; } else if (fKnownMode == 2 && fBMode == 1) { printf("Adjusting from Basic Mode to Terminal Mode\n"); fSetTMode = 1; fBMode = 0; } } } /*end-else have device_id */ ret = ipmi_getpicmg( &SerRecord.data[0], 16, fdebug); if (ret == 0) fpicmg = 1; ret = ReadSELinfo(); if (ret == 0) { /* talking to BMC ok */ /* find the first Serial channel via Channel Info */ for (j = 1; j < MAXCHAN; j++) { iData[0] = (uchar)j; /*channel #*/ rlen = sizeof(rData); ret = ipmi_cmd(GET_CHANNEL_INFO, iData, 1, rData, &rlen, &cc, 0); if (ret != 0) break; if (rData[1] == 4) { /* 4 = LAN type*/ if (fdebug) printf("chan[%d] = lan\n",j); lan_ch = (uchar)j; } else if (rData[1] == 5) { /* 5 = Serial type*/ if (fdebug) printf("chan[%d] = serial\n",j); if (ser_ch != SER_CH) { /* user set it */ if (j == ser_ch) break; } else { /* find the first serial channel */ ser_ch = (uchar)j; break; } } else /* 7 = SMBus, 12 = System Interface */ if (fdebug) printf("chan[%d] = %d\n",j,rData[1]); } if (fdebug) printf("ser_ch = %d\n",ser_ch); if (j >= MAXCHAN) { printf("No serial channel support found (channel %d)\n",ser_ch); ret = LAN_ERR_NOTSUPPORT; goto do_exit; } if (fdebug && fSetUser3 == 1) printf("user %d/%d: username=%s, password=%p\n", usernum,ser_user, rguser,rgpasswd); if (fgetlan && !fcanonical) { int ival; printf("%s, GetLanEntry for channel %d ...\n",progname,lan_ch); for (idx = 0; idx < NLAN; idx++) { ival = lanparams[idx].cmd; if (ival == 8 || ival == 9) continue; /* not implemented */ if (ival >= 96 && ival <= 98) continue; /* not implemented */ if (ival == CMDID_CA1) { ret = GetChanAcc(lan_ch, 0x40, &SerRecord); } else { ret = GetLanEntry((uchar)ival, &SerRecord); } if (ret == 0) { // Show the LAN record uchar * pc; int sz; pc = (uchar *)&SerRecord; sz = lanparams[idx].sz; printf("Lan Param(%d) %s%c ",ival,lanparams[idx].desc,bdelim); if (ival == 16) { printf("%s \n",pc); /* string */ } else { /* print results for others */ for (i = 0; i < sz; i++) { if (ival == 3 || ival == 6 || ival == 12 || ival == 14 || ival == 192) printf("%d ",pc[i]); /* IP addresses in dec */ else printf("%02x ",pc[i]); /* show in hex */ } /* if (ival == 4) { pc[0]: 01 = static, 02 = DHCP } */ printf("\n"); } } else /* ret != 0 */ printf("GetLanEntry(%d), ret = %d\n",ival,ret); } /*end for*/ } printf("%s, GetSerEntry for channel %d ...\n",progname,ser_ch); nalert = 1; ialert = 1; ndial = 1; idial = 1; ndest = 1; idest = 1; for (idx = 0; idx < NSER; idx++) { int ival; ival = serparams[idx].cmd; /* * ival is either the Serial Param# or a temp id. * Do the appropriate Get command, based on ival. */ if (ival == CMDID_CA1) { ret = GetChanAcc(ser_ch, 0x40, &SerRecord); } else if (ival == CMDID_UA1) { useridx = 1; ret = GetUserAccess(useridx,(uchar *)&SerRecord,uname); } else if (ival == CMDID_UA2) { useridx = 2; ret = GetUserAccess(useridx,(uchar *)&SerRecord,uname); } else if (ival == CMDID_UA3) { useridx = 3; ret = GetUserAccess(useridx,(uchar *)&SerRecord,uname); } else if (ival == CMDID_UA4) { useridx = 4; if (fIPMI20 == 0) continue; /* IPMI 1.5 only has 3 users */ ret = GetUserAccess(useridx,(uchar *)&SerRecord,uname); } else if (ival == CMDID_MUX) { SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x00; /* just get MUX status */ ret = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); } else if (ival == CMDID_BOOT) { SerRecord.data[0] = 0x03; /* Boot Param 3 */ SerRecord.data[1] = 0x00; /* Set Selector */ SerRecord.data[2] = 0x00; /* %%%% */ ret = GetMiscEntry(GET_BOOT_OPTIONS, &SerRecord, 3); } else { if (fcanonical) { switch(ival) { /*only show certain parameters*/ case 3: case 4: case 6: case 7: case 8: case 29: break; default: continue; break; } } if (vend_id == VENDOR_SUPERMICROX && ival == 8) continue; if (vend_id == VENDOR_SUPERMICRO && ival == 8) continue; if (ival == 17 || ival == 19) bset = ialert; else if (ival == 21) bset = idial; else if (ival == 23) bset = idest; else bset = 0; /*default*/ ret = GetSerEntry((uchar)ival, bset, &SerRecord); } /* * Now the Get command is done, check the status, and * show the raw output. */ if (ret == 0) { // Show the SER record uchar * pc; int sz; pc = (uchar *)&SerRecord; sz = serparams[idx].sz; /* save some input data for later reuse */ if (ival == 16) nalert = pc[0]; else if (ival == 20) ndial = pc[0]; else if (ival == 22) ndest = pc[0]; if (ival == CMDID_CA1) ; else if (ival > CMDID_CA1) printf("%s%c ",serparams[idx].desc,bdelim); else printf("Serial Param(%d) %s%c ",ival,serparams[idx].desc,bdelim); if (ival == 1) { /* Auth Type support*/ authmask = pc[0]; /* auth type support mask */ mystr[0] = 0; if (authmask & 0x01) strcat(mystr,"None "); if (authmask & 0x02) strcat(mystr,"MD2 "); if (authmask & 0x04) strcat(mystr,"MD5 "); if (authmask & 0x10) strcat(mystr,"Pswd "); if (authmask & 0x20) strcat(mystr,"OEM "); printf("%02x %c %s\n",authmask,bdelim,mystr); } else if (ival == 10) { /* modem init string */ pc[sz] = 0; printf("%02x %s\n",pc[0],&pc[1]); } else if (ival == 21) { /* modem dial string */ pc[sz] = 0; printf("%02x %02x %s\n",pc[0],pc[1],&pc[2]); } else if ((ival >= 11 && ival <= 13) || ival == 15) { /* strings */ pc[sz] = 0; printf("%s\n",pc); } else if (ival == 23) { /* Dest IP Address */ printf("%02x %d %d %d %d\n", pc[0], /*dest index*/ pc[1],pc[2],pc[3],pc[4]); } else if (ival == CMDID_CA1) { /* Channel Access */ ShowChanAccess(ser_ch,"Ser",pc[0],pc[1]); } else if (ival == CMDID_UA1 || ival == CMDID_UA2 || ival == CMDID_UA3 || ival == CMDID_UA4) { // ShowUserAccess(useridx,pc[0],pc[1],pc[2],pc[3],uname); } /*endif UA*/ else /* hex data */ { for (i = 0; i < sz; i++) { printf("%02x ",pc[i]); /* show in hex */ } /* * Raw hex data display is complete, now do post-processing. * Interpret some hex data. */ if (ival == 4) { /* Session Inactivity Timeout */ c = pc[0]; if (c == 0) strcpy(mystr,"infinite"); else sprintf(mystr,"%d sec",(c * 30)); printf(" %c %s",bdelim,mystr); } else if (ival == 7) { /*IPMI Msg Comm*/ uchar v; char *flow; char *dtr; char *baud; v = pc[0] & 0xc0; switch(v) { case 0x40: flow = "RTS/CTS"; break; case 0x80: flow = "XON/XOFF"; break; case 0x00: default: flow = "no_flow"; } if ((pc[0] & 0x20) == 0) dtr="no_DTR"; else dtr = "DTR"; baud = Baud2Str(pc[1]); printf("%c %s, %s, %s",bdelim,flow,dtr,baud); } else if (ival == 19) { /*Dest Comm Settings*/ uchar v; char *flow; char *baud; uchar chsz,parity,stopb; v = pc[1] & 0xc0; switch(v) { case 0x40: flow = "RTS/CTS"; break; case 0x80: flow = "XON/XOFF"; break; case 0x00: default: flow = "no_flow"; } if ((pc[1] & 0x10) == 0) stopb = 1; else stopb = 2; if ((pc[1] & 0x08) == 0) chsz = 8; else chsz = 7; v = pc[1] & 0x07; switch(v) { case 1: parity = 'O'; break; case 2: parity = 'E'; break; case 0: default: parity = 'N'; } baud = Baud2Str(pc[2]); printf("%c %s, %d%c%d, %s",bdelim,flow,chsz,parity,stopb,baud); } #ifdef TEST /* This MUX reading is volatile and may not be accurate */ else if (ival == CMDID_MUX) { if ((pc[0] & 0x01) == 1) printf("%c BMC",bdelim); else printf("%c System",bdelim); /*BIOS*/ } #endif printf("\n"); } /*end else hex*/ } /*endif show*/ if (ival == 17 || ival == 19) { /* alert params */ if (ialert < nalert) { ialert++; idx--; /* repeat this param*/ } else ialert = 1; } if (ival == 21) { /* dial param */ if (idial < ndial) { idial++; idx--; /* repeat this param*/ } else idial = 1; } if (ival == 23) { /* dest param */ if (idest < ndest) { idest++; idx--; /* repeat this param*/ } else idest = 1; } } /*end for(idx) serial params*/ for (i = 1; i <= show_users; i++) ret = GetUserAccess((uchar)i,(uchar *)&SerRecord,uname); if (!freadonly) { /* set serial channel parameters */ uchar access; if (fBasebdOn) { /* -m0 */ SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x03; /* force switch to Baseboard */ ret = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); printf("SetSerialMux(System), ret = %d, value = %02x\n", ret,SerRecord.data[0]); } else if (fTModeOn) { /* -m1 */ SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x04; /* force switch to BMC for TMode */ ret = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); printf("SetSerialMux(BMC), ret = %d, value = %02x\n", ret,SerRecord.data[0]); } else if (fDisable) { /* -d */ /* * DISABLE SERIAL CHANNEL ACCESS */ if (vend_id == VENDOR_INTEL && fuser1admin) { /* First, make sure null user (1) has admin privileges again */ SerRecord.data[0] = 0x90 | ser_ch; /*0x91*/ SerRecord.data[1] = 0x01; /*user 1*/ SerRecord.data[2] = ser_access; /* usu 0x04 admin access*/ SerRecord.data[3] = 0x00; ret = SetMiscEntry(SET_USER_ACCESS, &SerRecord, 4); printf("SetUserAccess(1/%02x), ret = %d\n",ser_access,ret); } if (usernum != 0) { /*disable usernum if specified*/ SerRecord.data[0] = 0x80 | ser_ch; /*0x81*/ SerRecord.data[1] = usernum; SerRecord.data[2] = 0x0F; /*No access*/ SerRecord.data[3] = 0x00; ret = SetMiscEntry(SET_USER_ACCESS, &SerRecord, 4); printf("SetUserAccess(%d/none), ret = %d\n",usernum,ret); } ret = SetChanAcc(ser_ch, 0x80, 0x20); /*vol access=disabled*/ if (fdebug) printf("SetChanAcc(ser/disable), ret = %d\n",ret); ret = SetChanAcc(ser_ch, 0x40, 0x20); /*nvol access=disabled*/ printf("SetChanAcc(ser/disable), ret = %d\n",ret); ret = GetChanAcc(ser_ch, 0x40, &SerRecord); access = SerRecord.data[0]; printf("GetChanAcc(ser/disable), ret = %d, new value = %02x\n", ret,access); if ((vend_id != VENDOR_SUPERMICROX) && (vend_id != VENDOR_SUPERMICRO)) { /* Also disable the Serial Parameter 3: Connection Mode */ SerRecord.data[0] = 0x00; /* Connection Mode = none */ ret = SetSerEntry(3, &SerRecord,1); printf("SetSerEntry(3/disable), ret = %d\n",ret); } } else if (fSetTMode || fBMode) { /* * ENABLE SERIAL CHANNEL ACCESS * Enable: configure everything for TMode and/or BMode * * Set Serial/EMP Channel Access * Use serial channel in shared mode * 0x20 means alerting=off, disabled (system only) * 0x22 means alerting=off, always avail * which would only show BMC messages, not OS messages * 0x23 means alerting=off, always avail + shared + user-auth on * 0x2A means alerting=off, always avail + user-auth off * 0x2B means alerting=off, always avail + shared + user-auth off * 0x0B means alerting=on, always avail + shared + user-auth off * SSU won't set 0x2B, but we need shared access mode. */ if (fconsoleonly) { access = ALWAYS_NOAUTH; /*0x2A*/ } else if (fnotshared) { /* serial IPMI, but no console (-e only) */ if (fSetTMode) access = ALWAYS_NOAUTH; /*0x2A*/ else access = ALWAYS_AUTH; /*0x22*/ } else { /* shared with BIOS console, normal */ if (fSetTMode) access = SHARED_NOAUTH; /*0x2B*/ else access = SHARED_AUTH; /*0x23*/ } ret = SetChanAcc(ser_ch, 0x80, access); if (fdebug) printf("SetChanAcc(ser/active), ret = %d\n",ret); ret = SetChanAcc(ser_ch, 0x40, access); printf("SetChanAcc(ser), ret = %d\n",ret); ret = GetChanAcc(ser_ch, 0x80, &SerRecord); if (fdebug) { access = SerRecord.data[0]; printf("GetChanAcc(ser/active), ret = %d, new value = %02x\n", ret,access); } ret = GetChanAcc(ser_ch, 0x40, &SerRecord); access = SerRecord.data[0]; printf("GetChanAcc(ser), ret = %d, new value = %02x\n", ret,access); ShowChanAccess(ser_ch,"ser",access,SerRecord.data[1]); /* Needed if (fSetTMode), otherwise extra. */ { /* auth types: pswd, MD5, MD2, none */ if (authmask == 0) authmask = 0x17; SerRecord.data[0] = (0x16 & authmask); /*Callback level*/ SerRecord.data[1] = (0x16 & authmask); /*User level */ SerRecord.data[2] = (0x16 & authmask); /*Operator level*/ SerRecord.data[3] = (0x16 & authmask); /*Admin level */ SerRecord.data[4] = 0x00; /*OEM level*/ ret = SetSerEntry(2, &SerRecord,5); printf("SetSerEntry(2), ret = %d\n",ret); } if (fconsoleonly) SerRecord.data[0] = 0x81; /*direct, Basic only */ else if (fBMode) SerRecord.data[0] = 0x83; /*direct; PPP & Basic */ else SerRecord.data[0] = 0x87; /*direct; TMode, PPP, Basic*/ if ((vend_id != VENDOR_SUPERMICROX) && (vend_id != VENDOR_SUPERMICRO)) { ret = SetSerEntry(3, &SerRecord,1); printf("SetSerEntry(3), ret = %d\n",ret); } /* * BMode inactivity timeout = 2 (* 30 sec = 60 sec) * TMode inactivity timeout = 0 (infinite) */ if (fBMode) SerRecord.data[0] = 0x02; else SerRecord.data[0] = inactivity; /*usu 0, infinite*/ ret = SetSerEntry(4, &SerRecord,1); printf("SetSerEntry(4), ret = %d\n",ret); if ((vend_id != VENDOR_SUPERMICROX) && (vend_id != VENDOR_SUPERMICRO)) { // SerRecord.data[0] = 0x02; /* enable inactivity, ignore DCD */ SerRecord.data[0] = 0x03; /* enable inactivity, enable DCD */ ret = SetSerEntry(6, &SerRecord,1); printf("SetSerEntry(6), ret = %d\n",ret); /* flow control: 60=RTS/CTS+DTR, 20=none+DTR */ SerRecord.data[0] = (bFlow << 6) | 0x20; SerRecord.data[1] = newbaud; /* baud default = 19.2K bps */ ret = SetSerEntry(7, &SerRecord,2); printf("SetSerEntry(7) baud %s, ret = %d\n",Baud2Str(newbaud),ret); if (fBMode) { SerRecord.data[0] = 0x1e; /* mux 2way control, GetChanAuth, PPP */ } else { /*TMode*/ // SerRecord.data[0] = 0x1e; /* mux 2way control,GetChanAuth,PPP */ SerRecord.data[0] = 0x16; /* mux 2way control, GetChanAuth,no PPP*/ /* 2way: ( and Q */ } if (fconsoleonly) SerRecord.data[1] = 0x09; /* enable serial port sharing, hb=not */ else if (fBMode && !fShared) /* Basic Mode and NOT shared */ SerRecord.data[1] = 0x0a; /* enable serial port sharing,heartbeat*/ else SerRecord.data[1] = 0x08; /* enable serial port sharing, hb=off */ ret = SetSerEntry(8, &SerRecord,2); printf("SetSerEntry(8), ret = %d\n",ret); } if (fSetUser3) { if (usernum == 0) usernum = ser_user; /* user 3 */ /* * Set up admin user for Serial User (usu User# 3) * Username: root * Password: password * * cmdtool 20 18 45 3 72 6F 6F 74 0 0 0 0 0 0 0 0 0 0 0 0 * cmdtool 20 18 47 3 2 70 61 73 73 77 6F 72 64 0 0 0 0 0 0 0 0 * cmdtool 20 18 47 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ SerRecord.data[0] = usernum; /* user 3 */ memset(&SerRecord.data[1],0,16); memcpy(&SerRecord.data[1],rguser,strlen(rguser)); ret = SetMiscEntry(SET_USER_NAME, &SerRecord, 17); printf("SetUserName(%d), ret = %d\n",usernum,ret); /* set password for user 3 */ SerRecord.data[0] = usernum; SerRecord.data[1] = 0x02; memset(&SerRecord.data[2],0,PSW_LEN); memcpy(&SerRecord.data[2],rgpasswd,strlen(rgpasswd)); ret = SetMiscEntry(SET_USER_PASSWORD, &SerRecord, 2+PSW_LEN); printf("SetUserPassword(%d,2), ret = %d\n",usernum,ret); /* enable user 3 */ SerRecord.data[0] = usernum; SerRecord.data[1] = 0x01; memset(&SerRecord.data[2],0,PSW_LEN); ret = SetMiscEntry(SET_USER_PASSWORD, &SerRecord, 2+PSW_LEN); printf("SetUserPassword(%d,1), ret = %d\n",usernum,ret); /* Testing User #3 password */ // cmdtool 20 18 47 3 3 70 61 73 73 77 6F 72 64 0 0 0 0 0 0 0 0 SerRecord.data[0] = usernum; SerRecord.data[1] = 0x03; memset(&SerRecord.data[2],0,PSW_LEN); memcpy(&SerRecord.data[2],rgpasswd,strlen(rgpasswd)); ret = SetMiscEntry(SET_USER_PASSWORD, &SerRecord, 2+PSW_LEN); printf("SetUserPassword(%d,3), ret = %d\n",usernum,ret); /* Set User #3 access up w/ ADMIN privilege for serial channel */ // cmdtool 20 18 43 91 3 4 0 SerRecord.data[0] = 0x90 | ser_ch; /*0x91*/ SerRecord.data[1] = usernum; /* user 3 */ SerRecord.data[2] = ser_access; /*usu 0x04; Admin*/ SerRecord.data[3] = 0x00; ret = SetMiscEntry(SET_USER_ACCESS, &SerRecord, 4); printf("SetUserAccess(%d/%02x), ret = %d\n",usernum,ser_access,ret); if (ipmi_reserved_user(vend_id,0x01) == 0) { /* Set NULL user access up w/ USER privilege for serial channel */ // cmdtool 20 18 43 91 1 2 0 SerRecord.data[0] = 0x90 | ser_ch; /*0x91*/ SerRecord.data[1] = 0x01; /* user 1 (default) */ SerRecord.data[2] = 0x02; /* user privilege */ SerRecord.data[3] = 0x00; ret = SetMiscEntry(SET_USER_ACCESS, &SerRecord, 4); printf("SetUserAccess(1/user), ret = %d\n",ret); } } else { /* No username specified, use NULL user 1 for Serial */ if (ipmi_reserved_user(vend_id,0x01) == 0) { /* Set NULL user password, if specified */ if (fSetPsw) { SerRecord.data[0] = 0x01; /*user 1*/ SerRecord.data[1] = 0x02; memset(&SerRecord.data[2],0,PSW_LEN); memcpy(&SerRecord.data[2],rgpasswd,strlen(rgpasswd)); ret = SetMiscEntry(SET_USER_PASSWORD, &SerRecord, 2+PSW_LEN); printf("SetUserPassword(1,2), ret = %d\n",ret); /* make sure user 1 is enabled */ SerRecord.data[0] = 0x01; SerRecord.data[1] = 0x01; memset(&SerRecord.data[2],0,PSW_LEN); ret = SetMiscEntry(SET_USER_PASSWORD, &SerRecord, 2+PSW_LEN); printf("SetUserPassword(1,1), ret = %d\n",ret); } /* Set NULL user access up w/ ADMIN privilege for serial channel */ // cmdtool 20 18 43 91 1 4 0 SerRecord.data[0] = 0x90 | ser_ch; /*0x91*/ SerRecord.data[1] = 0x01; /* user 1 */ SerRecord.data[2] = ser_access; /* admin */ SerRecord.data[3] = 0x00; ret = SetMiscEntry(SET_USER_ACCESS, &SerRecord, 4); printf("SetUserAccess(1/%02x), ret = %d\n",ser_access,ret); } } if (fSetTMode) { /* * Set the TMode configuration: * Enable line editing * Delete seq = bksp-sp-bksp * Enable echo * Handshake (hb) = off * Output newline seq = CR-LF * Input newline seq = CR */ if ((vend_id != VENDOR_SUPERMICROX) && (vend_id != VENDOR_SUPERMICRO)) { #ifdef TEST SerRecord.data[0] = 0xA6; /* sets bit for volatile - wrong */ SerRecord.data[1] = 0x11; ret = SetSerEntry(29, &SerRecord,2); #endif SerRecord.data[0] = 0x66; SerRecord.data[1] = 0x11; ret = SetSerEntry(29, &SerRecord,2); printf("SetSerEntry(29), ret = %d\n",ret); } /* Force mux switch to the BMC and start talking... */ /* Set Serial/Modem Mux */ /* cmdtool 20 30 12 1 4 */ SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x02; /* was 0x04 to force switch to BMC */ i = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); printf("SetSerialMux(BMC), ret = %d, value = %02x\n", i,SerRecord.data[0]); } /*endif fSetTMode*/ else { /* fBMode */ if (fShared) { uchar bval; /* workaround for BMC bug w BIOS Console Redirect */ SerRecord.data[0] = 0x03; /* Boot Param 3 */ if (bootflags < 16) { /* user specified a boot flag */ SerRecord.data[1] = bootflags; /* Flags */ bval = SerRecord.data[1]; ret = SetMiscEntry(SET_BOOT_OPTIONS, &SerRecord, 2); printf("SetBootOptions(3), new value = %02x, ret = %d\n", bval,ret); } /* Force mux switch to the Baseboard initially */ SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x03; /* force switch to Baseboard */ i = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); printf("SetSerialMux(System), ret = %d, value = %02x\n", i,SerRecord.data[0]); } else { /* not shared, BMode only */ /* Force mux switch to the BMC and start talking... */ SerRecord.data[0] = ser_ch; /* channel 1 = EMP */ SerRecord.data[1] = 0x04; /* 0x04 to force switch to BMC */ i = SetMiscEntry(SET_SER_MUX, &SerRecord, 2); printf("SetSerialMux(BMC), ret = %d, value = %02x\n", i,SerRecord.data[0]); } } /*end-else BMode*/ } /*end-else Enable (not Disable) */ else { /*not enable or disable BMode/TMode */ if (!fcanonical) printf("Please specify a configuration mode (b,d,e,m,s,t)\n"); } } /*endif not readonly */ } /* endif ok */ do_exit: ipmi_close_(); // show_outcome(progname,ret); return(ret); } /* end main()*/ /************************ DPC configuration stuff on serial. 16:25:08.165 outgoing: set system boot options[08] 20 00 E0 81 6C 08 02 02 07 16:25:08.165 outgoing: set system boot options[08] 20 00 E0 81 70 08 06 01 0B 28 11 02 45 1F 96 3C 84 16:25:08.165 outgoing: set system boot options[08] 20 00 E0 81 74 08 04 FF FF 01 16:25:08.165 outgoing: set system boot options[08] 20 00 E0 81 78 08 03 00 FC 16:25:08.245 INCOMING: SET SYSTEM BOOT OPTIONS[08] 81 04 7B 20 6C 08 -[00]- 6C 16:25:08.245 INCOMING: SET SYSTEM BOOT OPTIONS[08] 81 04 7B 20 70 08 -[00]- 68 16:25:08.245 outgoing: set system boot options[08] 20 00 E0 81 7C 08 05 80 00 4A 00 00 2C 16:25:08.255 outgoing: chassis control[02] 20 00 E0 81 80 02 03 FA ************************/ /* end iserial.c */ ipmiutil-3.1.9/util/ievents.c0000644000000000000000000026106714351572427014702 0ustar rootroot/* * ievents.c * * This file decodes the IPMI event into a readable string. * It is used by showsel.c and getevent.c. * * ievents.c compile flags: * METACOMMAND - defined if building for ipmiutil meta-command binary * ALONE - defined if building for ievents standalone binary * else it could be compiled with libipmiutil.a * LINUX, BSD, WIN32, DOS - defined for that OS * * Author: Andy Cress arcress at users.sourceforge.net * * Copyright (c) 2009 Kontron America, Inc. * Copyright (c) 2006 Intel Corporation. * * 05/26/05 Andy Cress - created from showsel.c (see there for history) * 06/20/05 Andy Cress - changed PowerSupply present/not to Inserted/Removed * 08/01/05 Andy Cress - added more Power Unit & Battery descriptions * 03/02/06 Andy Cress - more decoding for Power Unit 0b vs. 6f * 04/11/07 Andy Cress - added events -p decoding for PET data * 10/03/07 Andy Cress - added file_grep for -p in Windows * 03/03/08 Andy Cress - added -f to interpret raw SEL file */ /*M* Copyright (c) 2009 Kontron America, Inc. Copyright (c) 2006, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #include #ifdef WIN32 #include #include #include #elif defined(DOS) #include #include #include #else #include #include #include #include #include #include #endif #include #include "ipmicmd.h" #include "ievents.h" #define SELprintf printf #define SMS_SA 0x41 #define SMI_SA 0x21 #ifdef METACOMMAND extern char *progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil events"; #else static char *progver = "3.19"; static char *progname = "ievents"; #endif static char fsensdesc = 0; /* 1= get extended sensor descriptions*/ static char fcanonical = 0; /* 1= show canonical, delimited output*/ static char fgetdevid = 0; /* 1= get device ID */ static char fnewevt = 0; /* 1= generate New event */ static char futc = 0; /* 1= raw UTC time */ static uchar thr_sa = SMS_SA; /* 0x41 (Sms) used by ipmitool PlarformEvents */ static void *sdrcache = NULL; static int pet_guid = 8; /*bytes in the input data for the GUID*/ static int iopt = -1; /*iana option*/ static char bcomma = ','; static char bdelim = BDELIM; /* '|' */ #ifdef ALONE char fdebug = 0; /* 1= debug output, standalone*/ static char fsm_debug = 0; #else extern char fdebug; /* 1= debug output, from ipmicmd.c*/ extern char fsm_debug; /*mem_if.c*/ #endif #define SDR_SZ 80 #pragma pack(1) typedef struct { ushort record_id; uchar record_type; uint timestamp; ushort generator_id; /*slave_addr/channel*/ uchar evm_rev; //event message revision uchar sensor_type; uchar sensor_number; uchar event_trigger; uchar event_data1; uchar event_data2; uchar event_data3; } SEL_RECORD; #pragma pack() #ifdef WIN32 static char sensfil[80] = "sensor_out.txt"; static char sensfil2[80] = "%ipmiutildir%\\sensor_out.txt"; // static char outfil[64] = "stype.tmp"; #else static char sensfil[80] = "/var/lib/ipmiutil/sensor_out.txt"; static char sensfil2[80] = "/usr/share/ipmiutil/sensor_out.txt"; // static char outfil[] = "/tmp/stype.tmp"; #endif static char rawfil[80] = ""; char *evt_hdr = "RecId Date/Time_______ SEV Src_ Evt_Type___ Sens# Evt_detail - Trig [Evt_data]\n"; char *evt_hdr2 = "RecId | Date/Time | SEV | Src | Evt_Type | Sensor | Evt_detail \n"; #ifdef MOVED /* moved SEV_* to ipmicmd.h */ #define SEV_INFO 0 #define SEV_MIN 1 #define SEV_MAJ 2 #define SEV_CRIT 3 #endif #define NSEV 4 char *sev_str[NSEV] = { /*0*/ "INF", /*1*/ "MIN", /*2*/ "MAJ", /*3*/ "CRT" }; /* sensor_types: See IPMI 1.5 Table 36-3, IPMI 2.0 Table 42-3 */ #define NSTYPES 0x2F static const char *sensor_types[NSTYPES] = { /* 00h */ "reserved", /* 01h */ "Temperature", /* 02h */ "Voltage", /* 03h */ "Current", /* 04h */ "Fan", /* 05h */ "Platform Security", /* 06h */ "Security Violation", /* 07h */ "Processor", /* 08h */ "Power Supply", /* 09h */ "Power Unit", /* 0Ah */ "Cooling Device", /* 0Bh */ "FRU Sensor", /* 0Ch */ "Memory", /* 0Dh */ "Drive Slot", /* 0Eh */ "POST Memory Resize", /* 0Fh */ "System Firmware", /*incl POST code errors*/ /* 10h */ "Event Log", /*SEL Disabled or Cleared */ /* 11h */ "Watchdog_1", /* 12h */ "System Event", /* offset 0,1,2 */ /* 13h */ "Critical Interrupt", /* offset 0,1,2 */ /* 14h */ "Button", /* offset 0,1,2 */ /* 15h */ "Board", /* 16h */ "Microcontroller", /* 17h */ "Add-in Card", /* 18h */ "Chassis", /* 19h */ "Chip Set", /* 1Ah */ "Other FRU", /* 1Bh */ "Cable/Interconnect", /* 1Ch */ "Terminator", /* 1Dh */ "System Boot Initiated", /* 1Eh */ "Boot Error", /* 1Fh */ "OS Boot", /* 20h */ "OS Critical Stop", /* 21h */ "Slot/Connector", /* 22h */ "ACPI Power State", /* 23h */ "Watchdog_2", /* 24h */ "Platform Alert", /* 25h */ "Entity Presence", /* 26h */ "Monitor ASIC", /* 27h */ "LAN", /* 28h */ "Management Subsystem Health", /* 29h */ "Battery", /* 2Ah */ "SessionAudit", /* 2Bh */ "Version Change", /* 2Ch */ "FRU State", /* 2Dh */ "SMI Timeout", /* 0xF3 == OEM SMI Timeout */ /* 2Eh */ "ME" /* 0xDC == ME Node Manager */ }; #define NFWERRS 14 static struct { /* See Table 36-3, type 0Fh, offset 00h */ int code; char *msg; } fwerrs[NFWERRS + 1] = { { 0x00, "Unspecified"}, { 0x01, "No system memory"}, { 0x02, "No usable memory"}, { 0x03, "Unrecovered Hard Disk"}, { 0x04, "Unrecovered System Board"}, { 0x05, "Unrecovered Diskette"}, { 0x06, "Unrecovered Hard Disk Ctlr"}, { 0x07, "Unrecovered PS2 USB"}, { 0x08, "Boot media not found"}, { 0x09, "Unrecovered video controller"}, { 0x0A, "No video device"}, { 0x0B, "Firmware ROM corruption"}, { 0x0C, "CPU voltage mismatch"}, { 0x0D, "CPU speed mismatch"}, { 0x0E, "Reserved" } }; #define NFWSTAT 26 static struct { /* See Table 36-3, type 0Fh, offset 01h & 02h */ int code; char *msg; } fwstat[NFWSTAT + 1] = { { 0x00, "Unspecified"}, { 0x01, "Memory init"}, { 0x02, "Hard disk init"}, { 0x03, "Secondary processor"}, { 0x04, "User authentication"}, { 0x05, "User-init sys setup"}, { 0x06, "USB configuration"}, { 0x07, "PCI configuration"}, { 0x08, "Option ROM init"}, { 0x09, "Video init"}, { 0x0a, "Cache init"}, { 0x0b, "SM Bus init"}, { 0x0c, "Keyboard init"}, { 0x0d, "Mgt controller"}, { 0x0e, "Docking attach"}, { 0x0f, "Enabling docking"}, { 0x10, "Docking eject"}, { 0x11, "Disabling docking"}, { 0x12, "OS wake-up"}, { 0x13, "Starting OS boot"}, { 0x14, "Baseboard init"}, { 0x15, "reserved"}, { 0x16, "Floppy init"}, { 0x17, "Keyboard test"}, { 0x18, "Mouse test"}, { 0x19, "Primary processor"}, { 0x1A, "Reserved"} }; #define NGDESC 12 static struct { ushort g_id; const char desc[8]; } gen_desc[NGDESC] = { /*empirical, format defined in IPMI 1.5 Table 23-5 */ { 0x0000, "IPMB"}, { 0x0001, "EFI "}, { 0x0003, "BIOS"}, /* BIOS POST */ { BMC_SA, "BMC "}, /* 0x0020==BMC_SA*/ { SMI_SA, "SMI "}, /* 0x0021==SMI_SA, platform events */ { 0x0028, "CHAS"}, /* Chassis Bridge Controller */ { 0x0031, "mSMI"}, /* BIOS SMI/POST errors on miniBMC or ia64 */ { 0x0033, "Bios"}, /* BIOS SMI (runtime), usually for memory errors */ { SMS_SA, "Sms "}, /* 0x0041==SmsOs for MS Win2008 Boot, ipmitool event */ { 0x002C, "ME "}, /* ME Node Manager for S5500 */ { 0x602C, "ME "}, /* ME Node Manager for S5500/i7 bus=0x6, sa=0x2C */ { HSC_SA, "HSC "} /* 0x00C0==HSC_SA for SAF-TE Hot-Swap Controller*/ }; #define NCRITS 10 char * crit_int_str[NCRITS] = { /* Critical Interrupt descriptions */ /*00*/ "FP NMI ", /* Front Panel NMI */ /*01*/ "Bus Timout", /*02*/ "IOch NMI ", /* IO channel check NMI */ /*03*/ "Soft NMI ", /*04*/ "PCI PERR ", /*05*/ "PCI SERR ", /*06*/ "EISA Timout", /*07*/ "Bus Warn ", /* Bus Correctable Error */ /*08*/ "Bus Error", /* Bus Uncorrectable Error */ /*09*/ "Fatal NMI" }; #define NBOOTI 8 char * boot_init_str[NBOOTI] = { /* System Boot Initiated */ /*00*/ "Power Up ", /*01*/ "Hard Reset", /*02*/ "Warm Reset", /*03*/ "PXE Boot ", /*04*/ "Diag Boot ", /*05*/ "SW Hard Reset", /*06*/ "SW Warm Reset", /*07*/ "RestartCause" }; #define NOSBOOT 10 char * osboot_str[NOSBOOT] = { /* OS Boot */ /*00*/ "A: boot completed", /*01*/ "C: boot completed", /*02*/ "PXE boot completed", /*03*/ "Diag boot completed", /*04*/ "CDROM boot completed", /*05*/ "ROM boot completed", /*06*/ "Other boot completed", /*07*/ "USB7 boot completed", /*08*/ "USB8 boot completed" }; #define NSLOTC 9 char * slot_str[NSLOTC] = { /* Slot/Connector descriptions */ /*00*/ "Fault ", /*01*/ "Identify", /*02*/ "Inserted", /*03*/ "InsReady", /*04*/ "RemReady", /*05*/ "PowerOff", /*06*/ "RemRequest", /*07*/ "Interlock", /*08*/ "Disabled" }; #define NBATT 3 char * batt_str[NBATT] = { /* Battery assert descriptions */ /*00*/ "Low", /*01*/ "Failed", /*02*/ "Present" }; char * batt_clr[NBATT] = { /* Battery deassert descriptions */ /*00*/ "Low is OK now", /*01*/ "Failed is OK now", /*02*/ "Absent" }; #define N_NMH 6 char * nmh_str[N_NMH] = { /* ME Node Manager Health (73) descriptions */ /*10*/ "Policy Misconfig", /*11*/ "Power Sensor Err", /*12*/ "Inlet Temp Sensor Err", /*13*/ "Host Comm Err", /*14*/ "RTC Sync Err" , /*15*/ "Plat Shutdown" }; #define N_NMFW 6 char * nmfw_str[N_NMFW] = { /* ME Firmware Health (75) descriptions */ /*00*/ "Forced GPIO Recov", /*01*/ "Image Exec Fail", /*02*/ "Flash Erase Error", /*03*/ "Flash Corrupt" , /*04*/ "Internal Watchdog Timeout", // FW Watchdog Timeout, need to flash ME /*05*/ "BMC Comm Error" }; #define N_NM 4 char * nm_str[N_NM] = { /* Node Manager descriptions */ /*72*/ "NM Exception", /*or NM Alert Threshold*/ /*73*/ "NM Health", /*74*/ "NM Capabilities", /*75*/ "FW Health" }; #define NPROC 11 char * proc_str[NPROC] = { /* Processor descriptions */ /*00*/ "IERR", /*01*/ "Thermal Trip", /*02*/ "FRB1/BIST failure", /*03*/ "FRB2 timeout", /*04*/ "FRB3 Proc error", /*05*/ "Config error", /*06*/ "SMBIOS CPU error", /*07*/ "Present", /*08*/ "Disabled", /*09*/ "Terminator", /*0A*/ "Throttled" }; #define NACPIP 15 char * acpip_str[NACPIP] = { /* ACPI Power State descriptions */ /*00*/ "S0/G0 Working", /*01*/ "S1 sleeping, proc/hw context maintained", /*02*/ "S2 sleeping, proc context lost", /*03*/ "S3 sleeping, proc/hw context lost, mem ok", /*42 chars*/ /*04*/ "S4 non-volatile sleep/suspend", /*05*/ "S5/G2 soft-off", /*06*/ "S4/S5 soft-off, no specific state", /*07*/ "G3/Mechanical off", /*08*/ "Sleeping in an S1/S2/S3 state", /*09*/ "G1 sleeping", /*0A*/ "S5 entered by override", /*0B*/ "Legacy ON state", /*0C*/ "Legacy OFF state", /*0D*/ "Unknown", /*0E*/ "Unknown" }; #define NAUDIT 2 char * audit_str[NAUDIT] = { /* Session Audit descriptions */ /*00*/ "Activated", /*01*/ "Deactivated"}; #define N_AVAIL 9 char * avail_str[N_AVAIL] = { /* Discrete Availability, evtype 0x0A */ /*00*/ "chg to Running", /*01*/ "chg to In Test", /*02*/ "chg to Power Off", /*03*/ "chg to On Line", /*04*/ "chg to Off Line", /*05*/ "chg to Off Duty", /*06*/ "chg to Degraded", /*07*/ "chg to Power Save", /*08*/ "Install Error"}; #define NSDESC 88 struct { ushort genid; /* generator id: BIOS, BMC, etc. (slave_addr/channel) */ uchar s_typ; /* 1=temp,2=voltage,4=fan,... */ uchar s_num; uchar evtrg; /* event trigger/type, see IPMI 1.5 table 36.1 & 36.2 */ uchar data1; uchar data2; uchar data3; uchar sev; /* 0=SEV_INFO, 1=SEV_MIN, 2=SEV_MAJ, 3=SEV_CRIT */ const char desc[40]; } sens_desc[NSDESC] = { /* if value is 0xff, matches any value */ {0xffff,0x05, 0xff, 0x6f, 0x40,0xff,0xff, 1,"Chassis Intrusion"}, /*chassis*/ {0xffff,0x05, 0xff, 0xef, 0x40,0xff,0xff, 0,"Chassis OK"}, /*chassis*/ {0xffff,0x05, 0xff, 0x6f, 0x44,0xff,0xff, 1,"LAN unplugged"}, /*chassis*/ {0xffff,0x05, 0xff, 0xef, 0x44,0xff,0xff, 0,"LAN restored "}, /*chassis*/ {0xffff,0x06, 0xff, 0xff, 0x45,0xff,0xff, 0,"Password"}, /*security*/ {0xffff,0x07, 0xff, 0xff, 0x41,0xff,0xff, 3,"Thermal trip"}, /*processor*/ {0xffff,0x08, 0xff, 0x6f, 0x40,0xff,0xff, 0,"Inserted"}, /*PowerSupply*/ {0xffff,0x08, 0xff, 0x6f, 0x41,0xff,0xff, 2,"Failure detected"},/*PowerSupply*/ {0xffff,0x08, 0xff, 0x6f, 0x42,0xff,0xff, 1,"Predictive failure"}, {0xffff,0x08, 0xff, 0x6f, 0x43,0xff,0xff, 0,"AC Lost"}, {0xffff,0x08, 0xff, 0x6f, 0x46,0xff,0xff, 2,"Config Error"}, {0xffff,0x08, 0xff, 0xef, 0x40,0xff,0xff, 1,"Removed"}, /*PowerSupply*/ {0xffff,0x08, 0xff, 0xef, 0x41,0xff,0xff, 0,"is OK "}, /*PowerSupply*/ {0xffff,0x08, 0xff, 0xef, 0x42,0xff,0xff, 0,"Predictive OK"}, {0xffff,0x08, 0xff, 0xef, 0x43,0xff,0xff, 0,"AC Regained"}, /*PowerSupply*/ {0xffff,0x08, 0xff, 0xef, 0x46,0xff,0xff, 0,"Config OK now"}, {0xffff,0x0c, 0xff, 0xff, 0x00,0xff,0xff, 1,"Correctable ECC"}, /*memory*/ {0xffff,0x0f, 0x06, 0xff, 0xff,0xff,0xff, 2,"POST Code"}, {0xffff,0x10, 0x09, 0xff, 0x42,0x0f,0xff, 0,"Log Cleared"}, {0xffff,0x10, 0xff, 0xff, 0x02,0xff,0xff, 0,"Log Cleared"}, {0xffff,0x10, 0xff, 0xff, 0xc0,0x03,0xff, 1,"ECC Memory Errors"}, /* Often see these 3 Boot records with reboot: * 0003 12 83 6f 05 00 ff = System/SEL ClockSync_1 (start of POST) * 0003 12 83 6f 05 80 ff = System/SEL ClockSync_2 (end of POST) * 0003 12 83 6f 01 ff ff = OEM System Boot Event (after POST, loader), or * 0003 12 83 6f 41 0f ff = OEM System Boot Event (same w 01 & 41) * can be either 0003 (BIOS) or 0001 (EFI) */ {0xffff,0x12, 0xfe, 0xff, 0xc5,0x00,0xff, 0,"Boot: ClockSync_1"}, {0xffff,0x12, 0xfe, 0xff, 0xc5,0x80,0xff, 0,"Boot: ClockSync_2"}, {0xffff,0x12, 0x83, 0xff, 0x05,0x00,0xff, 0,"Boot: ClockSync_1"}, {0xffff,0x12, 0x83, 0xff, 0x05,0x80,0xff, 0,"Boot: ClockSync_2"}, {0xffff,0x12, 0x83, 0xff, 0x01,0xff,0xff, 0,"OEM System Booted"}, {0x0001,0x12, 0x08, 0xff, 0x01,0xff,0xff, 0,"OEM System Booted"}, /*ia64*/ {0xffff,0x12, 0x01, 0x6f, 0x01,0xff,0xff, 0,"OEM System Booted"}, /*S5000*/ {0xffff,0x12, 0x38, 0x6f, 0x00,0xff,0xff, 0,"OEM System Booted"}, /*KTC*/ {0xffff,0x12, 0x38, 0xef, 0x00,0xff,0xff, 0,"OEM System Booted"}, /*KTC*/ {0x0031,0x12, 0x00, 0x6f, 0xc3,0xff,0xff, 0,"PEF Action"}, /*ia64*/ {BMC_SA,0x12, 0x83, 0x6f, 0x80,0xff,0xff, 0,"System Reconfigured"}, /*BMC*/ {BMC_SA,0x12, 0x83, 0x0b, 0x80,0xff,0xff, 0,"System Reconfigured"}, /*BMC*/ {BMC_SA,0x12, 0x0b, 0x6f, 0x80,0xff,0xff, 0,"System Reconfigured"}, /*BMC*/ {BMC_SA,0x12, 0x83, 0xff, 0x41,0xff,0xff, 0,"OEM System Boot"}, /*BMC*/ {BMC_SA,0x12, 0x83, 0x6f, 0x42,0xff,0xff, 2,"System HW failure"}, /*BMC*/ {BMC_SA,0x12, 0x83, 0x6f, 0x04,0xff,0xff, 0,"PEF Action"}, /*BMC*/ {HSC_SA,0x0d, 0xff, 0x08, 0x00,0xff,0xff, 1,"Device Removed"}, /*HSC*/ {HSC_SA,0x0d, 0xff, 0x08, 0x01,0xff,0xff, 0,"Device Inserted"}, /*HSC*/ {0xffff,0x0d, 0xff, 0x6f, 0x00,0xff,0xff, 0,"Drive present"}, /*Romley BMC*/ {0xffff,0x0d, 0xff, 0xef, 0x00,0xff,0xff, 0,"Drive removed"}, /*BMC*/ {0xffff,0x0d, 0xff, 0x6f, 0x01,0xff,0xff, 2,"Drive fault"}, /*0x0D Drive*/ {0xffff,0x0d, 0xff, 0xef, 0x01,0xff,0xff, 0,"Drive fault OK"}, {0xffff,0x0d, 0xff, 0x6f, 0x02,0xff,0xff, 1,"Drive predict fail"}, {0xffff,0x0d, 0xff, 0x6f, 0x05,0xff,0xff, 1,"Drive not redundant"}, {0xffff,0x0d, 0xff, 0x6f, 0x07,0xff,0xff, 0,"Rebuild in progress"}, {0xffff,0x0d, 0xff, 0xef, 0x07,0xff,0xff, 0,"Rebuild complete"}, {0xffff,0x14, 0xff, 0xff, 0x42,0xff,0xff, 1,"Reset Button pressed"}, {0xffff,0x14, 0xff, 0xff, 0x40,0xff,0xff, 1,"Power Button pressed"}, {0xffff,0x14, 0xff, 0xff, 0x01,0xff,0xff, 0,"ID Button pressed"}, {0xffff,0x23, 0xff, 0xff, 0x40,0xff,0xff, 2,"Expired, no action"},/*watchdog2*/ {0xffff,0x23, 0xff, 0xff, 0x41,0xff,0xff, 3,"Hard Reset action"}, /*watchdog2*/ {0xffff,0x23, 0xff, 0xff, 0x42,0xff,0xff, 3,"Power down action"}, /*watchdog2*/ {0xffff,0x23, 0xff, 0xff, 0x43,0xff,0xff, 3,"Power cycle action"},/*watchdog2*/ {0xffff,0x23, 0xff, 0xff, 0x48,0xff,0xff, 2,"Timer interrupt"}, /*watchdog2*/ {0xffff,0xf3, 0xff, 0x83, 0x41,0xff,0xff, 0,"SMI de-asserted"}, {0xffff,0xf3, 0xff, 0x03, 0x41,0xff,0xff, 3,"SMI asserted"}, {0xffff,0x20, 0x00, 0xff, 0xff,0xff,0xff, 3,"OS Kernel Panic"}, {0xffff,0x01, 0xff, 0x03, 0x01,0xff,0xff, 2,"Temp Asserted"}, /*Discrete temp*/ {0xffff,0x01, 0xff, 0x83, 0x01,0xff,0xff, 0,"Temp OK"}, /*Discrete ok*/ {0xffff,0x01, 0xff, 0x05, 0x01,0xff,0xff, 2,"Temp Asserted"}, /*CPU Hot */ {0xffff,0x01, 0xff, 0x85, 0x01,0xff,0xff, 0,"Temp OK"}, /*CPU Hot ok*/ {0xffff,0x01, 0xff, 0x07, 0x01,0xff,0xff, 2,"Temp Asserted"}, /*Discrete temp*/ {0xffff,0x01, 0xff, 0x87, 0x01,0xff,0xff, 0,"Temp OK"}, /*Discrete ok*/ /*Thresholds apply to sensor types 1=temp, 2=voltage, 3=current, 4=fan*/ /*Note that last 2 bytes usu show actual & threshold values*/ /*evtrg: 0x01=thresh, 0x81=restored/deasserted */ {0xffff,0xff, 0xff, 0x01, 0x50,0xff,0xff, 1,"Lo Noncrit thresh"}, {0xffff,0xff, 0xff, 0x01, 0x51,0xff,0xff, 0,"Lo NoncritH OK now"}, {0xffff,0xff, 0xff, 0x01, 0x52,0xff,0xff, 2,"Lo Crit thresh"}, {0xffff,0xff, 0xff, 0x01, 0x53,0xff,0xff, 0,"Lo CritHi OK now"}, {0xffff,0xff, 0xff, 0x01, 0x54,0xff,0xff, 3,"Lo Unrec thresh"}, {0xffff,0xff, 0xff, 0x01, 0x55,0xff,0xff, 0,"Lo UnrecH OK now"}, {0xffff,0xff, 0xff, 0x01, 0x56,0xff,0xff, 0,"Hi NoncritL OK now"}, {0xffff,0xff, 0xff, 0x01, 0x57,0xff,0xff, 1,"Hi Noncrit thresh"}, {0xffff,0xff, 0xff, 0x01, 0x58,0xff,0xff, 0,"Hi CritLo OK now"}, {0xffff,0xff, 0xff, 0x01, 0x59,0xff,0xff, 2,"Hi Crit thresh"}, {0xffff,0xff, 0xff, 0x01, 0x5A,0xff,0xff, 0,"Hi UnrecL OK now"}, {0xffff,0xff, 0xff, 0x01, 0x5B,0xff,0xff, 3,"Hi Unrec thresh"}, {0xffff,0xff, 0xff, 0x81, 0x50,0xff,0xff, 0,"LoN thresh OK now"}, {0xffff,0xff, 0xff, 0x81, 0x51,0xff,0xff, 1,"LoNoncrit thresh"}, {0xffff,0xff, 0xff, 0x81, 0x52,0xff,0xff, 0,"LoC thresh OK now"}, {0xffff,0xff, 0xff, 0x81, 0x53,0xff,0xff, 2,"LoCritHi thresh"}, {0xffff,0xff, 0xff, 0x81, 0x54,0xff,0xff, 0,"LoU thresh OK now"}, {0xffff,0xff, 0xff, 0x81, 0x55,0xff,0xff, 3,"LoUnrecH thresh"}, {0xffff,0xff, 0xff, 0x81, 0x56,0xff,0xff, 1,"HiNoncrit thresh"}, {0xffff,0xff, 0xff, 0x81, 0x57,0xff,0xff, 0,"HiN thresh OK now"}, {0xffff,0xff, 0xff, 0x81, 0x58,0xff,0xff, 2,"HiCritLo thresh"}, {0xffff,0xff, 0xff, 0x81, 0x59,0xff,0xff, 0,"HiC thresh OK now"}, {0xffff,0xff, 0xff, 0x81, 0x5A,0xff,0xff, 3,"HiURecLo thresh"}, {0xffff,0xff, 0xff, 0x81, 0x5B,0xff,0xff, 0,"HiU thresh OK now"} }; #define NENTID 53 static struct { char * str; uchar styp; } entitymap[NENTID] = { /* 00 */ { "unspecified", 0x00 }, /* 01 */ { "other", 0x00 }, /* 02 */ { "unknown", 0x00 }, /* 03 */ { "Processor", 0x07 }, /* 04 */ { "Disk", 0x00 }, /* 05 */ { "Peripheral bay", 0x0D }, /* 06 */ { "Management module", 0x00 }, /* 07 */ { "System board", 0x00 }, /* 08 */ { "Memory module", 0x00 }, /* 09 */ { "Processor module", 0x00 }, /* 10 */ { "Power supply", 0x08 }, /* 11 */ { "Add-in card", 0x00 }, /* 12 */ { "Front panel bd", 0x00 }, /* 13 */ { "Back panel board", 0x00 }, /* 14 */ { "Power system bd", 0x00 }, /* 15 */ { "Drive backplane", 0x00 }, /* 16 */ { "Expansion board", 0x00 }, /* 17 */ { "Other system board", 0x15 }, /* 18 */ { "Processor board", 0x15 }, /* 19 */ { "Power unit", 0x09 }, /* 20 */ { "Power module", 0x08 }, /* 21 */ { "Power distr board", 0x09 }, /* 22 */ { "Chassis back panel bd", 0x00 }, /* 23 */ { "System Chassis", 0x00 }, /* 24 */ { "Sub-chassis", 0x00 }, /* 25 */ { "Other chassis board", 0x15 }, /* 26 */ { "Disk Drive Bay", 0x0D }, /* 27 */ { "Peripheral Bay", 0x00 }, /* 28 */ { "Device Bay", 0x00 }, /* 29 */ { "Fan", 0x04 }, /* 30 */ { "Cooling unit", 0x0A }, /* 31 */ { "Cable/interconnect", 0x1B }, /* 32 */ { "Memory device ", 0x0C }, /* 33 */ { "System Mgt Software", 0x28 }, /* 34 */ { "BIOS", 0x00 }, /* 35 */ { "Operating System", 0x1F }, /* 36 */ { "System bus", 0x00 }, /* 37 */ { "Group", 0x00 }, /* 38 */ { "Remote Mgt Comm Device", 0x00 }, /* 39 */ { "External Environment", 0x00 }, /* 40 */ { "battery", 0x29 }, /* 41 */ { "Processing blade", 0x00 }, /* 43 */ { "Processor/memory module", 0x0C }, /* 44 */ { "I/O module", 0x15 }, /* 45 */ { "Processor/IO module", 0x00 }, /* 46 */ { "Mgt Controller Firmware", 0x0F }, /* 47 */ { "IPMI Channel", 0x00 }, /* 48 */ { "PCI Bus", 0x00 }, /* 49 */ { "PCI Express Bus", 0x00 }, /* 50 */ { "SCSI Bus", 0x00 }, /* 51 */ { "SATA/SAS bus", 0x00, }, /* 52 */ { "Processor FSB", 0x00 } }; char *decode_entity_id(int id) { char *str = NULL; if (id < 0) id = 0; if (id > NENTID) { if (id >= 0x90 && id < 0xB0) str = "Chassis-specific"; else if (id >= 0xB0 && id < 0xD0) str = "Board-specific"; else if (id >= 0xD0 && id <= 0xFF) str = "OEM-specific"; else str = "invalid"; } else str = entitymap[id].str; return(str); } uchar entity2sensor_type(uchar ent) { uchar stype = 0x12; uchar b; if (ent < NENTID) { b = entitymap[ent].styp; if (fdebug) printf("entity2sensor_type(%x,%s), stype=%x\n",ent, entitymap[ent].str,b); if (b != 0) stype = b; } return(stype); } static char *mem_str(int off) { char *pstr; switch(off) { case 0x00: pstr = "Correctable ECC"; break; case 0x01: pstr = "Uncorrectable ECC"; break; case 0x02: pstr = "Parity"; break; case 0x03: pstr = "Memory Scrub Failed"; break; case 0x04: pstr = "Memory Device Disabled"; break; case 0x05: pstr = "ECC limit reached" ; break; case 0x07: pstr = "ConfigError: SMI Link Lane FailOver"; break; /*Quanta QSSC_S4R*/ case 0x08: pstr = "Spare"; break; /*uses data3 */ case 0x09: pstr = "Memory Automatically Throttled"; break; case 0x0A: pstr = "Critical Overtemperature"; break; default: pstr = "Other Memory Error"; break; } return(pstr); } #if defined(METACOMMAND) /* METACOMMAND is defined for ipmiutil meta-command build. */ /* These can only be external if linked with non-core objects. */ extern int GetSDR(int recid, int *recnext, uchar *sdr, int szsdr, int *slen); extern double RawToFloat(uchar raw, uchar *psdr); extern char *get_unit_type(uchar iunit, uchar ibase, uchar imod, int flg); extern int find_sdr_by_snum(uchar *psdr,uchar *pcache, uchar snum, uchar sa); extern int GetSensorType(int snum, uchar *stype, uchar *rtype); extern char * get_mfg_str(uchar *rgmfg, int *pmfg); /*from ihealth.c*/ extern int decode_post_intel(int prod, ushort code, char *outbuf,int szbuf); extern int decode_sel_kontron(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_kontron.c*/ extern int decode_sel_fujitsu(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_fujitsu.c*/ extern int decode_sel_intel(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_intel.c*/ extern int decode_sel_supermicro(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_supermicro.c*/ extern int decode_sel_lenovo(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_lenovo.c*/ extern int decode_sel_quanta(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_quanta.c*/ extern int decode_sel_newisys(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_newisys.c*/ extern int decode_sel_dell(uchar *evt, char *obuf,int sz,char fdesc,char fdbg); /*oem_dell.c*/ extern int decode_mem_intel(int prod, uchar b2, uchar b3, char *desc, int *psz); /*oem_intel.c*/ extern int decode_mem_supermicro(int prod, uchar b2, uchar b3, char *desc, int *psz); /*oem_intel.c*/ #else /* else it could be ALONE or for a libipmiutil.a build */ static int default_mem_desc(uchar b2, uchar b3, char *desc, int *psz) { int array, dimm, n; uchar bdata; if (desc == NULL || psz == NULL) return -1; if (b3 == 0xff) bdata = b2; /*ff is reserved*/ else bdata = b3; /* normal case */ array = (bdata & 0xc0) >> 6; dimm = bdata & 0x3f; if (bdata == 0xFF) n = sprintf(desc,DIMM_UNKNOWN); else n = sprintf(desc,DIMM_NUM,dimm); *psz = n; return(0); } static int decode_mem_intel(int prod, uchar b2, uchar b3, char *desc, int *psz) { return(default_mem_desc(b2,b3,desc,psz)); } static int decode_mem_supermicro(int prod, uchar b2, uchar b3, char *desc, int *psz) { return(default_mem_desc(b2,b3,desc,psz)); } static char * get_mfg_str(uchar *rgmfg, int *pmfg) { /* standalone routine here for minimal set of strings*/ char *mfgstr; int mfg; mfg = rgmfg[0] + (rgmfg[1] << 8) + (rgmfg[2] << 16); if (pmfg != NULL) *pmfg = mfg; if (mfg == VENDOR_INTEL) mfgstr = "Intel"; else if (mfg == VENDOR_MICROSOFT) mfgstr = "Microsoft"; else if (mfg == VENDOR_KONTRON) mfgstr = "Kontron"; else if (mfg == VENDOR_SUPERMICROX) mfgstr = "SuperMicro"; else if (mfg == VENDOR_SUPERMICRO) mfgstr = "SuperMicro"; else mfgstr = " "; return (mfgstr); } #ifdef SENSORS_OK extern int GetSDR(int recid, int *recnext, uchar *sdr, int szsdr, int *slen); extern double RawToFloat(uchar raw, uchar *psdr); extern char *get_unit_type(uchar iunit, uchar ibase, uchar imod, int flg); extern int find_sdr_by_snum(uchar *psdr,uchar *pcache, uchar snum, uchar sa); extern int GetSensorType(int snum, uchar *stype, uchar *rtype); #else static int GetSDR(int recid, int *recnext, uchar *sdr, int szsdr, int *slen) { return(-1); } static double RawToFloat(uchar raw, uchar *psdr) { return((double)raw); } static char *get_unit_type(uchar iunit, uchar ibase, uchar imod, int flg) { return(""); }; static int find_sdr_by_snum(uchar *psdr,uchar *pcache, uchar snum, uchar sa) { return(-1); } static int GetSensorType(int snum, uchar *stype, uchar *rtype) { return(-1); } #endif #endif #if defined(ALONE) /* ALONE is defined for ievents standalone build. */ /* IPMI Spec says that this is an index into the DIMMs. * Walking through the SDRs dynamically would be too slow, * but isel -e has an SDR cache which could be leveraged, * however not all platforms have DIMM slot SDRs. * The BIOS references the DIMM Locator descriptors from * SMBIOS type 17, and the descriptions vary for each baseboard. * We'll just show the index here by default. * Do the SMBIOS lookup if not standalone build. */ int g_vend_id = VENDOR_INTEL; /*assume a default of Intel*/ int strlen_(const char *s) { return((int)strlen(s)); } char *get_iana_str(int vend) { return(""); } /*from subs.c*/ void set_iana(int vend) { g_vend_id = vend; return; } char is_remote(void) { return(1); } /* act as if remote with standalone */ int get_MemDesc(int array, int idimm, char *desc, int *psz) { /* standalone, so use the default method for the DIMM index */ return(default_mem_desc(array,idimm,desc,psz)); } void get_mfgid(int *vend, int *prod) { if ((vend == NULL) || (prod == NULL)) return; *vend = g_vend_id; /*assume a default of Intel*/ *prod = 0; } char * decode_rv(int rv) { static char mystr[30]; char *pstr; switch(rv) { case 0: pstr = "completed successfully"; break; case ERR_BAD_PARAM: pstr = "invalid parameter"; break; case ERR_USAGE: pstr = "usage or help requested"; break; case ERR_FILE_OPEN: pstr = "cannot open file"; break; case ERR_NOT_FOUND: pstr = "item not found"; break; default: sprintf(mystr,"error = %d",rv); pstr = mystr; break; } return(pstr); } void dump_buf(char *tag, uchar *pbuf, int sz, char fshowascii) { uchar line[17]; uchar a; int i, j; char *stag; FILE *fpdbg1; fpdbg1 = stdout; if (tag == NULL) stag = "dump_buf"; /*safety valve*/ else stag = tag; fprintf(fpdbg1,"%s (len=%d): ", stag,sz); line[0] = 0; line[16] = 0; j = 0; if (sz < 0) { fprintf(fpdbg1,"\n"); return; } /*safety valve*/ for (i = 0; i < sz; i++) { if (i % 16 == 0) { line[j] = 0; j = 0; fprintf(fpdbg1,"%s\n %04x: ",line,i); } if (fshowascii) { a = pbuf[i]; if (a < 0x20 || a > 0x7f) a = '.'; line[j++] = a; } fprintf(fpdbg1,"%02x ",pbuf[i]); } if (fshowascii) { if ((j > 0) && (j < 16)) { /* space over the remaining number of hex bytes */ for (i = 0; i < (16-j); i++) fprintf(fpdbg1," "); } else j = 16; line[j] = 0; } fprintf(fpdbg1,"%s\n",line); return; } int ipmi_cmdraw(uchar cmd, uchar netfn, uchar sa, uchar bus, uchar lun, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { return(-9); } #else /* ipmicmd.h has ipmi_cmdraw() */ extern int get_MemDesc(int array, int dimm, char *desc, int *psz); /*mem_if.c*/ extern void get_mfgid(int *vend, int *prod); /*from ipmicmd.c*/ extern char is_remote(void); /*from ipmicmd.c*/ extern char * decode_rv(int rv); /*from ipmilan.c*/ extern void dump_buf(char *tag, uchar *pbuf, int sz, char fshowascii); #endif static int decode_mem_default(uchar b1, uchar b2, uchar b3, uchar etype, char *desc, int *psz) { int cpu, dimm, n; int rv = -1; int offset = 0; uchar bdata; if ((desc == NULL) || (psz == NULL)) return -1; offset = (b1 & 0x0F); if ((b1 & 0x20) != 0) { bdata = b3; } /*dimm data in byte 3*/ else if (b2 == 0xff) { bdata = b3; } /*ff is reserved*/ else { bdata = b2; } /*if here, should also have (b1 & 0x80)*/ if (bdata == 0xFF) n = sprintf(desc,DIMM_UNKNOWN); else { cpu = (bdata & 0xc0) >> 6; dimm = (bdata & 0x3F); n = sprintf(desc,DIMM_NUM,dimm); /* Use DMI if we get confirmation about cpu/dimm indices. */ if (! is_remote()) { fsm_debug = fdebug; rv = get_MemDesc(cpu,dimm,desc,psz); if (rv != 0) n = sprintf(desc,DIMM_NUM,dimm); } } *psz = n; if (fdebug) printf("decode_mem_default: bdata=%02x(%d) %d dimm=%d\n",bdata,bdata,offset,dimm); rv = 0; return(rv); } /*end decode_mem_default*/ int new_event(uchar *buf, int len) { int rlen, rv; uchar idata[8]; uchar rdata[4]; uchar cc; /* Platform Event Message command, inputs: offset 0 = GeneratorID, 0x20 for BMC, 0x21 for SMI/kernel, 0x33 for BIOS 1 = EVM Rev, 3=IPMI10, 4=IPMI15 2 = Sensor Type 3 = Sensor Number 4 = Event Type (0x6f = sensor specific) 5 = data1 6 = data2 7 = data3 */ idata[0] = buf[0]; /*GenID on input is two bytes, but one byte here*/ idata[1] = buf[2]; idata[2] = buf[3]; idata[3] = buf[4]; idata[4] = buf[5]; idata[5] = buf[6]; idata[6] = buf[7]; idata[7] = buf[8]; rlen = sizeof(rdata); rv = ipmi_cmdraw(0x02, NETFN_SEVT, BMC_SA, PUBLIC_BUS, BMC_LUN, idata,8, rdata,&rlen,&cc, fdebug); if (fdebug) printf("platform_event: rv = %d, cc = %02x\n",rv,cc); if ((rv == 0) && (cc != 0)) rv = cc; return(rv); } char *get_sensor_type_desc(uchar stype) { int i; static char stype_desc[25]; char *pstr; if (stype == 0xF3) i = 0x2D; /*OEM SMI*/ else if (stype == 0xDC) i = 0x2E; /*NM*/ else if (stype == SMI_SA) i = BMC_SA; /*SMI -> BMC*/ else if (stype >= NSTYPES) i = 0; else i = stype; if (i == 0) { /* reserved, show the raw sensor_type also */ if (stype == 0xCF) strncpy(stype_desc,"OEM Board Reset", sizeof(stype_desc)); else if (stype >= 0xC0) sprintf(stype_desc,"OEM(%02x)",stype); else sprintf(stype_desc,"%s(%02x)",sensor_types[i],stype); /*reserved*/ pstr = (char *)stype_desc; } else { pstr = (char *)sensor_types[i]; } return(pstr); } /*------------------------------------------------------------------------ * get_misc_desc * Uses the sens_desc array to decode misc entries not otherwise handled. * Called by decode_sel_entry *------------------------------------------------------------------------*/ char * get_misc_desc(ushort genid, uchar type, uchar num, uchar trig, uchar data1, uchar data2, uchar data3, uchar *sev) { int i; char *pstr = NULL; /* Use sens_desc array for other misc descriptions */ data1 &= 0x0f; /*ignore top half of sensor offset for matching */ for (i = 0; i < NSDESC; i++) { if ((sens_desc[i].s_typ == 0xff) || (sens_desc[i].s_typ == type)) { if (sens_desc[i].s_num != 0xff && sens_desc[i].s_num != num) continue; if (sens_desc[i].genid != 0xffff && sens_desc[i].genid != genid) continue; if (sens_desc[i].evtrg != 0xff && sens_desc[i].evtrg != trig) continue; if (sens_desc[i].data1 != 0xff && (sens_desc[i].data1 & 0x0f) != (data1 & 0x0f)) continue; if (sens_desc[i].data2 != 0xff && sens_desc[i].data2 != data2) continue; if (sens_desc[i].data3 != 0xff && sens_desc[i].data3 != data3) continue; /* have a match, use description */ pstr = (char *)sens_desc[i].desc; if (sev != NULL) *sev = sens_desc[i].sev; break; } } /*end for*/ return(pstr); } /* end get_misc_desc() */ time_t utc2local(time_t t) { struct tm * tm_tmp; int gt_year,gt_yday,gt_hour,lt_year,lt_yday,lt_hour; int delta_hour; time_t lt; // convert UTC time to local time // i.e. number of seconds from 1/1/70 0:0:0 1970 GMT tm_tmp=gmtime(&t); gt_year=tm_tmp->tm_year; gt_yday=tm_tmp->tm_yday; gt_hour=tm_tmp->tm_hour; tm_tmp=localtime(&t); lt_year=tm_tmp->tm_year; lt_yday=tm_tmp->tm_yday; lt_hour=tm_tmp->tm_hour; delta_hour=lt_hour - gt_hour; if ( (lt_year > gt_year) || ((lt_year == gt_year) && (lt_yday > gt_yday)) ) delta_hour += 24; if ( (lt_year < gt_year) || ((lt_year == gt_year) && (lt_yday < gt_yday)) ) delta_hour -= 24; if (fdebug) printf("utc2local: delta_hour = %d\n",delta_hour); lt = t + (delta_hour * 60 * 60); return(lt); } void fmt_time(time_t etime, char *buf, int bufsz) { time_t t; if (bufsz < 18) printf("fmt_time: buffer size should be >= 18\n"); if (futc) t = etime; else t = utc2local(etime); /*assume input time is UTC*/ strncpy(buf,"00/00/00 00:00:00",bufsz); strftime(buf,bufsz, "%x %H:%M:%S", gmtime(&t)); /*or "%x %T"*/ return; } /* * findmatch * Finds a matching pattern within a string buffer. * returns offset of the match if found, or -1 if not found. */ int findmatch(char *buffer, int sbuf, char *pattern, int spattern, char figncase) { int c, i, j, imatch; j = 0; imatch = 0; for (j = 0; j < sbuf; j++) { if ((sbuf - j) < spattern && imatch == 0) return(-1); c = buffer[j]; if (c == pattern[imatch]) { imatch++; } else if ((figncase == 1) && ((c & 0x5f) == (pattern[imatch] & 0x5f))) { imatch++; } else if (pattern[imatch] == '?') { /*wildcard char*/ imatch++; } else { if (imatch > 0) { if (j > 0) j--; /* try again with the first match char */ imatch = 0; } } if (imatch == spattern) break; } if (imatch == spattern) { i = (j+1) - imatch; /*buffer[i] is the match */ return(i); } else return (-1); /*not found*/ } /*end findmatch */ /* * file_grep * Search (grep) for a pattern within a file. * Inputs: fname = file name to search * pattn = pattern string to search for * line = line buffer * sline = size of line buffer * bmode = 0 to use last match, * 1 to use first match, * 2 to specify starting line number & use first match. * nret = IN: starting char offset, OUT: num chars read * Outputs: line = resulting line (stringified) that matches pattn * nret = resulting line number within file (0-based) * returns 0 if match, < 0 if error */ int file_grep(char *fname, char *pattn, char *line, int sline, char bmode, int *nret) { FILE *fp; char buff[1024]; int ret = ERR_NOT_FOUND; int i, plen, blen; int n = 0; int nstart = 0; int bufsz; if ((bmode == 2) && (nret != NULL)) nstart = *nret; bufsz = sizeof(buff); fp = fopen(fname,"r"); if (fp == NULL) { if (fdebug) printf("file_grep: Cannot open %s\n",fname); ret = ERR_FILE_OPEN; /*cannot open file*/ } else { plen = strlen_(pattn); fseek(fp, nstart, SEEK_SET); n = nstart; while (fgets(buff, bufsz, fp) != NULL) { blen = strlen_(buff); /* check for pattern in this line */ i = findmatch(&buff[0],blen,pattn,plen,0); if (i >= 0) { ret = 0; /* found it, success */ if ((line != NULL) && sline > 1) { if (blen >= sline) blen = sline - 1; strncpy(line,buff,blen); line[blen] = 0; /*stringify*/ } if (nret != NULL) *nret = n + i + plen; if (bmode > 0) break; /* else keep looking, use last one if multiples */ } n += blen; /*number of chars*/ } /*end while*/ fclose(fp); } /*end else file opened*/ return(ret); } /*end file_grep*/ char *get_sev_str(int val) { if (val >= NSEV) val = SEV_CRIT; return(sev_str[val]); } /* The htoi() routine is available in subs.c, but ievents.c also * needs a local copy of it if built with -DALONE. */ static uchar _htoi(char *inhex) { // char rghex[16] = "0123456789ABCDEF"; uchar val; char c; c = inhex[0] & 0x5f; /* force cap */ if (c > '9') c += 9; /* c >= 'A' */ val = (c & 0x0f) << 4; c = inhex[1] & 0x5f; /* force cap */ if (c > '9') c += 9; /* c >= 'A' */ val += (c & 0x0f); return(val); } /* * set_sel_opts is used to specify options for showing/decoding SEL events. * sensdesc : 0 = simple, no sensor descriptions * 1 = get sensor descriptions from sdr cache * 2 = get sensor descriptions from sensor file (-s) * canon : 0 = normal output * 1 = canonical, delimited output * sdrs : NULL = no sdr cache, dynamically get sdr cache if sensdesc==1 * ptr = use this pointer as existing sdr cache if sensdesc==1 * fdbg : 0 = normal mode * 1 = debug mode * futc : 0 = normal mode * 1 = show raw UTC time */ void set_sel_opts(int sensdesc, int canon, void *sdrs, char fdbg, char utc) { fsensdesc = (char)sensdesc; /*get extended sensor descriptions*/ fcanonical = (char)canon; /*show canonical, delimited output*/ if (sdrcache == NULL) sdrcache = sdrs; else printf("Warning: attempted to set_sel_opts(sdrcache) twice\n"); fdebug = fdbg; futc = utc; } /* get_sensdesc - get the sensor tag/description from the sensor.out file */ int get_sensdesc(uchar sa, int snum, char *sensdesc, int *pstyp, int *pidx) { int rv, i, j, len, idx; char pattn[20]; char sensline[100]; int nline = 0; uchar sa2; char *sfil; char *p; if (sensdesc == NULL) return ERR_BAD_PARAM; sensdesc[0] = 0; if (fdebug) printf("sensdesc(%02x,%02x) with %s\n",sa,snum,sensfil); sprintf(pattn,"snum %02x",snum); for (j = 0; j < 3; j++) { sfil = sensfil; /* Use this logic for both Linux and Windows */ rv = file_grep(sfil,pattn, sensline, sizeof(sensline), 2, &nline); if (rv != 0) { if (rv == ERR_FILE_OPEN) { if (fdebug) fprintf(stdout,"Cannot open file %s\n",sfil); sfil = sensfil2; rv = file_grep(sfil, pattn, sensline,sizeof(sensline), 2, &nline); if (fdebug && rv == ERR_FILE_OPEN) fprintf(stdout,"Cannot open file %s\n",sfil); } if (rv != ERR_FILE_OPEN) { if (fdebug) printf("Cannot find snum %02x in file %s\n",snum,sfil); rv = ERR_NOT_FOUND; } break; } if (rv == 0) { idx = _htoi(&sensline[2]) + (_htoi(&sensline[0]) << 8); sa2 = _htoi(&sensline[20]); if (fdebug) printf("sensdesc(%02x,%02x) found snum for sa %02x at offset %d\n", sa,snum,sa2,nline); if (sa == sa2) { /* truncate the sensor line to omit the reading */ len = strlen_(sensline); for (i = 0; i < len; i++) if (sensline[i] == '=') { sensline[i] = 0; break; } if (sensline[i-1] != ' ') { sensline[i] = ' '; sensline[++i] = 0; } /* skip to just the sensor description from the SDR */ p = strstr(sensline,"snum"); p += 8; /* skip 'snum 11 ' */ strcpy(sensdesc,p); if (pstyp != NULL) *pstyp = _htoi(&sensline[25]); if (pidx != NULL) *pidx = idx; break; } } } /*end-for j*/ if (j >= 3) rv = ERR_NOT_FOUND; /*not found*/ return(rv); } char *get_genid_str(ushort genid) { static char genstr[10]; char *gstr; int i; sprintf(genstr,"%04x",genid); gstr = genstr; /* default */ for (i = 0; i < NGDESC; i++) { if (gen_desc[i].g_id == genid) { gstr = (char *)gen_desc[i].desc; break; } } return(gstr); } static int is_threshold(uchar evtrg, ushort genid) { int val = 0; /*false*/ /* It would be better to check the SDR (if Full supports thresholds), * but we do not always have that available. */ if ( ((genid == BMC_SA) || /*from BMC*/ (genid == SMI_SA) || /*from SMI (simulated)*/ (genid == thr_sa)) && /*from HSC, or other*/ ((evtrg == 0x01) || /*threshold evt*/ (evtrg == 0x81))) /*threshold ok*/ val = 1; return(val); } static void get_sdr_tag(uchar *sdr, char *tagstr) { int i, j, k, len; len = sdr[4] + 5; switch(sdr[3]) { case 0x01: k = 48; break; /*full sensor*/ case 0x02: k = 32; break; /*compact sensor*/ case 0x03: k = 17; break; /*compact sensor*/ case 0x10: k = 16; break; /*compact sensor*/ case 0x11: k = 16; break; /*compact sensor*/ case 0x12: k = 16; break; /*compact sensor*/ default: k = 0; break; } if (k > 0 && k < len) { i = len - k; for (j = 0; j < i; j++) { if (sdr[k+j] == 0) break; tagstr[j] = sdr[k+j]; } tagstr[j++] = ' '; tagstr[j] = 0; } } /* * get_sensor_tag * * Get the sensor tag (name) based on the sensor number, etc. * Use one of 3 methods to get this: * 1) Parse the sensor_out.txt (sensfil) if fsensdesc==2. * Use this method if not METACOMMAND or if user-specified. * 2) Find this SDR in the SDR cache, if available. * 3) Do a GetSDR command function now (can be slow) * Input parameters: * isdr = index of SDR, use 0 if unknown * genid = genid or sa (slave address) of this sensor * snum = sensor number of this sensor * tag = pointer to a buffer for the sensor tag (min 17 bytes) * sdr = pointer to buffer for the SDR if found (usu <= 65 bytes) * szsdr = size of the SDR buffer * Output parameters: * tag = filled in with sensor tag (name) * sdr = filled in with SDR, if found. * Returns: * 0 if tag and sdr are found. * ERR_NOT_FOUND if SDR is not found (but tag may be found) * other errors, see ipmicmd.h */ int get_sensor_tag(int isdr, int genid, uchar snum, char *tag, uchar *sdr, int szsdr) { int rv, i, j = 0; if (tag == NULL) return(ERR_BAD_PARAM); if (sdr == NULL) return(ERR_BAD_PARAM); if (genid == SMS_SA) genid = BMC_SA; /*parse Sms as if BMC*/ if (genid == SMI_SA) genid = BMC_SA; /*parse SMI as if BMC*/ tag[0] = 0; if (fsensdesc == 2) { /*not connected, so do not try to GetSDR*/ rv = get_sensdesc((uchar)genid, snum, tag,NULL,&isdr); rv = ERR_NOT_FOUND; /*got tag, but did not get SDR*/ } else if (sdrcache != NULL) { /*valid sdr cache*/ rv = find_sdr_by_snum(sdr,sdrcache, snum, (uchar)genid); if (rv == 0) { get_sdr_tag(sdr,tag); } } else { /* try to get this SDR */ rv = GetSDR(isdr, &i,sdr,szsdr,&j); if (fdebug) printf("get_sensor_tag GetSDR[%x] rv=%d sz=%d\n",isdr,rv,j); if (rv == 0) { get_sdr_tag(sdr,tag); } else { /* use a saved sensor.out file */ rv = get_sensdesc((uchar)genid, snum, tag,NULL,&isdr); if (rv != 0) tag[0] = 0; rv = ERR_NOT_FOUND; /*got tag, but did not get SDR*/ } } if (rv != 0) strcpy(tag,"na "); if (fdebug) printf("get_sensor_tag(%d): find_sdr(%x,%x) rv=%d tag=/%s/\n", fsensdesc,snum,genid,rv,tag); return(rv); } static int decode_post_oem(int vend, int prod, ushort code, char *outbuf,int szbuf) { int rv = -1; if (outbuf == NULL || szbuf == 0) return(rv); #if defined(METACOMMAND) switch(vend) { case VENDOR_INTEL: rv = decode_post_intel(prod,code,outbuf,szbuf); break; default: break; } #endif if (rv != 0) snprintf(outbuf,szbuf,"POST Code %04x",code); return(rv); } static int decode_sel_oem(int vend, uchar *pevt, char *outbuf,int szbuf, char fdesc, char fdbg) { int rv = -1; #ifdef METACOMMAND switch(vend) { case VENDOR_KONTRON: rv = decode_sel_kontron(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_FUJITSU: /* Fujitsu does an OEM IPMI command to return the decoded string. */ rv = decode_sel_fujitsu(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_INTEL: thr_sa = HSC_SA; /* HSC_SA(0xC0) by default */ rv = decode_sel_intel(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_PEPPERCON: /*SuperMicro AOC-SIMSO*/ if (pevt[7] == 0x40) pevt[7] = BMC_SA; /*genid broken, fix it*/ break; case VENDOR_MAGNUM: case VENDOR_SUPERMICRO: case VENDOR_SUPERMICROX: rv = decode_sel_supermicro(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_LENOVO: case VENDOR_LENOVO2: rv = decode_sel_lenovo(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_QUANTA: rv = decode_sel_quanta(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_NEWISYS: rv = decode_sel_newisys(pevt,outbuf,szbuf,fdesc,fdbg); break; case VENDOR_DELL: rv = decode_sel_dell(pevt,outbuf,szbuf,fdesc,fdbg); break; default: break; } #endif if (fdebug) printf("decode_sel_oem(0x%04x) rv=%d\n",vend,rv); return(rv); } #define N_PWRUNIT 12 static struct { uchar trg; uchar data1; uchar sev; char *msg; } pwrunit_evts[N_PWRUNIT] = { { 0x6f, 0x00, 0,"Power Off "}, { 0x6f, 0x01, 0,"Power Cycle "}, { 0x6f, 0x02, 0,"240VA power down"}, { 0x6f, 0x03, 0,"Interlock power down"}, { 0x6f, 0x04, 1,"AC Lost"}, { 0x6f, 0x05, 2,"Soft Powerup failure"}, { 0x6f, 0x06, 2,"Failure detected"}, { 0x6f, 0x07, 1,"Predictive failure"}, { 0xef, 0x00, 0,"Power Restored"}, { 0xef, 0x01, 0,"Power Cycle ok"}, { 0xef, 0x04, 0,"AC Regained"}, { 0xef, 0x06, 0,"Failure OK now"} }; static int decode_pwrunit(uchar trg, uchar data1, char *pstr, uchar *psev) { int rv = -1; int i, j; j = data1 & 0x0f; if (psev == NULL || pstr == NULL) return(rv); sprintf(pstr,"_"); for (i = 0; i < N_PWRUNIT; i++) { if ((trg == pwrunit_evts[i].trg) && (j == pwrunit_evts[i].data1)) { *psev = pwrunit_evts[i].sev; sprintf(pstr,"%s",pwrunit_evts[i].msg); rv = 0; } } return(rv); } #define N_REDUN 16 static struct { uchar trg; uchar data1; uchar sev; char *msg; } redund_evts[N_REDUN] = { { 0x0B, 0x00, SEV_INFO,"Redundancy OK "}, { 0x0B, 0x01, SEV_MAJ, "Redundancy Lost"}, { 0x0B, 0x02, SEV_MAJ, "Redundancy Degraded"}, { 0x0B, 0x03, SEV_MAJ, "Not Redundant"}, { 0x0B, 0x04, SEV_MAJ, "Sufficient Resources"}, { 0x0B, 0x05, SEV_CRIT,"Insufficient Resources"}, { 0x0B, 0x06, SEV_MAJ, "Fully-to-Degraded"}, { 0x0B, 0x07, SEV_MIN, "NonR-to-Degraded"}, { 0x8B, 0x00, SEV_MAJ, "Redundancy NOT ok"}, { 0x8B, 0x01, SEV_INFO,"Redundancy Regained"}, { 0x8B, 0x02, SEV_INFO,"Redundancy Restored"}, { 0x8B, 0x03, SEV_INFO,"Redundant"}, { 0x8B, 0x04, SEV_MAJ, "Not Sufficient"}, { 0x8B, 0x05, SEV_INFO,"Not Insufficient"}, { 0x8B, 0x06, SEV_INFO,"Degraded-to-Fully"}, { 0x8B, 0x07, SEV_MIN, "Degraded-to-NonR"} }; static int decode_redund(uchar trg, uchar data1, char *pstr, uchar *psev) { int rv = -1; int i, j; j = data1 & 0x0f; if (psev == NULL || pstr == NULL) return(rv); sprintf(pstr,"_"); for (i = 0; i < N_REDUN; i++) { if ((trg == redund_evts[i].trg) && (j == redund_evts[i].data1)) { *psev = redund_evts[i].sev; sprintf(pstr,"%s",redund_evts[i].msg); rv = 0; } } return(rv); } #define N_PRESENT 2 static char * present_str[N_PRESENT] = { /* Availability, evtype 0x08 */ /*00*/ "Absent", /*Absent/Removed*/ /*01*/ "Present"}; /*Present/Inserted*/ static int decode_presence(uchar trg, uchar data1, char *pstr, uchar *psev) { int rv = -1; int i; if (psev == NULL || pstr == NULL) return(rv); sprintf(pstr,"_"); *psev = SEV_INFO; i = data1 & 0x0f; if (trg == 0x08) { if (i >= N_PRESENT) i = N_PRESENT - 1; sprintf(pstr,"%s",present_str[i]); rv = 0; } else if (trg == 0x88) { if (data1 & 0x01) i = 0; else i = 1; sprintf(pstr,"%s",present_str[i]); } return(rv); } void format_event(ushort id, time_t timestamp, int sevid, ushort genid, char *ptype, uchar snum, char *psens, char *pstr, char *more, char *outbuf, int outsz) { char sensdesc[36]; char timestr[40]; uchar sdr[MAX_BUFFER_SIZE]; /*sdr usu <= 65 bytes*/ char *gstr; int isdr = 0; int rv; if (more == NULL) more = ""; if (psens != NULL) ; /* use what was passed in */ else { /*psens==NULL, may need to get tag*/ psens = &sensdesc[0]; sensdesc[0] = 0; if (fsensdesc) { rv = get_sensor_tag(isdr,genid,snum,psens,sdr,sizeof(sdr)); if (fdebug) printf("get_sensor_tag(%x) rv = %d\n",snum,rv); } } fmt_time(timestamp, timestr, sizeof(timestr)); gstr = get_genid_str(genid); /*get Generator ID / Source string*/ if (fcanonical) { snprintf(outbuf,outsz,"%04x %c %s %c %s %c %s %c %s %c %s %c %s %s\n", id, bdelim, timestr, bdelim, get_sev_str(sevid), bdelim, gstr, bdelim, ptype, bdelim, psens, bdelim, pstr, more ); } else { snprintf(outbuf,outsz,"%04x %s %s %s %s #%02x %s %s %s\n", id, timestr, get_sev_str(sevid), gstr, ptype, snum, psens, pstr, more); } return; } /*------------------------------------------------------------------------ * decode_sel_entry * Parse and decode the SEL record into readable format. * This routine is constructed so that it could be used as a library * function. * Note that this routine outputs 14 of the 16 bytes in either text or * raw hex form. For the two bytes not shown: * . record type: usually = 02, is shown otherwise (e.g. OEM type) * . event msg revision: =03 if IPMI 1.0, =04 if IPMI 1.5 or IPMI 2.0 * * Input: psel, a pointer to the IPMI SEL record (16 bytes) * Output: outbuf, a description of the event, max 80 chars. * Called by: ReadSEL() * Calls: fmt_time() get_misc_desc() * * IPMI SEL record format (from IPMI Table 32-1): * Offset Meaning * 0-1 Record ID (LSB, MSB) * 2 Record Type (usu 0x02) * 3-6 Timestamp (LS byte first) * 7-8 Generator ID (LS first, usually 20 00) * 9 Event message format (=0x04, or =0x03 if IPMI 1.0) * 10 Sensor type * 11 Sensor number * 12 Event Dir | Event Type * 13 Event Data 1 * 14 Event Data 2 * 15 Event Data 3 *------------------------------------------------------------------------*/ int decode_sel_entry( uchar *pevt, char *outbuf, int szbuf) { char mystr[80] = "panic(123)"; /*used for panic string*/ char *pstr; char poststr[80] = "OEM Post Code = %x%x"; char sensstr[50]; char datastr[64]; char cstr[4]; char *psensstr; int i, j, k, n; time_t eventTime; uchar *evtime; char timebuf[40]; uchar *pc; SEL_RECORD *psel; uchar fdeassert = 0; uchar etype; uchar sev = SEV_INFO; uchar sdr[MAX_BUFFER_SIZE]; /*sdr usu <= 65 bytes*/ int isdr = 0; int vend, prod; int rv = 0; char fhave_sdr = 0; char mdesc[80]; /*used for oem memory description*/ int msz; char *mfgstr; int mfg; if (outbuf == NULL) return(ERR_BAD_PARAM); if (pevt == NULL) { outbuf[0] = 0; return(ERR_BAD_PARAM); } get_mfgid(&vend,&prod); /*saved from ipmi_getdeviceid */ psel = (SEL_RECORD *)pevt; etype = psel->event_trigger; j = decode_sel_oem(vend,pevt,outbuf,szbuf,fsensdesc,fdebug); if (j == 0) return(0); /*successful, have the description*/ if (psel->record_type == RT_OEMIU) { /* 0xDB usu ipmiutil OEM string */ /* ipmiutil OEM event with 9-byte string */ pc = (uchar *)&psel->generator_id; /* offset 7 */ evtime = (uchar *)&psel->timestamp; eventTime = evtime[0] + (evtime[1] << 8) + (evtime[2] << 16) + (evtime[3] << 24); fmt_time(eventTime, timebuf, sizeof(timebuf)); if (fcanonical) sprintf(outbuf,"%04x %c %s %c %s %c %02x %c OEM Event ", psel->record_id, bdelim, timebuf, bdelim, get_sev_str(sev), bdelim, psel->record_type, bdelim); else sprintf(outbuf,"%04x %s %s %02x OEM Event ", psel->record_id, timebuf, get_sev_str(sev), psel->record_type); j = strlen_(outbuf); for (i = 0; i < 9; i++) { /* 7:16 = 9 bytes string data */ if (pc[i] == 0) outbuf[j] = ' '; else sprintf(&outbuf[j],"%c",pc[i]); j += 1; } outbuf[j++] = '\n'; outbuf[j++] = 0; } else if (psel->record_type == 0xDC) { /* OEM Record: these are usually Microsoft */ evtime = (uchar *)&psel->timestamp; eventTime = evtime[0] + (evtime[1] << 8) + (evtime[2] << 16) + (evtime[3] << 24); fmt_time(eventTime, timebuf, sizeof(timebuf)); pc = (uchar *)&psel->generator_id; /* offset 7 */ mfgstr = get_mfg_str(&pc[0],&mfg); if (fcanonical) sprintf(outbuf,"%04x %c %s %c %s %c %02x %c %06x %c %s %c OEM Event ", psel->record_id, bdelim, timebuf, bdelim, get_sev_str(sev), bdelim, psel->record_type, bdelim, mfg, bdelim, mfgstr, bdelim); else sprintf(outbuf,"%04x %s %s %02x %06x %s OEM Event ", psel->record_id, timebuf, get_sev_str(sev), psel->record_type, mfg, mfgstr); j = strlen_(outbuf); for (i = 3; i < 9; i++) { /* 10:16 = 6 bytes data */ sprintf(&outbuf[j],"%02x ",pc[i]); j += 3; } outbuf[j++] = '\n'; outbuf[j++] = 0; } else if (psel->record_type == 0xDD) { /* usu Intel OEM string */ int ix = 0; /* Windows reboot reason string from MS ipmidrv.sys */ evtime = (uchar *)&psel->timestamp; eventTime = evtime[0] + (evtime[1] << 8) + (evtime[2] << 16) + (evtime[3] << 24); fmt_time(eventTime, timebuf, sizeof(timebuf)); pc = (uchar *)&psel->generator_id; /* IANA at offset 7 */ mfgstr = get_mfg_str(&pc[0],&mfg); if (fcanonical) sprintf(outbuf,"%04x %c %s %c %s %c %02x %c %06x %c %s %c OEM Event ", psel->record_id, bdelim, timebuf, bdelim, get_sev_str(sev), bdelim, psel->record_type, bdelim, mfg, bdelim, mfgstr, bdelim); else sprintf(outbuf,"%04x %s %s %02x %06x %s OEM Event ", psel->record_id, timebuf, get_sev_str(sev), psel->record_type, mfg, mfgstr ); j = strlen_(outbuf); for (i = 3; i < 9; i++) { /* 10:16 = 6 bytes data */ if (i == 3 || ix == 0) { if (i == 3) ix = pc[i]; sprintf(&outbuf[j],"%02x ",pc[i]); j += 3; } else { if (pc[i] == 0) outbuf[j] = ' '; else sprintf(&outbuf[j],"%c",pc[i]); j += 1; } } outbuf[j++] = '\n'; outbuf[j++] = 0; } else if (psel->record_type >= 0xe0) { /*OEM Record 26.3*/ /* 3 bytes header, 13 bytes data, no timestamp */ pc = (uchar *)&psel->timestamp; /*bytes 4:16*/ if (fcanonical) sprintf(outbuf,"%04x %c %s %c %s %c %02x %c %s %c %s %c OEM Event ", psel->record_id, bdelim, "", bdelim, get_sev_str(sev), bdelim, psel->record_type, bdelim, "", bdelim, "", bdelim); else sprintf(outbuf,"%04x %s %02x OEM Event ", psel->record_id,get_sev_str(sev),psel->record_type); j = strlen_(outbuf); for (i = 0; i < 13; i++) { /* 5:16 = 11 bytes data */ if ((psel->record_type == 0xf0) && (i >= 2)) { /* Linux panic string will be type 0xf0 */ if (pc[i] == 0) break; outbuf[j++] = pc[i]; } else if (psel->record_type == 0xf1) { /* custom ascii string record, type 0xf1 */ if (i == 0) { /*linux panic*/ outbuf[j++] = ':'; outbuf[j++] = ' '; } if (pc[i] == 0) break; outbuf[j++] = pc[i]; } else { sprintf(&outbuf[j],"%02x ",pc[i]); j += 3; } } outbuf[j++] = '\n'; outbuf[j++] = 0; } else if (psel->record_type >= 0xc0) { /*OEM Record 26.3*/ /* 10 bytes header, 6 bytes data, has timestamp */ evtime = (uchar *)&psel->timestamp; eventTime = evtime[0] + (evtime[1] << 8) + (evtime[2] << 16) + (evtime[3] << 24); fmt_time(eventTime, timebuf, sizeof(timebuf)); pc = (uchar *)&psel->generator_id; /* IANA at offset 7 */ if (fcanonical) sprintf(outbuf,"%04x %c %s %c %s %c %02x %c %02x%02x%02x %c %s %c OEM Event ", psel->record_id, bdelim, timebuf, bdelim, get_sev_str(sev), bdelim, psel->record_type, bdelim, pc[2],pc[1],pc[0], bdelim, "", bdelim); else sprintf(outbuf,"%04x %s %s %02x %02x%02x%02x OEM Event ", psel->record_id, timebuf, get_sev_str(sev), psel->record_type, pc[2],pc[1],pc[0] ); j = strlen_(outbuf); for (i = 3; i < 9; i++) { /* 10:16 = 6 bytes data */ sprintf(&outbuf[j],"%02x ",pc[i]); j += 3; } outbuf[j++] = '\n'; outbuf[j++] = 0; } else if (psel->record_type == 0x02) { uchar c = 0; /* most records are record type 2 */ /* Interpret the event by sensor type */ switch(psel->sensor_type) { case 0x20: /*OS Crit Stop*/ i = psel->event_data1 & 0x0f; switch(i) { case 0x00: pstr = "Startup Crit Stop"; sev = SEV_CRIT; break; case 0x02: pstr = "OS Graceful Stop"; break; case 0x03: pstr = "OS Graceful Shutdown"; break; case 0x04: pstr = "PEF Soft-Shutdown"; break; case 0x05: pstr = "Agent Not Responding"; break; case 0x01: /*OS Runtime Critical Stop (panic)*/ default: sev = SEV_CRIT; if (psel->sensor_number == 0) { /*Windows*/ pstr = "Runtime Crit Stop"; } else { /*Linux panic, get string*/ /* Show first 3 chars of panic string */ pstr = mystr; strcpy(mystr,"panic("); for (i = 6; i <= 8; i++) { switch(i) { case 6: c = psel->sensor_number; break; case 7: c = psel->event_data2; break; case 8: c = psel->event_data3; break; } c &= 0x7f; if (c < 0x20) c = '.'; mystr[i] = c; } mystr[9] = ')'; mystr[10] = 0; if (psel->sensor_number & 0x80) strcat(mystr,"Oops!"); if (psel->event_data2 & 0x80) strcat(mystr,"Int!"); if (psel->event_data3 & 0x80) strcat(mystr,"NullPtr!"); } break; } /*end data1 switch*/ break; case 0x01: /*Temperature events*/ if (is_threshold(psel->event_trigger, psel->generator_id)) { pstr = get_misc_desc( psel->generator_id, psel->sensor_type, psel->sensor_number, psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3, &sev); } else { /*else discrete temp event*/ /* data1 should usually be 0x01 */ if (psel->event_trigger & 0x80) strcpy(mystr,"Temp OK"); else strcpy(mystr,"Temp Asserted"); pstr = mystr; } /*end-else discrete*/ break; /* case 0X04 for Fan events is further below. */ case 0x07: /*Processor (CPU)*/ i = psel->event_data1 & 0x0f; if (psel->event_trigger == 0x6f) { /* Processor status sensor */ if (i >= NPROC) i = NPROC - 1; if (i == 7) sev = SEV_INFO; else if (i > 7) sev = SEV_MIN; else sev = SEV_CRIT; sprintf(mystr,"%s",proc_str[i]); pstr = mystr; } else if (psel->event_trigger == 0xef) { sev = SEV_CRIT; if (i >= NPROC) i = NPROC - 1; sprintf(mystr,"%s deasserted",proc_str[i]); pstr = mystr; } else if (psel->sensor_number == 0x80) { /*CATERR*/ char *p1, *p2; sev = SEV_CRIT; switch( psel->event_data2 & 0x0F) { case 1: p1 = "CATERR"; break; case 2: p1 = "CPU Core Error"; break; case 3: p1 = "MSID Mismatch"; break; default: p1 = "Unknown Error"; break; } if (psel->event_data2 & 0x01) p2 = "CPU0"; else if (psel->event_data2 & 0x02) p2 = "CPU1"; else if (psel->event_data2 & 0x04) p2 = "CPU2"; else if (psel->event_data2 & 0x08) p2 = "CPU3"; else p2 = "CPU4"; sprintf(mystr,"%s on %s",p1,p2); pstr = mystr; } else if (psel->event_trigger == 0x03) { if (i) {pstr = "Proc Config Error"; sev = SEV_CRIT;} else {pstr = "Proc Config OK"; sev = SEV_INFO; } } else if (psel->event_trigger == 0x83) { if (i) { pstr = "Proc Config OK"; sev = SEV_INFO; } else { pstr = "Proc Config Error"; sev = SEV_CRIT; } } else { /* else other processor sensor */ i = ((psel->event_trigger & 0x80) >> 7); if (i) { pstr = "ProcErr Deasserted"; sev = SEV_INFO;} else { pstr = "ProcErr Asserted"; sev = SEV_CRIT; } } break; case 0x08: /*Power Supply*/ pstr = NULL; /*falls through to unknown*/ if ((psel->event_trigger == 0x0b) || (psel->event_trigger == 0x8b)) { rv = decode_redund(psel->event_trigger, psel->event_data1, mystr, &sev); if (rv == 0) pstr = mystr; } else { pstr = get_misc_desc( psel->generator_id, psel->sensor_type, psel->sensor_number, psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3, &sev); } break; case 0x09: /*Power Unit*/ if ((psel->event_trigger == 0x0b) || (psel->event_trigger == 0x8b)) { rv = decode_redund(psel->event_trigger, psel->event_data1, mystr, &sev); } else { /*sensor-specific 0x6f/0xef*/ rv = decode_pwrunit(psel->event_trigger, psel->event_data1, mystr, &sev); } if (rv == 0) pstr = mystr; else pstr = NULL; /*falls through to unknown*/ break; case 0x0C: /*Memory*/ i = psel->event_data1 & 0x0f; /*memstr index*/ { /* now get the DIMM index from data2 or data3 */ uchar b2, b3, bdata; b2 = psel->event_data2; b3 = psel->event_data3; if ((vend == VENDOR_INTEL && prod == 0x4311) || (vend == VENDOR_NSC)) { /*mini-BMC*/ bdata = b2; } else if (b3 == 0xff) { /* FF is reserved */ bdata = b2; } else { /* normal case */ bdata = b3; } j = bdata & 0x3f; /* Now i==data1(lo nib) for memstr, j==DIMM index */ if (i == 0) sev = SEV_MIN; /*correctable ECC*/ else sev = SEV_MAJ; if (fdebug) printf("DIMM(%d) vend=%x prod=%x\n",j,vend,prod); msz = sizeof(mdesc); /* For Intel S5500/S2600 see decode_mem_intel */ if (vend == VENDOR_INTEL) { decode_mem_intel(prod,b2,b3,mdesc,&msz); sprintf(mystr,"%s%c %s",mem_str(i),bcomma,mdesc); } else if ((vend == VENDOR_SUPERMICRO) || (vend == VENDOR_SUPERMICROX)) { decode_mem_supermicro(prod,b2,b3,mdesc,&msz); sprintf(mystr,"%s%c %s",mem_str(i),bcomma,mdesc); } else { /*decode_mem_raw*/ decode_mem_default(psel->event_data1,b2,b3,etype,mdesc,&msz); sprintf(mystr,"%s%c %s",mem_str(i),bcomma,mdesc); //old: sprintf(mystr,"%s%c DIMM[%d]",mem_str(i),bcomma,j); /* DIMM[2] = 3rd one (zero-based index) */ } } pstr = mystr; break; case 0x0F: /*System Firmware events, incl POST Errs*/ sev = SEV_MAJ; /*usu major, but platform-specific*/ switch (psel->event_data1 & 0x0f) { case 0x00: /* System firmware errors */ i = psel->event_data2; if (i > NFWERRS) i = NFWERRS; pstr = fwerrs[i].msg; break; case 0x01: /* System firmware hang */ i = psel->event_data2; if (i > NFWSTAT) i = NFWSTAT; sprintf(poststr,"hang%c %s",bcomma, fwstat[i].msg); pstr = poststr; break; case 0x02: /* System firmware progress */ sev = SEV_INFO; i = psel->event_data2; if (i > NFWSTAT) i = NFWSTAT; sprintf(poststr,"prog%c %s",bcomma, fwstat[i].msg); pstr = poststr; break; case 0xa0: /* OEM post codes */ /* OEM post codes in bytes 2 & 3 (lo-hi) */ j = psel->event_data2 | (psel->event_data3 << 8); /* interpret some OEM post codes if -e */ i = decode_post_oem(vend,prod,(ushort)j, poststr,sizeof(poststr)); pstr = poststr; break; default: pstr = get_misc_desc( psel->generator_id, psel->sensor_type, psel->sensor_number, psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3, &sev); if (pstr == NULL) pstr = "POST Event"; /*default string*/ } /*end switch(data1)*/ break; case 0x13: /*Crit Int*/ sev = SEV_CRIT; i = psel->event_data1 & 0x0f; if (i >= NCRITS) i = NCRITS - 1; pstr = crit_int_str[i]; if ((psel->event_trigger == 0x70) || (psel->event_trigger == 0x71)) { uchar bus,dev,func; /* Intel AER< decode PCI bus:dev.func data */ bus = psel->event_data2; dev = ((psel->event_data3 & 0xf8) >> 3); func = (psel->event_data3 & 0x07); sprintf(mystr,"%s (on %02x:%02x.%d)", crit_int_str[i],bus,dev,func); pstr = mystr; } break; case 0x15: /*Board (e.g. IO Module)*/ if ((psel->event_trigger == 0x08) || (psel->event_trigger == 0x88)) { rv = decode_presence(psel->event_trigger, psel->event_data1, mystr, &sev); pstr = mystr; } else pstr = NULL; /*falls through to unknown*/ break; case 0x16: /*Microcontroller (e.g. ME or HDD)*/ // if (psel->event_trigger == 0x0A) // Availability { i = psel->event_data1 & 0x0f; if (i >= N_AVAIL) i = N_AVAIL - 1; if (i >= 4) sev = SEV_MIN; else sev = SEV_INFO; pstr = avail_str[i]; } break; case 0x1D: /*System Boot Initiated*/ i = psel->event_data1 & 0x0f; if (i >= NBOOTI) i = NBOOTI - 1; pstr = boot_init_str[i]; break; case 0x1F: /*OS Boot */ i = psel->event_data1 & 0x0f; if (i >= NOSBOOT) i = NOSBOOT - 1; pstr = osboot_str[i]; break; case 0x21: /*Slot/Con*/ i = psel->event_data1 & 0x0f; if (i >= NSLOTC) i = NSLOTC - 1; if (i == 0) sev = SEV_MAJ; /*Fault*/ else if (i == 8) sev = SEV_MIN; sprintf(mystr,"%s",slot_str[i]); /* could also decode data2/data3 here if valid */ pstr = mystr; break; case 0x22: /*ACPI Power state*/ i = psel->event_data1 & 0x0f; if (i >= NACPIP) i = NACPIP - 1; sprintf(mystr,"%s",acpip_str[i]); pstr = mystr; break; case 0x28: /*Management Subsystem Health*/ i = psel->event_data1 & 0x0f; if (i == 0x04) /*sensor error*/ sprintf(mystr,"Sensor %02x fault",psel->event_data2); else sprintf(mystr,"Other FW HAL error"); pstr = mystr; break; case 0x29: /*Battery*/ if (is_threshold(psel->event_trigger, psel->generator_id)) { pstr = get_misc_desc( psel->generator_id, psel->sensor_type, psel->sensor_number, psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3, &sev); } else { i = psel->event_data1 & 0x0f; if (i >= NBATT) i = NBATT - 1; /* sev defaults to SEV_INFO */ if (psel->event_trigger & 0x80) { /*deasserted*/ sprintf(mystr,"%s",batt_clr[i]); } else { /*asserted*/ sprintf(mystr,"%s",batt_str[i]); if (i == 0) sev = SEV_MIN; else if (i == 1) sev = SEV_MAJ; } pstr = mystr; } break; case 0x2A: /*Session Audit, new for IPMI 2.0*/ i = psel->event_data1 & 0x0f; if (i >= NAUDIT) i = NAUDIT - 1; sprintf(mystr,"%s User%d",audit_str[i], psel->event_data2); /* see also psel->event_data3 for cause/channel*/ pstr = mystr; break; case 0xDC: /*ME Node Manager, for S5500 Urbanna*/ i = psel->event_trigger; if (i & 0x80) { fdeassert = 1; i &= 0x7f; } if (i >= 0x72) i -= 0x72; if (i >= N_NM) i = N_NM - 1; sprintf(mystr,"%s",nm_str[i]); if (fdeassert) strcat(mystr," OK"); n = strlen_(mystr); sprintf(cstr,"%c ",bcomma); j = psel->event_data2; switch(i) { case 0x00: /*0x72 NM Exception*/ j = psel->event_data1; if ((j & 0x08) == 0) { k = j & 0x03; sprintf(&mystr[n], "%sThreshold %d Exceeded",cstr,k); } else { /*Policy event*/ sprintf(&mystr[n], "%sPolicy Time Exceeded",cstr); } sev = SEV_MIN; break; case 0x01: /*0x73 NM Health*/ j &= 0x0f; // if (j >= 0x10) j -= 0x10; if (j >= N_NMH) j = N_NMH - 1; if (j != 5) sev = SEV_MAJ; strcat(mystr,cstr); /*", "*/ strcat(mystr,nmh_str[j]); break; case 0x03: /*0x75 FW Health*/ if (j >= N_NMFW) j = N_NMFW - 1; sev = SEV_MAJ; strcat(mystr,cstr); /*", "*/ strcat(mystr,nmfw_str[j]); break; case 0x02: /*0x74 NM Capabilities*/ default: sev = SEV_MIN; break; } pstr = mystr; break; case 0x04: /*Fan sensor events */ if ((psel->event_trigger == 0x0b) || (psel->event_trigger == 0x8b)) { rv = decode_redund(psel->event_trigger, psel->event_data1, mystr, &sev); pstr = mystr; break; } else if ((psel->event_trigger == 0x08) || (psel->event_trigger == 0x88)) { rv = decode_presence(psel->event_trigger, psel->event_data1, mystr, &sev); pstr = mystr; break; } else if (psel->event_trigger == 0x06) { /* usu psel->event_data1 == 0x01 */ sev = SEV_MIN; strcpy(mystr,"Performance Lags"); pstr = mystr; break; } else if (psel->event_trigger == 0x86) { sev = SEV_INFO; strcpy(mystr,"Performance OK"); pstr = mystr; break; } /* else Fan threshold events handled below, trig=01/81*/ default: /* all other sensor types, see sens_desc */ pstr = get_misc_desc( psel->generator_id, psel->sensor_type, psel->sensor_number, psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3, &sev); break; } /*end switch(sensor_type)*/ if (pstr == NULL) { /* none found, unknown */ mystr[0] = '-'; mystr[1] = 0; pstr = mystr; } /*firmware timestamp is #seconds since 1/1/1970 localtime*/ evtime = (uchar *)&psel->timestamp; eventTime = evtime[0] + (evtime[1] << 8) + (evtime[2] << 16) + (evtime[3] << 24); if (fdebug) { char tbuf[40]; char *tz; char *lctime; strftime(timebuf,sizeof(timebuf), "%x %H:%M:%S %Z", localtime(&eventTime)); strftime(tbuf,sizeof(tbuf), "%x %H:%M:%S %Z", gmtime(&eventTime)); tz = getenv("TZ"); if (tz == NULL) tz = ""; lctime = getenv("LC_TIME"); if (lctime == NULL) lctime = ""; SELprintf("%s\nTZ=%s, LC_TIME=%s, gmtime=%s\n", timebuf,tz,lctime,tbuf); } psensstr = NULL; sensstr[0] = 0; if (fsensdesc) { rv = get_sensor_tag(isdr,psel->generator_id, psel->sensor_number, sensstr, sdr, sizeof(sdr)); if (rv == 0) { fhave_sdr = 1; psensstr = &sensstr[0]; } else rv = 0; /*no sdr but not an error*/ } /*endif fsensdesc*/ if (is_threshold(psel->event_trigger,psel->generator_id)) { /* Also usually ((psel->event_data1 & 0x50) == 0x50) */ /* We know that these two MCs should include the * actual and threshold raw values in data2 & data3 */ if (fsensdesc && fhave_sdr) { double v1, v2; char *u; /* if sdrcache, find_sdr_by_snum got the sdr above */ /* else, GetSDR tried to get the sdr above */ v1 = RawToFloat(psel->event_data2,sdr); v2 = RawToFloat(psel->event_data3,sdr); u = get_unit_type(sdr[20],sdr[21],sdr[22],1); sprintf(datastr, "actual=%.2f %s, threshold=%.2f %s", v1,u, v2,u); } else { // if (fsensdesc == 0 || (rv != 0)) { sprintf(datastr,"act=%02x thr=%02x", psel->event_data2, /*actual raw reading*/ psel->event_data3 ); /*threshold raw value*/ } } else { if (fcanonical) datastr[0] = 0; else sprintf(datastr,"%02x [%02x %02x %02x]", psel->event_trigger, psel->event_data1, psel->event_data2, psel->event_data3 ); } format_event(psel->record_id, eventTime, sev, psel->generator_id, get_sensor_type_desc(psel->sensor_type), psel->sensor_number, psensstr, pstr, datastr, outbuf,szbuf); } /*endif type 2 */ else { /* other misc record type */ if (fdebug) printf("Unrecognized record type %02x\n", psel->record_type); rv = ERR_NOT_FOUND; pc = (uchar *)&psel->record_type; sprintf(outbuf,"%04x Type%02x %s ", psel->record_id,pc[0],get_sev_str(sev)); j = strlen_(outbuf); for (i = 1; i < 14; i++) { sprintf(mystr,"%02x ",pc[i]); strcat(outbuf,mystr); } strcat(outbuf,"\n"); } /*endif misc type*/ return(rv); } /*end decode_sel_entry()*/ static void show_usage(void) { printf("Usage: %s [-bdfhprstux] 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10\n",progname); printf("where -b = interpret Binary raw SEL file, from ipmitool sel writeraw\n"); printf(" -d = get DeviceID for vendor/product-specific events\n"); printf(" -f = interpret File with raw ascii SEL data, from ipmiutil sel -r\n"); printf(" -h = interpret Hex binary raw SEL file (same as -b)\n"); #ifndef ALONE printf(" -o = specify the target vendor IANA number.\n"); #endif printf(" -n = generate New platform event, use last 9 event bytes\n"); printf(" -p = decode PET event bytes, use 34 PET data bytes,\n"); printf(" skipping the first 8 of the 47-byte PET data (-t=all).\n"); printf(" If not specified, assumes a 16-byte IPMI event.\n"); printf(" -r = interpret RAW ascii SEL file (same as -f)\n"); printf(" -s = sensor file with output of 'ipmiutil sensor', used\n"); printf(" to get the PET sensor_type from the sensor_num.\n"); printf(" The default is %s\n",sensfil); printf(" -t = decode PET trap bytes, use all 47 PET data bytes (-p=34)\n"); printf(" If not specified, assumes a 16-byte IPMI event.\n"); printf(" -u = use raw UTC time\n"); printf(" -x = show eXtra debug messages\n"); } /* * decode_raw_sel * input parameters: * raw_file : filename of raw SEL file * mode : 1 = ascii raw from ipmiutil sel -r * 2 = binary hex from ipmiutil sel writeraw {raw_file} */ int decode_raw_sel(char *raw_file, int mode) { FILE *fp; char buff[256]; char msg[132]; uchar hbuf[50]; int fvalid = 0; int len, i; fp = fopen(raw_file,"r"); if (fp == NULL) { printf("Cannot open file %s\n",raw_file); return(ERR_FILE_OPEN); } else { printf("%s",evt_hdr); /*"RecId Date/Time_______*/ if (mode == 1) { /*ascii raw*/ if (fdebug) printf("decoding raw ascii file with IPMI event bytes\n"); while (fgets(buff, 255, fp)) { len = strlen_(buff); fvalid = 0; if (buff[0] >= '0' && (buff[0] <= '9')) fvalid = 1; else if (buff[0] >= 'a' && (buff[0] <= 'f')) fvalid = 1; else if (buff[0] >= 'A' && (buff[0] <= 'F')) fvalid = 1; if (fvalid == 0) continue; for (i = 0; i < 16; i++) { hbuf[i] = _htoi(&buff[i*3]); } decode_sel_entry(hbuf,msg,sizeof(msg)); printf("%s", msg); } /*end while*/ } else { /*hex raw*/ if (fdebug) printf("decoding binary hex file with IPMI event bytes\n"); while (fread(hbuf, 1, 16, fp) == 16) { decode_sel_entry(hbuf,msg,sizeof(msg)); printf("%s", msg); } /*end while*/ } fclose(fp); } return(0); } /* * The events utility interprets standard 16-byte IPMI events into * human-readable form by default. * User must pass raw 16-byte event data from some log text for decoding. * * Sample IPMI event usage: * # ievents fb 07 02 e5 1a b8 44 21 00 03 1d 9a 6f 40 8f ff * RecId Date/Time_______ SEV Src_ Evt_Type___ Sens# Evt_detail - Trig [Evt_data] * 07fb 07/14/06 18:29:57 INF SMI System Boot Initiated #9a Power Up 6f [40 8f ff] * # ievents 14 04 02 BE 35 13 45 33 40 04 0C 08 6F 20 00 04 * RecId Date/Time_______ SEV Src_ Evt_Type___ Sens# Evt_detail - Trig [Evt_data] * 0414 09/21/06 21:00:46 MIN 4033 Memory #08 Correctable ECC, DIMM[4] 6f [20 00 04] * * If fPET, interpret the SNMP Platform Event Trap hex varbind data. * For interpreting the 47-byte hex data from SNMP Platform Event Traps, * specify events -p with the 34 data bytes following the 16-byte GUID. * * Sample SNMP PET Data for events: * 0000: 3C A7 56 85 08 C5 11 D7 C3 A2 00 04 23 BC AC 12 * 0010: 51 14 11 72 38 58 FF FF 20 20 00 10 83 07 01 41 * 0020: 0F FF 00 00 00 00 00 19 00 00 01 57 00 22 C1 * * Sample events -p command from above data: * # ievents -p C3 A2 00 04 23 BC AC 12 51 14 11 72 38 58 FF FF 20 20 00 10 83 07 01 41 0F FF 00 00 00 00 * RecId Date/Time_______ SEV Src_ Evt_Type___ Sens# Evt_detail - Trig [Evt_data] * 0014 04/11/07 12:03:20 INF BMC System Event #83 OEM System Booted 6f [41 0f ff] * * Platform Event Trap Format * Offset Len Meaning * 0 16 System GUID * 16 2 Sequence Number/Cookie * 18 4 Local Timestamp * 22 2 UTC Offset * 24 1 Trap Source Type (usu 0x20) * 25 1 Event Source Type (usu 0x20) * 26 1 Event Severity * 27 1 Sensor Device * 28 1 Sensor Number * 29 1 Entity * 30 1 Entity Instance * 31 8 Event Data (8 bytes max, 3 bytes used) * 39 1 Language Code (usu 0x19/25. = English) * 40 4 Manufacturer IANA number (Intel=0x000157) * 44 1-N OEM data, C1="No more fields" * If Intel (0x000157): * 44 2 Product ID * 46 1 0xC1 (No more fields) */ #if defined(ALONE) #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #else /* #elif defined(METACOMMAND) or if libipmiutil */ int i_events(int argc, char **argv) #endif { uchar buf[50]; uchar msg[132]; uchar *pmsg; int i, j, len; char fPET = 0; char frawfile = 0; char fhexfile = 0; int rv = 0; char c; uchar b = 0; #ifndef ALONE uchar devid[16]; #endif #if defined(METACOMMAND) char *p; #endif printf("%s version %s\n",progname,progver); if (argc > 0) { argc--; argv++; } /*skip argv[0], program name*/ /* ievents getopt: [ -bdfhnoprstux -NPRUEFJTVY */ while ((argc > 0) && argv[0][0] == '-') { c = argv[0][1]; switch(c) { case 'x': fdebug = 1; break; case 'd': fgetdevid = 1; break; /*get device id (vendor, product)*/ case 'n': fnewevt = 1; break; /* generate New event */ case 'p': /* PET format, minus first 8 bytes*/ /* This is important for some SNMP trap receivers that obscure * the first 8 bytes of the trap data */ fPET = 1; /*incoming data is in PET format*/ break; case 'u': futc = 1; break; /*use raw UTC time*/ case 'M': /* Set manufacturer IANA */ case 'o': /*specify OEM IANA manufacturer id */ if (argc > 1) { /*next argv is IANA number */ iopt = atoi(argv[1]); printf("setting IANA to %d (%s)\n",iopt,get_iana_str(iopt)); set_iana(iopt); argc--; argv++; } else { printf("option -%c requires an argument\n",c); rv = ERR_BAD_PARAM; } break; case 't': /*PET format Trap, use all data*/ /* This may be helpful if all bytes are available, or if * the GUID is relevant. */ fPET = 1; /*incoming data is in PET format*/ pet_guid = 16; break; case 'f': case 'r': /* interpret raw ascii SEL file from optarg */ frawfile = 1; if (argc > 1) { /*next argv is filename*/ len = strlen_(argv[1]); if (len >= sizeof(rawfil)) len = sizeof(rawfil) - 1; strncpy(rawfil,argv[1],len); rawfil[len] = 0; /*stringify*/ argc--; argv++; } else { printf("option -%c requires a filename argument\n",c); rv = ERR_BAD_PARAM; } break; case 'b': case 'h': /* interpret raw binary/hex SEL file from optarg */ fhexfile = 1; if (argc > 1) { /*next argv is filename*/ len = strlen_(argv[1]); if (len >= sizeof(rawfil)) len = sizeof(rawfil) - 1; strncpy(rawfil,argv[1],len); rawfil[len] = 0; /*stringify*/ argc--; argv++; } else { printf("option -%c requires a filename argument\n",c); rv = ERR_BAD_PARAM; } break; case 's': /* get sensor file from optarg */ if (argc > 1) { /*next argv is filename*/ FILE *fp; len = strlen_(argv[1]); if (len >= sizeof(sensfil)) len = sizeof(sensfil) - 1; strncpy(sensfil,argv[1],len); sensfil[len] = 0; /*stringify*/ fp = fopen(sensfil,"r"); if (fp == NULL) { printf("cannot open file %s\n",sensfil); rv = ERR_FILE_OPEN; } else fclose(fp); argc--; argv++; } else { printf("option -%c requires a filename argument\n",c); rv = ERR_BAD_PARAM; } fsensdesc = 2; break; #if defined(METACOMMAND) case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ if (c == 'Y' || c == 'E') p = NULL; else if (argc <= 1) { printf("option -%c requires an argument\n",c); rv = ERR_BAD_PARAM; } else { /* has an optarg */ p = argv[1]; argc--; argv++; } if (rv == 0) parse_lan_options(c,p,fdebug); break; #endif default: /*unknown option*/ printf("Unknown option -%c\n",c); show_usage(); rv = ERR_USAGE; goto do_exit; break; } argc--; argv++; } /*end while options*/ len = argc; /*number of data bytes*/ if (!fPET && len > 16) len = 16; /* IPMI event max is 16 */ if (frawfile || fhexfile) len = 0; else if (fnewevt) { if (len < 9) { printf("Need 9 bytes for a New event, got %d bytes input\n",len); show_usage(); rv = ERR_BAD_PARAM; } } else if (len < 16) { printf("Need 16 bytes for an IPMI event, got %d bytes input\n",len); show_usage(); rv = ERR_BAD_PARAM; } if (rv != 0) goto do_exit; #ifndef ALONE if (fgetdevid || fsensdesc) rv = ipmi_getdeviceid( devid, sizeof(devid),fdebug); /*sets mfgid*/ #endif for (i = 0; i < len; i++) { if (fPET) msg[i] = _htoi(argv[i]); else buf[i] = _htoi(argv[i]); } if (fPET != 0) /*PET, reorder bytes to std event format*/ { uchar snum, styp; int timestamp; int yrs, time2; char sensdesc[100]; int mfg; pmsg = &msg[pet_guid]; /*pet_guid=8, skip the GUID*/ if (fdebug) { printf("decoding IPMI PET event bytes\n"); dump_buf("PET buffer",msg,len,1); } /* pmsg[ 9] is event source type (gen id, usu 0x20) */ /* pmsg[10] is event severity */ /* pmsg[11] is sensor device */ /* pmsg[12] is sensor number */ /* pmsg[13] is Entity */ snum = pmsg[12]; styp = entity2sensor_type(pmsg[13]); rv = get_sensdesc(pmsg[9],snum,sensdesc,&i,NULL); if (rv == 0) { styp = (uchar)i; if (fdebug) printf("sensor[%02x]: %s\n",snum,sensdesc); set_sel_opts(2,0, NULL,fdebug,futc); } else { if (rv == ERR_NOT_FOUND) { printf("Cannot find snum %02x in %s\n",snum,sensfil); printf("Resolve this by doing 'ipmiutil sensor >sensorX.txt' " "on a system similar\nto the target, then use " "'ipmiutil events -s sensorX.txt ...'\n"); } /* Try GetSensorType(), which will work if local IPMI. */ rv = GetSensorType(snum,&b,NULL); if (fdebug) printf("sensor[%02x]: GetSensorType rv=%d stype=%x\n", snum,rv,b); if (rv == 0) styp = b; } buf[0] = pmsg[1]; /*record id (sequence num)*/ buf[1] = 0; /* was pmsg[0]; */ buf[2] = 0x02; /*event type*/ #ifdef RAW buf[3] = pmsg[5]; /*timestamp*/ buf[4] = pmsg[4]; /*timestamp*/ buf[5] = pmsg[3]; /*timestamp*/ buf[6] = pmsg[2]; /*timestamp*/ #else timestamp = pmsg[5] + (pmsg[4] << 8) + (pmsg[3] << 16) + (pmsg[2] << 24); /* add 28 years, includes 7 leap days, less 1 hour TZ fudge */ // yrs = ((3600 * 24) * 365 * 28) + (7 * (3600 * 24)) - 3600; yrs = 0x34aace70; time2 = timestamp + yrs; if (fdebug) printf("timestamp: %08x + %08x = %08x\n",timestamp,yrs,time2); buf[3] = time2 & 0x000000ff; /*timestamp*/ buf[4] = (time2 & 0x0000ff00) >> 8; /*timestamp*/ buf[5] = (time2 & 0x00ff0000) >> 16; /*timestamp*/ buf[6] = (time2 & 0xff000000) >> 24; /*timestamp*/ #endif buf[7] = pmsg[9]; /*generator_id*/ buf[8] = 0; buf[9] = 0x04; /*evm_rev*/ buf[10] = styp; /*derived sensor type, from above */ buf[11] = snum; /*sensor number*/ /* set the event trigger based on context */ switch(styp) { /*set the event trigger*/ case 0x12: buf[12] = 0x6f; break; /*system event (sensor-specific)*/ case 0x09: buf[12] = 0x0b; break; /*Power Unit*/ case 0x01: /*temp*/ case 0x02: /*voltage*/ case 0x03: /*current*/ case 0x04: /*fan*/ if (pmsg[10] == 0x04) buf[12] = 0x81; /*info severity, ok*/ else buf[12] = 0x01; /* threshold asserted*/ break; default: buf[12] = pmsg[14]; /*event trigger = Entity Instance */ /*Note that Entity Instance will not match an event trigger*/ buf[12] = 0x6f; /*set trigger to sensor-specific*/ break; } memcpy(&buf[13],&pmsg[15],3); /*event data*/ mfg = pmsg[27] + (pmsg[26] << 8) + (pmsg[25] << 16); if (fdebug) { printf("PET severity=%02x, mfgId=%02x%02x%02x%02x\n", pmsg[10], pmsg[24], pmsg[25], pmsg[26], pmsg[27]); dump_buf("IPMI event",buf,16,0); } if (mfg == VENDOR_SUN) { /* Sun = 0x00002A, extra OEM data */ j = 28 + pet_guid; /*offset 28+16=44 (OEM data) */ pmsg = &msg[j]; for (i = 0; (i+j) < len; ) { if (pmsg[i] == 0xC1) break; if (i == 0) i += 2; /* 2-byte header 0x0c 0x01 */ else if (pmsg[i] == 0x80) { /* 3-byte header, usu strings */ if (pmsg[i+2] == 0x03) printf(" %s\n",&pmsg[i+3]); i += (3 + pmsg[i+1]); } else i++; } } decode_sel_entry(buf,(char *)msg,sizeof(msg)); printf("%s", evt_hdr); /*"RecId Date/Time_______*/ printf("%s", msg); } else if (fnewevt) { rv = new_event(buf,len); /*do new platform event*/ } else if (frawfile) { rv = decode_raw_sel(rawfil,1); /*ascii raw data from file */ } else if (fhexfile) { rv = decode_raw_sel(rawfil,2); /*binary/hex raw data from file*/ } else { if (fdebug) printf("decoding standard IPMI event bytes\n"); if (fdebug) dump_buf("IPMI event",buf,16,0); set_sel_opts(2,0, NULL,fdebug,futc); rv = decode_sel_entry(buf,(char *)msg,sizeof(msg)); /* show header for the event record */ printf("%s", evt_hdr); /*"RecId Date/Time_______*/ printf("%s", msg); } do_exit: #ifndef METACOMMAND printf("%s, %s\n",progname,decode_rv(rv)); #endif return(rv); } // #endif /* end ievents.c */ ipmiutil-3.1.9/util/iekanalyzer.c0000644000000000000000000045053214144515623015533 0ustar rootroot/* * iekanalyzer.c * Handle FRU EKey Analyzer functions * * Change history: * 09/08/2010 ARCress - included in source tree * *--------------------------------------------------------------------- */ /* * Copyright (c) 2007 Kontron Canada, Inc. All Rights Reserved. * * Base on code from * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #include #include #include #include #ifdef WIN32 #include #include "getopt.h" #else #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include "ipmicmd.h" #include "iekanalyzer.h" #ifdef HAVE_EK extern int verbose; /*ipmilanplus.c*/ extern void lprintf(int level, const char * format, ...); /*ipmilanplus.c*/ extern void set_loglevel(int level); /* fseek wrapper for size_t/long compile warnings */ static int fseek_(FILE *fp, size_t offset, int whence) { return(fseek(fp, (long)offset, whence)); } /***************************************************************** * CONSTANT *****************************************************************/ const int ERROR_STATUS = -1; const int OK_STATUS = 0; const char * STAR_LINE_LIMITER = "*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*"; const char * EQUAL_LINE_LIMITER = "================================================================="; const int SIZE_OF_FILE_TYPE = 3; const unsigned char AMC_MODULE = 0x80; const int PICMG_ID_OFFSET = 3; #define MAX_ARGC (MAX_FILE_NUMBER+4) /*8+4=12*/ #define COMPARE_CANDIDATE 2 /*In AMC.0 or PICMG 3.0 specification offset start from 0 with 3 bytes of * Mfg.ID, 1 byte of Picmg record Id, and * 1 byte of format version, so the data offset start from 5 */ #define LOWER_OEM_TYPE 0xf0 #define UPPER_OEM_TYPE 0xfe const int START_DATA_OFFSET = 5; const unsigned char DISABLE_PORT = 0x1f; const struct valstr ipmi_ekanalyzer_module_type[] = { { ON_CARRIER_FRU_FILE, "On-Carrier Device" }, { A1_AMC_FRU_FILE, "AMC slot A1" }, { A2_AMC_FRU_FILE, "AMC slot A2" }, { A3_AMC_FRU_FILE, "AMC slot A3" }, { A4_AMC_FRU_FILE, "AMC slot A4" }, { B1_AMC_FRU_FILE, "AMC slot B1" }, { B2_AMC_FRU_FILE, "AMC slot B2" }, { B3_AMC_FRU_FILE, "AMC slot B3" }, { B4_AMC_FRU_FILE, "AMC slot B4" }, { RTM_FRU_FILE, "RTM" }, /*This is OEM specific module*/ { CONFIG_FILE, "Configuration file" }, { SHELF_MANAGER_FRU_FILE, "Shelf Manager" }, { 0xffff , NULL }, }; const struct valstr ipmi_ekanalyzer_IPMBL_addr[] = { { 0x72, "AMC slot A1" }, { 0x74, "AMC slot A2" }, { 0x76, "AMC slot A3" }, { 0x78, "AMC slot A4" }, { 0x7a, "AMC slot B1" }, { 0x7c, "AMC slot B2" }, { 0x7e, "AMC slot B3" }, { 0x80, "AMC slot B4" }, { 0x90, "RTM"}, /*This is OEM specific module*/ { 0xffff , NULL }, }; const struct valstr ipmi_ekanalyzer_link_type[] = { { 0x00, "Reserved" }, { 0x01, "Reserved" }, { 0x02, "AMC.1 PCI Express" }, { 0x03, "AMC.1 PCI Express Advanced Switching" }, { 0x04, "AMC.1 PCI Express Advanced Switching" }, { 0x05, "AMC.2 Ethernet" }, { 0x06, "AMC.4 Serial RapidIO" }, { 0x07, "AMC.3 Storage" }, /*This is OEM specific module*/ { 0xf0, "OEM Type 0"}, { 0xf1, "OEM Type 1"}, { 0xf2, "OEM Type 2"}, { 0xf3, "OEM Type 3"}, { 0xf4, "OEM Type 4"}, { 0xf5, "OEM Type 5"}, { 0xf6, "OEM Type 6"}, { 0xf7, "OEM Type 7"}, { 0xf8, "OEM Type 8"}, { 0xf9, "OEM Type 9"}, { 0xfa, "OEM Type 10"}, { 0xfb, "OEM Type 11"}, { 0xfc, "OEM Type 12"}, { 0xfd, "OEM Type 13"}, { 0xfe, "OEM Type 14"}, { 0xff , "Reserved" }, }; /*Reference: AMC.1 specification*/ const struct valstr ipmi_ekanalyzer_extension_PCIE[] = { { 0x00, "Gen 1 capable - non SSC" }, { 0x01, "Gen 1 capable - SSC" }, { 0x02, "Gen 2 capable - non SSC" }, { 0x03, "Gen 3 capable - SSC" }, { 0x0f, "Reserved"}, }; /*Reference: AMC.2 specification*/ const struct valstr ipmi_ekanalyzer_extension_ETHERNET[] = { { 0x00, "1000BASE-BX (SerDES Gigabit) Ethernet link" }, { 0x01, "10GBASE-BX4 10 Gigabit Ethernet link" }, }; /*Reference: AMC.3 specification*/ const struct valstr ipmi_ekanalyzer_extension_STORAGE[] = { { 0x00, "Fibre Channel (FC)" }, { 0x01, "Serial ATA (SATA)" }, { 0x02, "Serial Attached SCSI (SAS/SATA)" }, }; const struct valstr ipmi_ekanalyzer_asym_PCIE[] = { { 0x00, "exact match"}, { 0x01, "provides a Primary PCI Express Port" }, { 0x02, "provides a Secondary PCI Express Port" }, }; const struct valstr ipmi_ekanalyzer_asym_STORAGE[] = { { 0x00, "FC or SAS interface {exact match}" }, { 0x01, "SATA Server interface" }, { 0x02, "SATA Client interface" }, { 0x03, "Reserved" }, }; const struct valstr ipmi_ekanalyzer_picmg_record_id[] = { { 0x04, "Backplane Point to Point Connectivity Record" }, { 0x10, "Address Table Record" }, { 0x11, "Shelf Power Distribution Record" }, { 0x12, "Shelf Activation and Power Management Record" }, { 0x13, "Shelf Manager IP Connection Record" }, { 0x14, "Board Point to Point Connectivity Record" }, { 0x15, "Radial IPMB-0 Link Mapping Record" }, { 0x16, "Module Current Requirements Record" }, { 0x17, "Carrier Activation and Power Management Record" }, { 0x18, "Carrier Point-to-Point Connectivity Record" }, { 0x19, "AdvancedMC Point-to-Point Connectivity Record" }, { 0x1a, "Carrier Information Table" }, { 0x1b, "Shelf Fan Geography Record" }, { 0x2c, "Carrier Clock Point-to-Point Connectivity Record" }, { 0x2d, "Clock Configuration Record" }, }; struct ipmi_ek_multi_header { struct fru_multirec_header header; unsigned char * data; struct ipmi_ek_multi_header * prev; struct ipmi_ek_multi_header * next; }; struct ipmi_ek_amc_p2p_connectivity_record{ unsigned char guid_count; struct fru_picmgext_guid * oem_guid; unsigned char rsc_id; unsigned char ch_count; struct fru_picmgext_amc_channel_desc_record * ch_desc; unsigned char link_desc_count; struct fru_picmgext_amc_link_desc_record * link_desc; int * matching_result; /*For link descriptor comparision*/ }; /***************************************************************************** * Function prototype ******************************************************************************/ /* global variables */ static char * progname = "iekanalyzer"; static char * progver = "1.00"; static char fdebug = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; #ifndef HAVE_LANPLUS /* define these routines in ipmilanplus.c if no lanplus/helper.c */ extern const char * val2str(uint16_t val, const struct valstr *vs); #endif /**************************************************************************** * command Functions *****************************************************************************/ static int ipmi_ekanalyzer_print( int argc, char * opt, char ** filename, int * file_type ); static tboolean ipmi_ekanalyzer_ekeying_match( int argc, char * opt, char ** filename, int * file_type ); /**************************************************************************** * Linked list Functions *****************************************************************************/ static void ipmi_ek_add_record2list( struct ipmi_ek_multi_header ** record, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last ); static void ipmi_ek_display_record( struct ipmi_ek_multi_header * record, struct ipmi_ek_multi_header * list_head, struct ipmi_ek_multi_header * list_last ); static void ipmi_ek_remove_record_from_list( struct ipmi_ek_multi_header * record, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last ); static int ipmi_ekanalyzer_fru_file2structure( char * filename, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_record, struct ipmi_ek_multi_header ** list_last ); /**************************************************************************** * Ekeying match Functions *****************************************************************************/ static int ipmi_ek_matching_process( int * file_type, int index1, int index2, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last, char * opt, struct ipmi_ek_multi_header * pphysical ); static int ipmi_ek_get_resource_descriptor( int port_count, int index, struct fru_picmgext_carrier_p2p_descriptor * port_desc, struct ipmi_ek_multi_header * record ); static int ipmi_ek_create_amc_p2p_record( struct ipmi_ek_multi_header * record, struct ipmi_ek_amc_p2p_connectivity_record * amc_record ); static int ipmi_ek_compare_link( struct ipmi_ek_multi_header * physic_record, struct ipmi_ek_amc_p2p_connectivity_record record1, struct ipmi_ek_amc_p2p_connectivity_record record2, char * opt, int file_type1, int file_type2 ); static tboolean ipmi_ek_compare_channel_descriptor( struct fru_picmgext_amc_channel_desc_record ch_desc1, struct fru_picmgext_amc_channel_desc_record ch_desc2, struct fru_picmgext_carrier_p2p_descriptor * port_desc, int index_port, unsigned char rsc_id ); static int ipmi_ek_compare_link_descriptor( struct ipmi_ek_amc_p2p_connectivity_record record1, int index1, struct ipmi_ek_amc_p2p_connectivity_record record2, int index2 ); static int ipmi_ek_compare_asym( unsigned char asym[COMPARE_CANDIDATE] ); static int ipmi_ek_compare_number_of_enable_port( struct fru_picmgext_amc_link_desc_record link_desc[COMPARE_CANDIDATE] ); static int ipmi_ek_check_physical_connectivity( struct ipmi_ek_amc_p2p_connectivity_record record1, int index1, struct ipmi_ek_amc_p2p_connectivity_record record2, int index2, struct ipmi_ek_multi_header * record, int filetype1, int filetype2, char * option ); /**************************************************************************** * Display Functions *****************************************************************************/ static int ipmi_ek_display_fru_header( char * filename ); static void ipmi_ek_display_fru_header_detail( char * filename ); static void ipmi_ek_display_chassis_info_area( FILE * input_file, long offset ); static size_t ipmi_ek_display_board_info_area( FILE * input_file, char * board_type, unsigned int * board_length ); static void ipmi_ek_display_product_info_area( FILE * input_file, long offset ); static tboolean ipmi_ek_display_link_descriptor( int file_type, unsigned char rsc_id, char * str, struct fru_picmgext_amc_link_desc_record link_desc ); static void ipmi_ek_display_oem_guid( struct ipmi_ek_amc_p2p_connectivity_record amc_record1 ); static int ipmi_ek_diplay_carrier_connectivity( struct ipmi_ek_multi_header * record ); static int ipmi_ek_display_power( int argc, char * opt, char ** filename, int * file_type ); static void ipmi_ek_display_current_descriptor( struct fru_picmgext_carrier_activation_record car, struct fru_picmgext_activation_record * cur_desc, char * filename ); static void ipmi_ek_display_backplane_p2p_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_address_table_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_shelf_power_distribution_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_shelf_activation_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_shelf_ip_connection_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_board_p2p_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_radial_ipmb0_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_amc_current_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_amc_activation_record ( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_amc_p2p_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_amc_carrier_info_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_clock_carrier_p2p_record( struct ipmi_ek_multi_header * record ); static void ipmi_ek_display_clock_config_record( struct ipmi_ek_multi_header * record ); /************************************************************************** * * Function name: ipmi_ekanalyzer_usage * * Description : Print the usage (help menu) of ekeying analyzer tool * * Restriction : None * * Input : None * * Output : None * * Global : None * * Return : None * ***************************************************************************/ static void ipmi_ekanalyzer_usage( void ) { char * help_message = "Ekeying analyzer tool version 1.00 \r\n\ ekanalyzer Commands: \r\n\ print [carrier | power | all] ... \r\n\ frushow \r\n\ summary [match | unmatch | all] ... \r\n\ "; printf("%s",help_message); fflush(stdout); } /************************************************************************** * * Function name: ipmi_ek_get_file_type * * Description: this function takes an argument, then xtract the file type and * convert into module type (on carrier, AMC,...) value. * * * Restriction: None * * Input: argument: strings contain the type and the name of the file * together * * Output: None * * Global: None * * Return: Return value of module type: On carrier FRU file, A1 FRUM file... * if the file type is invalid, it return -1. See structure * ipmi_ekanalyzer_module_type for a list of valid type. ***************************************************************************/ static int ipmi_ek_get_file_type( char * argument ) { // int index_name=0; int filetype = ERROR_STATUS; if( strlen (argument) > MIN_ARGUMENT ){ if( strncmp( argument, "oc=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = ON_CARRIER_FRU_FILE; } else if( strncmp( argument, "a1=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = A1_AMC_FRU_FILE; } else if( strncmp( argument, "a2=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = A2_AMC_FRU_FILE; } else if( strncmp( argument, "a3=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = A3_AMC_FRU_FILE; } else if( strncmp( argument, "a4=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = A4_AMC_FRU_FILE; } else if( strncmp( argument, "b1=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = B1_AMC_FRU_FILE; } else if( strncmp( argument, "b2=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = B2_AMC_FRU_FILE; } else if( strncmp( argument, "b3=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = B3_AMC_FRU_FILE; } else if( strncmp( argument, "b4=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = B4_AMC_FRU_FILE; } else if( strncmp( argument, "rt=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = RTM_FRU_FILE; } else if( strncmp( argument, "rc=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = CONFIG_FILE; } else if( strncmp( argument, "sm=", SIZE_OF_FILE_TYPE ) == 0 ) { filetype = SHELF_MANAGER_FRU_FILE; } else{ filetype = ERROR_STATUS; } } return filetype; } /************************************************************************** * * Function name: ipmi_ekanalyzer_main * * Description: Main program of ekeying analyzer. It calls the appropriate * function according to the command received. * * Restriction: None * * Input: ipmi_intf * intf: ? * int argc : number of argument received * int ** argv: argument strings * * Output: None * * Global: None * * Return: OK_STATUS as success or ERROR_STATUS as error * ***************************************************************************/ int ipmi_ekanalyzer_main( void * intf, int argc, char ** argv ) { int rc = ERROR_STATUS; int file_type[MAX_FILE_NUMBER]; char * filename[MAX_FILE_NUMBER]; unsigned int argument_offset = 0; unsigned int type_offset = 0; /*list des multi record*/ struct ipmi_ek_multi_header * list_head = NULL; struct ipmi_ek_multi_header * list_record = NULL; struct ipmi_ek_multi_header * list_last = NULL; set_loglevel(LOG_NOTICE); if ( (argc == 0) || ( (argc - 1) > MAX_FILE_NUMBER ) ){ lprintf(LOG_ERR, "Too few or too many arguments."); ipmi_ekanalyzer_usage(); rc = ERR_BAD_PARAM; } else if ( strcmp(argv[argument_offset], "help") == 0) { ipmi_ekanalyzer_usage(); rc = ERR_USAGE; } else if ( (strcmp(argv[argument_offset], "frushow") == 0) && (argc > (MIN_ARGUMENT-1) ) ){ for ( type_offset = 0; (int)type_offset < (argc-1); type_offset++ ){ argument_offset++; file_type[type_offset] = ipmi_ek_get_file_type (argv[argument_offset]); if ( file_type[type_offset] != ERROR_STATUS ){ if ( file_type[type_offset] != CONFIG_FILE ){ /* because of strlen doesn't count '\0', we need to add 1 byte for * this character to filename size */ filename[type_offset] = malloc( strlen(argv[argument_offset]) + 1 - SIZE_OF_FILE_TYPE ); if( filename[type_offset] != NULL ){ strcpy(filename[type_offset], &argv[argument_offset][SIZE_OF_FILE_TYPE]); printf("Start converting file '%s'...\n", filename[type_offset]); /* Display FRU header offset */ rc = ipmi_ek_display_fru_header (filename[type_offset]); if ( rc != ERROR_STATUS ){ /* Display FRU header info in detail record */ ipmi_ek_display_fru_header_detail (filename[type_offset]); /* Convert from binary data into multi record structure */ rc = ipmi_ekanalyzer_fru_file2structure ( filename[type_offset], &list_head, &list_record, &list_last ); ipmi_ek_display_record ( list_record, list_head, list_last ); /* Remove record of list */ while ( list_head != NULL ){ ipmi_ek_remove_record_from_list( list_head, &list_head,&list_last ); if (verbose > 1) printf("record has been removed!\n"); } } free (filename[type_offset]); } } } else{ lprintf(LOG_ERR, "Invalid file type!"); lprintf(LOG_ERR, " ekanalyzer frushow ..."); } } } else if ( (strcmp(argv[argument_offset], "print") == 0) || (strcmp(argv[argument_offset], "summary") == 0) ){ /*Display help of the correspond command if there is not enought argument * passing in command line */ if ( argc < MIN_ARGUMENT ){ printf("Too few argument! \n"); if ( strcmp(argv[argument_offset], "print") == 0 ){ lprintf(LOG_ERR, " ekanalyzer print [carrier/power/all]" " [xx=frufile]" ); } else{ lprintf(LOG_ERR, " ekanalyzer summary [match/ unmatch/ all]" " [xx=frufile]" ); } } else{ char * option; /*index=1 indicates start position of first file name in command line*/ int index = 1; int filename_size=0; argument_offset++; if ( (strcmp(argv[argument_offset], "carrier") == 0) || (strcmp(argv[argument_offset], "power") == 0) || (strcmp(argv[argument_offset], "all") == 0) ){ option = argv[argument_offset]; index ++; argc--; } else if ( ( strcmp(argv[argument_offset], "match") == 0 ) || ( strcmp(argv[argument_offset], "unmatch") == 0 ) ){ option = argv[argument_offset]; index ++; argc--; } /*since the command line must receive xx=filename, so the position of * "=" sign is 2 */ else if ( strncmp(&argv[argument_offset][2], "=", 1) == 0 ){ option = "default"; /* Since there is no option from user, the first argument * becomes first file type */ index = 1; /* index of argument */ } else{ option = "invalid"; printf("Invalid option '%s'\n", argv[argument_offset]); argument_offset--; if (strcmp(argv[0], "print") == 0){ lprintf (LOG_ERR, " ekanalyzer print [carrier/power/all]" " [xx=frufile]" ); } else{ lprintf (LOG_ERR, " ekanalyzer summary [match/ unmatch/ all]" " [xx=frufile]" ); } rc = ERROR_STATUS; } if ( strcmp(option, "invalid") != 0 ){ int i=0; for ( i = 0; i < (argc-1); i++){ file_type[i] = ipmi_ek_get_file_type (argv[index]); if ( file_type[i] == ERROR_STATUS ){ /* display the first 2 charactors (file type) of argument */ lprintf(LOG_ERR, "Invalid file type: %c%c\n", argv[index][0], argv[index][1]); ipmi_ekanalyzer_usage(); rc = ERROR_STATUS; break; } /*size is equal to string size minus 3 bytes of file type plus * 1 byte of '\0' since the strlen doesn't count the '\0' */ filename_size = strlen_( argv[index] ) - SIZE_OF_FILE_TYPE + 1; if ( filename_size > 0 ){ filename[i] = malloc( filename_size ); if (filename[i] != NULL) strcpy( filename[i], &argv[index][SIZE_OF_FILE_TYPE] ); } rc = OK_STATUS; index++; } if ( rc != ERROR_STATUS ){ if (verbose > 0){ for (i = 0; i < (argc-1); i++){ printf ("Type: %s, ", val2str((uint16_t)file_type[i], ipmi_ekanalyzer_module_type)); printf("file name: %s\n", filename[i]); } } if (strcmp(argv[0], "print") == 0){ rc = ipmi_ekanalyzer_print( (argc-1), option, filename, file_type); } else{ rc = ipmi_ekanalyzer_ekeying_match( (argc-1), option, filename, file_type); } for (i = 0; i < (argc-1); i++){ if (filename[i] != NULL){ free (filename[i]); } } } /* End of ERROR_STATUS */ } /* End of comparison of invalid option */ } /* End of else MIN_ARGUMENT */ } /* End of print or summary option */ else{ lprintf(LOG_ERR, "Invalid ekanalyzer command: %s", argv[0]); ipmi_ekanalyzer_usage(); rc = ERROR_STATUS; } return rc; } /************************************************************************** * * Function name: ipmi_ekanalyzer_print * * Description: this function will display the topology, power or both * information together according to the option that it received. * * Restriction: None * * Input: int argc: number of the argument received * char* opt: option string that will tell what to display * char** filename: strings that contained filename of FRU data binary file * int* file_type: a pointer that contain file type (on carrier file, * a1 file, b1 file...). See structure * ipmi_ekanalyzer_module_type for a list of valid type * * Output: None * * Global: None * * Return: return 0 as success and -1 as error. * ***************************************************************************/ static int ipmi_ekanalyzer_print( int argc,char * opt, char ** filename, int * file_type ) { int return_value = OK_STATUS; /*Display carrier topology*/ if ( (strcmp(opt, "carrier") == 0) || (strcmp(opt, "default") == 0) ){ tboolean found_flag = FALSE; int index = 0; int index_name[MAX_ARGC]; int list = 0; /*list of multi record*/ struct ipmi_ek_multi_header * list_head[MAX_ARGC]; struct ipmi_ek_multi_header * list_record[MAX_ARGC]; struct ipmi_ek_multi_header * list_last[MAX_ARGC]; for ( list=0; list < argc; list++ ){ list_head[list] = NULL; list_record[list] = NULL; list_last[list] = NULL; } list=0; /* reset list count */ for ( index = 0; index < argc; index++ ){ if ( file_type[index] == ON_CARRIER_FRU_FILE ){ index_name[list] = index; return_value = ipmi_ekanalyzer_fru_file2structure( filename[index], &list_head[list], &list_record[list], &list_last[list] ); list++; found_flag = TRUE; } } if ( !found_flag ){ printf("No carrier file has been found\n"); return_value = ERROR_STATUS; } else{ int i = 0; for ( i = 0; i < argc; i++ ){ /*this is a flag to advoid displaying the same data multiple time*/ tboolean first_data = TRUE; for ( list_record[i] = list_head[i]; list_record[i] != NULL; list_record[i] = list_record[i]->next ){ if ( list_record[i]->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_P2P ){ if ( first_data ){ printf("%s\n", STAR_LINE_LIMITER); printf("From Carrier file: %s\n", filename[index_name[i]]); first_data = FALSE; } return_value = ipmi_ek_diplay_carrier_connectivity( list_record[i] ); } else if ( list_record[i]->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_INFO ){ /*See AMC.0 specification Table3-3 for mor detail*/ #define COUNT_OFFSET 6 if ( first_data ){ printf("From Carrier file: %s\n", filename[index_name[i]]); first_data = FALSE; } printf(" Number of AMC bays supported by Carrier: %d\n", list_record[i]->data[COUNT_OFFSET] ); } } } /*Destroy the list of record*/ for ( i = 0; i < argc; i++ ){ while ( list_head[i] != NULL ){ ipmi_ek_remove_record_from_list( list_head[i], &list_head[i], &list_last[i] ); } /* display deleted result when we reach the last record */ if ( ( i == (list-1) ) && verbose ) printf("Record list has been removed successfully\n"); } } } else if ( (strcmp(opt, "power") == 0) ){ printf("Print power information\n"); return_value = ipmi_ek_display_power(argc, opt, filename, file_type); } else if ( strcmp(opt, "all") == 0 ){ printf("Print all information\n"); return_value = ipmi_ek_display_power(argc, opt, filename, file_type); } else{ lprintf(LOG_ERR, "Invalid option %s", opt); return_value = ERROR_STATUS; } return return_value; } /************************************************************************** * * Function name: ipmi_ek_display_carrier_connectivity * * Description: Display the topology between a Carrier and all AMC modules by * using carrier p2p connectivity record * * Restriction: Ref: AMC.0 Specification: Table 3-13 and Table 3-14 * * Input: struct ipmi_ek_multi_header* record: a pointer to the carrier p2p * connectivity record. * * Output: None * * Global: None * * Return: return 0 on success and -1 if the record doesn't exist. * ***************************************************************************/ static int ipmi_ek_diplay_carrier_connectivity( struct ipmi_ek_multi_header * record ) { int return_value = ERROR_STATUS; struct fru_picmgext_carrier_p2p_record rsc_desc; struct fru_picmgext_carrier_p2p_descriptor port_desc; if ( record == NULL ){ lprintf(LOG_ERR, "P2P connectivity record is invalid\n"); return_value = ERROR_STATUS; } else{ int offset = START_DATA_OFFSET; if ( verbose > 1 ){ int k = 0; printf("Binary data of Carrier p2p connectivity"\ " record starting from mfg id\n"); for ( k = 0; k < ( record->header.len ); k++ ){ printf("%02x ", record->data[k]); } printf("\n"); } while ( offset <= (record->header.len - START_DATA_OFFSET) ){ rsc_desc.resource_id = record->data[offset++]; rsc_desc.p2p_count = record->data[offset++]; if ( verbose > 0 ){ printf("resource id= %02x port count= %d\n", rsc_desc.resource_id,rsc_desc.p2p_count); } /*check if it is an AMC Module*/ if ( ( (rsc_desc.resource_id & AMC_MODULE) ) == AMC_MODULE ) { /*check if it is an RTM module*/ if (rsc_desc.resource_id == AMC_MODULE) { printf(" %s topology:\n", val2str( RTM_IPMB_L, ipmi_ekanalyzer_IPMBL_addr)); } else{ /*The last four bits of resource ID represent site number * (mask = 0x0f) */ printf(" %s topology:\n", val2str( (rsc_desc.resource_id & 0x0f), ipmi_ekanalyzer_module_type)); } } else{ printf(" On Carrier Device ID %d topology: \n", (rsc_desc.resource_id & 0x0f)); } while ( rsc_desc.p2p_count > 0 ){ memcpy ( &port_desc, &record->data[offset], sizeof ( struct fru_picmgext_carrier_p2p_descriptor ) ); offset += sizeof ( struct fru_picmgext_carrier_p2p_descriptor ); if ( (port_desc.remote_resource_id & AMC_MODULE) == AMC_MODULE ){ printf("\tPort %d =====> %s, Port %d\n", port_desc.local_port, val2str( (port_desc.remote_resource_id & 0x0f), ipmi_ekanalyzer_module_type), port_desc.remote_port ); } else{ printf("\tPort %d =====> On Carrier Device ID %d, Port %d\n", port_desc.local_port,(port_desc.remote_resource_id & 0x0f), port_desc.remote_port ); } rsc_desc.p2p_count--; } } return_value = OK_STATUS; } return return_value; } /************************************************************************** * * Function name: ipmi_ek_display_power * * Description: Display the power management of the Carrier and AMC module by * using current management record. If the display option equal to all, * it will display power and carrier topology together. * * Restriction: Reference: AMC.0 Specification, Table 3-11 * * Input: int argc: number of the argument received * char* opt: option string that will tell what to display * char** filename: strings that contained filename of FRU data binary file * int* file_type: a pointer that contain file type (on carrier file, * a1 file, b1 file...) * * Output: None * * Global: None * * Return: return 0 on success and -1 if the record doesn't exist. * ***************************************************************************/ static int ipmi_ek_display_power(int argc, char * opt, char ** filename, int * file_type) { int num_file=0; int return_value = ERROR_STATUS; int index = 0; /*list des multi record*/ struct ipmi_ek_multi_header * list_head[MAX_ARGC]; struct ipmi_ek_multi_header * list_record[MAX_ARGC]; struct ipmi_ek_multi_header * list_last[MAX_ARGC]; for ( num_file = 0; num_file < argc; num_file++ ){ list_head[num_file] = NULL; list_record[num_file] = NULL; list_last[num_file] = NULL; } for ( num_file = 0; num_file < argc; num_file++ ){ tboolean is_first_data = TRUE; if ( file_type[num_file] == CONFIG_FILE ){ num_file++; } if ( is_first_data ){ printf("%s\n", STAR_LINE_LIMITER); printf("\nFrom %s file '%s'\n", val2str( (uint16_t)file_type[num_file], ipmi_ekanalyzer_module_type), filename[num_file]); is_first_data = FALSE; } return_value = ipmi_ekanalyzer_fru_file2structure( filename[num_file], &list_head[num_file], &list_record[num_file], &list_last[num_file]); if ( list_head[num_file] != NULL ){ for ( list_record[num_file] = list_head[num_file]; list_record[num_file] != NULL; list_record[num_file] = list_record[num_file]->next ){ if ( ( strcmp(opt, "all") == 0 ) && ( file_type[num_file] == ON_CARRIER_FRU_FILE ) ){ if ( list_record[num_file]->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_P2P ){ return_value = ipmi_ek_diplay_carrier_connectivity( list_record[num_file] ); } else if ( list_record[num_file]->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_INFO ){ /*Ref: See AMC.0 Specification Table 3-3: Carrier Information * Table about offset value */ printf( " Number of AMC bays supported by Carrier: %d\n", list_record[num_file]->data[START_DATA_OFFSET+1] ); } } /*Ref: AMC.0 Specification: Table 3-11 * Carrier Activation and Current Management Record */ if ( list_record[num_file]->data[PICMG_ID_OFFSET] == FRU_AMC_ACTIVATION ){ int index_data = START_DATA_OFFSET; struct fru_picmgext_carrier_activation_record car; struct fru_picmgext_activation_record * cur_desc; memcpy ( &car, &list_record[num_file]->data[index_data], sizeof (struct fru_picmgext_carrier_activation_record) ); index_data += sizeof (struct fru_picmgext_carrier_activation_record); cur_desc = malloc (car.module_activation_record_count * \ sizeof (struct fru_picmgext_activation_record) ); for(index=0; indexdata[index_data], sizeof (struct fru_picmgext_activation_record) ); index_data += sizeof (struct fru_picmgext_activation_record); } /*Display the current*/ ipmi_ek_display_current_descriptor( car, cur_desc, filename[num_file] ); free (cur_desc); } /*Ref: AMC.0 specification, Table 3-10: Module Current Requirement*/ else if ( list_record[num_file]->data[PICMG_ID_OFFSET] == FRU_AMC_CURRENT ){ float power_in_watt = 0; float current_in_amp = 0; printf(" %s power required (Current Draw): ", val2str ( (uint16_t)file_type[num_file], ipmi_ekanalyzer_module_type) ); current_in_amp = (float)(list_record[num_file]->data[START_DATA_OFFSET]*0.1); power_in_watt = current_in_amp * AMC_VOLTAGE; printf("%.2f Watts (%.2f Amps)\n",power_in_watt, current_in_amp); } } return_value = OK_STATUS; /*Destroy the list of record*/ for ( index = 0; index < argc; index++ ){ while ( list_head[index] != NULL ){ ipmi_ek_remove_record_from_list ( list_head[index], &list_head[index],&list_last[index] ); } if ( verbose > 1 ) printf("Record list has been removed successfully\n"); } } } printf("%s\n", STAR_LINE_LIMITER); return return_value; } /************************************************************************** * * Function name: ipmi_ek_display_current_descriptor * * Description: Display the current descriptor under format xx Watts (xx Amps) * * Restriction: None * * Input: struct fru_picmgext_carrier_activation_record car: contain binary data * of carrier activation record * struct fru_picmgext_activation_record * cur_desc: contain current * descriptor * char* filename: strings that contained filename of FRU data binary file * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_current_descriptor( struct fru_picmgext_carrier_activation_record car, struct fru_picmgext_activation_record * cur_desc, char * filename ) { int index = 0; float power_in_watt = 0.0; float current_in_amp = 0.0; for ( index = 0; index < car.module_activation_record_count; index++ ){ /*See AMC.0 specification, Table 3-12 for detail about calculation*/ current_in_amp = (float)(cur_desc[index].max_module_curr * 0.1); power_in_watt = (float) current_in_amp * AMC_VOLTAGE; printf(" Carrier AMC power available on %s:\n", val2str( cur_desc[index].ibmb_addr, ipmi_ekanalyzer_IPMBL_addr ) ); printf("\t- Local IPMB Address \t: %02x\n", cur_desc[index].ibmb_addr); printf("\t- Maximum module Current\t: %.2f Watts (%.2f Amps)\n", power_in_watt, current_in_amp ); } /*Display total power on Carrier*/ current_in_amp = (float)(car.max_internal_curr * 0.1); power_in_watt = (float) current_in_amp * AMC_VOLTAGE; printf(" Carrier AMC total power available for all bays from file '%s':", filename); printf(" %.2f Watts (%.2f Amps)\n", power_in_watt, current_in_amp ); } /************************************************************************** * * Function name: ipmi_ekanalyzer_ekeying_match * * Description: Check for possible Ekeying match between two FRU files * * Restriction: None * * Input: argc: number of the argument received * opt: string that contains display option received from user. * filename: strings that contained filename of FRU data binary file * file_type: a pointer that contain file type (on carrier file, * a1 file, b1 file...) * * Output: None * * Global: None * * Return: return TRUE on success and FALSE if the record doesn't exist. * ***************************************************************************/ static tboolean ipmi_ekanalyzer_ekeying_match( int argc, char * opt, char ** filename, int * file_type ) { tboolean return_value = FALSE; if ( (strcmp(opt, "carrier") == 0 ) || (strcmp(opt, "power") == 0) ){ lprintf(LOG_ERR, " ekanalyzer summary [match/ unmatch/ all]"\ " [xx=frufile]"); return_value = ERROR_STATUS; } else{ int num_file=0; // int index_data = 0; // int first_data = 1; tboolean amc_file = FALSE; /*used to indicate the present of AMC file*/ tboolean oc_file = FALSE; /*used to indicate the present of Carrier file*/ /*Check for possible ekeying match between files*/ for ( num_file=0; num_file < argc; num_file++ ){ if ( ( file_type[num_file] == ON_CARRIER_FRU_FILE ) || ( file_type[num_file] == CONFIG_FILE ) || ( file_type[num_file] == SHELF_MANAGER_FRU_FILE ) ){ amc_file = FALSE; } else { /*there is an amc file*/ amc_file = TRUE; break; } } if ( amc_file == FALSE ){ printf("\nNo AMC FRU file is provided --->" \ " No possible ekeying match!\n"); return_value = ERROR_STATUS; } else{ /*If no carrier file is provided, return error*/ for ( num_file=0; num_file < argc; num_file++ ){ if ( (file_type[num_file] == ON_CARRIER_FRU_FILE ) || ( file_type[num_file] == CONFIG_FILE ) || ( file_type[num_file] == SHELF_MANAGER_FRU_FILE ) ){ oc_file = TRUE; break; } } if ( !oc_file ){ printf("\nNo Carrier FRU file is provided" \ " ---> No possible ekeying match!\n"); return_value = ERROR_STATUS; } else{ /*list des multi record*/ struct ipmi_ek_multi_header * list_head[MAX_ARGC]; struct ipmi_ek_multi_header * list_record[MAX_ARGC]; struct ipmi_ek_multi_header * list_last[MAX_ARGC]; struct ipmi_ek_multi_header * pcarrier_p2p = NULL; int list = 0; int match_pair = 0; // tboolean match_result = FALSE; /*Create an empty list*/ for ( list=0; listnext ){ if ( pcarrier_p2p->data[PICMG_ID_OFFSET] == FRU_AMC_CARRIER_P2P ){ break; } } break; } } /*Determine the match making pair*/ while ( match_pair < argc ){ for ( num_file = (match_pair+1); num_file0){ printf("Start matching process\n"); } return_value = ipmi_ek_matching_process( file_type, match_pair, num_file, list_head, list_last, opt, pcarrier_p2p); } } } match_pair ++; } for( num_file=0; num_file < argc; num_file++ ){ if (list_head[num_file] != NULL ){ ipmi_ek_remove_record_from_list( list_head[num_file], &list_record[num_file], &list_last[num_file]); } if ( ( num_file == argc-1 ) && verbose ) printf("Record list has been removed successfully\n"); } return_value = OK_STATUS; } } } return return_value; } /************************************************************************** * * Function name: ipmi_ek_matching_process * * Description: This function process the OEM check, Physical Connectivity check, * and Link Descriptor comparison to do Ekeying match * * Restriction: None * * Input: file_type: a pointer that contain file type (on carrier file, * a1 file, b1 file...) * index1: position of the first record in the list of the record * index2: position of the second record in the list of the record * ipmi_ek_multi_header ** list_head: pointer to the header of a * linked list that contain FRU multi record * ipmi_ek_multi_header ** list_last: pointer to the tale of a * linked list that contain FRU multi record * opt: string that contain display option such as "match", "unmatch", or * "all". * pphysical: a pointer that contain a carrier p2p connectivity record * to perform physical check * * Output: None * * Global: None * * Return: return OK_STATUS on success and ERROR_STATUS if the record doesn't * exist. * ***************************************************************************/ static int ipmi_ek_matching_process( int * file_type, int index1, int index2, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last, char * opt, struct ipmi_ek_multi_header * pphysical ) { int result = ERROR_STATUS; struct ipmi_ek_multi_header * record; int num_amc_record1 = 0;/*Number of AMC records in the first module*/ int num_amc_record2 = 0;/*Number of AMC records in the second module*/ /* Comparison between an On-Carrier and an AMC*/ if ( file_type[index2] == ON_CARRIER_FRU_FILE ){ int index_temp = 0; index_temp = index1; index1 = index2; /*index1 indicate on carrier*/ index2 = index_temp; /*index2 indcate an AMC*/ } /*Calculate record size for Carrier file*/ for ( record=list_head[index1]; record != NULL;record = record->next ){ if ( record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){ num_amc_record2++; } } /*Calculate record size for amc file*/ for ( record=list_head[index2]; record != NULL;record = record->next){ if ( record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){ num_amc_record1++; } } if ( (num_amc_record1 > 0) && (num_amc_record2 > 0) ){ int index_record1 = 0; int index_record2 = 0; /* Multi records of AMC module */ struct ipmi_ek_amc_p2p_connectivity_record * amc_record1 = NULL; /* Multi records of Carrier or an AMC module */ struct ipmi_ek_amc_p2p_connectivity_record * amc_record2 = NULL; amc_record1 = malloc ( num_amc_record1 * \ sizeof(struct ipmi_ek_amc_p2p_connectivity_record)); amc_record2 = malloc ( num_amc_record2 * \ sizeof(struct ipmi_ek_amc_p2p_connectivity_record)); for (record=list_head[index2]; record != NULL;record = record->next){ if ( record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){ result = ipmi_ek_create_amc_p2p_record( record, &amc_record1[index_record1] ); if (result != ERROR_STATUS){ struct ipmi_ek_multi_header * current_record = NULL; for ( current_record=list_head[index1]; current_record != NULL ; current_record = current_record->next ){ if ( current_record->data[PICMG_ID_OFFSET] == FRU_AMC_P2P ){ result = ipmi_ek_create_amc_p2p_record( current_record, &amc_record2[index_record2] ); if ( result != ERROR_STATUS ){ if ( result == OK_STATUS ){ /*Compare Link descriptor*/ result = ipmi_ek_compare_link ( pphysical, amc_record1[index_record1], amc_record2[index_record2], opt, file_type[index1], file_type[index2]); } index_record2++; } } /*end of FRU_AMC_P2P */ } /* end of for loop */ index_record1++; } } } free(amc_record1) ; free(amc_record2) ; } else{ printf("No amc record is found!\n"); } return result; } /************************************************************************** * * Function name: ipmi_ek_check_physical_connectivity * * Description: This function check for point to point connectivity between * two modules by comparing each enable port in link descriptor * with local and remote ports of port descriptor in * carrier point-to-point connectivity record according to the * corresponding file type ( a1, b1, b2...). * * Restriction: In order to perform physical check connectivity, it needs to * compare between 2 AMC Modules, so the use of index ( 1 and 2 ) * can facilitate the comparison in this case. * * Input: record1: is an AMC p2p record for an AMC module * record2 is an AMC p2p record for an On-Carrier record or an AMC module * char* opt: option string that will tell if a matching result, unmatched * result or all the results will be displayed. * file_type1: indicates type of the first module * file_type2: indicates type of the second module * * Output: None * * Global: None * * Return: return OK_STATUS if both link are matched, otherwise * return ERROR_STATUS * ***************************************************************************/ static int ipmi_ek_check_physical_connectivity( struct ipmi_ek_amc_p2p_connectivity_record record1, int index1, struct ipmi_ek_amc_p2p_connectivity_record record2, int index2, struct ipmi_ek_multi_header * record, int filetype1, int filetype2, char * option ) { int return_status = OK_STATUS; if ( record == NULL ){ printf("NO Carrier p2p connectivity !\n"); return_status = ERROR_STATUS; } else{ #define INVALID_AMC_SITE_NUMBER -1 int index = START_DATA_OFFSET; int amc_site = INVALID_AMC_SITE_NUMBER; struct fru_picmgext_carrier_p2p_record rsc_desc; struct fru_picmgext_carrier_p2p_descriptor * port_desc = NULL; /* Get the physical connectivity record */ while ( index < record->header.len ) { rsc_desc.resource_id = record->data[index++]; rsc_desc.p2p_count = record->data[index++]; /* carrier p2p record starts with on-carrier device */ if ( (rsc_desc.resource_id == record1.rsc_id) || (rsc_desc.resource_id == record2.rsc_id) ){ if (rsc_desc.p2p_count <= 0){ printf("No p2p count\n"); return_status = ERROR_STATUS; } else{ port_desc = malloc ( rsc_desc.p2p_count * sizeof(struct fru_picmgext_carrier_p2p_descriptor) ); index = ipmi_ek_get_resource_descriptor( rsc_desc.p2p_count, index, port_desc, record ); amc_site = INVALID_AMC_SITE_NUMBER; break; } } else{ /* carrier p2p record starts with AMC module */ if (rsc_desc.resource_id == AMC_MODULE){ if (filetype1 != ON_CARRIER_FRU_FILE){ amc_site = filetype1; } else{ amc_site = filetype2; } } else{ amc_site = rsc_desc.resource_id & 0x0f; } if ( amc_site > 0 ){ if ( (amc_site == filetype1) || (amc_site == filetype2) ){ port_desc = malloc ( rsc_desc.p2p_count * sizeof(struct fru_picmgext_carrier_p2p_descriptor) ); index = ipmi_ek_get_resource_descriptor( rsc_desc.p2p_count, index, port_desc, record ); break; } } else{ return_status = ERROR_STATUS; } } /*If the record doesn't contain the same AMC site number in command * line, go to the next record */ index += ( sizeof(struct fru_picmgext_carrier_p2p_descriptor) * rsc_desc.p2p_count ); } if ( (port_desc != NULL) && (return_status != ERROR_STATUS) ){ int j=0; for ( j = 0; j < rsc_desc.p2p_count; j++ ){ /* Compare only enable channel descriptor */ if ( record1.ch_desc[index1].lane0port != DISABLE_PORT ){ /* matching result from channel descriptor comparison */ tboolean match_lane = FALSE; match_lane = ipmi_ek_compare_channel_descriptor ( record1.ch_desc[index1], record2.ch_desc[index2], port_desc, j, rsc_desc.resource_id ); if ( match_lane ){ if ( filetype1 != ON_CARRIER_FRU_FILE ){ if ( ( (filetype1 == (rsc_desc.resource_id & 0x0f)) && (filetype2 ==(port_desc[j].remote_resource_id &0x0f)) ) || ( (filetype2 == (rsc_desc.resource_id & 0x0f)) && (filetype1 ==(port_desc[j].remote_resource_id &0x0f)) ) ){ if ( ! (strcmp(option, "unmatch") == 0) ){ printf("%s port %d ==> %s port %d\n", val2str((uint16_t)filetype2, ipmi_ekanalyzer_module_type), record1.ch_desc[index1].lane0port, val2str((uint16_t)filetype1, ipmi_ekanalyzer_module_type), record2.ch_desc[index2].lane0port); } return_status = OK_STATUS; break; } else{ if (verbose >= 2){ //was == LOG_DEBUG) printf("No point 2 point connectivity\n"); } return_status = ERROR_STATUS; } } else{ if ( (record2.rsc_id == (rsc_desc.resource_id) ) && (filetype2 == (port_desc[j].remote_resource_id & 0x0f)) ){ if ( ! (strcmp(option, "unmatch") == 0) ){ printf("%s port %d ==> %s port %d\n", val2str((uint16_t)filetype2, ipmi_ekanalyzer_module_type), record1.ch_desc[index1].lane0port, val2str((uint16_t)filetype1, ipmi_ekanalyzer_module_type), record2.ch_desc[index2].lane0port); } return_status = OK_STATUS; break; } else if ( (filetype2 == (rsc_desc.resource_id & 0x0f) ) && (record2.rsc_id == (port_desc[j].remote_resource_id)) ){ if ( ! (strcmp(option, "unmatch") == 0) ){ printf("%s port %d ==> %s %x port %d\n", val2str((uint16_t)filetype2, ipmi_ekanalyzer_module_type), record1.ch_desc[index1].lane0port, val2str((uint16_t)filetype1, ipmi_ekanalyzer_module_type), record2.rsc_id,record2.ch_desc[index2].lane0port); } return_status = OK_STATUS; break; } else{ if (verbose >= 2){ //was == LOG_DEBUG printf("No point 2 point connectivity\n"); } return_status = ERROR_STATUS; } } } else{ if (verbose >= 2){ //was == LOG_DEBUG printf("No point 2 point connectivity\n"); } return_status = ERROR_STATUS; } } else{ /*If the link is disable, the result is always true*/ return_status = OK_STATUS; } } } else{ if (verbose >= 2) { //was == LOG_WARN printf("Invalid Carrier p2p connectivity record\n"); } return_status = ERROR_STATUS; } if (port_desc != NULL){ free (port_desc); } } return return_status; } /************************************************************************** * * Function name: ipmi_ek_compare_link * * Description: This function compares link grouping id of each * amc p2p connectiviy record * * Restriction: None * * Input: record1: is an AMC p2p record for an AMC module * record2 is an AMC p2p record for an On-Carrier record or an AMC module * char* opt: option string that will tell if a matching result, unmatched * result or all the results will be displayed. * file_type1: indicates type of the first module * file_type2: indicates type of the second module * * Output: None * * Global: None * * Return: return 0 if both link are matched, otherwise return -1 * ***************************************************************************/ static int ipmi_ek_compare_link( struct ipmi_ek_multi_header * physic_record, struct ipmi_ek_amc_p2p_connectivity_record record1, struct ipmi_ek_amc_p2p_connectivity_record record2, char * opt, int file_type1, int file_type2 ) { int result = ERROR_STATUS; int index1 = 0; /*index for AMC module*/ int index2 = 0; /*index for On-carrier type*/ record1.matching_result = malloc ( record1.link_desc_count * sizeof(int) ); record2.matching_result = malloc ( record2.link_desc_count * sizeof(int) ); /*Initialize all the matching_result to false*/ for( index2 = 0; index2 < record2.link_desc_count; index2++ ){ record2.matching_result[index2] = FALSE; } for( index1 = 0; index1 < record1.link_desc_count; index1++ ){ for( index2 = 0; index2 < record2.link_desc_count; index2++ ){ if( record1.link_desc[index1].group_id == 0 ){ if( record2.link_desc[index2].group_id == 0 ){ result = ipmi_ek_compare_link_descriptor( record1, index1, record2, index2 ); if ( result == OK_STATUS ){ /*Calculate the index for Channel descriptor in function of * link designator channel ID */ /*first channel_id in the AMC Link descriptor of record1*/ static int flag_first_link1; int index_ch_desc1; /*index of channel descriptor */ /*first channel_id in the AMC Link descriptor of record2*/ static int flag_first_link2; int index_ch_desc2; /*index of channel descriptor*/ if (index1==0){ /*this indicate the first link is encounter*/ flag_first_link1 = record1.link_desc[index1].channel_id; } index_ch_desc1 = record1.link_desc[index1].channel_id - flag_first_link1; if (index2==0){ flag_first_link2 = record2.link_desc[index2].channel_id; } index_ch_desc2 = record2.link_desc[index2].channel_id - flag_first_link2; /*Check for physical connectivity for each link*/ result = ipmi_ek_check_physical_connectivity ( record1, index_ch_desc1, record2, index_ch_desc2, physic_record, file_type1, file_type2, opt ); if ( result == OK_STATUS ){ /*Display the result if option = match or all*/ if ( (strcmp( opt, "match" ) == 0) || (strcmp( opt, "all" ) == 0) || (strcmp( opt, "default" ) == 0) ){ tboolean isOEMtype = FALSE; printf(" Matching Result\n"); isOEMtype = ipmi_ek_display_link_descriptor( file_type1, record2.rsc_id, "From", record2.link_desc[index2]); if (isOEMtype){ ipmi_ek_display_oem_guid (record2); } isOEMtype = ipmi_ek_display_link_descriptor( file_type2, record1.rsc_id, "To", record1.link_desc[index1] ); if (isOEMtype){ ipmi_ek_display_oem_guid (record1); } printf(" %s\n", STAR_LINE_LIMITER); } record2.matching_result[index2] = TRUE; record1.matching_result[index1] = TRUE; /*quit the fist loop since the match is found*/ index2 = record2.link_desc_count; } } } } else { /*Link Grouping ID is non zero, Compare all link descriptor * that has non-zero link grouping id together */ if (record2.link_desc[index2].group_id != 0 ){ result = ipmi_ek_compare_link_descriptor( record1, index1, record2, index2 ); if ( result == OK_STATUS ){ /*Calculate the index for Channel descriptor in function of * link designator channel ID */ /*first channel_id in the AMC Link descriptor of record1*/ static int flag_first_link1; int index_ch_desc1; /*index of channel descriptor */ /*first channel_id in the AMC Link descriptor of record2*/ static int flag_first_link2; int index_ch_desc2; /*index of channel descriptor*/ if (index1==0){ /*this indicate the first link is encounter*/ flag_first_link1 = record1.link_desc[index1].channel_id; } index_ch_desc1 = record1.link_desc[index1].channel_id - flag_first_link1; if (index2==0){ flag_first_link2 = record2.link_desc[index2].channel_id; } index_ch_desc2 = record2.link_desc[index2].channel_id - flag_first_link2; /*Check for physical connectivity for each link*/ result = ipmi_ek_check_physical_connectivity ( record1, index_ch_desc1, record2, index_ch_desc2, physic_record, file_type1, file_type2, opt ); if ( result == OK_STATUS ){ if ( (strcmp( opt, "match" ) == 0) || (strcmp( opt, "all" ) == 0) || (strcmp( opt, "default" ) == 0) ){ tboolean isOEMtype = FALSE; printf(" Matching Result\n"); isOEMtype = ipmi_ek_display_link_descriptor( file_type1, record2.rsc_id, "From", record2.link_desc[index2] ); if ( isOEMtype ){ ipmi_ek_display_oem_guid (record2); } isOEMtype = ipmi_ek_display_link_descriptor( file_type2, record1.rsc_id, "To", record1.link_desc[index1] ); if (isOEMtype){ ipmi_ek_display_oem_guid (record1); } printf(" %s\n", STAR_LINE_LIMITER); } record2.matching_result[index2] = TRUE; record1.matching_result[index1] = TRUE; /*leave the fist loop since the match is found*/ index2 = record2.link_desc_count; } } } } } } if ( (strcmp(opt, "unmatch") == 0) || (strcmp(opt, "all") == 0) ){ int isOEMtype = FALSE; printf(" Unmatching result\n"); for (index1 = 0; index1 < record1.link_desc_count; index1++){ isOEMtype = ipmi_ek_display_link_descriptor( file_type2, record1.rsc_id, "", record1.link_desc[index1] ); if ( isOEMtype ){ ipmi_ek_display_oem_guid (record1); } printf(" %s\n", STAR_LINE_LIMITER); } for ( index2 = 0; index2 < record2.link_desc_count; index2++){ if ( !record2.matching_result[index2] ){ isOEMtype = ipmi_ek_display_link_descriptor( file_type1, record2.rsc_id, "", record2.link_desc[index2] ); if ( isOEMtype ){ ipmi_ek_display_oem_guid (record2); } printf(" %s\n", STAR_LINE_LIMITER); } } } free (record1.matching_result); free (record2.matching_result); return result; } /************************************************************************** * * Function name: ipmi_ek_compare_channel_descriptor * * Description: This function compares 2 channel descriptors of 2 AMC * point-to-point connectivity records with port descriptor of * carrier point-to-point connectivity record. The comparison is * made between each enable port only. * * Restriction: Reference: AMC.0 specification: * - Table 3-14 for port descriptor * - Table 3-17 for channel descriptor * * Input: ch_desc1: first channel descriptor * ch_desc2: second channel descriptor * port_desc: a pointer that contain a list of port descriptor * index_port: index of the port descriptor * rsc_id: resource id that represents as local resource id in the * resource descriptor table. * * Output: None * * Global: None * * Return: return TRUE if both channel descriptor are matched, * or FALSE otherwise * ***************************************************************************/ static tboolean ipmi_ek_compare_channel_descriptor( struct fru_picmgext_amc_channel_desc_record ch_desc1, struct fru_picmgext_amc_channel_desc_record ch_desc2, struct fru_picmgext_carrier_p2p_descriptor * port_desc, int index_port, unsigned char rsc_id ) { tboolean match_lane = FALSE; /* carrier p2p record start with AMC_MODULE as local port */ if ( (rsc_id & AMC_MODULE) == AMC_MODULE ){ if ( (ch_desc1.lane0port == port_desc[index_port].local_port) && (ch_desc2.lane0port == port_desc[index_port].remote_port) ){ /*check if the port is enable*/ if (ch_desc1.lane1port != DISABLE_PORT){ index_port ++; if ( (ch_desc1.lane1port == port_desc[index_port].local_port) && (ch_desc2.lane1port == port_desc[index_port].remote_port) ){ if (ch_desc1.lane2port != DISABLE_PORT){ index_port++; if ( (ch_desc1.lane2port == port_desc[index_port].local_port) && (ch_desc2.lane2port == port_desc[index_port].remote_port) ){ if (ch_desc1.lane3port != DISABLE_PORT){ index_port++; if ( (ch_desc1.lane3port == port_desc[index_port].local_port) && (ch_desc2.lane3port == port_desc[index_port].remote_port) ){ match_lane = TRUE; } } else{ match_lane = TRUE; } } /* end of if lane2port */ } else{ match_lane = TRUE; } } /* end of if lane1port */ } else{ /*if the port is disable, the compare result is always true*/ match_lane = TRUE; } }/* end of if lane0port */ } /* carrier p2p record start with Carrier as local port */ else{ if ( (ch_desc1.lane0port == port_desc[index_port].remote_port) && (ch_desc2.lane0port == port_desc[index_port].local_port) ){ if (ch_desc1.lane1port != DISABLE_PORT){ index_port ++; if ( (ch_desc1.lane1port == port_desc[index_port].remote_port) && (ch_desc2.lane1port == port_desc[index_port].local_port) ){ if (ch_desc1.lane2port != DISABLE_PORT){ index_port++; if ( (ch_desc1.lane2port == port_desc[index_port].remote_port) && (ch_desc2.lane2port == port_desc[index_port].local_port) ){ if (ch_desc1.lane3port != DISABLE_PORT){ index_port++; if ( (ch_desc1.lane3port == port_desc[index_port].remote_port) && (ch_desc2.lane3port == port_desc[index_port].local_port) ){ match_lane = TRUE; } } else{ match_lane = TRUE; } } /* end of if lane2port */ } else{ match_lane = TRUE; } } /* end of if lane1port */ } else{ match_lane = TRUE; } } /* end of if lane0port */ } return match_lane; } /************************************************************************** * * Function name: ipmi_ek_compare_link_descriptor * * Description: This function compares 2 link descriptors of 2 * amc p2p connectiviy record * * Restriction: None * * Input: record1: AMC p2p connectivity record of the 1rst AMC or Carrier Module * index1: index of AMC link descriptor in 1rst record * record2: AMC p2p connectivity record of the 2nd AMC or Carrier Module * index1: index of AMC link descriptor in 2nd record * * Output: None * * Global: None * * Return: return OK_STATUS if both link are matched, * otherwise return ERROR_STATUS * ***************************************************************************/ static int ipmi_ek_compare_link_descriptor( struct ipmi_ek_amc_p2p_connectivity_record record1, int index1, struct ipmi_ek_amc_p2p_connectivity_record record2, int index2 ) { int result = ERROR_STATUS; if (record1.link_desc[index1].type == record2.link_desc[index2].type){ /*if it is an OEM type, we compare the OEM GUID*/ if ( (record1.link_desc[index1].type >= LOWER_OEM_TYPE) && (record1.link_desc[index1].type <= UPPER_OEM_TYPE) ){ if ( (record1.guid_count == 0) && (record2.guid_count == 0) ){ /*there is no GUID for comparison, so the result is always OK*/ result = OK_STATUS; } else{ int i=0; int j=0; for( i=0; i= LOWER_OEM_TYPE) && (link_desc.type <= UPPER_OEM_TYPE) ){ isOEMtype = TRUE; } return isOEMtype; } /************************************************************************** * * Function name: ipmi_ek_display_oem_guid * * Description: Display the oem guid of an AMC p2p connectivity record * * Restriction: None * * Input: amc_record: AMC p2p connectivity record * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_oem_guid( struct ipmi_ek_amc_p2p_connectivity_record amc_record ) { int index_oem = 0; int index = 0; if ( amc_record.guid_count == 0 ){ printf("\tThere is no OEM GUID for this module\n"); } for (index_oem = 0; index_oem < amc_record.guid_count; index_oem++){ printf(" - GUID: "); for(index = 0; index < SIZE_OF_GUID; index++){ printf("%02x", amc_record.oem_guid[index_oem].guid[index]); /*For a better look: putting a "-" after displaying four bytes of GUID*/ if (!(index % 4)){ printf("-"); } } printf("\n"); } } /************************************************************************** * * Function name: ipmi_ek_create_amc_p2p_record * * Description: this function create an AMC point 2 point connectivity record * that contain link descriptor, channel descriptor, oem guid * * Restriction: Reference: AMC.0 Specification Table 3-16 * * Input: record: a pointer to FRU multi record * * Output: amc_record: a pointer to the created AMC p2p record * * Global: None * * Return: Return OK_STATUS on success, or ERROR_STATUS if no record has been * created. * ***************************************************************************/ static int ipmi_ek_create_amc_p2p_record( struct ipmi_ek_multi_header * record, struct ipmi_ek_amc_p2p_connectivity_record * amc_record ) { int return_status = OK_STATUS; int index_data = START_DATA_OFFSET; amc_record->guid_count = record->data[index_data++]; if ( amc_record->guid_count > 0){ int index_oem = 0; amc_record->oem_guid = malloc (amc_record->guid_count * \ sizeof(struct fru_picmgext_guid) ); for (index_oem = 0; index_oem < amc_record->guid_count; index_oem++){ memcpy ( &amc_record->oem_guid[index_oem].guid, &record->data[index_data], SIZE_OF_GUID ); index_data += (int)SIZE_OF_GUID; } amc_record->rsc_id = record->data[index_data++]; amc_record->ch_count = record->data[index_data++]; /*Calculate link descriptor count*/ amc_record->link_desc_count = ( (record->header.len) - 8 - (SIZE_OF_GUID*amc_record->guid_count) - ( sizeof(struct fru_picmgext_amc_channel_desc_record)* amc_record->ch_count ) )/5 ; } else{ amc_record->rsc_id = record->data[index_data++]; amc_record->ch_count = record->data[index_data++]; /*Calculate link descriptor count see spec AMC.0 for detail*/ amc_record->link_desc_count = ( (record->header.len) - 8 - ( sizeof(struct fru_picmgext_amc_channel_desc_record)* amc_record->ch_count ) ) / 5; } if (amc_record->ch_count > 0){ int ch_index = 0; amc_record->ch_desc = malloc ( (amc_record->ch_count) * \ sizeof(struct fru_picmgext_amc_channel_desc_record)); for (ch_index = 0; ch_index < amc_record->ch_count; ch_index++){ memcpy(&amc_record->ch_desc[ch_index], &record->data[index_data], sizeof(struct fru_picmgext_amc_channel_desc_record) ); index_data += sizeof(struct fru_picmgext_amc_channel_desc_record) ; } } if (amc_record->link_desc_count > 0){ int i=0; amc_record->link_desc = malloc ( amc_record->link_desc_count * sizeof(struct fru_picmgext_amc_link_desc_record) ); for (i = 0; i< amc_record->link_desc_count; i++ ){ memcpy (&amc_record->link_desc[i], &record->data[index_data], sizeof(struct fru_picmgext_amc_link_desc_record) ); index_data += sizeof (struct fru_picmgext_amc_link_desc_record); } } else{ return_status = ERROR_STATUS; } return return_status; } /************************************************************************** * * Function name: ipmi_ek_get_resource_descriptor * * Description: this function create the resource descriptor of Carrier p2p * connectivity record. * * Restriction: None * * Input: port_count: number of port count * index: index to the position of data start offset * record: a pointer to FRU multi record * * Output: port_desc: a pointer to the created resource descriptor * * Global: None * * Return: Return index that indicates the current position of data in record. * ***************************************************************************/ static int ipmi_ek_get_resource_descriptor( int port_count, int index, struct fru_picmgext_carrier_p2p_descriptor * port_desc, struct ipmi_ek_multi_header * record ) { int num_port = 0; while ( num_port < port_count ){ memcpy ( &port_desc[num_port], &record->data[index], sizeof (struct fru_picmgext_carrier_p2p_descriptor) ); index += sizeof (struct fru_picmgext_carrier_p2p_descriptor); num_port++; } return index; } /************************************************************************** * * Function name: ipmi_ek_display_fru_header * * Description: this function display FRU header offset from a FRU binary file * * Restriction: Reference: IPMI Platform Management FRU Information Storage * Definition V1.0, Section 8 * * Input: filename: name of FRU binary file * * Output: None * * Global: None * * Return: Return OK_STATUS on sucess, ERROR_STATUS on error * ***************************************************************************/ static int ipmi_ek_display_fru_header( char * filename ) { FILE * input_file; /* this structure is declared in ipmi_fru.h */ struct fru_header header; int return_status = ERROR_STATUS; input_file = fopen ( filename, "r"); if ( input_file == NULL ){ lprintf(LOG_ERR, "file: '%s' is not found", filename); return_status = ERROR_STATUS; } else{ if ( !feof (input_file) ){ fread ( &header, sizeof (struct fru_header), 1, input_file ); printf("%s\n", EQUAL_LINE_LIMITER); printf("FRU Header Info\n"); printf("%s\n", EQUAL_LINE_LIMITER); printf("Format Version :0x%02x %s\n", (header.version & 0x0f), ((header.version & 0x0f)==1) ? "" : "{unsupported}"); printf("Internal Use Offset :0x%02x\n", header.offset.internal); printf("Chassis Info Offset :0x%02x\n", header.offset.chassis); printf("Board Info Offset :0x%02x\n", header.offset.board); printf("Product Info Offset :0x%02x\n", header.offset.product); printf("MultiRecord Offset :0x%02x\n", header.offset.multi); printf("Common header Checksum :0x%02x\n", header.checksum); return_status = OK_STATUS; } else{ lprintf(LOG_ERR, "Invalid FRU header!"); return_status = ERROR_STATUS; } fclose( input_file ); } return return_status; } /************************************************************************** * * Function name: ipmi_ek_display_fru_header_detail * * Description: this function display detail FRU header information * from a FRU binary file. * * Restriction: Reference: IPMI Platform Management FRU Information Storage * Definition V1.0, Section 8 * * Input: filename: name of FRU binary file * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_fru_header_detail( char * filename ) { FILE * input_file; struct fru_header header; input_file = fopen ( filename, "r"); if ( input_file == NULL ){ lprintf(LOG_ERR, "file: '%s' is not found", filename); } else{ /* the offset in each fru is in multiple of 8 bytes * See IPMI Platform Management FRU Information Storage Definition * for detail */ #define FACTOR_OFFSET 8 if ( !feof (input_file) ){ fread ( &header, sizeof( struct fru_header ), 1, input_file ); } else{ lprintf(LOG_ERR, "Invalid FRU header!"); } /*** Display FRU Internal Use Info ***/ if ( !feof (input_file) ){ unsigned char format_version; unsigned long len; printf("%s\n", EQUAL_LINE_LIMITER); printf("FRU Internal Use Info\n"); printf("%s\n", EQUAL_LINE_LIMITER); fread ( &format_version, 1, 1, input_file ); printf("Format Version: %d\n", (format_version & 0x0f) ); if ( header.offset.chassis > 0 ){ len = (header.offset.chassis * FACTOR_OFFSET) - (header.offset.internal * FACTOR_OFFSET); } else{ len = (header.offset.board * FACTOR_OFFSET) - (header.offset.internal * FACTOR_OFFSET); } printf("Length: %d\n", len); printf("Data dump:\n"); while ( (len > 0) && ( !feof (input_file) ) ) { unsigned char data; fread ( &data, 1, 1, input_file ); printf("0x%02x ", data); len --; } printf("\n"); } /*** Chassis Info Area ***/ if (header.offset.chassis != 0){ long offset = 0; offset = header.offset.chassis * FACTOR_OFFSET; ipmi_ek_display_chassis_info_area (input_file, offset); } /*** Display FRU Board Info Area ***/ if (header.offset.board != 0){ fseek_( input_file, (header.offset.board * FACTOR_OFFSET), SEEK_SET); if ( !feof(input_file) ){ unsigned char data; unsigned int board_length; size_t file_offset = ftell (input_file); printf("%s\n", EQUAL_LINE_LIMITER); printf("FRU Board Info Area\n"); printf("%s\n", EQUAL_LINE_LIMITER); fread ( &data, 1, 1, input_file ); /* Format version */ printf("Format Version: %d\n", (data & 0x0f)); if ( !feof(input_file) ){ fread ( &data, 1, 1, input_file ); /* Board Area Length */ board_length = (data * FACTOR_OFFSET); printf("Area Length: %d\n", board_length); /* Decrease the length of board area by 1 byte of format version * and 1 byte for area length itself. the rest of this length will * be used to check for additional custom mfg. byte */ board_length -= 2; } if ( !feof(input_file) ){ unsigned char lan_code; fread ( &lan_code, 1, 1, input_file ); /* Language Code */ printf("Language Code: %d\n", lan_code ); board_length --; } /* Board Mfg Date */ if ( !feof(input_file) ){ #define SIZE_MFG_DATE 3 time_t tval; unsigned char mfg_date[SIZE_MFG_DATE]; fread ( mfg_date, SIZE_MFG_DATE, 1, input_file ); tval=((mfg_date[2] << 16) + (mfg_date[1] << 8) + (mfg_date[0])); tval = tval * 60; tval = (time_t)(tval + secs_from_1970_1996); printf("Board Mfg Date: %ld, %s", tval, asctime(localtime(&tval))); board_length -= SIZE_MFG_DATE; /* Board Mfg */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Board Manufacture Data", &board_length); fseek_(input_file, file_offset, SEEK_SET); /* Board Product */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Board Product Name", &board_length); fseek_(input_file, file_offset, SEEK_SET); /* Board Serial */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Board Serial Number", &board_length); fseek_(input_file, file_offset, SEEK_SET); /* Board Part */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Board Part Number", &board_length); fseek_(input_file, file_offset, SEEK_SET); /* FRU file ID */ file_offset = ipmi_ek_display_board_info_area ( input_file, "FRU File ID", &board_length); fseek_(input_file, file_offset, SEEK_SET); /* Additional Custom Mfg. */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Custom", &board_length); } } } /*** Product Info Area ***/ if ( header.offset.product ){ if ( !feof(input_file) ){ long offset = 0; offset = header.offset.product * FACTOR_OFFSET; ipmi_ek_display_product_info_area (input_file, offset); } } fclose( input_file ); } } /************************************************************************** * * Function name: ipmi_ek_display_chassis_info_area * * Description: this function displays detail format of product info area record * into humain readable text format * * Restriction: Reference: IPMI Platform Management FRU Information Storage * Definition V1.0, Section 10 * * Input: input_file: pointer to file stream * offset: start offset of chassis info area * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_chassis_info_area( FILE * input_file, long offset ) { if ( input_file != NULL ){ printf("%s\n", EQUAL_LINE_LIMITER); printf("Chassis Info Area\n"); printf("%s\n", EQUAL_LINE_LIMITER); fseek_(input_file, offset, SEEK_SET); if ( !feof(input_file) ){ unsigned char data = 0; unsigned int len = 0; fread (&data, 1, 1, input_file); printf("Format Version Number: %d\n", (data & 0x0f) ); if ( !feof(input_file) ){ fread (&len, 1, 1, input_file); /* len is in factor of 8 bytes */ len = len * 8; printf("Area Length: %d\n", len); len -= 2; } if ( !feof(input_file) ){ unsigned char ch_type = 0; size_t file_offset = ftell (input_file); /* Chassis Type*/ fread (&ch_type, 1, 1, input_file); printf("Chassis Type: %d\n", ch_type); len --; /* Chassis Part Number*/ file_offset = ipmi_ek_display_board_info_area ( input_file, "Chassis Part Number", &len); fseek_(input_file, file_offset, SEEK_SET); /* Chassis Serial */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Chassis Serial Number", &len); fseek_(input_file, file_offset, SEEK_SET); /* Custom product info area */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Custom", &len); } } } else{ lprintf(LOG_ERR, "Invalid Chassis Info Area!"); } } /************************************************************************** * * Function name: ipmi_ek_display_board_info_area * * Description: this function displays board info area depending on board type * that pass in argument. Board type can be: * Manufacturer, Serial, Product or Part... * * Restriction: IPMI Platform Management FRU Information Storage * Definition V1.0, Section 11 * * Input: input_file: pointer to file stream * board_type: a string that contain board type * board_length: length of info area * * Output: None * * Global: None * * Return: the current position of input_file * ***************************************************************************/ static size_t ipmi_ek_display_board_info_area( FILE * input_file, char * board_type, unsigned int * board_length ) { size_t file_offset = ftell (input_file); unsigned char len = 0; /* Board length*/ if ( !feof(input_file) ){ fread ( &len, 1, 1, input_file ); (*board_length)--; } /* Board Data */ if ( !feof(input_file) ){ unsigned int size_board = 0; /*Bit 5:0 of Board Mfg type represent legnth*/ size_board = (len & 0x3f); if (size_board > 0){ if ( strncmp( board_type, "Custom", 6 ) == 0 ){ #define NO_MORE_INFO_FIELD 0xc1 while ( !feof(input_file) && (*board_length > 0) ){ if (len != NO_MORE_INFO_FIELD){ printf("Additional Custom Mfg. length: 0x%02x\n", len); if ( (size_board > 0) && (size_board < (*board_length)) ){ unsigned char * additional_data = NULL; int i=0; additional_data = malloc (size_board); if (additional_data != NULL){ fread ( additional_data, size_board, 1, input_file ); printf("Additional Custom Mfg. Data: %02x", additional_data[0]); for ( i =1; i<(int)size_board; i++){ printf("-%02x", additional_data[i]); } printf("\n"); free (additional_data); (*board_length) -= size_board; } } else{ printf("No Additional Custom Mfg. %d\n", *board_length); board_length = 0; } } else{ unsigned char padding; /*take the rest of data in the area minus 1 byte of checksum*/ printf("Additional Custom Mfg. length: 0x%02x\n", len); padding = (*board_length) - 1; /*we reach the end of the record, so its length is set to 0*/ board_length = 0; if ( ( padding > 0 ) && ( !feof(input_file) ) ){ printf("Unused space: %d (bytes)\n", padding); fseek_(input_file, padding, SEEK_CUR); } if ( !feof(input_file) ){ unsigned char checksum = 0; fread ( &checksum, 1, 1, input_file ); printf("Checksum: 0x%02x\n", checksum); } } } } else{ unsigned char * data; unsigned int i=0; #define TYPE_CODE 0xc0 /*Language code*/ data = malloc (size_board); fread ( data, size_board, 1, input_file ); printf("%s type: 0x%02x\n", board_type, len); printf("%s: ", board_type); for ( i = 0; i < size_board; i++ ){ if ( (len & TYPE_CODE) == TYPE_CODE ){ printf("%c", data[i]); } /*other than language code (binary, BCD, ASCII 6 bit...) is not * supported */ else{ printf("%02x", data[i]); } } printf("\n"); free (data); (*board_length) -= size_board; file_offset = ftell (input_file); } } else{ printf("%s: None\n", board_type); file_offset = ftell (input_file); } } return file_offset; } /************************************************************************** * * Function name: ipmi_ek_display_product_info_area * * Description: this function displays detail format of product info area record * into humain readable text format * * Restriction: Reference: IPMI Platform Management FRU Information Storage * Definition V1.0, Section 12 * * Input: input_file: pointer to file stream * offset: start offset of product info area * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_product_info_area( FILE * input_file, long offset ) { if ( input_file != NULL ){ printf("%s\n", EQUAL_LINE_LIMITER); printf("Product Info Area\n"); printf("%s\n", EQUAL_LINE_LIMITER); fseek_(input_file, offset, SEEK_SET); if ( !feof(input_file) ){ unsigned char data = 0; unsigned int len = 0; fread (&data, 1, 1, input_file); printf("Format Version Number: %d\n", (data & 0x0f) ); if ( !feof(input_file) ){ fread (&len, 1, 1, input_file); /* length is in factor of 8 bytes */ len = len * 8; printf("Area Length: %d\n", len); len -= 2; /* -1 byte of format version and -1 byte itself */ } if ( !feof(input_file) ){ size_t file_offset = ftell (input_file); fread (&data, 1, 1, input_file); printf("Language Code: %d\n", data); len --; /* Product Mfg */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Product Manufacture Data", &len); fseek_(input_file, file_offset, SEEK_SET); /* Product Name */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Product Name", &len); fseek_(input_file, file_offset, SEEK_SET); /* Product Part */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Product Part/Model Number", &len); fseek_(input_file, file_offset, SEEK_SET); /* Product Version */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Product Version", &len); fseek_(input_file, file_offset, SEEK_SET); /* Product Serial */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Product Serial Number", &len); fseek_(input_file, file_offset, SEEK_SET); /* Product Asset Tag */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Asset Tag", &len); fseek_(input_file, file_offset, SEEK_SET); /* FRU file ID */ file_offset = ipmi_ek_display_board_info_area ( input_file, "FRU File ID", &len); fseek_(input_file, file_offset, SEEK_SET); /* Custom product info area */ file_offset = ipmi_ek_display_board_info_area ( input_file, "Custom", &len); } } } else{ lprintf(LOG_ERR, "Invalid Product Info Area!"); } } /************************************************************************** * * Function name: ipmi_ek_display_record * * Description: this function displays FRU multi record information. * * Restriction: None * * Input: record: a pointer to current record * list_head: a pointer to header of the list * list_last: a pointer to tale of the list * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_record( struct ipmi_ek_multi_header * record, struct ipmi_ek_multi_header * list_head, struct ipmi_ek_multi_header * list_last ) { if ( list_head == NULL ){ printf("***empty list***\n"); } else{ printf("%s\n", EQUAL_LINE_LIMITER); printf("FRU Multi Info area\n"); printf("%s\n", EQUAL_LINE_LIMITER); for ( record = list_head; record != NULL; record = record->next ){ printf("Record Type ID: 0x%02x\n", record->header.type); printf("Record Format version: 0x%02x\n", record->header.format); if (record->header.len > PICMG_ID_OFFSET){ /* In picmg3.0 specification, picmg record id lower than 4 or * greater than 0x2d is not supported */ #define PICMG_ID_LOWER_LIMIT 0x04 #define PICMG_ID_UPPER_LIMIT 0x2d unsigned char picmg_id; picmg_id = record->data[PICMG_ID_OFFSET]; printf("Manufacturer ID: %02x%02x%02x h\n", record->data[2], record->data[1], record->data[0] ); if( ( picmg_id < PICMG_ID_LOWER_LIMIT ) || ( picmg_id > PICMG_ID_UPPER_LIMIT ) ){ printf("Picmg record ID: Unsupported {0x%02x}\n", picmg_id ); } else{ printf("Picmg record ID: %s {0x%02x}\n", val2str(picmg_id, ipmi_ekanalyzer_picmg_record_id), picmg_id ); } switch (picmg_id){ case FRU_PICMG_BACKPLANE_P2P: /*0x04*/ ipmi_ek_display_backplane_p2p_record (record); break; case FRU_PICMG_ADDRESS_TABLE: /*0x10*/ ipmi_ek_display_address_table_record (record); break; case FRU_PICMG_SHELF_POWER_DIST: /*0x11*/ ipmi_ek_display_shelf_power_distribution_record (record); break; case FRU_PICMG_SHELF_ACTIVATION: /*/0x12*/ ipmi_ek_display_shelf_activation_record (record); break; case FRU_PICMG_SHMC_IP_CONN: /*0x13*/ ipmi_ek_display_shelf_ip_connection_record (record); break; case FRU_PICMG_BOARD_P2P: /*0x14*/ ipmi_ek_display_board_p2p_record (record); break; case FRU_RADIAL_IPMB0_LINK_MAPPING: /*0x15*/ ipmi_ek_display_radial_ipmb0_record (record); break; case FRU_AMC_CURRENT: /*0x16*/ ipmi_ek_display_amc_current_record (record); break; case FRU_AMC_ACTIVATION: /*0x17*/ ipmi_ek_display_amc_activation_record (record); break; case FRU_AMC_CARRIER_P2P: /*0x18*/ ipmi_ek_diplay_carrier_connectivity (record); break; case FRU_AMC_P2P: /*0x19*/ ipmi_ek_display_amc_p2p_record (record); break; case FRU_AMC_CARRIER_INFO: /*0x1a*/ ipmi_ek_display_amc_carrier_info_record (record); break; case FRU_PICMG_CLK_CARRIER_P2P: /*0x2c*/ ipmi_ek_display_clock_carrier_p2p_record (record); break; case FRU_PICMG_CLK_CONFIG: /*0x2d*/ ipmi_ek_display_clock_config_record (record); break; default: if (verbose > 0){ int i; printf("%02x %02x %02x %02x %02x ", record->header.type, record->header.format, record->header.len, record->header.record_checksum, record->header.header_checksum ); for ( i = 0; i < record->header.len; i++ ){ printf("%02x ", record->data[i]); } printf("\n"); } break; } printf("%s\n", STAR_LINE_LIMITER); } } } } /************************************************************************** * * Function name: ipmi_ek_display_backplane_p2p_record * * Description: this function displays backplane p2p record. * * Restriction: Reference: PICMG 3.0 Specification Table 3-40 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_backplane_p2p_record( struct ipmi_ek_multi_header * record ) { uint8_t index; int offset = START_DATA_OFFSET; struct fru_picmgext_slot_desc * slot_d = (struct fru_picmgext_slot_desc*) &record->data[offset]; offset += sizeof(struct fru_picmgext_slot_desc); while ( offset <= record->header.len ) { printf(" Channel Type: "); switch ( slot_d -> chan_type ) { case 0x00: case 0x07: printf("PICMG 2.9\n"); break; case 0x08: printf("Single Port Fabric IF\n"); break; case 0x09: printf("Double Port Fabric IF\n"); break; case 0x0a: printf("Full Channel Fabric IF\n"); break; case 0x0b: printf("Base IF\n"); break; case 0x0c: printf("Update Channel IF\n"); break; default: printf("Unknown IF\n"); break; } printf(" Slot Address: %02x\n", slot_d -> slot_addr); printf(" Channel Count: %i\n", slot_d -> chn_count); for ( index = 0; index < (slot_d -> chn_count); index++ ) { struct fru_picmgext_chn_desc * d = (struct fru_picmgext_chn_desc *) &record->data[offset]; if ( verbose ){ printf( "\t" "Chn: %02x --> " "Chn: %02x in " "Slot: %02x\n", d->local_chn, d->remote_chn, d->remote_slot ); } offset += sizeof(struct fru_picmgext_chn_desc); } slot_d = (struct fru_picmgext_slot_desc*) &record->data[offset]; offset += sizeof(struct fru_picmgext_slot_desc); } } /************************************************************************** * * Function name: ipmi_ek_display_address_table_record * * Description: this function displays address table record. * * Restriction: Reference: PICMG 3.0 Specification Table 3-6 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_address_table_record( struct ipmi_ek_multi_header * record ) { unsigned char entries = 0; unsigned char i; int offset = START_DATA_OFFSET; #define SIZE_SHELF_ADDRESS_BYTE 20 printf(" Type/Len: 0x%02x\n", record->data[offset++]); printf(" Shelf Addr: "); for ( i = 0; i < SIZE_SHELF_ADDRESS_BYTE; i++ ){ printf("0x%02x ", record->data[offset++]); } printf("\n"); entries = record->data[offset++]; printf(" Addr Table Entries count: 0x%02x\n", entries); for ( i = 0; i < entries; i++ ){ printf("\tHWAddr: 0x%02x - SiteNum: 0x%02x - SiteType: 0x%02x \n", record->data[offset+0], record->data[offset+1], record->data[offset+2]); offset += 3; } } /************************************************************************** * * Function name: ipmi_ek_display_shelf_power_distribution_record * * Description: this function displays shelf power distribution record. * * Restriction: Reference: PICMG 3.0 Specification Table 3-70 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_shelf_power_distribution_record( struct ipmi_ek_multi_header * record ) { int offset = START_DATA_OFFSET; unsigned char i,j; unsigned char feeds = 0; feeds = record->data[offset++]; printf(" Number of Power Feeds: 0x%02x\n", feeds); for (i=0; idata[offset+0] | (record->data[offset+1]<<8); printf(" Max External Available Current: %ld Amps\n", (max_ext*10) ); offset += 2; max_int = record->data[offset+0] | (record->data[offset+1]<<8); printf(" Max Internal Current:\t %ld Amps\n", (max_int*10)); offset += 2; printf(" Min Expected Operating Voltage: %ld Volts\n", (record->data[offset++]/2)); entries = record->data[offset++]; printf(" Feed to FRU count: 0x%02x\n", entries); for (j=0; jdata[offset++]); printf("\tFRU ID: 0x%02x\n", record->data[offset++]); } } } /************************************************************************** * * Function name: ipmi_ek_display_shelf_activation_record * * Description: this function displays shelf activation record. * * Restriction: Reference: PICMG 3.0 Specification Table 3-73 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_shelf_activation_record( struct ipmi_ek_multi_header * record ) { unsigned char count = 0; int offset = START_DATA_OFFSET; printf(" Allowance for FRU Act Readiness: 0x%02x\n", record->data[offset++]); count = record->data[offset++]; printf(" FRU activation and Power Desc Cnt: 0x%02x\n", count); while ( count > 0 ) { printf(" FRU activation and Power descriptor:\n"); printf("\tHardware Address:\t\t0x%02x\n", record->data[offset++]); printf("\tFRU Device ID:\t\t\t0x%02x\n", record->data[offset++]); printf("\tMax FRU Power Capability:\t0x%04x Watts\n", ( record->data[offset+0] | (record->data[offset+1]<<8) )); offset += 2; printf("\tConfiguration parameter:\t0x%02x\n", record->data[offset++]); count --; } } /************************************************************************** * * Function name: ipmi_ek_display_shelf_ip_connection_record * * Description: this function displays shelf ip connection record. * * Restriction: Fix me: Don't test yet * Reference: PICMG 3.0 Specification Table 3-31 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_shelf_ip_connection_record( struct ipmi_ek_multi_header * record ) { int ioffset = START_DATA_OFFSET; if (ioffset > record->header.len){ printf(" Shelf Manager IP Address: %d.%d.%d.%d\n", record->data[ioffset+0], record->data[ioffset+1], record->data[ioffset+2], record->data[ioffset+3]); ioffset += 4; } if (ioffset > record->header.len){ printf(" Default Gateway Address: %d.%d.%d.%d\n", record->data[ioffset+0], record->data[ioffset+1], record->data[ioffset+2], record->data[ioffset+3]); ioffset += 4; } if (ioffset > record->header.len){ printf(" Subnet Mask: %d.%d.%d.%d\n", record->data[ioffset+0], record->data[ioffset+1], record->data[ioffset+2], record->data[ioffset+3]); ioffset += 4; } } #ifdef NOT_USED static void ipmi_ek_display_shelf_fan_geography_record( struct ipmi_ek_multi_header * record ); /************************************************************************** * * Function name: ipmi_ek_display_shelf_fan_geography_record * * Description: this function displays shelf fan geography record. * * Restriction: Fix me: Don't test yet * Reference: PICMG 3.0 Specification Table 3-75 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_shelf_fan_geography_record( struct ipmi_ek_multi_header * record ) { int ioffset = START_DATA_OFFSET; unsigned char fan_count = 0; fan_count = record->data[ioffset]; ioffset ++; printf(" Fan-to-FRU Entry Count: 0x%02x\n", fan_count); while ( (fan_count > 0) && (ioffset <= record->header.len) ){ printf(" Fan-to-FRU Mapping Entry: {%2x%2x%2x%2x}\n", record->data[ioffset], record->data[ioffset+1], record->data[ioffset+2], record->data[ioffset+3] ); printf(" Hardware Address: 0x%02x\n", record->data[ioffset++]); printf(" FRU device ID: 0x%02x\n", record->data[ioffset++]); printf(" Site Number: 0x%02x\n", record->data[ioffset++]); printf(" Site Type: 0x%02x\n", record->data[ioffset++]); fan_count --; } } #endif /************************************************************************** * * Function name: ipmi_ek_display_board_p2p_record * * Description: this function displays board pont-to-point record. * * Restriction: Reference: PICMG 3.0 Specification Table 3-44 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_board_p2p_record( struct ipmi_ek_multi_header * record ) { unsigned char guid_count; int offset = START_DATA_OFFSET; int i = 0; guid_count = record->data[offset++]; printf(" GUID count: %2d\n", guid_count); for (i = 0 ; i < guid_count; i++ ) { int j; printf("\tGUID: "); for (j=0; j < sizeof(struct fru_picmgext_guid); j++) { printf("%02x", record->data[offset+j]); } printf("\n"); offset += sizeof(struct fru_picmgext_guid); } for ( /*offset set above*/ ; offset < record->header.len; offset += sizeof(struct fru_picmgext_link_desc) ) { /* to solve little endian /big endian problem */ unsigned long data; struct fru_picmgext_link_desc * d; data = (record->data[offset+0]) | (record->data[offset+1] << 8)\ | (record->data[offset+2] << 16)\ | (record->data[offset+3] << 24); d = (struct fru_picmgext_link_desc *) &data; printf(" Link Descriptor\n"); printf("\tLink Grouping ID:\t0x%02x\n", d->grouping); printf("\tLink Type Extension:\t0x%02x - ", d->ext); if (d->type == FRU_PICMGEXT_LINK_TYPE_BASE){ switch (d->ext){ case 0: printf("10/100/1000BASE-T Link (four-pair)\n"); break; case 1: printf("ShMC Cross-connect (two-pair)\n"); break; default: printf("Unknwon\n"); break; } } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET){ switch (d->ext){ case 0: printf("Fixed 1000Base-BX\n"); break; case 1: printf("Fixed 10GBASE-BX4 [XAUI]\n"); break; case 2: printf("FC-PI\n"); break; default: printf("Unknwon\n"); break; } } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND){ printf("Unknwon\n"); } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR){ printf("Unknwon\n"); } else if (d->type == FRU_PICMGEXT_LINK_TYPE_PCIE){ printf("Unknwon\n"); } else{ printf("Unknwon\n"); } printf("\tLink Type:\t\t0x%02x - ",d->type); if (d->type == 0 || d->type == 0xff){ printf("Reserved\n"); } else if (d->type >= 0x06 && d->type <= 0xef) { printf("Reserved\n"); } else if (d->type >= LOWER_OEM_TYPE && d->type <= UPPER_OEM_TYPE) { printf("OEM GUID Definition\n"); } else { switch (d->type){ case FRU_PICMGEXT_LINK_TYPE_BASE: printf("PICMG 3.0 Base Interface 10/100/1000\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET: printf("PICMG 3.1 Ethernet Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND: printf("PICMG 3.2 Infiniband Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR: printf("PICMG 3.3 Star Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_PCIE: printf("PICMG 3.4 PCI Express Fabric Interface\n"); break; default: printf("Invalid\n"); break; } } printf("\tLink Designator: \n"); printf("\t Port 0 Flag: %s\n", (d->desig_port & 0x01) ? "enable" : "disable"); printf("\t Port 1 Flag: %s\n", (d->desig_port & 0x02) ? "enable" : "disable"); printf("\t Port 2 Flag: %s\n", (d->desig_port & 0x04) ? "enable" : "disable"); printf("\t Port 3 Flag: %s\n", (d->desig_port & 0x08) ? "enable" : "disable"); printf("\t Interface: 0x%02x - ", d->desig_if); switch (d->desig_if){ case FRU_PICMGEXT_DESIGN_IF_BASE: printf("Base Interface\n"); break; case FRU_PICMGEXT_DESIGN_IF_FABRIC: printf("Fabric Interface\n"); break; case FRU_PICMGEXT_DESIGN_IF_UPDATE_CHANNEL: printf("Update Channel\n"); break; case FRU_PICMGEXT_DESIGN_IF_RESERVED: printf("Reserved\n"); break; default: printf("Invalid"); break; } printf("\t Channel Number: 0x%02x\n", d->desig_channel); } } /************************************************************************** * * Function name: ipmi_ek_display_radial_ipmb0_record * * Description: this function displays radial IPMB-0 record. * * Restriction: Fix me: Don't test yet * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_radial_ipmb0_record( struct ipmi_ek_multi_header * record ) { int offset = START_DATA_OFFSET; #define SIZE_OF_CONNECTOR_DEFINER 3; /*bytes*/ /*Ref: PICMG 3.0 Specification Revision 2.0, Table 3-59*/ printf(" IPMB-0 Connector Definer: "); #ifndef WORDS_BIGENDIAN printf("%02x %02x %02x h\n", record->data[offset], record->data[offset+1], record->data[offset+2]); #else printf("%02x %02x %02x h\n", record->data[offset+2], record->data[offset+1], record->data[offset]); #endif /*3 bytes of connector definer was used*/ offset += SIZE_OF_CONNECTOR_DEFINER; printf (" IPMB-0 Connector version ID: "); #ifndef WORDS_BIGENDIAN printf("%02x %02x h\n", record->data[offset], record->data[offset+1]); #else printf("%02x %02x h\n", record->data[offset+1], record->data[offset]); #endif offset += 2; printf(" IPMB-0 Hub Descriptor Count: 0x%02x", record->data[offset++]); if (record->data[offset] > 0){ for (/*offset*/; offset < record->header.len;){ unsigned char entry_count = 0; printf(" IPMB-0 Hub Descriptor\n"); printf("\tHardware Address: 0x%02x\n", record->data[offset++]); printf("\tHub Info {0x%02x}: ", record->data[offset]); /* Bit mask specified in Table 3-59 of PICMG 3.0 Specification */ if ( (record->data[offset] & 0x01) == 0x01 ){ printf("IPMB-A only\n"); } else if ( (record->data[offset] & 0x02) == 0x02 ){ printf("IPMB-B only\n"); } else if ( (record->data[offset] & 0x03) == 0x03 ){ printf("IPMB-A and IPMB-B\n"); } else{ printf("Reserved.\n"); } offset ++; entry_count = record->data[offset++]; printf("\tAddress Entry count: 0x%02x", entry_count); while (entry_count > 0){ printf("\t Hardware Address: 0x%02x\n", record->data[offset++]); printf("\t IPMB-0 Link Entry: 0x%02x\n",record->data[offset++]); entry_count --; } } } } /************************************************************************** * * Function name: ipmi_ek_display_amc_current_record * * Description: this function displays AMC current record. * * Restriction: None * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_amc_current_record( struct ipmi_ek_multi_header * record ) { unsigned char current; current = record->data[START_DATA_OFFSET]; printf(" Current draw: %.1f A @ 12V => %.2f Watt\n", (float) current/10.0, ((float)current/10.0)*12.0 ); printf("\n"); } /************************************************************************** * * Function name: ipmi_ek_display_amc_activation_record * * Description: this function displays carrier activation and current management * record. * * Restriction: Reference: AMC.0 Specification Table 3-11 and Table 3-12 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_amc_activation_record( struct ipmi_ek_multi_header * record ) { uint16_t max_current; int offset = START_DATA_OFFSET; max_current = record->data[offset]; max_current |= record->data[++offset] << 8; printf(" Maximum Internal Current(@12V): %.2f A [ %.2f Watt ]\n", (float) max_current / 10, (float) max_current / 10 * 12); printf(" Module Activation Readiness: %i sec.\n", record->data[++offset]); printf(" Descriptor Count: %i\n", record->data[++offset]); for(++offset; (offset < record->header.len); offset += 3 ) { struct fru_picmgext_activation_record * a = (struct fru_picmgext_activation_record *) &record->data[offset]; printf("\tIPMB-Address:\t\t0x%x\n", a->ibmb_addr); printf("\tMax. Module Current:\t%.2f A\n", (float)a->max_module_curr/10); printf("\n"); } } /************************************************************************** * * Function name: ipmi_ek_display_amc_p2p_record * * Description: this function display amc p2p connectivity record in humain * readable text format * * Restriction: Reference: AMC.0 Specification Table 3-16 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_amc_p2p_record( struct ipmi_ek_multi_header * record ) { int index_data = START_DATA_OFFSET; int oem_count = 0; int ch_count = 0; int index=0; oem_count = record->data[index_data++]; printf("OEM GUID count: %02x\n", oem_count); if ( oem_count > 0 ){ while ( oem_count > 0 ){ printf("OEM GUID: "); for ( index = 1; index <= SIZE_OF_GUID; index++ ){ printf("%02x", record->data[index_data++]); /* For a better look, display a "-" character after each 5 bytes * of OEM GUID */ if ( !(index % 5) ){ printf("-"); } } printf("\n"); oem_count--; } } if ( ( record->data[index_data] & AMC_MODULE ) == AMC_MODULE ){ printf("AMC module connection\n"); } else{ printf("On-Carrier Device %02x h\n", ( record->data[index_data] & 0x0f )); } index_data ++; ch_count = record->data[index_data++]; printf("AMC Channel Descriptor count: %02x h\n", ch_count); if ( ch_count > 0 ){ for ( index = 0; index < ch_count; index++ ){ struct fru_picmgext_amc_channel_desc_record * ch_desc; printf(" AMC Channel Descriptor {%02x%02x%02x}\n", record->data[index_data+2], record->data[index_data+1], record->data[index_data] ); /*Warning: For gcc version between 4.0 and 4.3 this code doesnt work*/ ch_desc = ( struct fru_picmgext_amc_channel_desc_record * )\ &record->data[index_data]; printf(" Lane 0 Port: 0x%02x\n", ch_desc->lane0port); printf(" Lane 1 Port: 0x%02x\n", ch_desc->lane1port); printf(" Lane 2 Port: 0x%02x\n", ch_desc->lane2port); printf(" Lane 3 Port: 0x%02x\n\n", ch_desc->lane3port); index_data += sizeof (struct fru_picmgext_amc_channel_desc_record) ; } } while ( index_data < record->header.len ){ /*Warning: For gcc version between 4.0 and 4.3 this code doesnt work*/ struct fru_picmgext_amc_link_desc_record * link_desc = (struct fru_picmgext_amc_link_desc_record *)&record->data[index_data]; printf(" AMC Link Descriptor:\n" ); printf("\t- Link Type: %s \n", val2str (link_desc->type, ipmi_ekanalyzer_link_type)); switch ( link_desc->type ){ case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE: case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS1: case FRU_PICMGEXT_AMC_LINK_TYPE_PCIE_AS2: printf("\t- Link Type extension: %s\n", val2str (link_desc->type_ext, ipmi_ekanalyzer_extension_PCIE)); printf("\t- Link Group ID: %d\n ", link_desc->group_id ); printf("\t- Link Asym. Match: %s\n", val2str (link_desc->asym_match, ipmi_ekanalyzer_asym_PCIE)); break; case FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET: printf("\t- Link Type extension: %s\n", val2str (link_desc->type_ext, ipmi_ekanalyzer_extension_ETHERNET)); printf("\t- Link Group ID: %d \n", link_desc->group_id ); printf("\t- Link Asym. Match: %s\n", val2str (link_desc->asym_match, ipmi_ekanalyzer_asym_PCIE)); break; case FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE: printf("\t- Link Type extension: %s\n", val2str (link_desc->type_ext, ipmi_ekanalyzer_extension_STORAGE)); printf("\t- Link Group ID: %d \n", link_desc->group_id ); printf("\t- Link Asym. Match: %s\n", val2str (link_desc->asym_match, ipmi_ekanalyzer_asym_STORAGE)); break; default: printf("\t- Link Type extension: %i\n", link_desc->type_ext ); printf("\t- Link Group ID: %d \n", link_desc->group_id ); printf("\t- Link Asym. Match: %i\n", link_desc->asym_match); break; } printf("\t- AMC Link Designator:\n"); printf("\t Channel ID: %i\n", link_desc->channel_id); printf("\t\t Lane 0: %s\n", (link_desc->port_flag_0)?"enable":"disable"); printf("\t\t Lane 1: %s\n", (link_desc->port_flag_1)?"enable":"disable"); printf("\t\t Lane 2: %s\n", (link_desc->port_flag_2)?"enable":"disable"); printf("\t\t Lane 3: %s\n", (link_desc->port_flag_3)?"enable":"disable"); index_data += sizeof (struct fru_picmgext_amc_link_desc_record); } } /************************************************************************** * * Function name: ipmi_ek_display_amc_carrier_info_record * * Description: this function displays Carrier information table. * * Restriction: Reference: AMC.0 Specification Table 3-3 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: START_DATA_OFFSET * * Return: None * ***************************************************************************/ static void ipmi_ek_display_amc_carrier_info_record( struct ipmi_ek_multi_header * record ) { unsigned char extVersion; unsigned char siteCount; int offset = START_DATA_OFFSET; extVersion = record->data[offset++]; siteCount = record->data[offset++]; printf(" AMC.0 extension version: R%d.%d\n", (extVersion >> 0)& 0x0F, (extVersion >> 4)& 0x0F ); printf(" Carrier Sie Number Count: %d\n", siteCount); while (siteCount > 0){ printf("\tSite ID (%d): %s \n", record->data[offset], val2str(record->data[offset], ipmi_ekanalyzer_module_type) ); offset++; siteCount--; } printf("\n"); } /************************************************************************** * * Function name: ipmi_ek_display_clock_carrier_p2p_record * * Description: this function displays Carrier clock point-to-pont * connectivity record. * * Restriction: the following code is copy from ipmi_fru.c with modification in * reference to AMC.0 Specification Table 3-29 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_display_clock_carrier_p2p_record( struct ipmi_ek_multi_header * record ) { unsigned char desc_count; int i,j; int offset = START_DATA_OFFSET; desc_count = record->data[offset++]; for(i=0; idata[offset++]; channel_count = record->data[offset++]; printf(" Clock Resource ID: 0x%02x\n", resource_id); printf(" Type: "); if((resource_id & 0xC0)>>6 == 0) { printf("On-Carrier-Device\n"); } else if((resource_id & 0xC0)>>6 == 1) { printf("AMC slot\n"); } else if((resource_id & 0xC0)>>6 == 2) { printf("Backplane\n"); } else{ printf("reserved\n"); } printf(" Channel Count: 0x%02x\n", channel_count); for(j=0; jdata[offset++]; rem_channel = record->data[offset++]; rem_resource = record->data[offset++]; printf("\tCLK-ID: 0x%02x ---> ", loc_channel); printf(" remote CLKID: 0x%02x ", rem_channel); if((rem_resource & 0xC0)>>6 == 0) { printf("[ Carrier-Dev"); } else if((rem_resource & 0xC0)>>6 == 1) { printf("[ AMC slot "); } else if((rem_resource & 0xC0)>>6 == 2) { printf("[ Backplane "); } else{ printf("reserved "); } printf(" 0x%02x ]\n", rem_resource&0xF); } } printf("\n"); } /************************************************************************** * * Function name: ipmi_ek_display_clock_config_record * * Description: this function displays clock configuration record. * * Restriction: the following codes are copy from ipmi_fru.c with modification * in reference to AMC.0 Specification Table 3-35 and Table 3-36 * * Input: record: a pointer to current record to be displayed * * Output: None * * Global: START_DATA_OFFSET * * Return: None * ***************************************************************************/ void ipmi_ek_display_clock_config_record( struct ipmi_ek_multi_header * record ) { unsigned char resource_id, descr_count; int i; int offset = START_DATA_OFFSET; resource_id = record->data[offset++]; descr_count = record->data[offset++]; printf(" Clock Resource ID: 0x%02x\n", resource_id); printf(" Clock Configuration Descriptor Count: 0x%02x\n", descr_count); for(i=0; idata[offset++]; control = record->data[offset++]; printf("\tCLK-ID: 0x%02x - ", channel_id); printf("CTRL 0x%02x [ %12s ]\n", control, ((control&0x1)==0)?"Carrier IPMC":"Application"); indirect_cnt = record->data[offset++]; direct_cnt = record->data[offset++]; printf("\t Count: Indirect 0x%02x / Direct 0x%02x\n", indirect_cnt, direct_cnt ); /* indirect desc */ for(j=0; jdata[offset++]; dep_chn_id = record->data[offset++]; printf("\t\tFeature: 0x%02x [%8s] - ", feature, (feature&0x1)==1?"Source":"Receiver"); printf(" Dep. CLK-ID: 0x%02x\n", dep_chn_id); } /* direct desc */ for(j=0; jdata[offset++]; family = record->data[offset++]; accuracy = record->data[offset++]; freq = (record->data[offset+0] << 0 ) | (record->data[offset+1] << 8 ) | (record->data[offset+2] << 16) | (record->data[offset+3] << 24); offset += 4; min_freq = (record->data[offset+0] << 0 ) | (record->data[offset+1] << 8 ) | (record->data[offset+2] << 16) | (record->data[offset+3] << 24); offset += 4; max_freq = (record->data[offset+0] << 0 ) | (record->data[offset+1] << 8 ) | (record->data[offset+2] << 16) | (record->data[offset+3] << 24); offset += 4; printf("\t- Feature: 0x%02x - PLL: %x / Asym: %s\n", feature, (feature > 1) & 1, (feature&1)?"Source":"Receiver"); printf("\tFamily: 0x%02x - AccLVL: 0x%02x\n", family, accuracy); printf("\tFRQ: %-9d - min: %-9d - max: %-9d\n", freq, min_freq, max_freq); } printf("\n"); } } /************************************************************************** * * Function name: ipmi_ekanalyzer_fru_file2structure * * Description: this function convert a FRU binary file into a linked list of * FRU multi record * * Restriction: None * * Input/Ouput: filename1: name of the file that contain FRU binary data * record: a pointer to current record * list_head: a pointer to header of the list * list_last: a pointer to tale of the list * * Global: None * * Return: return -1 as Error status, and 0 as Ok status * ***************************************************************************/ static int ipmi_ekanalyzer_fru_file2structure( char * filename, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_record, struct ipmi_ek_multi_header ** list_last ) { int return_status = ERROR_STATUS; FILE * input_file; input_file = fopen ( filename, "r"); if ( input_file == NULL ){ lprintf(LOG_ERR, "File: '%s' is not found", filename); return_status = ERROR_STATUS; } else{ long multi_offset = 0; fseek_( input_file, START_DATA_OFFSET, SEEK_SET ); fread ( &multi_offset, 1, 1, input_file ); if ( multi_offset <= 0 ){ lprintf(LOG_NOTICE, "There is no multi record in the file %s\n", filename); } else{ int record_count = 0; if ( verbose >= 2) { // was == LOG_DEBUG printf( "start multi offset = 0x%02x\n", multi_offset ); } /*the offset value is in multiple of 8 bytes.*/ multi_offset = multi_offset * 8; fseek_( input_file, multi_offset, SEEK_SET ); while ( !feof( input_file ) ){ *list_record = malloc ( sizeof (struct ipmi_ek_multi_header) ); fread ( &(*list_record)->header, START_DATA_OFFSET, 1, input_file); if ( (*list_record)->header.len > 0 ){ (*list_record)->data = malloc ((*list_record)->header.len); if ( (*list_record)->data == NULL ){ lprintf(LOG_ERR, "Lack of memory"); } else{ unsigned char last_record = 0; fread ( (*list_record)->data, ((*list_record)->header.len), 1, input_file); if ( verbose > 0 ) printf("Record %d has length = %02x\n", record_count, (*list_record)->header.len); if ( verbose > 1 ){ int i; printf("%02x\t", (*list_record)->header.type); for ( i = 0; i < ( (*list_record)->header.len ); i++ ){ printf("%02x\t", (*list_record)->data[i]); } printf("\n"); } ipmi_ek_add_record2list ( list_record, list_head, list_last ); /*mask the 8th bits to see if it is the last record*/ last_record = ((*list_record)->header.format) & 0x80; if ( last_record ){ break; } } } record_count++; } } fclose( input_file ); return_status = OK_STATUS; } return return_status; } /************************************************************************** * * Function name: ipmi_ek_add_record2list * * Description: this function adds a sigle FRU multi record to a linked list of * FRU multi record. * * Restriction: None * * Input/Output: record: a pointer to current record * list_head: a pointer to header of the list * list_last: a pointer to tale of the list * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_add_record2list( struct ipmi_ek_multi_header ** record, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last ) { if (*list_head == NULL) { *list_head = *record; (*record)->prev = NULL; if (verbose > 2) printf("Adding first record to list\n"); } else { (*list_last)->next = *record; (*record)->prev = *list_last; if (verbose > 2) printf("Add 1 record to list\n"); } *list_last = *record; (*record)->next = NULL; } /************************************************************************** * * Function name: ipmi_ek_remove_record_from_list * * Description: this function removes a sigle FRU multi record from a linked * list of FRU multi record. * * Restriction: None * * Input/Output: record: a pointer to record to be deleted * list_head: a pointer to header of the list * list_last: a pointer to tale of the list * * Global: None * * Return: None * ***************************************************************************/ static void ipmi_ek_remove_record_from_list( struct ipmi_ek_multi_header * record, struct ipmi_ek_multi_header ** list_head, struct ipmi_ek_multi_header ** list_last ) { if (record->prev == NULL) *list_head = record->next; else record->prev->next = record->next; if ( record->next == NULL ) (*list_last) = record->prev; else record->next->prev = record->prev; free (record); } #ifdef METACOMMAND int i_ekanalyzer(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { void *intf = NULL; int rc = 0; int c, i; char *s1; printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"m:p:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 1; verbose = 2; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': ipmi_ekanalyzer_usage(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } rc = ipmi_ekanalyzer_main(intf, argc, argv); ipmi_close_(); return rc; } #else /* ekanalyzer stub */ #ifdef METACOMMAND int i_ekanalyzer(int argc, char **argv) { printf("ekanalyzer function is not enabled\n"); return -1; } #endif #endif /*end iekanalyzer.c*/ ipmiutil-3.1.9/util/oem_dell.h0000644000000000000000000004621514144515623015001 0ustar rootroot/**************************************************************************** Copyright (c) 2008, Dell Inc All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of Dell Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ #ifndef IPMI_DELLOEM_H #define IPMI_DELLOEM_H #if HAVE_CONFIG_H # include #endif #ifdef HAVE_ATTRIBUTE_PACKING /* this attribute is not very portable */ #define ATTRIBUTE_PACKING __attribute__ ((packed)) #else /* use #pragma pack(1) instead */ #define ATTRIBUTE_PACKING #endif #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define IPMI_SET_SYS_INFO 0x58 #define IPMI_GET_SYS_INFO 0x59 /* Dell selector for LCD control - get and set unless specified */ #define IPMI_DELL_LCD_STRING_SELECTOR 0xC1 /* RW get/set the user string */ #define IPMI_DELL_LCD_CONFIG_SELECTOR 0xC2 /* RW set to user/default/none */ #define IPMI_DELL_LCD_GET_CAPS_SELECTOR 0xCF /* RO use when available*/ #define IPMI_DELL_LCD_STRINGEX_SELECTOR 0xD0 /* RW get/set the user string use first when available*/ #define IPMI_DELL_LCD_STATUS_SELECTOR 0xE7 /* LCD string when config set to default.*/ #define IPMI_DELL_PLATFORM_MODEL_NAME_SELECTOR 0xD1 /* LCD string when config set to default.*/ /* Dell defines for picking which string to use */ #define IPMI_DELL_LCD_CONFIG_USER_DEFINED 0x00 /* use string set by user*/ #define IPMI_DELL_LCD_CONFIG_DEFAULT 0x01 /* use platform model name*/ #define IPMI_DELL_LCD_CONFIG_NONE 0x02 /* blank*/ #define IPMI_DELL_LCD_iDRAC_IPV4ADRESS 0x04 /* use string set by user*/ #define IPMI_DELL_LCD_IDRAC_MAC_ADDRESS 0x08 /* use platform model name*/ #define IPMI_DELL_LCD_OS_SYSTEM_NAME 0x10 /* blank*/ #define IPMI_DELL_LCD_SERVICE_TAG 0x20 /* use string set by user*/ #define IPMI_DELL_LCD_iDRAC_IPV6ADRESS 0x40 /* use string set by user*/ #define IPMI_DELL_LCD_AMBEINT_TEMP 0x80 /* use platform model name*/ #define IPMI_DELL_LCD_SYSTEM_WATTS 0x100 /* blank*/ #define IPMI_DELL_LCD_ASSET_TAG 0x200 #define IPMI_DELL_LCD_ERROR_DISP_SEL 0x01 /* use platform model name*/ #define IPMI_DELL_LCD_ERROR_DISP_VERBOSE 0x02 /* blank*/ #define IPMI_DELL_IDRAC_VALIDATOR 0xDD #define IPMI_DELL_POWER_CAP_STATUS 0xBA #define IPMI_DELL_AVG_POWER_CONSMP_HST 0xEB #define IPMI_DELL_PEAK_POWER_CONSMP_HST 0xEC #define SYSTEM_BOARD_SYSTEM_LEVEL_SENSOR_NUM 0x98 #define IDRAC_11G 1 #define IDRAC_12G 2 // Return Error code for license #define LICENSE_NOT_SUPPORTED 0x6F #define VFL_NOT_LICENSED 0x33 #define btuphr 0x01 #define watt 0x00 #define IPMI_DELL_POWER_CAP 0xEA #define percent 0x03 /* Not on all Dell servers. If there, use it.*/ #pragma pack(1) typedef struct _tag_ipmi_dell_lcd_caps { uint8_t parm_rev; /* 0x11 for IPMI 2.0 */ uint8_t char_set; /* always 1 for printable ASCII 0x20-0x7E */ uint8_t number_lines; /* 0-4, 1 for 9G. 10G tbd */ uint8_t max_chars[4]; /* 62 for triathlon, 0 if not present (glacier) */ /* [0] is max chars for line 1 */ }IPMI_DELL_LCD_CAPS; #define IPMI_DELL_LCD_STRING_LENGTH_MAX 62 /* Valid for 9G. Glacier ??. */ #define IPMI_DELL_LCD_STRING1_SIZE 14 #define IPMI_DELL_LCD_STRINGN_SIZE 16 /* vFlash subcommands */ #define IPMI_GET_EXT_SD_CARD_INFO 0xA4 typedef struct _tag_ipmi_dell_lcd_string { uint8_t parm_rev; /* 0x11 for IPMI 2.0 */ uint8_t data_block_selector; /* 16-byte data block number to access, 0 based.*/ union { struct { uint8_t encoding : 4; /* 0 is printable ASCII 7-bit */ uint8_t length; /* 0 to max chars from lcd caps */ uint8_t data[IPMI_DELL_LCD_STRING1_SIZE]; /* not zero terminated. */ }selector_0_string; uint8_t selector_n_data[IPMI_DELL_LCD_STRINGN_SIZE]; }lcd_string; } ATTRIBUTE_PACKING IPMI_DELL_LCD_STRING; /* Only found on servers with more than 1 line. Use if available. */ typedef struct _tag_ipmi_dell_lcd_stringex { uint8_t parm_rev; /* 0x11 for IPMI 2.0 */ uint8_t line_number; /* LCD line number 1 to 4 */ uint8_t data_block_selector; /* 16-byte data block number to access, 0 based.*/ union { struct { uint8_t encoding : 4; /* 0 is printable ASCII 7-bit */ uint8_t length; /* 0 to max chars from lcd caps */ uint8_t data[IPMI_DELL_LCD_STRING1_SIZE]; /* not zero terminated. */ } selector_0_string; uint8_t selector_n_data[IPMI_DELL_LCD_STRINGN_SIZE]; } lcd_string; } ATTRIBUTE_PACKING IPMI_DELL_LCD_STRINGEX; typedef struct _lcd_status { char vKVM_status; char lock_status; char Resv1; char Resv; } ATTRIBUTE_PACKING LCD_STATUS; typedef struct _lcd_mode { uint8_t parametersel; uint32_t lcdmode; uint16_t lcdqualifier; uint32_t capabilites; uint8_t error_display; uint8_t Resv; } ATTRIBUTE_PACKING LCD_MODE; #pragma pack() #define PARAM_REV_OFFSET (uint8_t)(0x1) #define LOM_MACTYPE_ETHERNET 0 #define LOM_MACTYPE_ISCSI 1 #define LOM_MACTYPE_RESERVED 3 #define LOM_ETHERNET_ENABLED 0 #define LOM_ETHERNET_DISABLED 1 #define LOM_ETHERNET_PLAYINGDEAD 2 #define LOM_ETHERNET_RESERVED 3 #define LOM_ACTIVE 1 #define LOM_INACTIVE 0 #define MACADDRESSLENGH 6 #define MAX_LOM 8 #define IPMI_NETFN_SE (uint8_t)(0x04) #define IPMI_NETFN_APP (uint8_t)(0x06) //NETFN_APP #define IPMI_NETFN_STORAGE (uint8_t)(0x0a) //NETFN_STOR #define IPMI_CMD_GET_SEL_TIME 0x48 #define GET_FRU_INFO 0x10 #define GET_FRU_DATA 0x11 #define BSWAP_16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) #define APP_NETFN (uint8_t)(0x6) #define GET_SYSTEM_INFO_CMD (uint8_t)(0x59) #define EMB_NIC_MAC_ADDRESS_11G (uint8_t)(0xDA) #define EMB_NIC_MAC_ADDRESS_9G_10G (uint8_t)(0xCB) #define IMC_IDRAC_10G (uint8_t) (0x08) #define IMC_CMC (uint8_t) (0x09) #define IMC_IDRAC_11G_MONOLITHIC (uint8_t) (0x0A) #define IMC_IDRAC_11G_MODULAR (uint8_t) (0x0B) #define IMC_UNUSED (uint8_t) (0x0C) #define IMC_MASER_LITE_BMC (uint8_t) (0x0D) #define IMC_IDRAC_12G_MONOLITHIC (uint8_t) (0x10) #define IMC_IDRAC_12G_MODULAR (uint8_t) (0x11) #pragma pack(1) #ifdef LOM_OLD typedef struct { unsigned int BladSlotNumber : 4; unsigned int MacType : 2; unsigned int EthernetStatus : 2; unsigned int NICNumber : 5; unsigned int Reserved : 3; uint8_t MacAddressByte[MACADDRESSLENGH]; } LOMMacAddressType; #else typedef struct { uint8_t b0; uint8_t b1; uint8_t MacAddressByte[MACADDRESSLENGH]; } LOMMacAddressType; #endif #pragma pack() #pragma pack(1) typedef struct { LOMMacAddressType LOMMacAddress [MAX_LOM]; } EmbeddedNICMacAddressType; typedef struct { uint8_t MacAddressByte[MACADDRESSLENGH]; } MacAddressType; typedef struct { MacAddressType MacAddress [MAX_LOM]; } EmbeddedNICMacAddressType_10G; struct fru_info { uint16_t size; uint8_t access:1; }; struct fru_header { uint8_t version; struct { uint8_t internal; uint8_t chassis; uint8_t board; uint8_t product; uint8_t multi; } offset; uint8_t pad; uint8_t checksum; } ATTRIBUTE_PACKING; struct entity_id { uint8_t id; /* physical entity id */ #if WORDS_BIGENDIAN uint8_t logical : 1; /* physical/logical */ uint8_t instance : 7; /* instance number */ #else uint8_t instance : 7; /* instance number */ uint8_t logical : 1; /* physical/logical */ #endif } ATTRIBUTE_PACKING; struct sdr_record_mask { union { struct { uint16_t assert_event; /* assertion event mask */ uint16_t deassert_event; /* de-assertion event ma sk */ uint16_t read; /* discrete reading mask */ } ATTRIBUTE_PACKING discrete; /*...*/ } ATTRIBUTE_PACKING type; } ATTRIBUTE_PACKING ; struct sdr_record_full_sensor { struct { uint8_t owner_id; #if WORDS_BIGENDIAN uint8_t channel:4; /* channel number */ uint8_t __reserved1:2; uint8_t lun:2; /* sensor owner lun */ #else uint8_t lun:2; /* sensor owner lun */ uint8_t __reserved2:2; uint8_t channel:4; /* channel number */ #endif uint8_t sensor_num; /* unique sensor number */ } ATTRIBUTE_PACKING keys; struct entity_id entity; struct { struct { #if WORDS_BIGENDIAN uint8_t __reserved3:1; uint8_t scanning:1; uint8_t events:1; uint8_t thresholds:1; uint8_t hysteresis:1; uint8_t type:1; uint8_t event_gen:1; uint8_t sensor_scan:1; #else uint8_t sensor_scan:1; uint8_t event_gen:1; uint8_t type:1; uint8_t hysteresis:1; uint8_t thresholds:1; uint8_t events:1; uint8_t scanning:1; uint8_t __reserved4:1; #endif } ATTRIBUTE_PACKING init; struct { #if WORDS_BIGENDIAN uint8_t ignore:1; uint8_t rearm:1; uint8_t hysteresis:2; uint8_t threshold:2; uint8_t event_msg:2; #else uint8_t event_msg:2; uint8_t threshold:2; uint8_t hysteresis:2; uint8_t rearm:1; uint8_t ignore:1; #endif } ATTRIBUTE_PACKING capabilities; uint8_t type; } ATTRIBUTE_PACKING sensor; uint8_t event_type; /* event/reading type code */ struct sdr_record_mask mask; struct { #if WORDS_BIGENDIAN uint8_t analog:2; uint8_t rate:3; uint8_t modifier:2; uint8_t pct:1; #else uint8_t pct:1; uint8_t modifier:2; uint8_t rate:3; uint8_t analog:2; #endif struct { uint8_t base; uint8_t modifier; } ATTRIBUTE_PACKING type; } ATTRIBUTE_PACKING unit; #define SDR_SENSOR_L_LINEAR 0x00 #define SDR_SENSOR_L_LN 0x01 #define SDR_SENSOR_L_LOG10 0x02 #define SDR_SENSOR_L_LOG2 0x03 #define SDR_SENSOR_L_E 0x04 #define SDR_SENSOR_L_EXP10 0x05 #define SDR_SENSOR_L_EXP2 0x06 #define SDR_SENSOR_L_1_X 0x07 #define SDR_SENSOR_L_SQR 0x08 #define SDR_SENSOR_L_CUBE 0x09 #define SDR_SENSOR_L_SQRT 0x0a #define SDR_SENSOR_L_CUBERT 0x0b #define SDR_SENSOR_L_NONLINEAR 0x70 uint8_t linearization; /* 70h=non linear, 71h-7Fh=non linear, OEM */ uint16_t mtol; /* M, tolerance */ uint32_t bacc; /* accuracy, B, Bexp, Rexp */ struct { #if WORDS_BIGENDIAN uint8_t __reserved5:5; uint8_t normal_min:1; /* normal min field specified */ uint8_t normal_max:1; /* normal max field specified */ uint8_t nominal_read:1; /* nominal reading field specified */ #else uint8_t nominal_read:1; /* nominal reading field specified */ uint8_t normal_max:1; /* normal max field specified */ uint8_t normal_min:1; /* normal min field specified */ uint8_t __reserved5:5; #endif } ATTRIBUTE_PACKING analog_flag; uint8_t nominal_read; /* nominal reading, raw value */ uint8_t normal_max; /* normal maximum, raw value */ uint8_t normal_min; /* normal minimum, raw value */ uint8_t sensor_max; /* sensor maximum, raw value */ uint8_t sensor_min; /* sensor minimum, raw value */ struct { struct { uint8_t non_recover; uint8_t critical; uint8_t non_critical; } ATTRIBUTE_PACKING upper; struct { uint8_t non_recover; uint8_t critical; uint8_t non_critical; } ATTRIBUTE_PACKING lower; struct { uint8_t positive; uint8_t negative; } ATTRIBUTE_PACKING hysteresis; } ATTRIBUTE_PACKING threshold; uint8_t __reserved6[2]; uint8_t oem; /* reserved for OEM use */ uint8_t id_code; /* sensor ID string type/length code */ uint8_t id_string[16]; /* sensor ID string bytes, only if id_code != 0 */ } ATTRIBUTE_PACKING; struct sdr_record_list { uint16_t id; uint8_t version; uint8_t type; uint8_t length; union { struct sdr_record_full_sensor *full; } ATTRIBUTE_PACKING record; uint8_t *raw; struct sdr_record_list *next; } ATTRIBUTE_PACKING; #pragma pack() #define TRANSPORT_NETFN (uint8_t)(0xc) #define GET_LAN_PARAM_CMD (uint8_t)(0x02) #define MAC_ADDR_PARAM (uint8_t)(0x05) #define LAN_CHANNEL_NUMBER (uint8_t)(0x01) #define IDRAC_NIC_NUMBER (uint8_t)(0x8) #define TOTAL_N0_NICS_INDEX (uint8_t)(0x1) // 12g supported #define SET_NIC_SELECTION_12G_CMD (uint8_t)(0x28) #define GET_NIC_SELECTION_12G_CMD (uint8_t)(0x29) // 11g supported #define SET_NIC_SELECTION_CMD (uint8_t)(0x24) #define GET_NIC_SELECTION_CMD (uint8_t)(0x25) #define GET_ACTIVE_NIC_CMD (uint8_t)(0xc1) #define POWER_EFFICENCY_CMD (uint8_t)(0xc0) #define SERVER_POWER_CONSUMPTION_CMD (uint8_t)(0x8F) #define POWER_SUPPLY_INFO (uint8_t)(0xb0) #define IPMI_ENTITY_ID_POWER_SUPPLY (uint8_t)(0x0a) #define SENSOR_STATE_STR_SIZE (uint8_t)(64) #define SENSOR_NAME_STR_SIZE (uint8_t)(64) #define GET_PWRMGMT_INFO_CMD (uint8_t)(0x9C) #define CLEAR_PWRMGMT_INFO_CMD (uint8_t)(0x9D) #define GET_PWR_HEADROOM_CMD (uint8_t)(0xBB) #define GET_PWR_CONSUMPTION_CMD (uint8_t)(0xB3) #define GET_FRONT_PANEL_INFO_CMD (uint8_t)0xb5 #pragma pack(1) typedef struct _ipmi_power_monitor { uint32_t cumStartTime; uint32_t cumReading; uint32_t maxPeakStartTime; uint32_t ampPeakTime; uint16_t ampReading; uint32_t wattPeakTime; uint16_t wattReading; } ATTRIBUTE_PACKING IPMI_POWER_MONITOR; #define MAX_POWER_FW_VERSION 8 typedef struct _ipmi_power_supply_infoo { /*No param_rev it is not a System Information Command */ uint16_t ratedWatts; uint16_t ratedAmps; uint16_t ratedVolts; uint32_t vendorid; uint8_t FrimwareVersion[MAX_POWER_FW_VERSION]; uint8_t Powersupplytype; uint16_t ratedDCWatts; uint16_t Resv; } ATTRIBUTE_PACKING IPMI_POWER_SUPPLY_INFO; typedef struct ipmi_power_consumption_data { uint16_t actualpowerconsumption; uint16_t powerthreshold; uint16_t warningthreshold; uint8_t throttlestate; uint16_t maxpowerconsumption; uint16_t throttlepowerconsumption; uint16_t Resv; } ATTRIBUTE_PACKING IPMI_POWER_CONSUMPTION_DATA; typedef struct ipmi_inst_power_consumption_data { uint16_t instanpowerconsumption; uint16_t instanApms; uint16_t resv1; uint8_t resv; } ATTRIBUTE_PACKING IPMI_INST_POWER_CONSUMPTION_DATA; typedef struct _ipmi_avgpower_consump_histroy { uint8_t parameterselector; uint16_t lastminutepower; uint16_t lasthourpower; uint16_t lastdaypower; uint16_t lastweakpower; } ATTRIBUTE_PACKING IPMI_AVGPOWER_CONSUMP_HISTORY; typedef struct _ipmi_power_consump_histroy { uint8_t parameterselector; uint16_t lastminutepower; uint16_t lasthourpower; uint16_t lastdaypower; uint16_t lastweakpower; uint32_t lastminutepowertime; uint32_t lasthourpowertime; uint32_t lastdaypowertime; uint32_t lastweekpowertime; } ATTRIBUTE_PACKING IPMI_POWER_CONSUMP_HISTORY; typedef struct _ipmi_delloem_power_cap { uint8_t parameterselector; uint16_t PowerCap; uint8_t unit; uint16_t MaximumPowerConsmp; uint16_t MinimumPowerConsmp; uint16_t totalnumpowersupp; uint16_t AvailablePower ; uint16_t SystemThrottling; uint16_t Resv; } ATTRIBUTE_PACKING IPMI_POWER_CAP; typedef struct _power_headroom { uint16_t instheadroom; uint16_t peakheadroom; } ATTRIBUTE_PACKING POWER_HEADROOM; struct vFlashstr { uint8_t val; const char * str; }; typedef struct ipmi_vFlash_extended_info { uint8_t vflashcompcode; uint8_t sdcardstatus; uint32_t sdcardsize; uint32_t sdcardavailsize; uint8_t bootpartion; uint8_t Resv; } IPMI_DELL_SDCARD_INFO; #pragma pack() typedef struct _SensorReadingType { uint8_t sensorReading; uint8_t sensorFlags; uint16_t sensorState; }SensorReadingType; struct standard_spec_sel_rec{ uint32_t timestamp; uint16_t gen_id; uint8_t evm_rev; uint8_t sensor_type; uint8_t sensor_num; #if WORDS_BIGENDIAN uint8_t event_dir : 1; uint8_t event_type : 7; #else uint8_t event_type : 7; uint8_t event_dir : 1; #endif #define DATA_BYTE2_SPECIFIED_MASK 0xc0 /* event_data[0] bit mask */ #define DATA_BYTE3_SPECIFIED_MASK 0x30 /* event_data[0] bit mask */ #define EVENT_OFFSET_MASK 0x0f /* event_data[0] bit mask */ uint8_t event_data[3]; }; #define SEL_OEM_TS_DATA_LEN 6 #define SEL_OEM_NOTS_DATA_LEN 13 struct oem_ts_spec_sel_rec{ uint32_t timestamp; uint8_t manf_id[3]; uint8_t oem_defined[SEL_OEM_TS_DATA_LEN]; }; struct oem_nots_spec_sel_rec{ uint8_t oem_defined[SEL_OEM_NOTS_DATA_LEN]; }; #pragma pack(1) struct sel_event_record { uint16_t record_id; uint8_t record_type; union{ struct standard_spec_sel_rec standard_type; struct oem_ts_spec_sel_rec oem_ts_type; struct oem_nots_spec_sel_rec oem_nots_type; } sel_type; } ATTRIBUTE_PACKING; // __attribute__ ((packed)); #pragma pack() uint16_t compareinputwattage(IPMI_POWER_SUPPLY_INFO* powersupplyinfo, uint16_t inputwattage); int ipmi_delloem_main(void * intf, int argc, char ** argv); int ipmi_delloem_getled_state (void * intf, uint8_t *state); #endif /*IPMI_DELLOEM_H*/ ipmiutil-3.1.9/util/ipmiutil.h0000644000000000000000000000552414144515623015053 0ustar rootroot/*********************************************** * ipmiutil.h * * Definitions for ipmiutil.c * ***********************************************/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2006, Intel Corporation Copyright (c) 2009 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------*/ #ifndef IPMIUTIL_H_ #define IPMIUTIL_H_ int i_alarms(int argc, char **argv); int i_health(int argc, char **argv); int i_fru(int argc, char **argv); int i_getevt(int argc, char **argv); int i_reset(int argc, char **argv); int i_cmd(int argc, char **argv); int i_lan(int argc, char **argv); int i_serial(int argc, char **argv); int i_sensor(int argc, char **argv); int i_sel(int argc, char **argv); int i_wdt(int argc, char **argv); int i_sol(int argc, char **argv); int i_discover(int argc, char **argv); int i_config(int argc, char **argv); int i_events(int argc, char **argv); int i_picmg(int argc, char **argv); int i_firewall(int argc, char **argv); int i_fwum(int argc, char **argv); int i_hpm(int argc, char **argv); int i_sunoem(int argc, char **argv); int i_delloem(int argc, char **argv); int i_ekanalyzer(int argc, char **argv); int i_tsol(int argc, char **argv); int i_dcmi(int argc, char **argv); int i_smcoem(int argc, char **argv); int i_user(int argc, char **argv); #endif // IPMIUTIL_H_ ipmiutil-3.1.9/util/itsol.c0000644000000000000000000004631114144515623014343 0ustar rootroot/* * Copyright (c) 2005 Tyan Computer Corp. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #include #include #include #include #include #include #ifdef WIN32 #include #include #include #include #include "getopt.h" #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int typedef uint32_t socklen_t; #define inet_ntop InetNtop #define inet_pton InetPton int InetPton(int af, char *pstr, void *addr); /*see ws2_32.dll*/ char *InetNtop(int af, void *addr, char *pstr, int sz); char *InetNtop(int af, void *addr, char *pstr, int sz) { return NULL; }; int gettimeofday(struct timeval *tv, struct timezone *tz); #undef POLL_OK #else #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_CONFIG_H) #include "config.h" #endif #if defined(HPUX) /* getopt is defined in stdio.h */ #undef POLL_OK #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #include #undef POLL_OK #else #include #include #define POLL_OK 1 #endif #if defined (HAVE_SYS_TERMIOS_H) #include #else // #if defined(HAVE_TERMIOS_H) #include #endif #endif #include "ipmicmd.h" #include "itsol.h" extern int verbose; extern char fdebug; /*from ipmicmd.c*/ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil tsol"; #else static char * progver = "3.08"; static char * progname = "itsol"; #endif static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static char hostname[SZGNODE]; static SockType sockfd = -1; static char sol_escape_char = '~'; static struct timeval _start_keepalive; static int _in_raw_mode = 0; static int _altterm = 0; static SOCKADDR_T haddr; static int haddrlen = 0; static int hauth, hpriv, hcipher; #ifdef WIN32 #define NI_MAXHOST 80 #define NI_MAXSERV 80 struct pollfd { int fd; short events; short revents; }; struct winsize { int x; int y; }; #else static struct termios _saved_tio; static struct winsize _saved_winsize; #endif static int ipmi_tsol_command(void * intf, char *recvip, int port, unsigned char cmd) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char data[6]; unsigned ip1, ip2, ip3, ip4; if (sscanf(recvip, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) { lprintf(LOG_ERR, "Invalid IP address: %s", recvip); return -1; } memset(&req, 0, sizeof(struct ipmi_rq)); req.msg.netfn = IPMI_NETFN_TSOL; req.msg.cmd = cmd; req.msg.data_len = 6; req.msg.data = data; memset(data, 0, sizeof(data)); data[0] = ip1; data[1] = ip2; data[2] = ip3; data[3] = ip4; data[4] = (port & 0xff00) >> 8; data[5] = (port & 0xff); rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { lprintf(LOG_ERR, "Unable to perform TSOL command"); return rv; } if (rv > 0) { lprintf(LOG_ERR, "Unable to perform TSOL command: %s", decode_cc(0,rv)); return -1; } return 0; } static int ipmi_tsol_start(void * intf, char *recvip, int port) { return ipmi_tsol_command(intf, recvip, port, IPMI_TSOL_CMD_START); } static int ipmi_tsol_stop(void * intf, char *recvip, int port) { return ipmi_tsol_command(intf, recvip, port, IPMI_TSOL_CMD_STOP); } static int ipmi_tsol_send_keystroke(void * intf, char *buff, int length) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char data[16]; static unsigned char keyseq = 0; memset(&req, 0, sizeof(struct ipmi_rq)); req.msg.netfn = IPMI_NETFN_TSOL; req.msg.cmd = IPMI_TSOL_CMD_SENDKEY; req.msg.data_len = length + 2; req.msg.data = data; memset(data, 0, sizeof(data)); data[0] = length + 1; memcpy(data + 1, buff, length); data[length + 1] = keyseq++; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (verbose) { if (rv < 0) { lprintf(LOG_ERR, "Unable to send keystroke"); return rv; } if (rv > 0) { lprintf(LOG_ERR, "Unable to send keystroke: %s", decode_cc(0,rv)); return -1; } } return length; } static int tsol_keepalive(void * intf) { struct timeval end; int rv; gettimeofday(&end, 0); if (end.tv_sec - _start_keepalive.tv_sec <= 30) return 0; // intf->keepalive(intf); rv = lan_keepalive(1); /*1=getdevid, 2=empty sol*/ gettimeofday(&_start_keepalive, 0); return rv; } static void print_escape_seq(void *intf) { lprintf(LOG_NOTICE, " %c. - terminate connection\r\n" " %c^Z - suspend ipmiutil\r\n" " %c^X - suspend ipmiutil, but don't restore tty on restart\r\n" " %c? - this message\r\n" " %c%c - send the escape character by typing it twice\r\n" " (Note that escapes are only recognized immediately after newline.)\r", sol_escape_char, sol_escape_char, sol_escape_char, sol_escape_char, sol_escape_char, sol_escape_char); } #ifdef WIN32 static int leave_raw_mode(void) { return(0); } static int enter_raw_mode(void) { return(0); } static void set_terminal_size(int rows, int cols) { return; } static void do_terminal_cleanup(void) { int err; err = get_LastError(); lprintf(LOG_ERR, "Exiting due to error %d", err); show_LastError("",err); } static void suspend_self(int restore_tty) { return; } #else static int leave_raw_mode(void) { if (!_in_raw_mode) return -1; else if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1) lperror(LOG_ERR, "tcsetattr(stdin)"); else if (tcsetattr(fileno(stdout), TCSADRAIN, &_saved_tio) == -1) lperror(LOG_ERR, "tcsetattr(stdout)"); else _in_raw_mode = 0; return 0; } static int enter_raw_mode(void) { struct termios tio; if (tcgetattr(fileno(stdout), &_saved_tio) < 0) { lperror(LOG_ERR, "tcgetattr failed"); return -1; } tio = _saved_tio; if (_altterm) { tio.c_iflag &= (ISTRIP | IGNBRK ); tio.c_cflag &= ~(CSIZE | PARENB | IXON | IXOFF | IXANY); tio.c_cflag |= (CS8 |CREAD) | (IXON|IXOFF|IXANY); tio.c_lflag &= 0; tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; } else { tio.c_iflag |= IGNPAR; tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN); tio.c_oflag &= ~OPOST; tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; } if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0) lperror(LOG_ERR, "tcsetattr(stdin)"); else if (tcsetattr(fileno(stdout), TCSADRAIN, &tio) < 0) lperror(LOG_ERR, "tcsetattr(stdout)"); else _in_raw_mode = 1; return 0; } static void do_terminal_cleanup(void) { if (_saved_winsize.ws_row > 0 && _saved_winsize.ws_col > 0) ioctl(fileno(stdout), TIOCSWINSZ, &_saved_winsize); leave_raw_mode(); if (errno) lprintf(LOG_ERR, "Exiting due to error %d -> %s", errno, strerror(errno)); } static void set_terminal_size(int rows, int cols) { struct winsize winsize; if (rows <= 0 || cols <= 0) return; /* save initial winsize */ ioctl(fileno(stdout), TIOCGWINSZ, &_saved_winsize); /* set new winsize */ winsize.ws_row = rows; winsize.ws_col = cols; ioctl(fileno(stdout), TIOCSWINSZ, &winsize); } static void suspend_self(int restore_tty) { leave_raw_mode(); kill(getpid(), SIGTSTP); if (restore_tty) enter_raw_mode(); } #endif static int do_inbuf_actions(void *intf, char *in_buff, int len) { static int in_esc = 0; static int last_was_cr = 1; int i; for(i = 0; i < len ;) { if (!in_esc) { if (last_was_cr && (in_buff[i] == sol_escape_char)) { in_esc = 1; memmove(in_buff, in_buff + 1, len - i - 1); len--; continue; } } if (in_esc) { if (in_buff[i] == sol_escape_char) { in_esc = 0; i++; continue; } switch (in_buff[i]) { case '.': printf("%c. [terminated ipmiutil]\r\n", sol_escape_char); return -1; case 'Z' - 64: printf("%c^Z [suspend ipmiutil]\r\n", sol_escape_char); suspend_self(1); /* Restore tty back to raw */ break; case 'X' - 64: printf("%c^X [suspend ipmiutil]\r\n", sol_escape_char); suspend_self(0); /* Don't restore to raw mode */ break; case '?': printf("%c? [ipmiutil help]\r\n", sol_escape_char); print_escape_seq(intf); break; } memmove(in_buff, in_buff + 1, len - i - 1); len--; in_esc = 0; continue; } last_was_cr = (in_buff[i] == '\r' || in_buff[i] == '\n'); i++; } return len; } static void print_tsol_usage(void) { lprintf(LOG_NOTICE, "Usage: tsol [recvip] [port=NUM] [ro|rw] [rows=NUM] [cols=NUM] [altterm]"); lprintf(LOG_NOTICE, " recvip Receiver IP Address [default=local]"); lprintf(LOG_NOTICE, " port=NUM Receiver UDP Port [default=%d]", IPMI_TSOL_DEF_PORT); lprintf(LOG_NOTICE, " ro|rw Set Read-Only or Read-Write [default=rw]"); #ifdef POLL_OK { struct winsize winsize; ioctl(fileno(stdout), TIOCGWINSZ, &winsize); lprintf(LOG_NOTICE, " rows=NUM Set terminal rows [default=%d]", winsize.ws_row); lprintf(LOG_NOTICE, " cols=NUM Set terminal columns [default=%d]", winsize.ws_col); } #endif lprintf(LOG_NOTICE, " altterm Alternate terminal setup [default=off]"); } int ipmi_tsol_main(void * intf, int argc, char ** argv) { char *recvip = NULL; int result, i; int ip1, ip2, ip3, ip4; int read_only = 0, rows = 0, cols = 0; int port = IPMI_TSOL_DEF_PORT; #ifdef POLL_OK SOCKADDR_T sin, myaddr; socklen_t mylen; struct pollfd fds_wait[3], fds_data_wait[3], *fds; int fd_socket; int out_buff_fill, in_buff_fill; char out_buff[IPMI_BUF_SIZE * 8], in_buff[IPMI_BUF_SIZE]; char buff[IPMI_BUF_SIZE + 4]; char mystr[NI_MAXHOST]; #endif if (! is_remote()) { lprintf(LOG_ERR, "Error: Tyan SOL is only available over lan interface"); return -1; } for (i = 0; isa_family, &myaddr, mystr, sizeof(mystr)-1); if (recvip == NULL) { lprintf(LOG_ERR, "Unable to find local IP address"); return -1; } } printf("[Starting %sSOL with receiving address %s:%d]\r\n", read_only ? "Read-only " : "", recvip, port); set_terminal_size(rows, cols); enter_raw_mode(); /* * talk to smdc to start Console redirect - IP address and port as parameter * ipmiutil -I lan -H 192.168.168.227 -U Administrator raw 0x30 0x06 0xC0 0xA8 0xA8 0x78 0x1A 0x0A */ result = ipmi_tsol_start(intf, recvip, port); if (result < 0) { leave_raw_mode(); lprintf(LOG_ERR, "Error starting SOL"); return -1; } printf("[SOL Session operational. Use %c? for help]\r\n", sol_escape_char); gettimeofday(&_start_keepalive, 0); fd_socket = sockfd; fds_wait[0].fd = fd_socket; fds_wait[0].events = POLLIN; fds_wait[0].revents = 0; fds_wait[1].fd = fileno(stdin); fds_wait[1].events = POLLIN; fds_wait[1].revents = 0; fds_wait[2].fd = -1; fds_wait[2].events = 0; fds_wait[2].revents = 0; fds_data_wait[0].fd = fd_socket; fds_data_wait[0].events = POLLIN | POLLOUT; fds_data_wait[0].revents = 0; fds_data_wait[1].fd = fileno(stdin); fds_data_wait[1].events = POLLIN; fds_data_wait[1].revents = 0; fds_data_wait[2].fd = fileno(stdout); fds_data_wait[2].events = POLLOUT; fds_data_wait[2].revents = 0; out_buff_fill = 0; in_buff_fill = 0; fds = fds_wait; for (;;) { result = poll(fds, 3, 15*1000); if (result < 0) break; /* send keepalive packet */ tsol_keepalive(intf); if ((fds[0].revents & POLLIN) && (sizeof(out_buff) > out_buff_fill)){ socklen_t sin_len = sizeof(sin); result = recvfrom(fd_socket, buff, sizeof(out_buff) - out_buff_fill + 4, 0, (struct sockaddr *)&sin, &sin_len); /* read the data from udp socket, skip some bytes in the head */ if((result - 4) > 0 ){ int length = result - 4; #if 1 length = (unsigned char)buff[2] & 0xff; length *= 256; length += ((unsigned char)buff[3] & 0xff); if ((length <= 0) || (length > (result - 4))) length = result - 4; #endif memcpy(out_buff + out_buff_fill, buff + 4, length); out_buff_fill += length; } } if ((fds[1].revents & POLLIN) && (sizeof(in_buff) > in_buff_fill)) { result = read(fileno(stdin), in_buff + in_buff_fill, sizeof(in_buff) - in_buff_fill); // read from keyboard if (result > 0) { int bytes; bytes = do_inbuf_actions(intf, in_buff + in_buff_fill, result); if(bytes < 0) { result = ipmi_tsol_stop(intf, recvip, port); do_terminal_cleanup(); return result; } if (read_only) bytes = 0; in_buff_fill += bytes; } } if ((fds[2].revents & POLLOUT) && out_buff_fill) { result = write(fileno(stdout), out_buff, out_buff_fill); // to screen if (result > 0) { out_buff_fill -= result; if (out_buff_fill) { memmove(out_buff, out_buff + result, out_buff_fill); } } } if ((fds[0].revents & POLLOUT) && in_buff_fill) { /* * translate key and send that to SMDC using IPMI * ipmiutil cmd -N 192.168.168.227 -U Administrator 0x30 0x03 0x04 0x1B 0x5B 0x43 */ result = ipmi_tsol_send_keystroke(intf, in_buff, MIN(in_buff_fill,14)); if (result > 0) { gettimeofday(&_start_keepalive, 0); in_buff_fill -= result; if (in_buff_fill) { memmove(in_buff, in_buff + result, in_buff_fill); } } } fds = (in_buff_fill || out_buff_fill )? fds_data_wait : fds_wait; } #endif return 0; } #ifdef METACOMMAND int i_tsol(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { void *intf = NULL; int rc = 0; int c, i; char *s1; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); while ( (c = getopt( argc, argv,"m:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'x': fdebug = 1; verbose = 1; set_loglevel(LOG_DEBUG); break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': print_tsol_usage(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } rc = ipmi_tsol_main(intf, argc, argv); ipmi_close_(); // show_outcome(progname,rc); return rc; } /* end itsol.c */ ipmiutil-3.1.9/util/oem_kontron.c0000644000000000000000000007060714144515623015550 0ustar rootroot/* * oem_kontron.c * This code implements Kontron OEM proprietary commands. * * Change history: * 08/25/2010 ARCress - included in source tree * *--------------------------------------------------------------------- */ /* * Copyright (c) 2004 Kontron Canada, Inc. All Rights Reserved. * * Base on code from * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ /* * Tue Mar 7 14:36:12 2006 * * * This code implements an Kontron OEM proprietary commands. */ #ifdef WIN32 #include #include #include #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int typedef uint32_t socklen_t; #else #include #include #include #include #endif #include #include #include #include "ipmicmd.h" #include "ievents.h" #include "oem_kontron.h" #define FRU_TYPE_COMPONENT 0x01 #define FRU_TYPE_BASEBOARD 0x07 #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil kontronoem"; #else static char * progver = "3.08"; static char * progname = "ikontronoem"; #endif const struct valstr ktc5520_post[] = { /*from EAS*/ { 0x0003, "Start POST Init" }, { 0x0004, "Check CMOS" }, { 0x0005, "Init interrupt HW" }, { 0x0006, "Init INT1Ch" }, { 0x0008, "Init CPUs" }, { 0x000A, "Init 8042 Keyboard" }, { 0x000B, "Detect PS2 Mouse" }, { 0x000C, "Detect KBC Keyboard" }, { 0x000E, "Test Input Devices" }, { 0x0013, "PreInit chipset regs" }, { 0x0024, "Init platform modules" }, { 0x002A, "Init PCI devices" }, { 0x002C, "Init Video" }, { 0x002E, "Init Output devices" }, { 0x0030, "Init SMI" }, { 0x0031, "Init ADM module" }, { 0x0033, "Init Silent boot" }, { 0x0037, "Show first message" }, { 0x0038, "Init Buses" }, { 0x0039, "Init DMAC" }, { 0x003A, "Init RTC" }, { 0x003B, "Memory Test" }, { 0x003C, "MidInit chipset regs" }, { 0x0040, "Detect Ports" }, { 0x0050, "Adjust RAM size" }, { 0x0052, "Update CMOS size" }, { 0x0060, "Init Kbd Numlock" }, { 0x0075, "Init Int13" }, { 0x0078, "Init IPL" }, { 0x007A, "Init OpRoms" }, { 0x007C, "Write ESCD to NV" }, { 0x0084, "Log errors" }, { 0x0085, "Display errors" }, { 0x0087, "Run BIOS Setup" }, { 0x008C, "LateInit chipset regs" }, { 0x008D, "Build ACPI Tables" }, { 0x008E, "Program peripherals" }, { 0x0090, "LateInit SMI" }, { 0x00A0, "Check Boot password" }, { 0x00A1, "PreBoot Cleanup" }, { 0x00A2, "Init Runtime image" }, { 0x00A4, "Init Runtime lang" }, { 0x00A7, "Show Config, Init MTRR" }, { 0x00A8, "Prep CPU for OS boot" }, { 0x00A9, "Wait for input" }, { 0x00AA, "Deinit ADM, Int1C" }, { 0x00AB, "Prepare BBS" }, { 0x00AC, "EndInit chipse regs" }, { 0x00B1, "Save context for ACPI" }, { 0x00C0, "EarlyCPU Init APIC" }, { 0x00C1, "Setup BSP info" }, { 0x00C2, "Setup BSP for POST" }, { 0x00C5, "Setup App Processors" }, { 0x00C6, "Setup BSP cache" }, { 0x00C7, "EarlyCPU Init exit" }, { 0x0000, "OS Loader" }, { 0xffff , NULL } /*end of list*/ }; /* 61-70, OEM POST Error. This range is reserved for chipset vendors & system manufacturers. The error associated with this value may be different from one platform to the next. DD-DE, OEM PCI init debug POST code during DIMM init, See DIM Code Checkpoints section of document for more information. DD-DE, OEM PCI init debug POST code during DIMM init. DEh during BUS number */ extern int verbose; /*ipmilanplus.c*/ #ifdef METACOMMAND extern int load_fru(uchar sa, uchar frudev, uchar frutype, uchar **pfrubuf); extern int write_fru_data(uchar id, ushort offset, uchar *data, int dlen, char fdebug); /*ifru.c*/ #endif /* local function prototypes */ static void ipmi_kontron_help(void); static int ipmi_kontron_set_serial_number(void * intf); static int ipmi_kontron_set_mfg_date (void * intf); static void print_buf( uint8_t * buf, int len, char * desc) { dump_buf(desc,buf,len,0); } #ifdef METACOMMAND /* get_fru_area_str - Parse FRU area string from raw data * @data: raw FRU data * @offset: offset into data for area * returns pointer to FRU area string */ static char * get_fru_area_str(uint8_t * data, uint32_t * offset) { static const char bcd_plus[] = "0123456789 -.:,_"; char * str; int len, off, size, i, j, k, typecode; union { uint32_t bits; char chars[4]; } u; size = 0; off = *offset; /* bits 6:7 contain format */ typecode = ((data[off] & 0xC0) >> 6); /* bits 0:5 contain length */ len = data[off++]; len &= 0x3f; switch (typecode) { case 0: /* 00b: binary/unspecified */ /* hex dump -> 2x length */ size = (len*2); break; case 2: /* 10b: 6-bit ASCII */ /* 4 chars per group of 1-3 bytes */ size = ((((len+2)*4)/3) & ~3); break; case 3: /* 11b: 8-bit ASCII */ case 1: /* 01b: BCD plus */ /* no length adjustment */ size = len; break; } if (size < 1) { *offset = off; return NULL; } str = malloc(size+1); if (str == NULL) return NULL; memset(str, 0, size+1); if (len == 0) { str[0] = '\0'; *offset = off; return str; } switch (typecode) { case 0: /* Binary */ strncpy(str, buf2str(&data[off], len), len*2); break; case 1: /* BCD plus */ for (k=0; k 1 ? data[off+i+1] : 0); u.chars[1] = (k > 2 ? data[off+i+2] : 0); #define CHAR_IDX 3 #else memcpy((void *)&u.bits, &data[off+i], k); #define CHAR_IDX 0 #endif for (k=0; k<4; k++) { str[j++] = ((u.chars[CHAR_IDX] & 0x3f) + 0x20); u.bits >>= 6; } } str[j] = '\0'; break; case 3: memcpy(str, &data[off], len); str[len] = '\0'; break; } off += len; *offset = off; return str; } #endif static char *bootdev[] = {"BIOS", "FDD", "HDD", "CDROM", "network", 0}; static void ipmi_kontron_nextboot_help(void) { int i; printf("nextboot \n" "Supported devices:\n"); for (i = 0; bootdev[i] != 0; i++) { printf("- %s\n", bootdev[i]); } } /* ipmi_kontron_next_boot_set - Select the next boot order on CP6012 * * @intf: ipmi interface * @id: fru id * * returns -1 on error * returns 1 if successful */ static int ipmi_kontron_nextboot_set(void * intf, int argc, char **argv) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; uint8_t msg_data[8]; int i; memset(msg_data, 0, sizeof(msg_data)); msg_data[0] = 0xb4; msg_data[1] = 0x90; msg_data[2] = 0x91; msg_data[3] = 0x8b; msg_data[4] = 0x9d; msg_data[5] = 0xFF; msg_data[6] = 0xFF; /* any */ for (i = 0; bootdev[i] != 0; i++) { if (strcmp(argv[0], bootdev[i]) == 0) { msg_data[5] = (uchar)i; break; } } /* Invalid device selected? */ if (msg_data[5] == 0xFF) { printf("Unknown boot device: %s\n", argv[0]); return -1; } memset(&req, 0, sizeof(req)); req.msg.netfn = 0x3E; req.msg.cmd = 0x02; req.msg.data = msg_data; req.msg.data_len = 7; /* Set Lun temporary, necessary for this oem command */ req.msg.lun = 0x03; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); return (rv); } if (rv > 0) { printf(" NextBoot Device error (%s)\n",decode_cc(0,rv)); return(rv); } return (rv); } #ifdef METACOMMAND int ipmi_kontronoem_main(void * intf, int argc, char ** argv) { int rc = 0; if (argc == 0) ipmi_kontron_help(); else if (strncmp(argv[0], "help", 4) == 0) ipmi_kontron_help(); else if(!strncmp(argv[0], "setsn", 5)) { if(argc >= 1) { rc = ipmi_kontron_set_serial_number(intf); if(rc == 0) { printf("FRU serial number set successfully\n"); } else { printf("FRU serial number set failed\n"); } } else { printf("fru setsn\n"); } } else if(!strncmp(argv[0], "setmfgdate", 5)) { if(argc >= 1) { rc = ipmi_kontron_set_mfg_date(intf); if (rc == 0) { printf("FRU manufacturing date set successfully\n"); } else { printf("FRU manufacturing date set failed\n"); } } else { printf("fru setmfgdate\n"); } } else if (!strncmp(argv[0], "nextboot", sizeof("nextboot")-1)) { if (argc > 1) { if ((rc = ipmi_kontron_nextboot_set(intf, argc-1, argv+1)) == 0) { printf("Nextboot set successfully\n"); } else { printf("Nextboot set failed\n"); } } else { ipmi_kontron_nextboot_help(); } } else { printf("Invalid Kontron command: %s", argv[0]); ipmi_kontron_help(); rc = ERR_USAGE; } return rc; } static void ipmi_kontron_help(void) { printf("Kontron Commands: setsn setmfgdate nextboot\n"); } /* ipmi_fru_set_serial_number - Set the Serial Number in FRU * * @intf: ipmi interface * @id: fru id * * returns -1 on error * returns 1 if successful */ static int ipmi_kontron_set_serial_number(void * intf) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; struct fru_info fru; struct fru_header header; uint8_t msg_data[4]; char *sn; uint8_t sn_size, checksum; uint8_t *fru_data; char *fru_area; uint32_t fru_data_offset, fru_data_offset_tmp, board_sec_len, prod_sec_len, i; uint8_t bus, sa, lun, mtype; sn = NULL; fru_data = NULL; ipmi_get_mc(&bus, &sa, &lun, &mtype); memset(msg_data, 0, 4); msg_data[0] = 0xb4; msg_data[1] = 0x90; msg_data[2] = 0x91; msg_data[3] = 0x8b; memset(&req, 0, sizeof(req)); req.msg.netfn = 0x3E; req.msg.cmd = 0x0C; req.msg.data = msg_data; req.msg.data_len = 4; /* Set Lun, necessary for this oem command */ req.msg.lun = 0x03; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); return (rv); } if (rv > 0) { if (verbose) printf("sernum cmd ccode = %02x\n",rv); printf(" This option is not implemented for this board\n"); #ifdef TEST strcpy(rsp,"serialnumber"); rsp_len = 12; #else return (rv); #endif } sn_size = (uchar)rsp_len; if (sn_size < 1) { printf(" Original serial number is zero length, was cleared.\n"); return(ERR_BAD_LENGTH); } sn = malloc(sn_size + 1); if(sn == NULL) { printf("Out of memory!"); return(-1); } memset(sn, 0, sn_size + 1); memcpy(sn, rsp, sn_size); if(verbose >= 1) { printf("Original serial number is : [%s]\n", sn); } memset(msg_data, 0, 4); msg_data[0] = 0; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.cmd = GET_FRU_INFO; req.msg.data = msg_data; req.msg.data_len = 1; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); free(sn); return (rv); } if (rv > 0) { printf(" Device not present (%s)\n",decode_cc(0,rv)); free(sn); return (rv); } fru.size = (rsp[1] << 8) | rsp[0]; fru.access = rsp[2] & 0x1; if (fru.size < 1) { printf(" Invalid FRU size %d", fru.size); free(sn); return(ERR_BAD_LENGTH); } /* * retrieve the FRU header */ msg_data[0] = 0; msg_data[1] = 0; msg_data[2] = 0; msg_data[3] = 8; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.cmd = GET_FRU_DATA; req.msg.data = msg_data; req.msg.data_len = 4; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); free(sn); return(rv); } if (rv > 0) { printf(" Device not present (%s)\n",decode_cc(0,rv)); free(sn); return(rv); } if (verbose >= 1) print_buf(rsp, rsp_len, "FRU DATA"); memcpy(&header, rsp + 1, 8); if (header.version != 1) { printf(" Unknown FRU header version 0x%02x\n", header.version); free(sn); return(-1); } /* Set the Board Section */ board_sec_len = (header.offset.product * 8) - (header.offset.board * 8); rv = load_fru(sa,0, FRU_TYPE_BASEBOARD, &fru_data); if (rv != 0) { printf(" Cannot Read FRU, error %d\n",rv); free(sn); if (fru_data != NULL) free(fru_data); return(rv); } if (verbose >= 1) print_buf(fru_data, fru.size, "FRU BUFFER"); /*Position at Board Manufacturer*/ fru_data_offset = (header.offset.board * 8) + 6; fru_area = &fru_data[fru_data_offset]; if (verbose) printf("board_area: offset=0x%x len=%d\n",fru_data_offset,board_sec_len); fru_area = get_fru_area_str(fru_data, &fru_data_offset); /*Position at Board Product Name*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset); fru_data_offset_tmp = fru_data_offset; /*Position at Serial Number*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp); if (fru_area == NULL) { printf("Bad FRU area data read.\n"); free(sn); free(fru_data); return(-1); } fru_data_offset ++; if (verbose) printf("%x: Old board sernum [%s], New board sernum [%s]\n", fru_data_offset,fru_area,sn); if (strlen(fru_area) != sn_size) { printf("The length of the serial number in the FRU Board Area is wrong.\n"); free(sn); free(fru_data); return(ERR_BAD_LENGTH); } /* Copy the new serial number in the board section saved in memory*/ memcpy(fru_data + fru_data_offset, sn, sn_size); /* Calculate Header Checksum */ checksum = 0; for( i = (header.offset.board * 8); i < (((header.offset.board * 8)+board_sec_len) - 2) ; i ++ ) { checksum += fru_data[i]; } checksum = (~checksum) + 1; fru_data[(header.offset.board * 8)+board_sec_len - 1] = checksum; #ifdef TEST if (verbose >= 1) print_buf(fru_data, fru.size, "FRU BUFFER, New"); /* Write the new FRU Board section */ rv = write_fru_data(0, 0, fru_data, fru.size, verbose); // if(write_fru_area(intf, &fru, 0, (header.offset.board * 8), (header.offset.board * 8), board_sec_len, fru_data) < 0) if ( rv != 0 ) { printf(" Cannot Write FRU, error %d\n",rv); free(sn); free(fru_data); return(rv); } if (fru_data != NULL) { free(fru_data); fru_data = NULL; } rv = load_fru(sa,0, FRU_TYPE_BASEBOARD, &fru_data); if (rv != 0) { printf(" Cannot Read FRU, error %d\n",rv); free(sn); if (fru_data != NULL) free(fru_data); return(rv); } #endif /* Set the Product Section */ prod_sec_len = (header.offset.multi * 8) - (header.offset.product * 8); /*Position at Product Manufacturer*/ fru_data_offset = (header.offset.product * 8) + 3; fru_area = get_fru_area_str(fru_data, &fru_data_offset); /*Position at Product Name*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset); /*Position at Product Part*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset); /*Position at Product Version*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset); fru_data_offset_tmp = fru_data_offset; /*Position at Serial Number*/ fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp); fru_data_offset ++; if (verbose) printf("%x: Old product sernum [%s], New product sernum [%s]\n", fru_data_offset,fru_area,sn); if(strlen(fru_area) != sn_size) { free(sn); free(fru_data); printf("The length of the serial number in the FRU Product Area is wrong.\n"); return(ERR_BAD_LENGTH); } /* Copy the new serial number in the product section saved in memory*/ memcpy(fru_data + fru_data_offset, sn, sn_size); /* Calculate Header Checksum */ checksum = 0; for( i = (header.offset.product * 8); i < (((header.offset.product * 8)+prod_sec_len) - 2) ; i ++ ) { checksum += fru_data[i]; } checksum = (~checksum) + 1; fru_data[(header.offset.product * 8)+prod_sec_len - 1] = checksum; if (verbose >= 1) print_buf(fru_data, fru.size, "FRU BUFFER, New"); /* Write the new FRU Board section */ rv = write_fru_data(0, 0, fru_data, fru.size, (char)verbose); if ( rv != 0 ) { printf(" Cannot Write FRU, error %d\n",rv); /* fall through and free(sn); free(fru_data); return(rv); */ } free(sn); free(fru_data); return(rv); } /* ipmi_fru_set_mfg_date - Set the Manufacturing Date in FRU * * @intf: ipmi interface * @id: fru id * * returns -1 on error * returns 1 if successful */ static int ipmi_kontron_set_mfg_date (void * intf) { uchar rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; struct fru_info fru; struct fru_header header; uint8_t msg_data[4]; uint8_t mfg_date[3]; uint32_t board_sec_len, i; uint8_t *fru_data, checksum; uint8_t bus, sa, lun, mtype; ipmi_get_mc(&bus, &sa, &lun, &mtype); memset(msg_data, 0, 4); msg_data[0] = 0xb4; msg_data[1] = 0x90; msg_data[2] = 0x91; msg_data[3] = 0x8b; memset(&req, 0, sizeof(req)); req.msg.netfn = 0x3E; req.msg.cmd = 0x0E; req.msg.data = msg_data; req.msg.data_len = 4; /* Set Lun temporary, necessary for this oem command */ req.msg.lun = 0x03; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf("Device not present (No Response)\n"); return(rv); } if (rv > 0) { printf("This option is not implemented for this board\n"); return(rv); } if(rsp_len != 3) { printf("Invalid response for the Manufacturing date\n"); return(ERR_BAD_LENGTH); } if(rsp[0] == 0 && rsp[1] == 0 && rsp[2] == 0) { printf("Manufacturing date is zero, has been cleared\n"); return(ERR_BAD_FORMAT); } memset(mfg_date, 0, 3); memcpy(mfg_date, rsp, 3); memset(msg_data, 0, 4); msg_data[0] = 0; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.cmd = GET_FRU_INFO; req.msg.data = msg_data; req.msg.data_len = 1; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); return(rv); } if (rv > 0) { printf(" Device not present (%s)\n",decode_cc(0,rv)); return(rv); } fru.size = (rsp[1] << 8) | rsp[0]; fru.access = rsp[2] & 0x1; if (fru.size < 1) { printf(" Invalid FRU size %d", fru.size); return(ERR_BAD_LENGTH); } /* * retrieve the FRU header */ msg_data[0] = 0; msg_data[1] = 0; msg_data[2] = 0; msg_data[3] = 8; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_STORAGE; req.msg.cmd = GET_FRU_DATA; req.msg.data = msg_data; req.msg.data_len = 4; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv < 0) { printf(" Device not present (No Response)\n"); return(rv); } if (rv > 0) { printf(" Device not present (%s)\n",decode_cc(0,rv)); return(rv); } if (verbose > 1) print_buf(rsp, rsp_len, "FRU DATA"); memcpy(&header, &rsp[1], 8); if (header.version != 1) { printf(" Unknown FRU header version 0x%02x", header.version); return(ERR_BAD_FORMAT); } board_sec_len = (header.offset.product * 8) - (header.offset.board * 8); rv = load_fru(sa,0, FRU_TYPE_BASEBOARD, &fru_data); if (rv != 0) #ifdef NOT /* do not re-read the same fru buffer */ fru_data = malloc( fru.size); if(fru_data == NULL) { printf("Out of memory!"); return(-1); } memset(fru_data, 0, fru.size); rv = read_fru_area(intf ,&fru ,0 ,(header.offset.board * 8) ,board_sec_len , fru_data); if(rv < 0) #endif { if (fru_data != NULL) free(fru_data); return(rv); } /* Copy the new manufacturing date in the board section saved in memory*/ memcpy(fru_data + (header.offset.board * 8) + 3, mfg_date, 3); checksum = 0; /* Calculate Header Checksum */ for( i = (header.offset.board * 8); i < (((header.offset.board * 8)+board_sec_len) - 2) ; i ++ ) { checksum += fru_data[i]; } checksum = (~checksum) + 1; fru_data[(header.offset.board * 8)+board_sec_len - 1] = checksum; /* Write the new FRU Board section */ #ifdef NOT if(write_fru_area(intf, &fru, 0, (header.offset.board * 8), (header.offset.board * 8), board_sec_len, fru_data) < 0) #endif rv = write_fru_data(0, 0, fru_data, fru.size, (char)verbose); if ( rv != 0 ) { printf(" Cannot Write FRU, error %d\n",rv); /* fall through and free(fru_data); return(rv); */ } free(fru_data); return(rv); } #endif static char *assert_str(uchar val) { char *pstr; if ((val & 0x0f) == 0) pstr = "Deasserted"; else pstr = "Asserted"; return(pstr); } /* * decode_sel_kontron * inputs: * evt = the 16-byte IPMI SEL event * outbuf = points to the output string buffer * outsz = size of the output buffer * outputs: * rv = 0 if this event was successfully interpreted here, * non-zero otherwise, to use default interpretations. * outbuf = will contain the interpreted event text string (if rv==0) */ int decode_sel_kontron(uint8_t *evt, char *outbuf, int outsz, char fdesc, char fdebug) { int rv = -1; uint16_t id; uint8_t rectype; int oemid; uint32_t timestamp; char timestr[40]; char mybuf[64]; char oembuf[64]; char *type_str = NULL; char *gstr = NULL; char *pstr = NULL; int sevid; ushort genid; uchar snum; char *p1, *p2; sevid = SEV_INFO; id = evt[0] + (evt[1] << 8); /* instead try to decode some events manually */ rectype = evt[2]; timestamp = evt[3] + (evt[4] << 8) + (evt[5] << 16) + (evt[6] << 24); genid = evt[7] | (evt[8] << 8); snum = evt[11]; if (rectype == 0xc1) { /* OEM type C1 */ oemid = evt[7] + (evt[8] << 8) + (evt[9] << 16); if (oemid == VENDOR_KONTRON) { fmt_time(timestamp, timestr, sizeof(timestr)); type_str = "Kontron"; gstr = "BMC "; switch(evt[10]) { case 0x01: default: sprintf(mybuf,"OEM Event %02x %02x %02x %02x %02x %02x", evt[10], evt[11], evt[12], evt[13], evt[14], evt[15]); break; } snprintf(outbuf, outsz, "%04x %s %s %s %s %s\n", id,timestr,get_sev_str(sevid), gstr, type_str, mybuf); rv = 0; } /*endif kontron*/ } else if (rectype == 0x02) { type_str = ""; gstr = "BMC "; sprintf(mybuf,"%02x [%02x %02x %02x]", evt[12],evt[13],evt[14],evt[15]); switch(evt[10]) { /*sensor type*/ /* TODO: 0xC0, 0xC2, 0xC6 */ case 0xCF: /* Board Reset */ type_str = "Board Reset"; if (evt[12] == 0x03) { /*event trigger/type = discrete [de]assert */ pstr = ""; /*default*/ switch(evt[13]) { /*data1/offset*/ case 0x01: pstr = "Asserted"; break; case 0xa1: /*data2,3 bytes have meaning*/ /* data2: usually 0x01 */ /* data3: 05, 08, ff */ switch(evt[14]) { /*data2*/ case 0x00: p1 = "warm reset"; break; case 0x01: p1 = "cold reset"; break; case 0x02: p1 = "forced cold"; break; case 0x03: p1 = "soft reset"; break; case 0x04: p1 = "hard reset"; break; case 0x05: p1 = "forced hard"; break; default: p1 = "other"; break; } switch(evt[15]) { /*data3*/ case 0x00: p2 = "IPMI watchdog"; break; case 0x01: p2 = "IPMI command"; break; case 0x02: p2 = "Proc check stop"; break; /*internal*/ case 0x03: p2 = "Proc reset request"; break; /*internal*/ case 0x04: p2 = "Reset button"; break; case 0x05: p2 = "Power up"; break; case 0x06: p2 = "Legacy int watchdog"; break; /*internal*/ case 0x07: p2 = "Legacy prg watchdog"; break; /*programmable*/ case 0x08: p2 = "Software initiated"; break; case 0x09: p2 = "Setup reset"; break; case 0x0a: p2 = "Power cycle"; break; default: p2 = "Other"; break; } sprintf(oembuf,"%s/%s",p1,p2); pstr = oembuf; break; default: break; } rv = 0; } break; case 0x12: /* System Event */ /* snum 38, 6f 00, or ef 00 */ /* if (snum == 0x38) */ type_str = "System Event"; if (evt[12] == 0x6f) pstr = assert_str(1); /*asserted*/ else pstr = assert_str(0); /*0xef means deasserted*/ rv = 0; break; case 0x24: /* Platform Alert */ /* usu 03 01 */ type_str = "Platform Alert"; pstr = assert_str(evt[13]); /*data1*/ rv = 0; break; case 0x2B: /* Version Change */ /* 6f c1 02 ff */ type_str = "Version Change"; if ((evt[13] & 0x80) == 0) pstr = ""; else switch(evt[14]) { /*data2*/ case 0x01: pstr = "HW Changed"; break; case 0x02: pstr = "SW Changed"; break; case 0x03: pstr = "HW incompatible"; break; default: pstr = "Change failed"; break; /*TODO: add detail here*/ } rv = 0; break; case 0x70: type_str = "OEM Firmware Info 1"; pstr = assert_str(evt[13]); /*data1*/ rv = 0; break; case 0x71: type_str = "OEM Firmware Info 2"; pstr = assert_str(evt[13]); /*data1*/ rv = 0; break; default: break; } if (rv == 0) { format_event(id,timestamp, sevid, genid, type_str, snum,NULL,pstr,mybuf,outbuf,outsz); } } return rv; } /*end decode_sel_kontron*/ int decode_sensor_kontron(uchar *sdr,uchar *reading,char *pstring, int slen) { int rv = -1; uchar stype; char *pstr = NULL; int rdval; if (sdr == NULL || reading == NULL) return(rv); if (pstring == NULL || slen == 0) return(rv); if (sdr[3] != 0x02) return(rv); /*skip if not compact sensor*/ stype = sdr[12]; rdval = reading[2] | ((reading[3] & 0x7f) << 8); /* usually reading3 == 0x80 */ switch(stype) { case 0x08: /* Power Supply or PwrGood ... */ if (sdr[14] == 0x02) { if (reading[2] & 0x02) pstr = "Failed"; else pstr = "OK"; rv = 0; } break; case 0xC0: /* IPMI Info-N */ if (reading[2] == 0) pstr = "OK"; else pstr = "Asserted"; rv = 0; break; case 0xC2: /* IniAgent Err */ if ((reading[2] & 0x01) == 1) pstr = "OK"; else pstr = "Error"; /*could be 0x02*/ rv = 0; break; case 0xC6: /* POST Value */ pstr = (char *)val2str((ushort)rdval,ktc5520_post); if (pstr == NULL) { if (rdval >= 0x61 && rdval <= 0x71) pstr = "Error"; else if (rdval >= 0xDD && rdval <= 0xDE) pstr = "DIMM Debug"; else pstr = "Other"; } rv = 0; break; case 0xCF: /* Board Reset */ if ((reading[2] & 0x01) == 1) pstr = "OK"; else pstr = "Asserted"; rv = 0; break; default: break; } if (rv == 0) strncpy(pstring, pstr, slen); return(rv); } #ifdef METACOMMAND int i_kontronoem(int argc, char **argv) { printf("%s ver %s\n", progname,progver); return(0); } #endif /* end oem_kontron.c */ ipmiutil-3.1.9/util/getopt.h-win320000644000000000000000000000340114144515623015451 0ustar rootroot/* * getopt.h * * 07/13/07 ARCress - created. * Copyright (c) 2007 Andy Cress BSD-3-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c. Neither the name of Kontron, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _GETOPT_H_ #define _GETOPT_H_ extern int getopt(int argc, char **argv, char *opts); extern int optind; extern int optopt; extern int opterr; extern char *optarg; #endif ipmiutil-3.1.9/util/md2.c0000644000000000000000000000656614144515623013703 0ustar rootroot/* * md2.c * Used in ipmilan.c * * 05/26/2006 ARCress - copied from freeipmi ipmi-md2.c, * added md2_sum() subroutine, added WIN32 flag * 08/14/2008 ARCress - moved md2 routines from md2.c to md2.h */ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2002-2008, Intel Corporation Copyright (c) 2009 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------*/ #include #include #include #include #include #undef MD2_GPL #undef MD2_LIB #if defined(ALLOW_GNU) #define MD2_GPL 1 /*use md2.h GPL code*/ #else /* if here, ALLOW_GPL is not defined, check for lanplus libcrypto. */ #if defined(HAVE_LANPLUS) #define MD2_LIB 1 /*use MD2 version from lanplus libcrypto */ #endif /* if libcrypto does not have EVP_md2, then skip MD2. */ #if defined(SKIP_MD2) #undef MD2_LIB #endif #endif /* use GPL md2.h only if "configure --enable-gpl" set ALLOW_GPL */ #ifdef MD2_GPL /* * The md2.h contains some GPL code that may not be desired in some cases. * If GPL is not desired, the md2.h can be deleted without modifying the * configure/make process. * If GPL is ok, then "configure --enable-gpl" should be used. */ #include "md2.h" #else /* else MD2_GPL is not set */ #ifdef MD2_LIB /* Use EVP_md2() from the openssl libcrypto.so */ #include void md2_sum(unsigned char *pdata, int sdata, unsigned char *digest) { EVP_MD_CTX ctx; unsigned int mdlen; static int fmd2added = 0; const EVP_MD *md = NULL; md = EVP_md2(); if (fmd2added == 0) { EVP_add_digest(md); fmd2added = 1; } EVP_MD_CTX_init(&ctx); EVP_DigestInit_ex(&ctx, md, NULL); EVP_DigestUpdate(&ctx, pdata, sdata); mdlen = 16; EVP_DigestFinal_ex(&ctx, digest, &mdlen); EVP_MD_CTX_cleanup(&ctx); } #endif #endif /*end md2.c */ ipmiutil-3.1.9/util/ipmiutillib.def0000644000000000000000000000104114144515623016037 0ustar rootrootLIBRARY 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 ipmiutil-3.1.9/util/ipmidir.c0000644000000000000000000014263614144515623014655 0ustar rootroot/************************************************ * * ipmidir.c * * Supports direct raw KCS and SMBus user-space I/Os. * Use this if no other IPMI driver is present. * This interface would not be sufficient if more * than one application is using IPMI at a time. * This code is currently included for Linux, not for * Windows. Windows requires imbdrv.sys or ipmidrv.sys. * * 08/21/06 Andy Cress - added as a new module * 09/22/06 Andy Cress - improved SMBus base address detection * 09/27/06 Andy Cress - fixed passing slave addrs other than BMC (0x20) * 01/16/08 Andy Cress - more DBG messages * ************************************************/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2006, Intel Corporation Copyright (c) 2009 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------*/ #if defined(__IA64__) #define STUB_IO 1 #endif #if defined(STUB_IO) /* May stub out direct io. For instance, PPC does not support */ #define UCHAR unsigned char #define UINT16 unsigned short int ipmi_open_direct(int fdebugcmd) { return(-1); } int ipmi_close_direct(void) { return(-1); } int ipmi_cmdraw_direct(UCHAR cmd, UCHAR netfn, UCHAR lun, UCHAR sa, UCHAR bus, UCHAR *pdata, int sdata, UCHAR *presp, int *sresp, UCHAR *pcc, char fdebugcmd) { return(-1); } int ipmi_cmd_direct(UINT16 icmd, UCHAR *pdata, int sdata, UCHAR *presp, int *sresp, UCHAR *pcc, char fdebugcmd) { return(-1); } int ipmi_set_max_kcs_loops(int ms) { return(0); } #elif defined(LINUX) || defined(BSD) || defined(DOS) || defined(MACOS) || defined(HPUX) #include #include #include #include #include // for ProcessSendMessage timeout #include #include #ifdef DOS #include #else #include #endif #include "imb_api.h" #include "ipmicmd.h" #include "ipmidir.h" /* No special includes for 64-bit are needed. */ #if defined(LINUX) #include #elif defined(BSD) || defined(MACOS) || defined(HPUX) // #include int iofd = -1; static __inline uchar inbc(ushort port) { uchar data; /* from Linux sys/io.h: * __asm__ __volatile__ ("inb %w1,%0":"=a" (data):"Nd" (port)); * from BSD machine/cpufunc.h: * __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((ushort)(port))); */ __asm __volatile("inb %1,%0" : "=a" (data) : "d" (port)); return (data); } static __inline void outbc(ushort port, uchar data) { /* from Linux sys/io.h: * __asm__ __volatile__ ("outb %b0,%w1": :"a" (data), "Nd" (port)); * from BSD machine/cpufunc.h: * __asm __volatile("outb %0,%1" : : "a" (data), "id" ((ushort)(port))); */ __asm __volatile("outb %0,%1" : : "a" (data), "d" (port)); } static __inline uint inl(ushort port) { uint data; __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port)); return (data); } static __inline void outl(ushort port, uint data) { __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port)); } #endif /* Linux & BSD define usleep() in unistd.h, but DOS has delay() instead. */ #if defined(DOS) void usleep(ulong usec) /*missing from DOS*/ { delay(usec); } #endif /* DBGP() is enabled with -x, DBGP2 is enabled if LINUX_DEBUG & -x */ #define DBGP(fmt, args...) if (fdebugdir) fprintf(stdout,fmt, ##args) #if defined(DOS) #define DBGP2() ; /*no extra debug output*/ #elif defined(LINUX_DEBUG) #define DBGP2(fmt, args...) if (fdebugdir) fprintf(stderr,fmt, ##args) #else #define DBGP2(fmt, args...) ; /*no extra debug output*/ #endif #ifdef ALONE static int fjustpass = 0; #else // DRV_KCS, DRV_SMB types defined in ipmicmd.h // extern int fDriverTyp; // use set_driver_type() instead extern ipmi_cmd_t ipmi_cmds[NCMDS]; extern int fjustpass; #endif /*****************************************************************************/ /* * GLOBAL DATA */ /* KCS base addr: use 0xca2 for ia32, 0x8a2 for ia64 * some use 0xca8/0xcac w register spacing */ #if defined(__ia64__) /* gcc defines __ia64__, or Makefile.am defines __IA64__ */ static UINT16 kcsBaseAddress = 0x8a2; /* for Itanium2 KCS */ static UINT8 kcs_inc = 1; /*register spacing*/ #else static UINT16 kcsBaseAddress = 0xca2; /* for ia32 KCS */ static UINT8 kcs_inc = 1; /*register spacing*/ #endif /* * SMBus/SSIF: see dmidecode for I2C Slave Address & Base Addr. * Slave Addr is constant for all Intel SSIF platforms (=0x84). * 0x0540 base <= PCI ID 24D38086 at 00:1f.3 is JR (ICH5) * 0x0400 base <= PCI ID 25A48086 at 00:1f.3 is TP (Hance_Rapids) */ UINT8 mBMCADDR = 0x84; /* SMBus I2C slave address = (0x42 << 1) */ UINT16 mBMC_baseAddr = 0x540; /* usu. 0x0540 (JR), or 0x0400 if TP */ UINT16 BMC_base = 0; /* resulting BMC base address (KCS or SMBus)*/ static char lock_dir_file[] = "/var/tmp/ipmiutil_dir_lock"; /* SSIF/SMBus defines */ #define STATUS_REQ 0x60 #define WR_START 0x61 #define WR_END 0x62 #define READ_BYTE 0x68 #define COMMAND_REG (kcsBaseAddress+kcs_inc) #define STATUS_REG (kcsBaseAddress+kcs_inc) #define DATA_IN_REG (kcsBaseAddress) #define DATA_OUT_REG (kcsBaseAddress) #if defined(DOS) extern unsigned inp(unsigned _port); extern unsigned outp(unsigned _port, unsigned _value); #pragma intrinsic(inp, outp) #define _INB(addr) inp((addr)) #define _OUTB(data, addr) outp((addr),(data)) #define _IOPL(data) 0 #define ReadPortUchar( addr, valp ) (*valp) = inp((addr)) #define WritePortUchar( addr, val ) outp((addr),(val)) #define WritePortUlong( addr, val ) ( outp((addr),(val)) ) #define ReadPortUlong( addr, valp ) (*(valp) = inp((addr)) ) #elif defined(BSD) || defined(MACOS) || defined(HPUX) #define _INB(addr) inbc((addr)) #define _OUTB(data, addr) outbc((addr),(data)) #define _IOPL(data) 0 #define ReadPortUchar( addr, valp ) (*valp) = inbc((addr)) #define WritePortUchar( addr, val ) outbc((addr),(val)) #define WritePortUlong( addr, val ) ( outl((addr),(val)) ) #define ReadPortUlong( addr, valp ) (*(valp) = inl((addr)) ) #else #define _INB(addr) inb((addr)) #define _OUTB(data, addr) outb((data),(addr)) #define _IOPL(data) iopl((data)) #define ReadPortUchar( addr, valp ) (*valp) = inb((addr)) #define WritePortUchar( addr, val ) outb((val),(addr)) #define WritePortUlong( addr, val ) ( outl((val), (addr)) ) #define ReadPortUlong( addr, valp ) (*(valp) = inl((addr)) ) #endif /* Static data for Driver type, BMC type, etc. */ static int g_DriverType = DRV_KCS; static UINT16 g_ipmiVersion = IPMI_VERSION_UNKNOWN; static UINT16 g_bmcType = BMC_UNKNOWN; struct SMBCharStruct SMBChar; static int fdebugdir = 0; static char fDetectedIF = 0; /*****************************************************************************/ /* Subroutine prototypes */ #ifdef ALONE int set_driver_type(char * typ) { return; } int get_IpmiStruct(UCHAR *iftype, UCHAR *ver, UCHAR *sa, int *base, UCHAR *inc) { return(-1); } #else /* extern int set_driver_type(char * typ); in ipmicmd.h */ extern char fsm_debug; /*in mem_if.c*/ extern int get_IpmiStruct(UCHAR *iftype, UCHAR *ver, UCHAR *sa, int *base, UCHAR *inc); #endif int SendTimedImbpRequest_kcs( IMBPREQUESTDATA *requestData, unsigned int timeout, UINT8 *resp_data, int *respDataLen, UINT8 *compCode); int SendTimedImbpRequest_ssif( IMBPREQUESTDATA *requestData, unsigned int timeout, UINT8 *resp_data, int *respDataLen, UINT8 *compCode); int ImbInit_dir(void); static int SendmBmcRequest( unsigned char* request, UINT32 reqLength, unsigned char* response, UINT32* respLength, UINT32 ipmiOldFlag); static int ReadResponse( unsigned char* resp, struct SMBCharStruct* smbChar); static int SendRequest( unsigned char* req, int length, struct SMBCharStruct* smbChar ); static int GetDeviceId(UINT16 *bmcType, UINT16 *ipmiVersion); static int send_raw_kcs(UINT8 *rqData, int rqLen, UINT8 *rsData, int *rsLen ); static int ProcessTimedMessage(BMC_MESSAGE *p_reqMsg, BMC_MESSAGE *p_respMsg, const UINT32 timeout); static int wait_for_SMS_flag(void); /*****************************************************************************/ /* Subroutines */ static int ProcessMessage(BMC_MESSAGE *p_reqMsg, BMC_MESSAGE *p_respMsg) { int status = STATUS_OK; UINT32 timeout = 1000 * GETMSGTIMEOUT; // value is in milliseconds status = ProcessTimedMessage(p_reqMsg, p_respMsg, timeout); return status; } static char *BmcDesc(unsigned char drvtype) { /* return BMC Driver type description string */ char *msg; switch(drvtype) { case DRV_KCS: msg = "KCS"; break; /*BMC Sahalee KCS*/ case DRV_SMB: msg = "SMBus"; break; /*mBMC SMBus (SSIF)*/ default: msg = ""; } return(msg); } int get_ipmi_if(void) { /* Only care about Linux since ipmidir is not used for Windows. */ char *if_file = "/var/lib/ipmiutil/ipmi_if.txt"; char *if_file2 = "/usr/share/ipmiutil/ipmi_if.txt"; FILE *fp; char line[80]; char *p; char *r; int rv = ERR_NO_DRV; int i, j; ulong mybase = 0; int myinc = 1; // uchar *rgbase; fp = fopen(if_file,"r"); if (fp == NULL) fp = fopen(if_file2,"r"); if (fp == NULL) { /*error opening ipmi_if file*/ return -1; } else { /*read the data from the ipmi_if file*/ while ( (p = fgets(line,sizeof(line),fp)) != NULL) { if (strstr(line,"Interface type:") != NULL) { if (strstr(line,"KCS") != NULL) { g_DriverType = DRV_KCS; } else { g_DriverType = DRV_SMB; } } else if (strstr(line,"Base Address:") != NULL) { r = strchr(line,':'); i = strspn(++r," \t"); /* skip leading spaces */ r += i; j = strcspn(r," \t\r\n"); /* end at next whitespace */ r[j] = 0; /*stringify*/ /* convert the "0x0000000000000401" string to an int */ if (strncmp(r,"0x",2) == 0) { r += 2; j -= 2; } DBGP2("base addr 0x: %s, mybase=%x j=%d\n",r,mybase,j); mybase = strtol(r, NULL, 16); /*hex string is base 16*/ DBGP2("base addr 0x: %s, mybase=%x \n",r,mybase); } else if (strstr(line,"Register Spacing:") != NULL) { r = strchr(line,':'); i = strspn(++r," \t"); /* skip leading spaces */ r += i; j = strcspn(r," \t"); /* end at next whitespace */ r[j] = 0; /*stringify*/ myinc = atoi(r); } } fclose(fp); DBGP("ipmi_if: Driver = %d (%s), Base = 0x%04lx, Spacing = %d\n", g_DriverType,BmcDesc(g_DriverType),mybase,myinc); if (g_DriverType == DRV_SMB) { if (mybase & 0x0001) mybase -= 1; /* 0x0401 -> 0x0400 */ if (mybase != 0 && (mybase & 0x0F) == 0) { /* valid base address */ mBMC_baseAddr = mybase; BMC_base = mBMC_baseAddr; rv = 0; } } else { /*KCS*/ if (mybase != 0) { /* valid base address */ kcsBaseAddress = (mybase & 0x0000ffff); BMC_base = kcsBaseAddress; if (myinc > 1) kcs_inc = myinc; rv = 0; } } DBGP2("ipmi_if: BMC_base = 0x%04x, kcs_inc = %d, ret = %d\n", BMC_base, kcs_inc,rv); } return(rv); } static int set_lock_dir(void) { int rv = 0; FILE *fp; fp = fopen(lock_dir_file,"w"); if (fp == NULL) rv = -1; else { fclose(fp); rv = 0; } return(rv); } static int clear_lock_dir(void) { int rv = 0; rv = remove(lock_dir_file); /*same as unlink() */ if (fdebugdir) printf("clear_lock rv = %d\n",rv); return(rv); } static int check_lock_dir(void) { int rv = 0; #ifdef LOCK_OK FILE *fp; fp = fopen(lock_dir_file,"r"); if (fp == NULL) rv = 0; else { fclose(fp); rv = -1; /*error, lock file exists*/ } #endif return(rv); } int ipmi_open_direct(int fdebugcmd) { int status = 0; //char *dmsg = ""; int i; DBGP2("open_direct(%d) called\n",fdebugcmd); if (fdebugcmd) { fdebugdir = fdebugcmd; #if defined(LINUX_DEBUG) && !defined(ALONE) fsm_debug = fdebugcmd; #endif } /* Read ipmi_if config file data, if present. */ status = get_ipmi_if(); if (status == -1) { uchar iftype, iver, sa, inc; int mybase; /* Read SMBIOS to get IPMI struct */ status = get_IpmiStruct(&iftype,&iver,&sa,&mybase,&inc); if (status == 0) { if (iftype == 0x04) { g_DriverType = DRV_SMB; mBMC_baseAddr = mybase; } else { /*0x01==KCS*/ g_DriverType = DRV_KCS; BMC_base = mybase; if (sa == 0x20 && mybase != 0) { /*valid*/ kcsBaseAddress = mybase; kcs_inc = inc; } } DBGP("smbios: Driver=%d(%s), sa=%02x, Base=0x%04x, Spacing=%d\n", g_DriverType,BmcDesc(g_DriverType),sa,mybase,inc); } else { return ERR_NO_DRV; /*no SMBIOS IPMI record*/ } } #ifndef DOS /* superuser/root priv is required for direct I/Os */ i = geteuid(); /*direct is Linux only anyway*/ if (i > 1) { fprintf(stdout,"Not superuser (%d)\n", i); return ERR_NO_DRV; } #endif /* check lock for driverless interface */ i = check_lock_dir(); if (i != 0) { fprintf(stdout,"open_direct interface locked, %s in use\n", lock_dir_file); return ERR_NO_DRV; } /* Find the SMBIOS IPMI driver type, data */ status = ImbInit_dir(); DBGP2("open_direct Init status = %d\n",status); DBGP2("open_direct base=%x spacing=%d\n",BMC_base,kcs_inc); if (status == 0) { fDetectedIF = 1; /*Successfully detected interface */ /* Send a command to the IPMI interface */ if (!fjustpass) status = GetDeviceId(&g_bmcType,&g_ipmiVersion); if (status == 0) { char *typ; if (g_DriverType == DRV_SMB) typ = "smb"; else typ = "kcs"; set_driver_type(typ); } /* set lock for driverless interface */ i = set_lock_dir(); } DBGP("open_direct: status=%d, %s drv, ipmi=%d\n", status,BmcDesc(g_DriverType),g_ipmiVersion); return status; } int ipmi_close_direct(void) { int status = 0; #if defined(BSD) || defined(MACOS) || defined(HPUX) if (iofd >= 0) { close(iofd); iofd = -1; } #endif /* clear lock for driverless interface */ status = clear_lock_dir(); return status; } int ipmi_cmdraw_direct(UCHAR cmd, UCHAR netfn, UCHAR lun, UCHAR sa, UCHAR bus, UCHAR *pdata, int sdata, UCHAR *presp, int *sresp, UCHAR *pcc, char fdebugcmd) { BMC_MESSAGE sendMsg; BMC_MESSAGE respMsg; int status; int len = 0; if (g_bmcType == BMC_UNKNOWN) { /* User-specified a driver type, but need open */ status = ipmi_open_direct(fdebugcmd); } fdebugdir = fdebugcmd; if (sdata > IPMI_REQBUF_SIZE) return(LAN_ERR_BADLENGTH); if (fjustpass) { status = send_raw_kcs(pdata, sdata, presp, sresp); *pcc = 0; return(status); } sendMsg.Bus = bus; sendMsg.DevAdd = sa; sendMsg.NetFn = netfn; sendMsg.LUN = lun; sendMsg.Cmd = cmd; sendMsg.Len = sdata; if (sdata > 0) memcpy(sendMsg.Data,pdata,sdata); status = ProcessMessage(&sendMsg, &respMsg); if (status == STATUS_OK) { *pcc = respMsg.CompCode; if (respMsg.Len > 0) { len = respMsg.Len; if (len > *sresp) len = *sresp; } else len = 0; if (len > 0) memcpy(presp,respMsg.Data,len); *sresp = len; } return(status); } #ifndef ALONE int ipmi_cmd_direct(UINT16 icmd, UCHAR *pdata, int sdata, UCHAR *presp, int *sresp, UCHAR *pcc, char fdebugcmd) { UINT8 cmd, netfn, sa, lun, bus; int status; int i; fdebugdir = fdebugcmd; for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == icmd) { cmd = (icmd & 0x00ff); sa = ipmi_cmds[i].sa; bus = ipmi_cmds[i].bus; netfn = ipmi_cmds[i].netfn; lun = ipmi_cmds[i].lun; break; } } if (i >= NCMDS) { DBGP("ipmidir: icmd %04x not found, defaults used\n",icmd); cmd = (icmd & 0xFF); netfn = (icmd & 0xFF00) >> 8; sa = BMC_ADDR; lun = BMC_LUN; bus = 0; } status = ipmi_cmdraw_direct(cmd, netfn, lun, sa, bus, pdata, sdata, presp, sresp, pcc, fdebugcmd); return(status); } #endif static UINT8 CalculateChecksum(UINT8* p_buff, int length) { UINT8 sum = 0; int i; for (i = 0; i < length; i++) sum+= p_buff[i]; return (~sum) + 1; } static int GetDeviceId(UINT16 *bmcType, UINT16 *ipmiVersion) { int status = STATUS_OK; UINT16 thisBmcType = BMC_UNKNOWN; BMC_MESSAGE sendMsg; BMC_MESSAGE respMsg; DBGP2("open_direct: detecting interface, bmc: %X ver: %X drv=%s\n", g_bmcType, g_ipmiVersion, BmcDesc(g_DriverType)); // if the BMC type has not yet been detected - detect it if( g_bmcType == BMC_UNKNOWN ) { // Try sending the GetDeviceId command to the default interface sendMsg.DevAdd = BMC_ADDR; sendMsg.NetFn = NETFN_APP; sendMsg.LUN = BMC_LUN; sendMsg.Cmd = CMD_GET_DEVICE_ID; sendMsg.Len = 0; DBGP2("open_direct: Try Get_Device_ID with %s driver\n", BmcDesc(g_DriverType)); status = ProcessMessage(&sendMsg, &respMsg); if (status == STATUS_OK) { if (g_DriverType == DRV_KCS) thisBmcType = BMC_SAHALEE; else thisBmcType = BMC_MBMC_87431M; } else { /*error, switch interfaces*/ DBGP("open_direct: ProcessMessage(%s) error = %d\n", BmcDesc(g_DriverType),status); if (!fDetectedIF) { /* if not yet detected, try other IF type */ if (g_DriverType == DRV_KCS) { DBGP2("open_direct: Not KCS, try SSIF/SMBus\n"); g_DriverType = DRV_SMB; } else { DBGP2("open_direct: Not SSIF, try KCS\n"); g_DriverType = DRV_KCS; } } } /*end-else error*/ // If error, try again with the other interface if (thisBmcType == BMC_UNKNOWN) { // send the command via KCS/SMBus to get the IPMI version. status = ProcessMessage(&sendMsg, &respMsg); if (status == STATUS_OK) { if (g_DriverType == DRV_KCS) thisBmcType = BMC_SAHALEE; else thisBmcType = BMC_MBMC_87431M; } else { // If sending message fails status = ER_NO_BMC_IF; } } g_bmcType = thisBmcType; // if we contacted the BMC, decode its version if( status == STATUS_OK ) { if( g_bmcType == BMC_MBMC_87431M ) { // Decode the miniBMC productID } if( respMsg.Data[4] == 0x51 ) g_ipmiVersion = (UINT16)IPMI_VERSION_1_5; else if( respMsg.Data[4] == 0x02 ) g_ipmiVersion = IPMI_VERSION_2_0; } } /* endif unknown BMC */ // set the version info and leave *ipmiVersion = g_ipmiVersion; *bmcType = g_bmcType; DBGP2("open_direct: AFTER bmc: %X ver: %X\n", g_bmcType, g_ipmiVersion); return status; } //***************************************************************************** #if defined (WIN64) // Do Nothing for WIN64 as we are not using these functions here #else static int ProcessSendMessage(BMC_MESSAGE *p_reqMsg, BMC_MESSAGE *p_respMsg, const UINT8 bus, const UINT8 slave, const UINT32 timeout) { int status = STATUS_OK; BMC_MESSAGE sendReq; static UINT8 sendSeq = 1; static UINT8 incTestCount=0; BMC_MESSAGE reqMsg,respMsg; int retryCount; UINT32 i; UINT nRetryCount = 0; int testCount; // Windows will be using Async Imb request interface to poll for // messages in the BMC SMS message queue // format the send message packet sendReq.Cmd = SENDMESSAGE_CMD; sendReq.DevAdd = BMC_ADDR; sendReq.LUN = 0; sendReq.NetFn = NETFN_APP; sendReq.Data[0] = bus; sendReq.Data[1] = slave; // NetFn is the upper 6 bits of the data byte, the LUN is the lower two sendReq.Data[2] = ((p_reqMsg->NetFn << 2) | (p_reqMsg->LUN & 0x03)); sendReq.Data[3] = CalculateChecksum(&sendReq.Data[1], 2); sendReq.Data[4] = BMC_ADDR; // NetFn is the upper 6 bits of the data byte, the LUN is the lower two sendReq.Data[5] = ((sendSeq << 2) | (SMS_MSG_LUN & 0x03)); // sequence number = 1 << 2 and BMC message response lun = 0x02 sendReq.Data[6] = p_reqMsg->Cmd; // loop to copy the command data to the send message data format i = 0; for(i=0; i < p_reqMsg->Len; i++) sendReq.Data[7+i] = p_reqMsg->Data[i]; // create a checksum sendReq.Data[7+i] = CalculateChecksum(&sendReq.Data[4], p_reqMsg->Len + 3); // send data length plus the values from index 3 - 6 // send length plus 0 - 7 and checksum byte sendReq.Len = p_reqMsg->Len + 8; /* * Send the message with retries * For get Device ID & Read FRU data, retry less, in case * HSC/LCP is not present, */ if (p_reqMsg->NetFn != 0x08 ) retryCount = BMC_MAX_RETRIES+2; else retryCount = BMC_MAX_RETRIES+20; do { // send the message if( (status = ProcessMessage(&sendReq, p_respMsg)) == STATUS_OK ) { // some error, maybe because the controller was not ready yet. if( p_respMsg->CompCode == 0x83 ) { // Sleep for 1 second and try again sleep(1); incTestCount = 1; // true continue; // try again } else if( p_respMsg->CompCode == 0x82 ) { DBGP("ProcessSendMessage(sa=%02x,%02x,%02x) " "ccode=82 bus error\n", slave,p_reqMsg->NetFn,p_reqMsg->Cmd); status = ERGETTINGIPMIMESSAGE; break; // exit with error } else if( p_respMsg->CompCode != 0x00 ) continue; //break; // exit with error status = wait_for_SMS_flag(); /* new, added */ if (status == -1) DBGP("wait_for_SMS_flag timeout\n"); // Only for windows we use Imb Asyn interface for polling // For Unix we issue GetMessage command // issue a getmessage command reqMsg.DevAdd = BMC_ADDR; reqMsg.NetFn = NETFN_APP; reqMsg.LUN = BMC_LUN; reqMsg.Cmd = GETMESSAGE_CMD; reqMsg.Len = 0; nRetryCount = 0; testCount = 100; /* For HSC */ if (slave == 0x22 || incTestCount == 1) // true testCount=1000; /*added for LCP */ do { /* Loop here for the response with the correct * sequence number. */ if( (status = ProcessMessage( &reqMsg, &respMsg )) != 0 ) { DBGP("Breaking after Getmsg, Status is %d\n",status); break; } if( slave == 0x22 && p_reqMsg->Cmd == 0x04 ) { /* give debug if LCP ever gets here. */ DBGP("LCP get: cnt[%d,%d] seq[%02x,%02x] cc=%02x status=%u\n", testCount,retryCount, sendSeq, ((respMsg.Data[4] & 0xFC)>>2), respMsg.CompCode,status) ; return STATUS_OK; } if (respMsg.CompCode != 0) { DBGP2("get, cnt[test=%d] slave=%02x, cc==%02x\n", testCount,slave,respMsg.CompCode); /* Used to wait 1 ms via usleep(1000), but not needed. */ // usleep(1000); } } while(((respMsg.CompCode == 0x83 ||(respMsg.CompCode == 0x80)) && --testCount > (int) 0) || (respMsg.CompCode == 0x0 && ((respMsg.Data[4] & 0xFC) >> 2) != sendSeq) ); DBGP("get cnt[test=%d,retry=%d] seq[Send=0x%02x Recv=0x%02x] " "CompCode=0x%x status=%u\n", testCount,retryCount, sendSeq,((respMsg.Data[4] & 0xFC)>>2), respMsg.CompCode,status); if( (respMsg.CompCode == 0x00) && (status == STATUS_OK) && ((respMsg.Data[4] & 0xFC) >> 2 == sendSeq) ) { // format the GetMessage response (*p_respMsg) = (*p_reqMsg); // The first data byte is the channel number the message // was sent on p_respMsg->DevAdd = respMsg.Data[3]; p_respMsg->NetFn = respMsg.Data[1] >> 2; p_respMsg->LUN = respMsg.Data[4] & 0x03; p_respMsg->Cmd = respMsg.Data[5]; p_respMsg->CompCode = respMsg.Data[6]; // comp code p_respMsg->Len = respMsg.Len - 8; // the last data byte is the checksum if ( p_respMsg->CompCode == 0xCC) { DBGP2(" Cmd=%d Len=%d ccode=CC ", p_respMsg->Cmd, p_respMsg->Len); } for(i=0; i < p_respMsg->Len; i++) p_respMsg->Data[i] = respMsg.Data[7+i]; break; } } // this will retry the read the number of times in retryCount } while( --retryCount > 0 ); if( retryCount <= 0 ) status = ERGETTINGIPMIMESSAGE; /* Increment the sequence number * sequence number can't be greater 63 (6bit number), * so wrap the counter if it is */ ++sendSeq; if( sendSeq >= 64 ) sendSeq = 1; return status; } #endif /* All other than WIN64 */ /* #define MAX_KCS_LOOP 30000 *was 7000*/ /* Set a failsafe MAX KCS Loops to prevent infinite loop on status reg */ /* max was 7000, but need longer for ClearSEL cmd */ static int max_kcs_loop = 30000; /*means 300ms*/ static int max_sms_loop = 500; /*means 500ms*/ static int peak_loops = 0; int ipmi_set_max_kcs_loops(int ms) { max_kcs_loop = ms * 100; /*300 ms * 100 = 30000 loops*/ max_sms_loop = ms; return 0; } static int wait_for_SMS_flag(void) { int i = 0; while((_INB(STATUS_REG) & 0x04) == 0) { usleep(2 * 1000); /*sleep for 2 msec*/ i += 2; if ( i > max_sms_loop ) return -1; } return 0; } static int wait_for_IBF_clear(void) { int i = 0; while ((_INB(STATUS_REG) & 0x02) == 0x02) { if (i > 0 && (i % 100) == 0) usleep(1000); /*sleep for 1 msec*/ if (i > max_kcs_loop) { DBGP("wait_for_IBF_clear: max loop %d\n",i); return -1; // break; } i++; } if (i > peak_loops) peak_loops = i; return 0; } static int wait_for_OBF_set(void) { int i = 0; while ((_INB(STATUS_REG) & 0x01) == 0x00) { if (i > 0 && (i % 100) == 0) usleep(1000); /*sleep for 1 msec*/ if (i > max_kcs_loop) { DBGP("wait_for_OBF_set: max loop %d\n",i); return -1; // break; } i++; } if (i > peak_loops) peak_loops = i; return 0; } static inline int get_write_state(void) { if ((_INB(STATUS_REG) >> 6) != 0x02) return -1; return 0; } static inline int get_read_state(void) { if ((_INB(STATUS_REG) >> 6) != 0x01) return -1; return 0; } static inline int get_idle_state(void) { if ((_INB(STATUS_REG) >> 6) != 0x00) return -1; return 0; } UINT8 dummy2; static inline void clear_OBF(void) { dummy2 = _INB(DATA_IN_REG); } static int send_raw_kcs (UINT8 *rqData, int rqLen, UINT8 *rsData, int *rsLen ) { int length; unsigned char dummy; unsigned char rx_data[64]; int rxbuf_len; int rv; if (fdebugdir) { int cnt; DBGP("send_raw_kcs: "); for ( cnt=0; cnt < rqLen ; cnt++) DBGP(" %02x",rqData[cnt]); DBGP("\n"); } wait_for_IBF_clear(); clear_OBF(); _OUTB(WR_START,COMMAND_REG); rv = wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); if (rv != 0) return LAN_ERR_SEND_FAIL; for(length = 0;length < rqLen-1;length++) { _OUTB(rqData[length],DATA_OUT_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); } _OUTB(WR_END,COMMAND_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); _OUTB(rqData[length],DATA_OUT_REG); /* write phase complete, start read phase */ rxbuf_len = *rsLen; *rsLen = 0; while(*rsLen <= IPMI_RSPBUF_SIZE) { wait_for_IBF_clear(); if (get_read_state() != 0) { if (get_idle_state() != 0) { DBGP2("not idle in rx_data (%02x)\n",_INB(STATUS_REG)); // clear_lock_dir(); return LAN_ERR_RECV_FAIL; } else { rv = wait_for_OBF_set(); if (rv != 0) return LAN_ERR_RECV_FAIL; dummy = _INB(DATA_IN_REG); /* done, copy the data */ for (length=0;length < *rsLen;length++) rsData[length] = rx_data[length]; return ACCESS_OK; } } else { rv = wait_for_OBF_set(); if (rv != 0) return LAN_ERR_RECV_FAIL; rx_data[*rsLen] = _INB(DATA_IN_REG); DBGP2("rx_data[%d] is 0x%x\n",*rsLen,rx_data[*rsLen]); _OUTB(READ_BYTE,DATA_IN_REG); (*rsLen)++; } if (*rsLen > rxbuf_len) { DBGP("ipmidir: rx buffer overrun, size = %d\n",rxbuf_len); break; /*stop if user buffer max*/ } } /*end while*/ return ACCESS_OK; } /* * SendTimedImbpRequest_kcs - write bytes to KCS interface, read response * The bytes are written in this order: * 1 netfn * 2 cmdType * 3-N data, if any */ int SendTimedImbpRequest_kcs (IMBPREQUESTDATA *requestData, unsigned int timeout, UINT8 *resp_data, int *respDataLen, unsigned char *compCode) { /*SendTimedImb for KCS*/ int length; unsigned char dummy; unsigned char rx_data[64]; int rxbuf_len, rv; if (fdebugdir) { int cnt; DBGP("Send Netfn=%02x Cmd=%02x, raw: %02x %02x %02x %02x", requestData->netFn, requestData->cmdType, requestData->busType, requestData->rsSa, (requestData->netFn<<2), requestData->cmdType); for ( cnt=0; cnt < requestData->dataLength ; cnt++) DBGP(" %02x",requestData->data[cnt]); DBGP("\n"); } rv = wait_for_IBF_clear(); clear_OBF(); if (rv != 0) return LAN_ERR_SEND_FAIL; _OUTB(WR_START,COMMAND_REG); rv = wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); if (rv != 0) return LAN_ERR_SEND_FAIL; _OUTB((requestData->netFn << 2),DATA_OUT_REG); rv = wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); if (requestData->dataLength == 0) { _OUTB(WR_END,COMMAND_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); _OUTB(requestData->cmdType,DATA_OUT_REG); } else { _OUTB(requestData->cmdType,DATA_OUT_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); for(length = 0;length < requestData->dataLength-1;length++) { _OUTB(requestData->data[length],DATA_OUT_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); } _OUTB(WR_END,COMMAND_REG); wait_for_IBF_clear(); if (get_write_state() != 0) return LAN_ERR_SEND_FAIL; clear_OBF(); _OUTB(requestData->data[length],DATA_OUT_REG); } /********************************** WRITE PHASE OVER ***********************/ #ifdef TEST_ERROR if (fdebugdir == 5) { /*introduce an error test case*/ printf("Aborting after KCS write, before read\n"); return(rv); } #endif // length = 0; // usleep(100000); /********************************** READ PHASE START ***********************/ rxbuf_len = *respDataLen; *respDataLen = 0; while(*respDataLen <= IPMI_RSPBUF_SIZE) { wait_for_IBF_clear(); if (get_read_state() != 0) { if (get_idle_state() != 0) { DBGP2("not idle in rx_data (%02x)\n",_INB(STATUS_REG)); // clear_lock_dir(); return LAN_ERR_RECV_FAIL; } else { rv = wait_for_OBF_set(); if (rv != 0) { return LAN_ERR_RECV_FAIL; } dummy = _INB(DATA_IN_REG); /* done, copy the data, if valid */ if (*respDataLen < 3) { /* data not valid, no cc */ (*respDataLen) = 0; *compCode = 0xCA; /*cannot return #bytes*/ // clear_lock_dir(); return LAN_ERR_TIMEOUT; } else { /*valid*/ requestData->netFn = rx_data[0]; requestData->cmdType = rx_data[1]; *compCode = rx_data[2]; (*respDataLen) -= 3; for (length=0;length < *respDataLen;length++) resp_data[length] = rx_data[length+3]; } DBGP2("ipmidir: peak_loops = %d\n",peak_loops); return ACCESS_OK; } } else { rv = wait_for_OBF_set(); if (rv != 0) { return LAN_ERR_RECV_FAIL; } rx_data[*respDataLen] = _INB(DATA_IN_REG); DBGP2("rx_data[%d] is 0x%x\n",*respDataLen,rx_data[*respDataLen]); _OUTB(READ_BYTE,DATA_IN_REG); (*respDataLen)++; } if (*respDataLen > rxbuf_len) { DBGP("ipmidir: rx buffer overrun, size = %d\n",rxbuf_len); break; /*stop if user buffer max*/ } } /*end while*/ return ACCESS_OK; } /* end SendTimedImbpRequest_kcs */ static int ProcessTimedMessage(BMC_MESSAGE *p_reqMsg, BMC_MESSAGE *p_respMsg, const UINT32 timeout) { int status = STATUS_OK; IMBPREQUESTDATA requestData = {0}; int respDataLen = IPMI_RSPBUF_SIZE; UINT8 compCode = 0; // static UINT8 sendSeq = 1; // UINT8 buff[DATA_BUF_SIZE] = {0}; ACCESN_STATUS accessn; int i, j; j = p_reqMsg->Len; if (j > IPMI_REQBUF_SIZE) return(LAN_ERR_BADLENGTH); // Initialize Response Message Data for(i = 0; i < IPMI_RSPBUF_SIZE; i++) { p_respMsg->Data[i] = 0; } /* show the request */ DBGP("ipmidir Cmd=%02x NetFn=%02x Lun=%02x Sa=%02x Data(%d): ", p_reqMsg->Cmd, p_reqMsg->NetFn, p_reqMsg->LUN, p_reqMsg->DevAdd, j); for (i=0; iData[i]); DBGP("\n"); j = _IOPL(3); if (j != 0) { DBGP("ipmi_direct: iopl errno = %d\n",errno); return(errno); } // Initializes Request Message // Call into IPMI if (p_reqMsg->DevAdd == 0x20) { requestData.cmdType = p_reqMsg->Cmd; requestData.rsSa = 0x20; requestData.busType = 0; requestData.netFn = p_reqMsg->NetFn; requestData.rsLun = p_reqMsg->LUN; requestData.data = p_reqMsg->Data; requestData.dataLength = (int)p_reqMsg->Len; if (g_DriverType == DRV_KCS) /*KCS*/ accessn = SendTimedImbpRequest_kcs(&requestData, timeout, p_respMsg->Data, &respDataLen, &compCode); else if (g_DriverType == DRV_SMB) /*SMBus*/ accessn = SendTimedImbpRequest_ssif(&requestData, timeout, p_respMsg->Data, &respDataLen, &compCode); else { /* should never happen */ printf("ipmi_direct: g_DriverType invalid [%d]\n",g_DriverType); return(ERR_NO_DRV); } status = accessn; // Return Response Message p_respMsg->DevAdd = p_reqMsg->DevAdd; p_respMsg->NetFn = requestData.netFn; p_respMsg->LUN = p_reqMsg->LUN; p_respMsg->Cmd = requestData.cmdType; p_respMsg->CompCode = compCode; p_respMsg->Len = respDataLen; } else { /*DevAdd != 0x20*/ status = ProcessSendMessage(p_reqMsg, p_respMsg, p_reqMsg->Bus, p_reqMsg->DevAdd,10000); DBGP2("ProcessSendMessage(cmd=%02x,rs,sa=%02x,10000) = %d\n", p_reqMsg->Cmd,p_reqMsg->DevAdd,status); } /* validate the response data length */ if (p_respMsg->Len > IPMI_RSPBUF_SIZE) p_respMsg->Len = IPMI_RSPBUF_SIZE; /* show the response */ j = p_respMsg->Len; DBGP("ipmidir Resp(%x,%x): status=%d cc=%02x, Data(%d): ", (p_respMsg->NetFn >> 2), p_respMsg->Cmd, status,p_respMsg->CompCode, j); if (status == 0) for (i=0; iData[i]); DBGP("\n"); return status; } /* * ImbInit_dir * Uses SMBIOS to determine the driver type and base address. * It also checks the status register if KCS. */ int ImbInit_dir(void) { uchar v = 0xff; /* Read SMBIOS to get IPMI struct */ DBGP2("ImbInit: BMC_base = 0x%04x\n",BMC_base); if (BMC_base == 0) { /*use get_IpmiStruct routine from mem_if.c */ uchar iftype, iver, sa, inc; int mybase, status; char *ifstr; status = get_IpmiStruct(&iftype,&iver,&sa,&mybase,&inc); if (status == 0) { if (iftype == 0x04) { g_DriverType = DRV_SMB; ifstr = "SSIF"; mBMC_baseAddr = mybase; } else /*0x01==KCS*/ { g_DriverType = DRV_KCS; BMC_base = mybase; ifstr = "KCS"; if (sa == BMC_SA && mybase != 0) { /*valid*/ kcsBaseAddress = mybase; kcs_inc = inc; } } DBGP("SMBIOS IPMI Record found: type=%s sa=%02x base=0x%04x spacing=%d\n", ifstr, sa, mybase, inc); } } /* Use KCS here. There are no known SMBus implementations on 64-bit */ if (BMC_base == 0) { DBGP("No IPMI Data Structure Found in SMBIOS Table,\n"); #ifdef TRY_KCS g_DriverType = DRV_KCS; BMC_base = kcsBaseAddress; DBGP("Continuing with KCS on Default Port 0x%04x\n",kcsBaseAddress); #else printf("No IPMI interface detected...Exiting\n"); return ERR_NO_DRV; #endif } #if defined(BSD) || defined(MACOS) || defined(HPUX) iofd = open("/dev/io",O_RDWR); if (iofd < 0) { printf("Cannot open /dev/io...Exiting\n"); return ERR_NO_DRV; } #endif if (g_DriverType == DRV_SMB) { /* Perhaps add controller type in ipmi_if.txt (?)*/ /* Intel SSIF: 0x0540=SJR, 0x0400=STP */ if (mBMC_baseAddr == 0x540 || mBMC_baseAddr == 0x400) SMBChar.Controller = INTEL_SMBC; else /*else try ServerWorks*/ SMBChar.Controller = SW_SMBC; SMBChar.baseAddr = mBMC_baseAddr; DBGP("BMC SSIF/SMBus Interface at i2c=%02x base=0x%04x\n", mBMCADDR,mBMC_baseAddr); } if (g_DriverType == DRV_KCS) { v = _IOPL(3); v = _INB(STATUS_REG); DBGP2("inb(%x) returned %02x\n",STATUS_REG,v); if (v == 0xff) { printf("No Response from BMC...Exiting\n"); return ERR_NO_DRV; } DBGP("BMC KCS Initialized at 0x%04x\n",kcsBaseAddress); } return STATUS_OK; } int SendTimedImbpRequest_ssif ( IMBPREQUESTDATA *requestData, unsigned int timeout, UINT8 *resp_data, int *respDataLen, unsigned char *compCode) { /* SendTimedImb for SMBus */ unsigned char rq[IPMI_REQBUF_SIZE+35] = {0,}; /*SIZE + MAX_ISA_LENGTH=35*/ unsigned char rp[IPMI_RSPBUF_SIZE+35] = {0,}; /*SIZE + MAX_ISA_LENGTH=35*/ unsigned int i, rpl=0; int status; int respMax, rlen; i = _IOPL(3); rq[0] = ((requestData->netFn << 2) | (requestData->rsLun & 0x03)); rq[1] = requestData->cmdType; if (sizeof(rq) < (requestData->dataLength + 2)) return(LAN_ERR_BADLENGTH); for (i=0;i<=(unsigned int)requestData->dataLength;i++) rq[i+2] = requestData->data[i]; respMax = *respDataLen; if (respMax == 0) respMax = IPMI_RSPBUF_SIZE; status = SendmBmcRequest(rq,requestData->dataLength+2,rp,&rpl,0); if (status == IMB_SEND_ERROR) { *respDataLen = 0; return LAN_ERR_SEND_FAIL; } if (rpl < 3) { *respDataLen = 0; *compCode = 0xCA; /*cannot return #bytes*/ return LAN_ERR_TIMEOUT; } else { rlen = rpl-3; /* Chop off netfn/LUN , compcode, command */ if (rlen > respMax) rlen = respMax; *respDataLen = rlen; *compCode = rp[2]; for (i = 0; i < rlen; i++) resp_data[i] = rp[i+3]; } return ACCESS_OK; } int SendmBmcRequest ( unsigned char* request, UINT32 reqLength, unsigned char* response, UINT32 * respLength, UINT32 ipmiOldFlag ) { int retries = 5; /* Send Request - Retry 5 times at most */ do{ if (SendRequest(request, reqLength, &SMBChar) == 0) break; } while (0 < retries--); if (retries <= 0) { return IMB_SEND_ERROR; } /* Read Response - Retry 5 times at most */ retries = 5; do{ if ((*respLength = ReadResponse(response, &SMBChar))!=(-1)) { break; // Success } }while (0 < retries--); if (retries <= 0) { return IMB_SEND_ERROR; } return IMB_SUCCESS; } static int SendRequest(unsigned char* req, int length, struct SMBCharStruct* smbChar) { UINT8 data = 0; // unsigned char* msgBuf = req; int i; UINT8 status = 0; // Delay of 50 ms before request is sent usleep(100000); // Handle Intel & ServerWorks Chipsets // Clear all status bits, Host Status Register switch (smbChar->Controller) { // Intel Status Register case INTEL_SMBC: status = ICH_HST_STA_ALL_ERRS|ICH_HST_STA_INTR|ICH_HST_STA_BYTE_DONE_STS; break; // ServerWorks Status Register case SW_SMBC: status = ICH_HST_STA_ALL_ERRS|ICH_HST_STA_INTR; break; }// End of Switch // Status Register WritePortUchar( (((smbChar->baseAddr))+ICH_HST_STA), status); // Block protocol, Host Control Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), (UINT8)(ICH_HST_CNT_SMB_CMD_BLOCK)); // IPMI command, Host Command Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CMD), (UINT8)(0x02)); // Slave address, Host Address Register WritePortUchar(((smbChar->baseAddr)+ICH_XMIT_SLVA), (UINT8)(mBMCADDR)); // Block length, Host DATA0 Register WritePortUchar(((smbChar->baseAddr)+ICH_D0), (UINT8)(length)); // Initialize timer switch (smbChar->Controller) { // Handle Intel Chipset case INTEL_SMBC: // the first byte WritePortUchar(((smbChar->baseAddr)+ICH_BLOCK_DB), *(UINT8 *)((UINT8 *)req )); // Block protocol and Start, Host Control Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), ICH_HST_CNT_START | ICH_HST_CNT_SMB_CMD_BLOCK); // Send byte by byte for ( i = 1; i < length; i++ ) { // OsSetTimer(&SendReqTimer); * Start timer * do { // Read host status register ReadPortUchar((smbChar->baseAddr+ICH_HST_STA), &data); // if (OsTimerTimedout(&SendReqTimer)) return -1; // Any error or Interrupt bit or byte done bit set ? } while ((data & status) == 0); // OsCancelTimer(&SendReqTimer); * End Timer * // Check for byte completion in block transfer if ((data & ICH_HST_STA_BYTE_DONE_STS) != ICH_HST_STA_BYTE_DONE_STS) break; // Write next byte WritePortUchar(((smbChar->baseAddr)+ICH_BLOCK_DB), *(UINT8 *)((UINT8 *)req + i)); // Clear status bits, Host Status Register WritePortUchar((smbChar->baseAddr), (UINT8)(data & status)); } // End of for - Send byte by byte break; // End of Intel Chipset Handling // Handle ServerWorks Chipset case SW_SMBC: // Block length, Host DATA1 Register WritePortUchar(((smbChar->baseAddr)+ICH_D1), (UINT8)(length)); // Reset block inex ReadPortUchar(((smbChar->baseAddr)+ICH_HST_CNT), &data); // Put all bytes of the message to Block Data Register for ( i = 0; i < length; i++ ) WritePortUchar(((smbChar->baseAddr)+ICH_BLOCK_DB), *(UINT8 *)((UINT8 *)req + i)); // Block protocol and Start, Host Control Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), ICH_HST_CNT_START | ICH_HST_CNT_SMB_CMD_BLOCK); // OsSetTimer(&SendReqTimer); * Start timer * do { // Read host status register ReadPortUchar((smbChar->baseAddr+ICH_HST_STA), &data); // if (OsTimerTimedout(&SendReqTimer)) return -1; } while ((data & status) == 0); // Any error or Interrupt bit set ? // OsCancelTimer(&SendReqTimer); * End Timer * break; // End of ServerWorks Chipset Handling } // End of Switch Controller // Clear status bits, Host Status Register WritePortUchar((smbChar->baseAddr), (UINT8)(data & status)); if (data & ICH_HST_STA_ALL_ERRS) return -1; // Success return 0; } static int ReadResponse( unsigned char* resp, struct SMBCharStruct * smbChar) { UINT8 data, dummy, length, status = 0; UINT8 * msgBuf = (UINT8 *) resp; int i; //, timeout =0; // os_timer_t SendReqTimer; // Delay current thread - time to delay in uSecs // 100 msec = 100000 microsec usleep(100000); // Handle Intel & ServerWorks Chipsets switch (smbChar->Controller) { case INTEL_SMBC: status = ICH_HST_STA_ALL_ERRS|ICH_HST_STA_INTR|ICH_HST_STA_BYTE_DONE_STS; break; case SW_SMBC: status = ICH_HST_STA_ALL_ERRS|ICH_HST_STA_INTR; break; } // End of Switch WritePortUchar(((smbChar->baseAddr)+ICH_HST_STA), status); // Block protocol, Host Control Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), ICH_HST_CNT_SMB_CMD_BLOCK); // Slave address, Host Address Register WritePortUchar(((smbChar->baseAddr)+ICH_XMIT_SLVA), (UINT8)(mBMCADDR |ICH_XMIT_SLVA_READ)); // IPMI command, Host Command Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CMD), 0x03); // Reset block index ReadPortUchar(((smbChar->baseAddr)+ICH_HST_CNT), &data); // Block protocol and Start, Host Control Register WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), ICH_HST_CNT_START | ICH_HST_CNT_SMB_CMD_BLOCK); // Initialize timer do { // Read host status register ReadPortUchar((smbChar->baseAddr+ICH_HST_STA), &data); } while ((data & status) == 0); // Any error or Interrupt bit set ? // End Timer // Clear status bits, Host Status Register WritePortUchar((smbChar->baseAddr), (UINT8)(data & status)); if (data & ICH_HST_STA_ALL_ERRS) return -1; // Block length, Host DATA0 Register ReadPortUchar(((smbChar->baseAddr)+ICH_D0), &length); /* check recv length > MAX (35) */ if (length > MAX_ISA_LENGTH) length = MAX_ISA_LENGTH; switch (smbChar->Controller) { case INTEL_SMBC: // Read the first byte ReadPortUchar((smbChar->baseAddr+ICH_BLOCK_DB), &(msgBuf[0])); // Put all bytes of the message to Block Data Register for ( i = 1; i < length; i++ ) { if (i == (length-1)) { // Set Last Byte bit ReadPortUchar(((smbChar->baseAddr)+ICH_HST_CNT),&dummy); WritePortUchar(((smbChar->baseAddr)+ICH_HST_CNT), (UINT8)(dummy | ICH_HST_CNT_LAST_BYTE)); } // Clear status bits, Host Status Register WritePortUchar((smbChar->baseAddr), (UINT8)(data & status)); do { // Read host status register ReadPortUchar((smbChar->baseAddr+ICH_HST_STA), &data); } while ((data & status) == 0); // Any error or Interrupt bit set ? if (data & ICH_HST_STA_ALL_ERRS) return -1; ReadPortUchar((smbChar->baseAddr+ICH_BLOCK_DB), &(msgBuf[i])); } break; case SW_SMBC: // Put all bytes of the message to Block Data Register for ( i = 0; i < length; i++ ) { ReadPortUchar((smbChar->baseAddr+ICH_BLOCK_DB), &(msgBuf[i])); } break; } /* end of switch */ if (data & ICH_HST_STA_ALL_ERRS) return -1; return length; } #endif /* end ipmidir.c */ ipmiutil-3.1.9/util/ipmicmd.h0000644000000000000000000005520714144515623014644 0ustar rootroot/*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_SDR_MALFORMED -25 /*SDR is malformed */ #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 VENDOR_LENOVO 0x004A66 #define VENDOR_LENOVO2 0x004F4D #define VENDOR_ASUS 0x000A3F #define VENDOR_MITAC 6653 /*=0x19FD*/ #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 */ #define RT_OEMIU 0xDB /*record type for OEM ipmiutil events*/ #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 typedef struct { char node[SZGNODE+1]; char user[SZGNODE+1]; char pswd[PSW_MAX+1]; int auth_type; /* if 0, use any: MD5, MD2, etc.*/ int priv; /* IPMI_PRIV_LEVEL_USER or IPMI_PRIV_LEVEL_ADMIN */ int cipher; unsigned char addr[128]; /* sizeof(struct sockaddr_storage) = 128 */ int addr_len; /* struct sockaddr_in/_in6 gaddr; _in6=28, _in=16 bytes*/ int port; } LAN_OPT; /* used for IPMI LAN, specified with option -NUP, etc. */ #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 'p': UDP port 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(int opt); 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 set_driver_options(int fdir); 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, char *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 */ ipmiutil-3.1.9/util/ifwum.h0000644000000000000000000000521614144515623014344 0ustar rootroot/* * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifndef IPMI_KFWUM_H #define IPMI_KFWUM_H // #include // #include #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int #define IPMI_NETFN_APP 0x6 #define IPMI_NETFN_FIRMWARE 0x8 #define IPMI_BMC_SLAVE_ADDR 0x20 #define BMC_GET_DEVICE_ID 0x1 #define IPM_DEV_MANUFACTURER_ID(x) \ ((uint32_t) ((x[2] & 0x0F) << 16 | x[1] << 8 | x[0])) //struct valstr { // uint16_t val; // const char * str; //}; #pragma pack(1) struct ipm_devid_rsp { uint8_t device_id; uint8_t device_revision; uint8_t fw_rev1; uint8_t fw_rev2; uint8_t ipmi_version; uint8_t adtl_device_support; uint8_t manufacturer_id[3]; uint8_t product_id[2]; uint8_t aux_fw_rev[4]; }; // __attribute__ ((packed)); #pragma pack() /* routines from lib/lanplus/helper.c */ uint16_t buf2short(uint8_t * buf); //const char * val2str(uint16_t val, const struct valstr * vs); #endif /* IPMI_KFWUM_H */ ipmiutil-3.1.9/util/AnsiTerm.h0000644000000000000000000002332014144515623014733 0ustar rootroot/* * AnsiTerm.h * Windows ANSI Terminal Emulation * * Author: Robert Nelson robertnelson at users.sourceforge.net * Copyright (c) 2009 Robert Nelson * * 10/07/09 Robert Nelson - Created * See ChangeLog for further changes */ /* Copyright (c) 2009, Robert Nelson All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once class CAnsiTerm { public: struct KeyCode { unsigned char bKeyDown:1; unsigned char bEnhanced:1; unsigned char bCapsLock:1; unsigned char bScrollLock:1; unsigned char bNumLock:1; unsigned char bShift:1; unsigned char bControl:1; unsigned char bAlt:1; unsigned char RepeatCount; unsigned char VirtualKeyCode; unsigned char AsciiChar; }; private: enum ControlCharacters { CH_NUL = 0x00, // Ignored on input CH_ENQ = 0x05, // Transmit answerback CH_BEL = 0x07, // Ring Bell CH_BS = 0x08, // Move left one character, no effect in column 0 CH_HT = 0x09, // Tab CH_LF = 0x0A, // Line feed or new line depending on line mode CH_VT = 0x0B, // Vertical tab, same as line feed CH_FF = 0x0C, // Form feed, same as line feed CH_CR = 0x0D, // Carriage return, return to column 0 CH_SO = 0x0E, // Shift Out, Invoke G1 charset CH_SI = 0x0F, // Shift In, Invoke G0 charset CH_XON = 0x11, // Resume transmission CH_XOF = 0x13, // Suspend transmission CH_CAN = 0x18, // Cancel, aborts the current control sequence CH_SUB = 0x1A, // Same as Cancel CH_ESC = 0x1B, // Escape, start of control sequence CH_DEL = 0x7F // Delete, ignored }; enum DECModes { DECCKM = 1, // Cursor Key Mode (set = application codes) DECANM = 2, // Ansi Mode (set = ansi) DECCOLM = 3, // 80/132 Column Mode (set = 132) DECSCLM = 4, // Scroll Mode (set = smooth) DECSCNM = 5, // Screen Mode (set = black on white) DECOM = 6, // Origin Mode (set = origin relative to top margin) DECAWM = 7, // Autowrap Mode (set = wrap) DECARM = 8, // Autorepeat Mode (set = repeat) DECINLM = 9, // Interlace Mode (set = interlace) DECTCEM = 25 // Text Cursor Enable Mode }; enum DisplayState { DS_None, DS_Normal, DS_UTF8, DS_Escape, DS_CSIParam, DS_DECPrivate, DS_SelectG0, DS_SelectG1 }; enum SelectedCharset { CharsetG0, CharsetG1 }; enum CharacterSet { AsciiCharset = 0, SpecialGraphicsCharset = 1, UKCharset = 2 }; enum EraseType { EraseCursorToEnd = 0, EraseBeginningToCursor = 1, EraseAll = 2 }; static const int kMaxParameterCount = 16; static const int kOutputBufferSize = 256; static const int kMinGraphicsChar = 0x5F; static const int kMaxGraphicsChar = 0x7E; static const int kColorTableSize = 16; static const WORD kDefaultAttribute = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; struct CSICode { char chCode; DisplayState dsNextState; bool (CAnsiTerm::*pfnProcess)(void); }; struct CSIFunction { char chCode; bool (CAnsiTerm::*pfnProcess)(void); }; protected: typedef struct _CONSOLE_SCREEN_BUFFER_INFOEX { ULONG cbSize; COORD dwSize; COORD dwCursorPosition; WORD wAttributes; SMALL_RECT srWindow; COORD dwMaximumWindowSize; WORD wPopupAttributes; BOOL bFullscreenSupported; COLORREF ColorTable[16]; } CONSOLE_SCREEN_BUFFER_INFOEX, *PCONSOLE_SCREEN_BUFFER_INFOEX; typedef BOOL (WINAPI *PFN_GetConsoleScreenBufferInfoEx)( HANDLE hConsoleOutput, PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx); typedef BOOL (WINAPI *PFN_SetConsoleScreenBufferInfoEx)( HANDLE hConsoleOutput, PCONSOLE_SCREEN_BUFFER_INFOEX lpConsoleScreenBufferInfoEx); static PFN_GetConsoleScreenBufferInfoEx s_pfnGetConsoleScreenBufferInfoEx; static PFN_SetConsoleScreenBufferInfoEx s_pfnSetConsoleScreenBufferInfoEx; private: static CSICode s_CSITable[]; static CSIFunction s_DECFunction[]; static CSIFunction s_CSIFunction[]; static wchar_t s_GraphicChars[kMaxGraphicsChar - kMinGraphicsChar + 1]; static wchar_t s_OemToUnicode[256]; static COLORREF s_ColorTable[kColorTableSize]; public: CAnsiTerm(void); virtual ~CAnsiTerm(void); void WindowSizeChanged(bool bInitial); int ProcessInput(KeyCode keyCode, unsigned char *pOutput, int iOutputLen); bool ProcessOutput(const unsigned char *szData, int iLength); protected: virtual bool ResetTerm(void); virtual bool GetCursorPosition(void); virtual bool SetCursorPosition(void); virtual bool DisplayCursor(void); virtual bool ScrollDisplay(int nLines, bool bWindowOnly); virtual bool EraseLine(EraseType eType); virtual bool EraseDisplay(EraseType eType); virtual bool UpdateTextAttribute(void); virtual DWORD OutputText(void); private: bool ProcessBackspace(void); bool ProcessTab(void); bool ProcessLinefeed(bool bNewLine); bool ProcessReverseLinefeed(void); bool ProcessReturn(void); void AddOutputData(wchar_t wchData) { m_OutputBuffer[m_dwOutputCount++] = wchData; if (m_dwOutputCount >= kOutputBufferSize) { OutputText(); } } void DisplayCSI(char ch); bool ProcessSCSG0(char ch); bool ProcessSCSG1(char ch); bool ProcessDECALN(void); bool ProcessDECDHLB(void); bool ProcessDECDHLT(void); bool ProcessDECDWL(void); bool ProcessDECID(void); bool ProcessDECKPAM(void); bool ProcessDECKPNM(void); bool ProcessDECLL(void); bool ProcessDECRC(void); bool ProcessDECREQTPARM(void); bool ProcessDECSC(void); bool ProcessDECSTBM(void); bool ProcessDECSWL(void); bool ProcessDECTST(void); bool ProcessCUB(void); bool ProcessCUD(void); bool ProcessCUF(void); bool ProcessCUP(void); bool ProcessCUU(void); bool ProcessDA(void); bool ProcessDSR(void); bool ProcessED(void); bool ProcessEL(void); bool ProcessHTS(void); bool ProcessHVP(void); bool ProcessIND(void); bool ProcessNEL(void); bool ProcessRCP(void); bool ProcessRI(void); bool ProcessRIS(void); bool ProcessRM(void); bool ProcessSCP(void); bool ProcessSGR(void); bool ProcessSM(void); bool ProcessTBC(void); private: HANDLE m_hConsole; DWORD m_dwOrigConsoleMode; WORD m_wOrigConsoleAttribute; DWORD m_dwOrigCursorSize; COLORREF m_OrigColorTable[kColorTableSize]; bool m_bResetColorTable; DisplayState m_State; SelectedCharset m_SelectedCharset; CharacterSet m_G0Charset; CharacterSet m_G1Charset; COORD m_BufferSize; COORD m_WindowSize; COORD m_WindowOrigin; COORD m_Cursor; COORD m_SavedCursor; SHORT m_sTopMargin; SHORT m_sBottomMargin; WORD m_Attribute; wchar_t m_OutputBuffer[kOutputBufferSize]; DWORD m_dwOutputCount; unsigned char m_UTF8Buffer[3]; int m_UTF8Count; int m_UTF8Size; int m_Parameters[kMaxParameterCount]; int m_ParameterCount; bool m_bParametersStart; bool m_bPrivateParameters; // Modes bool m_bLineFeedNewLineMode; // LNM bool m_bCursorKeyMode; // DECCKM // Always set - VT52 not supported bool m_bAnsiMode; // DECANM // Not used - column width is based on width of console window bool m_bColumnMode; // DECCOLM // Not used - always reset bool m_bScrollingMode; // DECSCLM // Not implemented - always reset bool m_bScreenMode; // DECSCNM bool m_bOriginMode; // DECOM bool m_bAutoWrapMode; // DECAWM // Not implemented - always set bool m_bAutoRepeatingMode; // DECARM // Not implemented - always reset bool m_bInterlaceMode; // DECINLM bool m_bDisplayCursor; // DECTCEM }; ipmiutil-3.1.9/util/ipmilan2.h0000644000000000000000000000550714144515623014733 0ustar rootroot/*********************************************** * 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_ ipmiutil-3.1.9/util/ipmi_sample_evt.c0000644000000000000000000003317414144515623016371 0ustar rootroot/* * ipmi_sample_evt.c * * A sample IPMI utility to get IPMI SEL events. * * 09/10/12 Andy Cress - created */ /*M* Copyright (c) 2012, Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Kontron America, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *M*/ #ifdef WIN32 #include #include #include #include "getopt.h" #else #include #include #include #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include "ipmicmd.h" extern int decode_sel_entry(uchar *evt, char *obuf, int sz); /*see ievents.c*/ extern void set_sel_opts(int sensdesc, int canon, void *sdrs, char dbg, char u); extern char *get_sensor_type_desc(uchar stype); /*see ievents.c*/ extern int get_sdr_cache(uchar **pret); /*see isensor.c*/ extern void free_sdr_cache(uchar *pret); /*see isensor.c*/ extern int write_syslog(char *msg); /*see isel.c*/ /* * Global variables */ static char * progname = "ipmi_sample_evt"; static char * progver = "1.0"; static char fdebug = 0; static char fset_mc = 0; static char fipmilan = 0; static char finit_ok = 0; static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static char *mytag = NULL; static char *sdrfile = NULL; static ushort sel_recid = 0; static uint sel_time = 0; static int wait_interval = 3; /* 3 seconds between calls */ static uchar *sdrs = NULL; static int drvtype = 0; /* driver_type from ipmicmd.h: 3=MV_OpenIPMI */ FILE *fdout = NULL; #define LAST_REC 0xFFFF #ifdef WIN32 static char idxfile[80] = "c:\\ipmievt.idx"; static char outfile[80] = "c:\\ipmievt.log"; #else static char idxfile[80] = "/var/lib/ipmiutil/ipmievt.idx"; static char outfile[80] = "/var/log/ipmievt.log"; #endif /* These routines were copied from igetevent.c * msgout, getevent_sel, syncevent_sel, show_event, ievt_cleanup */ static void ievt_cleanup(void); static void msgout(char *pattn, ...) { va_list arglist; if (fdout == NULL) return; va_start( arglist, pattn ); vfprintf( fdout, pattn, arglist ); va_end( arglist ); fflush( fdout ); } #if defined(WIN32) | defined(DOS) /* no daemon code */ static void ievt_siginit(void) { return; } #else /* Linux daemon code */ #include static void ievt_sighnd(int sig) { ievt_cleanup(); exit(EXIT_SUCCESS); } static void ievt_siginit(void); static void ievt_siginit(void) { struct sigaction sact; /* handle signals for cleanup */ sact.sa_handler = ievt_sighnd; sact.sa_flags = 0; sigemptyset(&sact.sa_mask); sigaction(SIGINT, &sact, NULL); sigaction(SIGQUIT, &sact, NULL); sigaction(SIGTERM, &sact, NULL); } #endif static int get_sel_entry(ushort recid, ushort *nextid, uchar *rec) { uchar ibuf[6]; uchar rbuf[32]; int rlen; ushort xid, id = 0; uchar cc; int rv; ibuf[0] = 0; ibuf[1] = 0; ibuf[2] = (recid & 0x00ff); ibuf[3] = (recid & 0xff00) >> 8; ibuf[4] = 0; ibuf[5] = 0xFF; /*get entire record*/ rlen = sizeof(rbuf); rv = ipmi_cmd(GET_SEL_ENTRY, ibuf, 6, rbuf, &rlen, &cc, fdebug); if (rv == 0) { if (cc != 0) rv = cc; else { /*success*/ xid = rbuf[0] + (rbuf[1] << 8); /*next rec id*/ memcpy(rec,&rbuf[2],16); *nextid = xid; id = rbuf[2] + (rbuf[3] << 8); /*curr rec id*/ /* recid (requested) should match newid (received) */ if (fdebug) { if ((recid != id) && (recid != LAST_REC) && (recid != 0)) { /* the OpenIPMI driver does this sometimes */ msgout("get_sel MISMATCH: recid=%x newid=%x next=%x\n", recid,id,xid); dump_buf("get_sel cmd",ibuf,6,0); dump_buf("get_sel rsp",rbuf,rlen,0); } } } } if (fdebug) msgout("get_sel(%x) rv=%d cc=%x id=%x next=%x\n", recid,rv,cc,id,*nextid); return(rv); } static int getevent_sel(uchar *rdata, int *rlen, uchar *ccode) { uchar rec[24]; int rv = 0; ushort newid; ushort nextid; ushort recid; /* get current last record */ recid = sel_recid; rv = get_sel_entry(recid,&nextid,rec); if (rv == 0xCB && recid == 0) { /* SEL is empty */ *ccode = (uchar)rv; /* save the real ccode */ rv = 0x80; /* this is ok, just keep waiting */ } if (rv == 0) { if (fdebug) msgout("sel ok, id=%x next=%x\n",recid,nextid); if ((nextid == LAST_REC) || (recid == nextid)) { *ccode = 0x80; /*nothing new*/ } else { recid = nextid; /* else get new one */ rv = get_sel_entry(recid,&nextid,rec); if (rv == 0) { /* new event */ newid = rec[0] + (rec[1] << 8); if (drvtype == DRV_MV && recid != newid) { /* handle MV driver bug, try to get next one. */ if (fdebug) msgout("%s bug, record mismatch\n", show_driver_type(DRV_MV)); } if (fdebug) msgout("recid=%x newid=%x next=%x\n", recid,newid,nextid); memcpy(rdata,rec,16); *rlen = 16; *ccode = 0; sel_recid = recid; /*or newid*/ memcpy(&sel_time,&rec[2],4); } } } else { /* Error reading last recid saved */ if (fdebug) msgout("sel recid %x error, rv = %d\n",recid,rv); /* We want to set sel_recid = 0 here for some errors. */ if (rv == 0xCB || rv == 0xCD) { /* empty, or wrong SDR id */ sel_recid = 0; *ccode = (uchar)rv; rv = 0x80; /* wait again */ } } return(rv); } static int startevent_sel(ushort *precid, uint *ptime) { FILE *fd; uchar rec[24]; uint t = 0; ushort r = 0; ushort r2 = 0; int rv = -1; fd = fopen(idxfile,"r"); if (fdebug) msgout("start: idxfile=%s fd=%p\n",idxfile,fd); if (fd != NULL) { // Read the file, get savtime & savid rv = fscanf(fd,"%x %x",&t,&r); fclose(fd); if (r == LAST_REC) r = 0; rv = 0; /*read it, success*/ } else { /* treat as first time */ r = LAST_REC; rv = get_sel_entry(r,&r2,rec); if (rv == 0) { memcpy(&t,&rec[2],4); r = rec[0] + (rec[1] << 8); /*use current rec id*/ } else r = 0; rv = 1; /*first time*/ } if (fdebug) msgout("start: recid=%x time=%x\n",r,t); *ptime = t; *precid = r; return(rv); } static int syncevent_sel(ushort recid, uint itime) { FILE *fd; int rv; // Rewrite the saved time & record id if (fdebug) msgout("sync: recid=%x time=%x\n",recid,itime); fd = fopen(idxfile,"w"); if (fd == NULL) { msgout("syncevent: cannot open %s for writing\n",idxfile); rv = -1; } else { fprintf(fd,"%x %x\n",itime,recid); fclose(fd); rv = 0; } return(rv); } static void ievt_cleanup(void) { char obuf[48]; snprintf(obuf,sizeof(obuf),"%s exiting.\n",progname); msgout(obuf); write_syslog(obuf); if (finit_ok) { syncevent_sel(sel_recid,sel_time); free_sdr_cache(sdrs); } ipmi_close_(); /*inert if not opened*/ exit(EXIT_SUCCESS); } void show_event(uchar *evt,char *obuf, int sz) { int i; char sysbuf[250]; /* obuf should be 132 chars or more */ msgout("event data: "); for (i=0; i<16; i++) msgout("%02x ",evt[i]); msgout("\n"); decode_sel_entry(evt,obuf,sz); msgout(obuf); /*writes to outfile*/ /* write the message to syslog also. */ snprintf(sysbuf,sizeof(sysbuf),"%s: %s",progname,obuf); write_syslog(sysbuf); } #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) { int ret = 0; char c; uchar devrec[16]; uchar event[32]; /*usu 16 bytes */ char outbuf[160]; char *s1; int i, rlen; uchar ccode; uchar sensor_type; fdout = stderr; printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"m:p:s:t:xEF:N:P:R:T:U:V:YZ:?")) != EOF ) switch(c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 's': sdrfile = optarg; break; case 't': mytag = optarg; break; /* specific sensor tag */ case 'x': fdebug = 1; break; /* debug messages */ case 'p': /* port */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; default: printf("Usage: %s [-msx -NUPREFTVY]\n", progname); printf(" where -x show eXtra debug messages\n"); printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n"); printf(" -s File loads SDRs from File\n"); printf(" -t tag search for 'tag' in SDRs\n"); print_lan_opt_usage(1); exit(1); } /* Rather than parse_lan_options above, the set_lan_options function * could be used if the program already knows the nodename, etc. */ fipmilan = is_remote(); ret = ipmi_getdeviceid(devrec,16,fdebug); if (ret != 0) { printf("Cannot do ipmi_getdeviceid, ret = %d\n",ret); goto do_exit; } else { /*success*/ uchar ipmi_maj, ipmi_min; ipmi_maj = devrec[4] & 0x0f; ipmi_min = devrec[4] >> 4; show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min); } drvtype = get_driver_type(); /* could make it a daemon here, if desired */ fdout = fopen(outfile,"a"); if (fdout == NULL) { printf("%s: Cannot open %s\n", progname,outfile); fdout = stderr; } else { sprintf(outbuf,"%s ver %s started\n", progname,progver); msgout(outbuf); } sprintf(outbuf,"%s reading sensors ...\n",progname); write_syslog(outbuf); ret = get_sdr_cache(&sdrs); if (fdebug) msgout("get_sdr_cache ret = %d\n",ret); if (ret == 0) set_sel_opts(1,0, sdrs,fdebug,0); if (fipmilan) { char *node; node = get_nodename(); strcat(idxfile,"-"); strcat(idxfile,node); strcat(outfile,"-"); strcat(outfile,node); } ret = startevent_sel(&sel_recid,&sel_time); ievt_siginit(); finit_ok = 1; ret = 0; /*ignore any earlier errors, keep going*/ i = 0; while (ret == 0) { /*wait for bmc message events*/ if (fdebug) msgout("%s: %d Polling every %d sec for a new event after id %x\n", progname, i, wait_interval, sel_recid); rlen = sizeof(event); ret = getevent_sel(event,&rlen,&ccode); if (ret == 0) ret = ccode; if (fdebug) msgout("getevent_sel ret = %d\n",ret); if (ret == 0) { /* got an event successfully */ sensor_type = event[10]; msgout("got event id %04x, sensor_type = %02x\n", sel_recid,sensor_type); show_event(event,outbuf,sizeof(outbuf)); syncevent_sel(sel_recid,sel_time); } else if (ret == 0x80) { ret = 0; /*keep waiting*/ } else { msgout("get_event error: ret = 0x%x\n",ret); break; } i++; os_usleep(wait_interval,0); } /*end while loop*/ do_exit: ievt_cleanup(); show_outcome(progname,ret); exit (ret); } /* end main()*/ /* end ipmi_sample_evt.c */ ipmiutil-3.1.9/util/ipmilan.c0000644000000000000000000022736114144515623014650 0ustar rootroot/*M* // PVCS: // $Workfile: ipmilan.c $ // $Revision: 1.0 $ // $Modtime: 2 Feb 2006 15:31:14 $ // $Author: arcress at users.sourceforge.net $ // // This implements support for the IPMI LAN interface natively. // // 02/02/06 ARC - created. // 05/16/06 ARC - more added. // 06/19/06 ARCress - fixed sequence numbers for 1.7.1 // 08/08/06 ARCress - fix AUTHTYPE masks // 08/11/06 ARCress - added lan command retries // 10/17/06 ARCress - special case for no MsgAuth headers // 11/28/06 ARCress - added ipmi_cmd_ipmb routine // 05/08/07 ARCress - added 1.5 SOL data packet format to _send_lan_cmd, // not working yet. // 08/21/07 ARCress - handle Dell 1855 blades that return different authcode // 04/17/08 ARCress - check FD_ISSET in fd_wait *M*/ /*----------------------------------------------------------------------* The BSD License Copyright (c) 2005-2006, Intel Corporation Copyright (c) 2009 Kontron America, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: a.. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. b.. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. c.. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------*/ #ifdef WIN32 #include #include #include #include #include #include #include //#define HAVE_IPV6 1 #ifdef HAVE_IPV6 #include //#include //#include #else #include #define MSG_WAITALL 0x100 /* Wait for a full request */ #endif #define INET_ADDRSTRLEN 16 #define MSG_NONE 0x000 #define int32_t int #define u_int32_t unsigned int #define uint32 unsigned int #define uchar unsigned char #define RECV_MSG_FLAGS MSG_NONE typedef unsigned int socklen_t; #elif defined(DOS) #include #include #include #include #undef HAVE_LANPLUS #else /* Linux, BSD, etc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HPUX #define RECV_MSG_FLAGS 0x40 /*match MSG_WAITALL for HPUX*/ #else #define RECV_MSG_FLAGS MSG_WAITALL #endif #endif #include "ipmicmd.h" #include "ipmilan.h" #if defined(HAVE_CONFIG_H) #include "config.h" #else #if defined(MACOS) typedef unsigned int socklen_t; #endif #endif #if defined(LINUX) /* TODO: fixups in BSD/Solaris for ipv6 method */ #define HAVE_IPV6 1 #endif #if defined(CROSS_COMPILE) #undef HAVE_IPV6 static struct hostent *xgethostbyname(const char *nstr) { static struct hostent hptr; if (StrIsIp(nstr)) { /* the string is an IP address */ hptr.h_name = (char *)nstr; inet_aton(nstr,(struct in_addr *)&hptr.h_addr); return(&hptr); } else { /*the string is a node name */ return(NULL); } } #else #define xgethostbyname gethostbyname #endif // #define TEST_LAN 1 /*++++TEST_LAN for DEBUG++++*/ #if defined(ALLOW_GNU) #define MD2OK 1 /*use md2.h GPL code*/ #else /* if here, ALLOW_GPL is not defined, check for lanplus libcrypto. */ #if defined(HAVE_LANPLUS) #define MD2OK 1 /*use MD2 version from lanplus libcrypto */ #endif /* if libcrypto does not have EVP_md2, then skip MD2. */ #if defined(SKIP_MD2) #undef MD2OK #endif #endif /* Connection States: * 0 = init, 1 = socket() complete, 2 = bind/gethost complete, * 3 = ping sent, 4 = pong received, 5 = session activated. * see also conn_state_str[] below */ #define CONN_STATE_INIT 0 #define CONN_STATE_SOCK 1 #define CONN_STATE_BIND 2 #define CONN_STATE_PING 3 #define CONN_STATE_PONG 4 #define CONN_STATE_ACTIVE 5 #define SOL_DATA 0xFD /*SOL Data command*/ #define SOL_MSG 0x10000000 /*SOL message type*/ #define SOL_HLEN 14 // SZGNODE == 80 #define SZ_CMD_HDR 4 /*cmd, netfn/lun, sa*/ #define SWID_REMOTE 0x81 #define SWID_SMSOS 0x41 #pragma pack(1) typedef struct { /*first 30 bytes conform to IPMI header format*/ uchar rmcp_ver; uchar rmcp_res; uchar rmcp_seq; uchar rmcp_type; uchar auth_type; uint32 seq_num; /*outgoing seq*/ uint32 sess_id; uchar auth_code[16]; uchar msg_len; /* size here = 30 bytes = RQ_HDR_LEN */ uchar swid; /* usu SWID_REMOTE. From here down, order is changeable */ uchar swseq; /* outgoing swseq */ uchar swlun; uchar priv_level; uint32 iseq_num; /*incoming seq */ uchar bmc_addr; /*usu BMC_SA*/ uchar target_addr; uchar target_chan; uchar target_lun; uchar target_cmd; uchar target_netfn; uchar transit_addr; uchar transit_chan; uchar bridge_level; uchar password[16]; uchar challenge[16]; } IPMI_HDR; #pragma pack() typedef struct { int type; int len; char *data; } SOL_RSP_PKT; /* extern void atoip(uchar *array,char *instr); *subs.c*/ extern FILE *open_log(char *mname); /*ipmicmd.c*/ extern char * get_iana_str(int mfg); /*subs.c*/ #define dbglog printf #define dbg_dump dump_buf extern FILE *fperr; /*defined in ipmicmd.c, usu stderr */ extern FILE *fpdbg; /*defined in ipmicmd.c, usu stdout */ extern int gshutdown; /* from ipmicmd.c, usu =0 */ extern int fauth_type_set; /* from ipmicmd.c */ extern LAN_OPT lanp; /* from ipmicmd.c */ //extern char *gnode; /* from ipmicmd.c */ //extern char *guser; /* from ipmicmd.c */ //extern char *gpswd; /* from ipmicmd.c */ //extern int gauth_type; /* from ipmicmd.c */ //extern int gpriv_level; /* from ipmicmd.c */ extern ipmi_cmd_t ipmi_cmds[NCMDS]; static IPMI_HDR ipmi_hdr = { 0x06, 0, 0xFF, 0x07, 0x00, 0, 0, /*auth_code*/{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0, /*msg_len*/ /*swid*/SWID_REMOTE, 1,0,0,0, BMC_SA,0,0,0,0,0,0,0,0 /*bridge_level*/ }; // static IPMI_HDR *phdr; static uchar bmc_sa = BMC_SA; /*usu 0x20*/ static uchar sms_swid = SWID_REMOTE; /*usu 0x81*/ static int vend_id = 0; static int prod_id = 0; #if defined(DOS) || defined(EFI) int ipmi_open_lan(char *node, char *user, int port, char *pswd, int fdebugcmd) { printf("IPMI LAN is not supported under DOS.\n"); return(-1); } int ipmi_close_lan(char *node) { printf("IPMI LAN is not supported under DOS.\n"); return(-1); } int ipmi_cmd_lan(char *node, ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { printf("IPMI LAN is not supported under DOS.\n"); return(-1); } int ipmi_cmdraw_lan(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { printf("IPMI LAN is not supported under DOS.\n"); return(-1); } int ipmicmd_lan(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { printf("IPMI LAN is not supported under DOS.\n"); return(-1); } #else /* All other OSs can support IPMI LAN */ /* * These variables pertain to ipmilan, for the node given at open time. * The assumption here is that these are utilities, so no more than one * node will be open at a given time. * See also gnode, guser, gpswd in ipmicmd.c */ typedef struct { int connect_state; /*=CONN_STATE_INIT*/ SockType sockfd; int finsession; uint32 session_id; uint32 in_seq; /*=1*/ uint32 start_out_seq; /*=1*/ uchar fMsgAuth; /*0=AuthNone 1=PerMsgAuth 2=UserLevelAuth*/ uchar auth_type; /*=AUTHTYPE_INIT*/ } LAN_CONN; /*see also IPMI_HDR below*/ // static int connect_state = CONN_STATE_INIT; // static int sockfd = 0; // static int finsession = 0; // static uint32 session_id = 0; // static uint32 in_seq = 0x01; /* inbound sequence num */ // static uint32 start_out_seq = 0x01; /* initial outbound sequence num */ // static uchar fMsgAuth = 1; static uchar auth_type = AUTHTYPE_INIT; /*initial value, not set*/ static char nodename[SZGNODE+1] = ""; static char gnodename[SZGNODE+1] = ""; /*nodename returned after connection*/ #if defined(AI_NUMERICSERV) static int my_ai_flags = AI_NUMERICSERV; /*0x0400 Dont use name resolution NEW*/ // static int my_ai_flags = AI_NUMERICHOST; /*0x0004 Dont use name resolution*/ #else #undef HAVE_IPV6 #endif #ifdef HAVE_IPV6 #define SOCKADDR_T struct sockaddr_storage #else #define SOCKADDR_T struct sockaddr_in static char _dest_ip[INET_ADDRSTRLEN+1]; // static char _dest[MAXHOSTNAMELEN+1]; #endif static SOCKADDR_T _srcaddr; static SOCKADDR_T _destaddr; static int _destaddr_len = 0; #ifdef TEST_LAN static int fdebuglan = 3; #else static int fdebuglan = 0; #endif static int fdoping = 0; /* =1 do ping first, set to 0 b/c no added value*/ static int fdopoke1 = 0; static int fdopoke2 = 0; static int frequireping = 0; /*=1 if ping is required, =0 ignore ping error */ static LAN_CONN conn = {CONN_STATE_INIT,0,0,0,1,1,1}; static LAN_CONN *pconn = &conn; static char *authcode = NULL; static int authcode_len = 0; static int ping_timeout = 1; /* timeout: 1 sec */ static int ipmi_timeout = 2; /* timeout: 10 sec -> 2 sec */ static int ipmi_try = 4; /* retries: 4 */ static uchar bridgePossible = 0; static char *conn_state_str[6] = { "init state", "socket complete", "bind complete", "ping sent", "pong received", "session activated" }; int lasterr = 0; static uchar sol_op = 0x80; /* encrypted/not */ static uchar sol_snd_seq = 0; /* valid if non-zero*/ static uchar sol_rcv_seq = 0; static uchar sol_rcv_cnt = 0; static uchar sol_rcv_ctl = 0x00; // static uchar sol_offset = 0; static uchar sol_seed_cnt = 0x01; /* set after activate response */ static char sol_Encryption = 0; /*for SOL 1.5*/ static uint32 g_Seed[ 16 ]; /*for SOL 1.5*/ static uchar g_Cipher[ 16 ][ 16 ]; /*SeedCount x CipherHash for SOL 1.5*/ #define BUSY_MAX 10 /*for Dell FS12-TY Node Busy errors*/ #ifdef WIN32 int econnrefused = WSAECONNREFUSED; /*=10061.*/ int econnreset = WSAECONNRESET; /*=10054.*/ #else int econnrefused = ECONNREFUSED; /*=111. from Linux asm/errno.h */ int econnreset = ECONNRESET; /*=104.*/ #endif #ifdef WIN32 WSADATA lan_ws; /* See http://msdn2.microsoft.com/en-us/library/ms740668.aspx * or doc/winsockerr.txt */ #define NWINERRS 21 static struct { int err; char *desc; } winerrs[NWINERRS] = { WSAEINTR /*10004*/, "Interrupted function call", WSAEBADF /*10009*/, "File handle is not valid", WSAEACCES /*10013*/, "Permission denied", WSAEFAULT /*10014*/, "Bad address", WSAEINVAL /*10022*/, "Invalid argument", WSAEMFILE /*10024*/, "Too many open files", WSAENOTSOCK /*10038*/, "Socket operation on nonsocket", WSAEDESTADDRREQ /*10039*/, "Destination address required", WSAEMSGSIZE /*10040*/, "Message too long", WSAEOPNOTSUPP /*10045*/, "Operation not supported", WSAEADDRINUSE /*10048*/, "Address already in use", WSAEADDRNOTAVAIL /*10049*/, "Cannot assign requested address", WSAENETDOWN /*10050*/, "Network is down", WSAENETUNREACH /*10051*/, "Network is unreachable", WSAENETRESET /*10052*/, "Network dropped connection on reset", WSAECONNABORTED /*10053*/, "Software caused connection abort", WSAECONNRESET /*10054*/, "Connection reset by peer", WSAENOTCONN /*10057*/, "Socket is not connected", WSAECONNREFUSED /*10061*/, "Connection refused", WSAEHOSTDOWN /*10064*/, "Host is down", WSAEHOSTUNREACH /*10065*/, "No route to host" }; char * strlasterr(int rv) { char *desc; int i; for (i = 0; i < NWINERRS; i++) { if (winerrs[i].err == rv) { desc = winerrs[i].desc; break; } } if (i >= NWINERRS) desc = ""; return(desc); } #endif #ifdef MD2OK extern void md2_sum(uchar *string, int len, uchar *mda); /*from md2.c*/ #endif extern void md5_sum(uchar *string, int len, uchar *mda); /*from md5.c*/ int _ipmilan_cmd(SockType s, struct sockaddr *to, int tolen, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *sdata, int slen, uchar *rdata, int *rlen, int fdebugcmd); static int _send_lan_cmd(SockType s, uchar *pcmd, int scmd, uchar *presp, int *sresp, struct sockaddr *to, int tolen); static int ipmilan_open_session(SockType sfd, struct sockaddr *destaddr, int destaddr_len, uchar auth_type, char *username, char *authcode, int authcode_len, uchar priv_level, uint32 init_out_seqnum, uint32 *session_seqnum, uint32 *session_id); static int ipmilan_close_session(SockType sfd, struct sockaddr *destaddr, int destaddr_len, uint32 session_id); uchar cksum(const uchar *buf, register int len); char *decode_rv(int rv); /*moved to ipmicmd.c*/ void show_LastError(char *tag, int err) { #ifdef WIN32 fprintf(fperr,"%s LastError = %d %s\n",tag,err,strlasterr(err)); #else char *s; s = strerror(err); if (s == NULL) s = "error"; fprintf(fperr,"%s errno = %d, %s\n",tag,err,s); #endif } int get_LastError( void ) { #ifdef WIN32 lasterr = WSAGetLastError(); #else lasterr = errno; #endif return(lasterr); } static void cc_challenge(int cc) { switch(cc) { case 0x81: printf("GetSessChallenge: Invalid user name\n"); break; case 0x82: printf("GetSessChallenge: Null user name not enabled\n"); break; default: printf("GetSessChallenge: %s\n",decode_cc((ushort)0,cc)); break; } } static void cc_session(int cc) { switch(cc) { case 0x81: printf("ActivateSession: No session slots available from BMC\n"); break; case 0x82: printf("ActivateSession: No sessions available for this user\n"); break; case 0x83: printf("ActivateSession: No sessions for this user/privilege\n"); break; case 0x84: printf("ActivateSession: Session sequence number out of range\n"); break; case 0x85: printf("ActivateSession: Invalid session ID in request\n"); break; case 0x86: printf("ActivateSession: Privilege level exceeds user/channel limit\n"); break; default: printf("%s\n",decode_cc((ushort)0,cc)); break; } return; } int StrIsIp(char *str) { int i, j, n; char ipchars[11] = "0123456789."; int ndot = 0; int rv = 0; /* checks if the string looks like an IP address. */ if (str == NULL) return(rv); n = (int)strlen(str); for (i = 0; i < n; i++) { for (j = 0; j < 11; j++) if (str[i] == ipchars[j]) break; if (j >= 11) break; /*some other char, not valid*/ if (str[i] == '.') ndot++; } if ((i == n) && (ndot == 3)) rv = 1; /*valid*/ return(rv); } void close_sockfd(SockType sfd); void close_sockfd(SockType sfd) { if (sfd == 0) return; #ifdef WIN32 // shutdown(sfd,SD_SEND); /*done sending*/ closesocket(sfd); /*close lan socket */ WSACleanup(); #else alarm(0); signal(SIGALRM,SIG_DFL); signal(SIGINT,SIG_DFL); close(sfd); /*close lan socket */ #endif pconn->sockfd = 0; /*set global to zero */ } int open_sockfd(char *node, int port, SockType *sfd, SOCKADDR_T *daddr, int *daddr_len, int foutput); int open_sockfd(char *node, int port, SockType *sfd, SOCKADDR_T *daddr, int *daddr_len, int foutput) { int rv = 0; SockType s, _sockfd = -1; #ifdef HAVE_IPV6 struct addrinfo hints; struct addrinfo *res, *res0; char service[NI_MAXSERV]; #else struct hostent *hptr; #endif #ifdef WIN32 DWORD rvl; if (sfd == NULL || daddr == NULL || daddr_len == NULL) return(-3); /* invalid pointer */ rvl = WSAStartup(0x0202,&lan_ws); if (rvl != 0) { fprintf(fperr,"lan, WSAStartup(2.2) error %ld, try 1.1\n", rvl); WSACleanup(); rvl = WSAStartup(0x0101,&lan_ws); if (rvl != 0) { fprintf(fperr,"lan, WSAStartup(1.1) error %ld\n", rvl); WSACleanup(); return((int)rvl); } } #else if (sfd == NULL || daddr == NULL || daddr_len == NULL) return(-3); /* invalid pointer */ #endif pconn->connect_state = CONN_STATE_INIT; #ifdef HAVE_IPV6 memset(&_srcaddr, 0, sizeof(_srcaddr)); memset(daddr, 0, sizeof(_destaddr)); sprintf(service, "%d", port); /* Obtain address(es) matching host/port */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = my_ai_flags; hints.ai_protocol = IPPROTO_UDP; /* */ rv = getaddrinfo(node, service, NULL, &res); if (rv != 0) { printf("Address lookup for %s failed, getaddrinfo error %d\n", node,rv); return rv; } /* getaddrinfo() returns a list of address structures. * Try each address until we successfully connect(2). * If socket(2) (or connect(2)) fails, we (close the socket * and) try the next address. */ for (res0 = res; res0 != NULL; res0 = res0->ai_next) { /* valid protocols are IPPROTO_UDP, IPPROTO_IPV6 */ if (res0->ai_protocol == IPPROTO_TCP) continue; /*IPMI != TCP*/ s = socket(res0->ai_family, res0->ai_socktype, res0->ai_protocol); if (s == SockInvalid) continue; else _sockfd = s; pconn->connect_state = CONN_STATE_SOCK; rv = connect(_sockfd, res0->ai_addr, res0->ai_addrlen); if (fdebuglan) printf("socket(%d,%d,%d), connect(%d) rv = %d\n", res0->ai_family, res0->ai_socktype, res0->ai_protocol, s,rv); if (rv != -1) { memcpy(daddr, res0->ai_addr, res0->ai_addrlen); *daddr_len = res0->ai_addrlen; break; /* Success */ } close_sockfd(_sockfd); _sockfd = -1; } freeaddrinfo(res); /* Done with addrinfo */ if (_sockfd < 0) { printf("Connect to %s failed\n", node); // ipmi_close_(); rv = -1; } #else /* Open lan interface (ipv4 method) */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s == SockInvalid) return (-1); else _sockfd = s; pconn->connect_state = CONN_STATE_SOCK; memset(&_srcaddr, 0, sizeof(_srcaddr)); _srcaddr.sin_family = AF_INET; _srcaddr.sin_port = htons(0); _srcaddr.sin_addr.s_addr = htonl(INADDR_ANY); rv = bind(_sockfd, (struct sockaddr *)&_srcaddr, sizeof(_srcaddr)); if (rv < 0) { close_sockfd(_sockfd); return (rv); } memset(daddr, 0, sizeof(SOCKADDR_T)); daddr->sin_family = AF_INET; daddr->sin_port = htons(port); /*RMCP_PRI_RMCP_PORT 0x26f = 623.*/ if (StrIsIp(node)) { /* the node string is an IP address */ uchar in_ip[4]; atoip(in_ip,node); memcpy(&daddr->sin_addr.s_addr,in_ip,4); if ((hptr = xgethostbyname(node)) == NULL) /*gethost error*/ strncpy(gnodename,node,SZGNODE); /*but not fatal*/ else strncpy(gnodename,hptr->h_name,SZGNODE); } else if ((hptr = xgethostbyname(node)) == NULL) { if (foutput) { #ifdef WIN32 fprintf(fperr,"lan, gethostbyname(%s): errno=%d\n", node,get_errno()); #elif SOLARIS fprintf(fperr,"lan, gethostbyname(%s): errno=%d\n", node,get_errno()); #elif defined(HPUX) /*added by ugene */ fprintf(fperr,"lan, gethostbyname(%s): errno=%d\n", node,errno); #else fprintf(fperr,"lan, gethostbyname(%s): %s\n", node,hstrerror(errno)); #endif } close_sockfd(_sockfd); return(LAN_ERR_HOSTNAME); } else { /*gethostbyname(name) succeeded*/ daddr->sin_addr = *((struct in_addr *)hptr->h_addr); strncpy(gnodename,hptr->h_name,SZGNODE); } *daddr_len = sizeof(SOCKADDR_T); #endif *sfd = _sockfd; return(rv); } static void sig_timeout(int sig) { #ifndef WIN32 alarm(0); signal(SIGALRM,SIG_DFL); #endif fprintf(fpdbg,"ipmilan_cmd timeout, after %s\n",conn_state_str[pconn->connect_state]); _exit(LAN_ERR_TIMEOUT); /*timeout signal*/ } static void sig_abort(int sig) { static int sig_aborting = 0; int rv; if (sig_aborting == 0) { sig_aborting = 1; if (pconn->sockfd != 0) { /* socket is open */ if (pconn->session_id != 0) { /* session is open */ // cmd_rs = buf_rs; rv = ipmilan_close_session(pconn->sockfd, (struct sockaddr *)&_destaddr, _destaddr_len, ipmi_hdr.sess_id); } close_sockfd(pconn->sockfd); } signal(SIGINT,SIG_DFL); fprintf(fpdbg,"ipmilan_cmd interrupt, after %s\n", conn_state_str[pconn->connect_state]); _exit(LAN_ERR_ABORT); /*abort signal*/ } /*endif*/ } /*end sig_abort*/ int fd_wait(SockType fd, int nsec, int usec) { fd_set readfds; struct timeval tv; int rv; FD_ZERO(&readfds); FD_SET(fd, &readfds); tv.tv_sec = nsec; tv.tv_usec = usec; rv = select((int)(fd+1), &readfds, NULL, NULL, &tv); if (rv <= 0 || !FD_ISSET(fd,&readfds)) return(-1); else return(0); } #ifndef WIN32 /* LINUX, Solaris, BSD */ /* do_sleep() is currently unused. */ /* signal handlers + sleep(3) is a bad idea */ int do_sleep(unsigned int sleep_len) { struct timeval tv; if (sleep_len == 0) return 0; tv.tv_sec = sleep_len; tv.tv_usec = 0; if (select(1, NULL, NULL, NULL, &tv) < 0) { if (errno != EINTR) return(errno); } return 0; } #endif static void h2net(uint h, uchar *net, int n) { int i = 0; net[i++] = h & 0xff; net[i++] = (h >> 8) & 0xff; if (n == 2) return; net[i++] = (h >> 16) & 0xff; net[i++] = (h >> 24) & 0xff; return; } static void net2h(uint32 *h, uchar *net, int n) { uint32 v; v = (net[1] << 8) | net[0]; if (n == 2) { *h = v; return; } v |= (uint32)(net[3] << 24) | (net[2] << 16); *h = v; return; } /* * _ipmilan_cmd * local routine to send & receive each command. * called by global ipmicmd_lan() */ int _ipmilan_cmd(SockType sockfd, struct sockaddr *hostaddr, int hostaddr_len, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *sdata, int slen, uchar *rdata, int *rlen, int fdebugcmd) { uchar cmd_rq[RQ_LEN_MAX+SZ_CMD_HDR]; uchar cmd_rs[RS_LEN_MAX+SZ_CMD_HDR+1]; int rv = 0; int rs_len; int clen; uchar cc = 0; #ifndef TEST_LAN fdebuglan = fdebugcmd; #endif if (sockfd == 0 || hostaddr == NULL || sdata == NULL || rdata == NULL) return(LAN_ERR_INVPARAM);; if (fdebuglan > 2) dbglog("_ipmilan_cmd(%02x,%02x,%02x,%02x,%02x)\n", cmd,netfn,lun,sa,bus); clen = SZ_CMD_HDR; cmd_rq[0] = cmd; cmd_rq[1] = (netfn << 2) + (lun & 0x03); cmd_rq[2] = sa; cmd_rq[3] = bus; memcpy(&cmd_rq[clen],sdata,slen); rs_len = sizeof(cmd_rs); memset(cmd_rs, 0, rs_len); rv = _send_lan_cmd(sockfd, cmd_rq, slen+clen, cmd_rs, &rs_len, hostaddr, hostaddr_len); if (rv == 0 && rs_len == 0) cc = 0; else cc = cmd_rs[0]; if (fdebugcmd) fprintf(fpdbg,"_ipmilan_cmd[%02x]: rv = %d, cc=%x rs_len=%d\n", cmd_rq[0],rv,cc,rs_len); if (rv == 0 && cc != 0) { /* completion code error */ if (fdebugcmd) { dump_buf("cmd_rq",cmd_rq,slen+clen,0); dump_buf("cmd_rs",cmd_rs,rs_len,0); } } if (rv == 0) { if (rs_len < 0) rs_len = 0; if (*rlen <= 0) *rlen = 1; /*failsafe*/ if (rs_len > 0) { if (rs_len > *rlen) rs_len = *rlen; memcpy(rdata,&cmd_rs[0],rs_len); } else { /*(rs_len == 0)*/ rv = LAN_ERR_TOO_SHORT; /*no completion code returned*/ } } else { rdata[0] = cc; if (rs_len < 1) rs_len = 1; } *rlen = rs_len; return (rv); } /*end _ipmilan_cmd()*/ static void hash(uchar *pwd, uchar *id, uchar *chaldata, int chlen, uint32 seq, uchar *mda, uchar md) { uchar pbuf[80]; /* 16 + 4 + 16 + 4 + 16 = 56 */ int blen, n, i; blen = 0; n = 16; memcpy(&pbuf[blen], pwd,n); /* password */ blen += n; n = 4; memcpy(&pbuf[blen],id,n); /* session id */ blen += n; memcpy(&pbuf[blen],chaldata,chlen); /* ipmi msg data, incl challenge */ blen += chlen; n = 4; h2net(seq,&pbuf[blen],n); /* in_seq num */ blen += n; n = 16; memcpy(&pbuf[blen],pwd,n); /* password */ blen += n; if (md == IPMI_SESSION_AUTHTYPE_MD2) i = 2; else i = 5; #ifdef TEST_AUTH if (fdebuglan) { fprintf(fpdbg,"hash: calling md%d_sum with seq %u\n",i,seq); dump_buf("pbuf",pbuf,blen,0); } #endif #ifdef MD2OK if (md == IPMI_SESSION_AUTHTYPE_MD2) md2_sum(pbuf,blen,mda); else /* assume md5 */ #endif md5_sum(pbuf,blen,mda); #ifdef TEST_AUTH if (fdebuglan) { fprintf(fpdbg,"Hashed MD%d AuthCode: \n",i); dump_buf("AuthCode",mda,16,0); } #endif } /* end hash() */ static void hash_special(uchar *pwd, uchar *chaldata, uchar *mda) { uchar md_pwd[16]; uchar challenge[16]; int i; /* Only used by SuperMidro, must be MD5 auth_type */ memset(md_pwd, 0, 16); md5_sum(pwd,16,md_pwd); memset(challenge, 0, 16); for (i = 0; i < 16; i++) challenge[i] = chaldata[i] ^ md_pwd[i]; memset(mda, 0, 16); md5_sum(challenge,16,mda); } static int ipmilan_sendto(SockType s, const void *msg, size_t len, int flags, const struct sockaddr *to, int tolen) { int fusepad = 0; int n; if (fdebuglan > 2) { dbg_dump("ipmilan_sendto",(uchar *)msg,(int)len,0); } /* Check whether we need a pad byte */ /* Note from Table 12-8, RMCP Packet for IPMI via Ethernet footnote. */ if (len == 56 || len == 84 || len == 112 || len == 128 || len == 156) { /* include pad byte at end, require input buffer to have one extra */ fusepad = 1; len += 1; } n = (int)sendto(s,msg,len,flags,to,(socklen_t)tolen); if (fusepad && (n > 0)) n--; return(n); } static int ipmilan_recvfrom(SockType s, void *buf, size_t len, int flags, struct sockaddr *from, int *fromlen) { int rv; rv = (int)recvfrom(s,buf,len,flags,from,(socklen_t *)fromlen); #ifdef OLD /* Sometimes the OS sends an ECONNREFUSED error, but * retrying will catch the BMC's reply packet. */ if (rv < 0) { int err; err = get_LastError(); if (err == econnrefused) { if (fdebuglan) fprintf(fpdbg,"ipmilan_recvfrom rv=%d econnrefused, retry\n",rv); rv = recvfrom(s,buf,len,flags,from,(socklen_t *)fromlen); } } #endif return(rv); } static int ipmilan_poke1(SockType sfd, struct sockaddr *destaddr, int destlen) { int rv; uchar asfpkt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x18, 0xc8, 0xc2, 0x01, 0x01, 0x3c }; if (fdebuglan) fprintf(fpdbg,"sending ipmilan poke1\n"); rv = ipmilan_sendto(sfd, asfpkt, 16, 0, destaddr, destlen); os_usleep(0,100); return rv; } static int ipmilan_poke2(SockType sfd, struct sockaddr *destaddr, int destlen) { int rv; uchar asfpkt[16] = "poke2"; /*any junk*/ if (fdebuglan) fprintf(fpdbg,"sending ipmilan poke2\n"); rv = ipmilan_sendto(sfd, asfpkt, 10, 0, destaddr, destlen); os_usleep(0,100); return rv; } static void do_hash(uchar *password, uchar *sessid, uchar *pdata, int sdata, uint32 seq_num, uchar auth_type, uchar *auth_out) { /* finish header with auth_code */ if (auth_type != IPMI_SESSION_AUTHTYPE_NONE) { /*fdoauth==1*/ if (auth_type == IPMI_SESSION_AUTHTYPE_MD5) hash(password, sessid, pdata, sdata, seq_num, auth_out,IPMI_SESSION_AUTHTYPE_MD5); #ifdef MD2OK else if (auth_type == IPMI_SESSION_AUTHTYPE_MD2) hash(password, sessid, pdata, sdata, seq_num, auth_out,IPMI_SESSION_AUTHTYPE_MD2); #endif else /* IPMI_SESSION_AUTHTYPE_PASSWORD */ memcpy(auth_out,password,16); } } static uint32 inc_seq_num(uint32 seq) { seq++; if (seq == 0) seq = 1; return(seq); } static int inc_sol_seq(int seq) { seq++; if (seq > 0x0f) seq = 1; /*limit to 4 bits*/ return(seq); } void ipmi_lan_set_timeout(int ipmito, int tries, int pingto) { ipmi_timeout = ipmito; /*default 2*/ ipmi_try = tries; /*default 4*/ ping_timeout = pingto; /*default 1*/ } /* * _send_lan_cmd * Internal routine called by local _ipmilan_cmd() and by * ipmilan_open_session(). * Writes the data to the lan socket in IPMI LAN format. * Authentication, sequence numbers, checksums are handled here. * * Input Parameters: * s = socket descriptor for this session * pcmd = buffer for the command and data * Arbitrary pcmd format: * cmd[0] = IPMI command * cmd[1] = NETFN/LUN byte * cmd[2] = Slave Address (usu 0x20) * cmd[3] = Bus (usu 0x00) * cmd[4-N] = command data * scmd = size of command buffer (3+sdata) * presp = pointer to existing response buffer * sresp = On input, size of response buffer, * On output, length of response data. * to = sockaddr structure for to/destination * tolen = length of to sockaddr */ static int _send_lan_cmd(SockType s, uchar *pcmd, int scmd, uchar *presp, int *sresp, struct sockaddr *to, int tolen) { uchar cbuf[SEND_BUF_SZ]; uchar rbuf[RECV_BUF_SZ]; // uint32 out_seq = 0; /* outbound */ int clen, rlen, hlen, msglen; int flags; int sz, n, i, j; int cs1, cs2, cs3 = 0, cs4 = 0; uchar *pdata; int sdata; IPMI_HDR *phdr; uchar *psessid; uchar iauth[16]; int fdoauth = 1; uint32 sess_id_tmp; int rv = 0; int itry; uchar fsentok; /* set up LAN req hdr */ phdr = &ipmi_hdr; hlen = RQ_HDR_LEN; /* phdr->bmc_addr set in open_session */ phdr->target_addr = pcmd[2]; phdr->target_chan = pcmd[3]; phdr->target_lun = (pcmd[1] & 0x03); phdr->target_netfn = (pcmd[1] >> 2); phdr->target_cmd = pcmd[0]; if (phdr->seq_num != 0) pconn->finsession = 1; if ( ((phdr->target_cmd == CMD_ACTIVATE_SESSION) || (phdr->target_cmd == CMD_SET_SESSION_PRIV)) && (phdr->target_netfn == NETFN_APP) ) { pconn->finsession = 1; /*so do seq_num*/ fdoauth = 1; /*use msg auth*/ } if (phdr->auth_type == IPMI_SESSION_AUTHTYPE_NONE) fdoauth = 0; else if (pconn->finsession && (pconn->fMsgAuth == 0)) { /* Forcing the type may be necessary with IBM eServer 360S. */ if (fauth_type_set) fdoauth = 1; /*user set it, so try anyway*/ else fdoauth = 0; /*auth not supported*/ } if (fdoauth == 0) hlen = RQ_HDR_LEN - 16; /* copy command */ if (scmd < SZ_CMD_HDR) return(LAN_ERR_INVPARAM); sdata = scmd - SZ_CMD_HDR; /* scmd = 4 + datalen */ msglen = 7 + sdata; if (fdebuglan > 2) { dbglog("_send_lan_cmd: cmd=%02x, hlen=%d, msglen=%02x, authtype=%02x\n", pcmd[0], hlen, msglen, phdr->auth_type); } clen = hlen + msglen; if (clen > sizeof(cbuf)) { fprintf(fpdbg,"message size %d > buffer size %lu\n",clen,sizeof(cbuf)); return(LAN_ERR_TOO_SHORT); } if ((phdr->target_cmd == SOL_DATA) && (phdr->target_netfn == NETFN_SOL) ) /*SOL 1.5 data packet*/ { hlen = SOL_HDR_LEN; /*RMCP header + 26 */ if (fdoauth == 0) hlen = SOL_HDR_LEN - 16; msglen = sdata; memcpy(&cbuf[0], phdr, 4); /* copy RMCP header to buffer */ pdata = &cbuf[4]; pdata[0] = phdr->auth_type; memcpy(&pdata[1],&phdr->seq_num,4); sess_id_tmp = phdr->sess_id | SOL_MSG; memcpy(&pdata[5],&sess_id_tmp,4); if (fdebuglan > 2) dbglog("auth_type=%x/%x fdoauth=%d hlen=%d seq_num=%x\n", /*SOL*/ phdr->auth_type,lanp.auth_type,fdoauth,hlen,phdr->seq_num); if (fdoauth) { psessid = (uchar *)&sess_id_tmp; do_hash(phdr->password, psessid, &cbuf[hlen],msglen, phdr->seq_num, phdr->auth_type, iauth); /* copy hashed authcode to header */ memcpy(&pdata[9],iauth,16); } // pdata[hlen-1] = msglen; pdata = &cbuf[hlen]; memcpy(pdata,&pcmd[SZ_CMD_HDR],msglen); /*copy the data*/ clen = hlen + msglen; if (fdebuglan > 2) dbg_dump("sol data, before",pdata,sdata,1); /*SOL TEST*/ } else { /*not SOL packet, normal IPMI packet*/ pdata = &cbuf[hlen]; j = cs1 = 0; if ((phdr->target_addr == phdr->bmc_addr) || !bridgePossible || (phdr->target_addr == SWID_REMOTE) || (phdr->target_addr == SWID_SMSOS)) { phdr->bridge_level = 0; msglen = sdata + 7; clen = hlen + msglen; } else { phdr->bridge_level = 1; if (phdr->transit_addr != 0 && phdr->transit_addr != phdr->bmc_addr) { msglen = sdata + 15 + 8; phdr->bridge_level++; } else { msglen = sdata + 15; } if (fdebuglan > 2) { dbglog("bridge_level=%d cmd=%02x target=%02x transit=%02x\n", phdr->bridge_level, phdr->target_cmd, phdr->target_addr, phdr->transit_addr); dbglog("bridge target_ch=%x transit_ch=%x\n", phdr->target_chan, phdr->transit_chan); } clen = hlen + msglen; pdata[j++] = bmc_sa; /*[0]=sa */ pdata[j++] = (NETFN_APP << 2); /*[1]=netfn/lun*/ pdata[j] = cksum(&pdata[cs1],j-cs1); /*[2]=cksum1*/ j++; cs3 = j; /*start for cksum3*/ pdata[j++] = phdr->swid; /*[3]=swid, usu SWID_REMOTE */ pdata[j++] = (phdr->swseq << 2); /*[4]=swseq/lun*/ pdata[j++] = CMD_SEND_MESSAGE; /*[5]=cmd*/ if (phdr->bridge_level == 1) { pdata[j++] = (0x40|phdr->target_chan); /*channel*/ } else { /*double bridge*/ pdata[j++] = (0x40|phdr->transit_chan); /*channel*/ cs1 = j; pdata[j++] = phdr->transit_addr; /*[0]=sa */ pdata[j++] = (NETFN_APP << 2); /*[1]=netfn/lun*/ pdata[j] = cksum(&pdata[cs1],j-cs1); /*[2]=cksum1*/ j++; cs4 = j; /*start for cksum4*/ pdata[j++] = bmc_sa; /*[3]=swid */ pdata[j++] = (phdr->swseq << 2); /*[4]=swseq/lun*/ pdata[j++] = CMD_SEND_MESSAGE; /*[5]=cmd*/ pdata[j++] = (0x40|phdr->target_chan); /*channel*/ } } /*end-else bridged*/ /* normal IPMI LAN commmand packet */ cs1 = j; /*start for cksum1*/ pdata[j++] = pcmd[2]; /*[0]=sa (phdr->target_addr)*/ pdata[j++] = pcmd[1]; /*[1]=netfn/lun*/ pdata[j] = cksum(&pdata[cs1],j-cs1); /*[2]=cksum1*/ j++; cs2 = j; /*start for cksum2*/ if (phdr->bridge_level == 0) pdata[j++] = phdr->swid; /*[3]=swid*/ else /*bridged message*/ pdata[j++] = phdr->bmc_addr; /*[3]=swid*/ pdata[j++] = (phdr->swseq << 2) + phdr->swlun; /*[4]=swseq/lun*/ pdata[j++] = phdr->target_cmd; /*[5]=cmd (pcmd[0])*/ if (sdata > 0) { memcpy(&pdata[j],&pcmd[SZ_CMD_HDR],sdata); /*[6]=data*/ j += sdata; } pdata[j] = cksum(&pdata[cs2],j-cs2); /*cksum2*/ j++; if (phdr->bridge_level > 0) { if (phdr->bridge_level > 1) { pdata[j] = cksum(&pdata[cs4],j-cs4); /*cksum4*/ j++; } pdata[j] = cksum(&pdata[cs3],j-cs3); /*cksum3*/ j++; } if (fdebuglan && (msglen != j)) fprintf(fpdbg,"warning: msglen(%d)!=j(%d), hlen=%d clen=%d\n", msglen,j,hlen,clen); if (fdoauth) { psessid = (uchar *)&phdr->sess_id; do_hash(phdr->password, psessid, &cbuf[hlen],msglen, phdr->seq_num, phdr->auth_type, iauth); /* copy hashed authcode to header */ memcpy(phdr->auth_code,iauth,16); } memcpy(&cbuf[0], phdr, hlen); /* copy header to buffer */ } /*end-else normal IPMI */ if (fdoauth == 0 && phdr->auth_type != IPMI_SESSION_AUTHTYPE_NONE) { /* force the packet auth type to NONE (0) */ IPMI_HDR *pchdr; pchdr = (IPMI_HDR *)&cbuf[0]; pchdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; // memset(phdr->auth_code,0,16); } cbuf[hlen-1] = (uchar)msglen; /* IPMI Message Length = 7 + data */ if (fdebuglan > 2) { if ((phdr->target_cmd == SOL_DATA) && (phdr->target_netfn == NETFN_SOL) ) { // phdr->sess_id = sess_id_sav; /*restore sess_id*/ if (fdebuglan) fprintf(fpdbg,"sending lan sol data (len=%d)\n",clen); } else { if (fdebuglan) fprintf(fpdbg,"sending ipmi lan data (len=%d)\n",clen); } } flags = 0; rlen = 0; if ((fdebuglan > 2) && (phdr->target_cmd == CMD_GET_CHAN_AUTH_CAP) && (phdr->target_netfn == NETFN_APP) ) dbg_dump("get_chan_auth_cap command",cbuf,clen,1); memset(rbuf,0,sizeof(rbuf)); fsentok = 0; for (itry = 0; (itry < ipmi_try) && (rlen == 0); itry++) { if (fdebuglan > 2) dbglog("ipmilan_cmd(seq=%x) fsentok=%d itry=%d\n", phdr->seq_num, fsentok, itry); if (fsentok == 0) { if (fdebuglan) fprintf(fpdbg,"ipmilan_sendto(seq=%x,clen=%d)\n", phdr->seq_num, clen); sz = ipmilan_sendto(s,cbuf,clen,flags,to,tolen); if (sz < 1) { lasterr = get_LastError(); if (fdebuglan) show_LastError("ipmilan_sendto",lasterr); rv = LAN_ERR_SEND_FAIL; os_usleep(0,5000); continue; /* retry */ } fsentok = 1; /*sent ok, no need to resend*/ } /* receive the response */ rv = fd_wait(s, ipmi_timeout,0); if (rv != 0) { if (fdebuglan) fprintf(fpdbg,"ipmilan_cmd timeout, after request, seq=%x itry=%d\n", phdr->seq_num, itry); rv = LAN_ERR_RECV_FAIL; if (fdopoke2) ipmilan_poke2(s, to, tolen); os_usleep(0,5000); continue; /* retry */ } flags = RECV_MSG_FLAGS; rlen = ipmilan_recvfrom(s,rbuf,sizeof(rbuf),flags,to,&tolen); if (rlen < 0) { lasterr = get_LastError(); if (fdebuglan) { fprintf(fpdbg,"ipmilan_recvfrom rlen=%d, err=%d iseq=%x itry=%d\n", rlen,lasterr,phdr->iseq_num,itry); show_LastError("ipmilan_recvfrom",lasterr); } rv = rlen; /* -3 = LAN_ERR_RECV_FAIL */ rlen = 0; *sresp = rlen; /* Sometimes the OS sends an ECONNREFUSED error, but * retrying will catch the BMC's reply packet. */ if (lasterr == econnrefused) continue; /*try again*/ else if (lasterr == econnreset) continue; /*try again*/ else break; /* goto EXIT; */ } else { /* successful receive */ net2h(&phdr->iseq_num,&rbuf[5],4); /*incoming seq_num from hdr*/ if (fdebuglan) { fprintf(fpdbg,"ipmilan_recvfrom rlen=%d, iseq=%x\n", rlen,phdr->iseq_num); if (fdebuglan > 2) dbg_dump("ipmilan_recvfrom", rbuf,rlen,1); } /* incoming auth_code may differ from request auth code, (Dell 1855)*/ if (rbuf[4] == IPMI_SESSION_AUTHTYPE_NONE) { /* if AUTH_NONE */ phdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; hlen = RQ_HDR_LEN - 16; /*RMCP header + 10*/ } else { hlen = RQ_HDR_LEN; /*RMCP header + 26 */ // memcpy(phdr->iauth_code,&rbuf[13],16); /*iauthcode*/ } i = hlen + 6; if (rlen <= i) rv = LAN_ERR_TOO_SHORT; else { /* successful */ n = rlen - i - 1; if (bridgePossible && (phdr->target_addr != bmc_sa)) { if (phdr->bridge_level && ((rbuf[hlen+1] >> 2) == (NETFN_APP + 1)) && /*0x07*/ rbuf[hlen+5] == CMD_SEND_MESSAGE) /*0x34*/ { phdr->bridge_level--; if (n <= 1) { /* no data, wait for next */ if (fdebuglan) fprintf(fpdbg,"bridged response empty, cc=%x\n",rbuf[i]); if (rbuf[i] == 0) { /* if sendmsg cc==0, recv again*/ rlen = 0; continue; } /*else done*/ } else { /* has data, copy it*/ //if (fdebuglan) fprintf(fpdbg,"bridged response, n=%d\n",n); // memmove(&rbuf[i-7],&rbuf[i],n); phdr->swseq = rbuf[i-3] >> 2; /*needed?*/ rbuf[i-8] -= 8; n -= 8; i -= 7; if (fdebuglan) dump_buf("bridged response",&rbuf[i],n,1); continue; /*recv again*/ } } } /*endif bridge*/ if (n > *sresp) n = *sresp; memcpy(presp,&rbuf[i],n); *sresp = n; rv = 0; } } /*end else success*/ } /*end for loop*/ // EXIT: #ifdef NOT /* do not increment sequence numbers for SEND_MESSAGE command */ if ((phdr->target_cmd == IPMB_SEND_MESSAGE) && (phdr->target_netfn == NETFN_APP) ) pconn->finsession = 0; #endif if (pconn->finsession) { /* increment seqnum - even if error */ phdr->seq_num = inc_seq_num( phdr->seq_num ); if (rlen > 0) pconn->in_seq = phdr->iseq_num; else pconn->in_seq = inc_seq_num(pconn->in_seq); phdr->swseq = (uchar)inc_seq_num(phdr->swseq); } return(rv); } /*end _send_lan_cmd*/ static char *auth_type_str(int authcode) { char *pstr; switch(authcode) { case IPMI_SESSION_AUTHTYPE_MD5: pstr = "MD5"; break; case IPMI_SESSION_AUTHTYPE_MD2: pstr = "MD2"; break; case IPMI_SESSION_AUTHTYPE_PASSWORD: pstr = "PSWD"; break; case IPMI_SESSION_AUTHTYPE_OEM: pstr = "OEM"; break; case IPMI_SESSION_AUTHTYPE_NONE: pstr = "NONE"; break; default: pstr = "Init"; break; /* AUTHTYPE_INIT, etc. */ } return (pstr); } #ifdef NOT_USED static uchar auth_type_mask(int authcode, uchar allowed) { uchar mask; switch(authcode) { case IPMI_SESSION_AUTHTYPE_MD5: mask = IPMI_MASK_AUTHTYPE_MD5; break; case IPMI_SESSION_AUTHTYPE_MD2: mask = IPMI_MASK_AUTHTYPE_MD2; break; case IPMI_SESSION_AUTHTYPE_PASSWORD: mask = IPMI_MASK_AUTHTYPE_PASSWORD; break; case IPMI_SESSION_AUTHTYPE_OEM: mask = IPMI_MASK_AUTHTYPE_OEM; break; case IPMI_SESSION_AUTHTYPE_NONE: mask = IPMI_MASK_AUTHTYPE_NONE; break; default: /* AUTHTYPE_INIT, etc. */ mask = 0; break; } return (mask); } #endif /* * ipmilan_open_session * Performs the various command/response sequence needed to * initiate an IPMI LAN session. */ static int ipmilan_open_session(SockType sfd, struct sockaddr *destaddr, int destaddr_len, uchar auth_type, char *username, char *authcode, int authcode_len, uchar priv_level, uint32 init_out_seqnum, uint32 *session_seqnum, uint32 *session_id) { int rv = 0; uchar ibuf[RQ_LEN_MAX+3]; uchar rbuf[RS_LEN_MAX+4]; uint32 iseqn; uchar ipasswd[16]; uchar iauthtype; uchar iauthcap, imsgauth; int rlen, ilen; IPMI_HDR *phdr; uchar cc; int busy_tries = 0; if (fdebuglan) fprintf(fpdbg,"ipmilan_open_session(%d,%02x,%s,%02x,%x) called\n", sfd,auth_type,username,priv_level,init_out_seqnum); if (sfd == 0 || destaddr == NULL) return LAN_ERR_INVPARAM; phdr = &ipmi_hdr; /* Initialize ipmi_hdr fields */ memset(phdr,0,sizeof(ipmi_hdr)); phdr->rmcp_ver = 0x06; phdr->rmcp_res = 0x00; phdr->rmcp_seq = 0xFF; phdr->rmcp_type = 0x07; phdr->swid = sms_swid; phdr->swseq = 1; phdr->priv_level = priv_level; /* Get Channel Authentication */ phdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; /*use none(0) at first*/ ibuf[0] = 0x0e; /*this channel*/ ibuf[1] = phdr->priv_level; rlen = sizeof(rbuf); if (fdebuglan) fprintf(fpdbg,"GetChanAuth(sock %x, level %x) called\n",sfd,ibuf[1]); rv = _ipmilan_cmd(sfd, destaddr, destaddr_len, CMD_GET_CHAN_AUTH_CAP, NETFN_APP,BMC_LUN,bmc_sa, PUBLIC_BUS, ibuf,2, rbuf,&rlen, fdebuglan); if (rv != 0) { /*retry if error*/ rv = _ipmilan_cmd(sfd, destaddr, destaddr_len, CMD_GET_CHAN_AUTH_CAP, NETFN_APP,BMC_LUN,bmc_sa, PUBLIC_BUS, ibuf,2, rbuf,&rlen, fdebuglan); } cc = rbuf[0]; if (fdebuglan) fprintf(fpdbg,"GetChanAuth rv = %d, cc=%x rbuf: %02x %02x %02x " "%02x %02x %02x %02x\n", rv, rbuf[0],rbuf[1],rbuf[2],rbuf[3], rbuf[4],rbuf[5],rbuf[6],rbuf[7]); if (rv != 0 || cc != 0) goto ERREXIT; /* Check Channel Auth params */ if ((rbuf[2] & 0x80) != 0) { /*have IPMI 2.0 extended capab*/ if ( ((rbuf[4]&0x02) != 0) && ((rbuf[4]&0x01) == 0) ) { if (fdebuglan) fprintf(fpdbg,"GetChanAuth reports only v2 capability\n"); rv = LAN_ERR_V2; /*try v2 instead*/ goto ERREXIT; } else { /* Always switch to IPMI LAN 2.0 if detected. */ /* This avoids errors from Dell & Huawei firmware */ if (fdebuglan) fprintf(fpdbg,"GetChanAuth detected v2, so switch to v2\n"); rv = LAN_ERR_V2; /*use v2 instead*/ goto ERREXIT; } } /* Check authentication support */ imsgauth = rbuf[3]; if ((imsgauth & 0x10) == 0) pconn->fMsgAuth = 1; /*per-message auth*/ else if ((imsgauth & 0x08) == 0) pconn->fMsgAuth = 2; /*user-level auth*/ else pconn->fMsgAuth = 0; /*no auth support*/ iauthcap = rbuf[2] & 0x3f; if (fauth_type_set) { iauthtype = (uchar)lanp.auth_type; // set by user auth_type = iauthtype; } else { iauthtype = AUTHTYPE_INIT; /*initial value, not set*/ } if (auth_type != iauthtype) { /* default of MD5 is preferred, but try what BMC allows */ if (iauthcap & IPMI_MASK_AUTHTYPE_MD5) { iauthtype = IPMI_SESSION_AUTHTYPE_MD5; auth_type = iauthtype; #ifdef MD2OK } else if (iauthcap & IPMI_MASK_AUTHTYPE_MD2) { iauthtype = IPMI_SESSION_AUTHTYPE_MD2; auth_type = iauthtype; if (fdebuglan) fprintf(fpdbg,"auth_type set to MD2 (%02x)\n",iauthtype); #endif } else if (iauthcap & IPMI_MASK_AUTHTYPE_PASSWORD) { iauthtype = IPMI_SESSION_AUTHTYPE_PASSWORD; auth_type = iauthtype; if (fdebuglan) fprintf(fpdbg,"auth_type set to Password (%02x)\n",iauthtype); } else { if (fdebuglan) fprintf(fpdbg, "auth_type set to %02x, using None\n",auth_type); iauthtype = IPMI_SESSION_AUTHTYPE_NONE; auth_type = iauthtype; } } if (fdebuglan) fprintf(fpdbg, "auth_type=%02x(%s) allow=%02x iauthtype=%02x msgAuth=%d(%02x)\n", auth_type,auth_type_str(auth_type),iauthcap,iauthtype, pconn->fMsgAuth,imsgauth); /* get session challenge */ phdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; memset(ibuf,0,17); ibuf[0] = iauthtype; if (username != NULL) strncpy(&ibuf[1],username,16); while (busy_tries < BUSY_MAX) { rlen = sizeof(rbuf); rv = _ipmilan_cmd(sfd, destaddr,destaddr_len, CMD_GET_SESSION_CHALLENGE, NETFN_APP,BMC_LUN,bmc_sa, PUBLIC_BUS, ibuf,17, rbuf,&rlen, fdebuglan); cc = rbuf[0]; if (rv != 0) break; else if (cc == 0xc0) busy_tries++; else break; } if (fdebuglan) { if ((rv == 0) && (cc == 0)) dump_buf("GetSessionChallenge rv=0, rbuf",rbuf,rlen,0); else fprintf(fpdbg,"GetSessionChallenge rv=%d cc=%x rlen=%d tries=%d\n", rv, cc, rlen,busy_tries); } if (rv != 0) goto ERREXIT; else if (cc != 0) { cc_challenge(cc); goto ERREXIT; } /* save challenge response data */ memcpy(&phdr->sess_id, &rbuf[1], 4); memcpy(phdr->challenge, &rbuf[5], 16); /* Save authtype/authcode in ipmi_hdr for later use in _send_lan_cmd. */ phdr->bmc_addr = bmc_sa; phdr->auth_type = iauthtype; if (authcode_len > 16 || authcode_len < 0) authcode_len = 16; memset(&ipasswd,0,16); if (authcode != NULL && authcode_len > 0) memcpy(&ipasswd,(uchar *)authcode,authcode_len); /* AuthCode=passwd */ memcpy(phdr->password,&ipasswd,16); /* save password */ /* ActivateSession request */ ibuf[0] = phdr->auth_type; ibuf[1] = phdr->priv_level; if (vend_id == VENDOR_SUPERMICRO) { /* if supermicro, do special auth logic here */ hash_special(phdr->password, phdr->challenge, ipasswd); memcpy(phdr->password,ipasswd,16); memset(&ibuf[2],0,16); /*zero challenge string here*/ if (fdebuglan) printf("Using supermicro OEM challenge\n"); } else { memcpy(&ibuf[2],phdr->challenge,16); /*copy challenge string to data*/ } phdr->seq_num = 0; iseqn = init_out_seqnum; h2net(iseqn,&ibuf[18],4); /* write iseqn to buffer */ ilen = 22; if (fdebuglan) dump_buf("ActivateSession req",ibuf,ilen,0); rlen = sizeof(rbuf); rv = _ipmilan_cmd(sfd,destaddr,destaddr_len,CMD_ACTIVATE_SESSION, NETFN_APP,BMC_LUN,bmc_sa, PUBLIC_BUS, ibuf, ilen, rbuf, &rlen, fdebuglan); cc = rbuf[0]; if (fdebuglan) { if (rv > 0) fprintf(fpdbg,"ActivateSession rv = 0x%02x\n",rv); /*cc*/ else fprintf(fpdbg,"ActivateSession rv = %d\n",rv); } if (rv != 0) goto ERREXIT; else if (cc != 0) { cc_session(cc); goto ERREXIT; } if (pconn->fMsgAuth == 2) /*user-level auth*/ phdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; memcpy(&phdr->sess_id,&rbuf[2],4); /* save new session id */ net2h(&iseqn, &rbuf[6],4); /* save returned out_seq_num */ if (iseqn == 0) iseqn = inc_seq_num(iseqn); /* was ++iseqn */ phdr->seq_num = iseqn; /* new session seqn */ if (fdebuglan) fprintf(fpdbg,"sess_id=%x seq_num=%x priv_allow=%x priv_req=%x\n", phdr->sess_id,phdr->seq_num,rbuf[10],phdr->priv_level); /* set session privileges (set_session_privilege_level) */ ibuf[0] = phdr->priv_level; rlen = sizeof(rbuf); rv = _ipmilan_cmd(sfd, destaddr, destaddr_len, CMD_SET_SESSION_PRIV, NETFN_APP,BMC_LUN,bmc_sa, PUBLIC_BUS, ibuf,1, rbuf,&rlen, fdebuglan); cc = rbuf[0]; if (fdebuglan) fprintf(fpdbg,"SetSessionPriv(%x) rv = %d\n",ibuf[0], rv); bridgePossible = 1; *session_id = phdr->sess_id; *session_seqnum = phdr->seq_num; ERREXIT: if (rv == 0 && cc != 0) rv = cc; return(rv); } /*end ipmilan_open_session*/ /* * ipmilan_close_session */ static int ipmilan_close_session(SockType sfd, struct sockaddr *destaddr, int destaddr_len, uint32 session_id) { uchar ibuf[RQ_LEN_MAX+3]; uchar rbuf[RS_LEN_MAX+4]; int rlen; int rv = 0; if (session_id == 0) return(0); /* send close session command */ memcpy(ibuf,&session_id,4); rlen = sizeof(rbuf); bridgePossible = 0; rv = _ipmilan_cmd(sfd, destaddr, destaddr_len, CMD_CLOSE_SESSION, NETFN_APP,BMC_LUN,bmc_sa,PUBLIC_BUS, ibuf,4, rbuf,&rlen, fdebuglan); if (fdebuglan) fprintf(fpdbg,"CloseSession rv = %d, cc = %02x\n", rv, rbuf[0]); if (rbuf[0] != 0) rv = rbuf[0]; /*comp code*/ if (rv == 0) pconn->session_id = 0; ipmi_hdr.seq_num = 0; ipmi_hdr.swseq = 1; ipmi_hdr.iseq_num = 0; ipmi_hdr.sess_id = 0; pconn->finsession = 0; return(rv); } int rmcp_ping(SockType sfd, struct sockaddr *saddr, int saddr_len, int foutput) { /* The ASF spec says to use network byte order */ uchar asf_pkt[40] = {06,0,0xFF,06,0x00,0x00,0x11,0xBE,0x80,0,0,0 }; struct sockaddr from_addr; int from_len; int rv; int iana; /* Send RMCP ASF ping to verify IPMI LAN connection. */ asf_pkt[9] = 1; /*tag*/ rv = ipmilan_sendto(sfd, asf_pkt, 12, 0, saddr, saddr_len); if (foutput) fprintf(fpdbg,"ipmilan ping, sendto len=%d\n",rv); if (rv < 0) return(LAN_ERR_PING); pconn->connect_state = CONN_STATE_PING; /*ping was sent ok*/ from_len = sizeof(struct sockaddr); rv = fd_wait(sfd,ping_timeout,0); if (rv != 0) { fprintf(fpdbg,"ping timeout, after %s\n", conn_state_str[pconn->connect_state]); rv = LAN_ERR_CONNECT; } else { rv = ipmilan_recvfrom(sfd, asf_pkt, sizeof(asf_pkt), 0, &from_addr,&from_len); if (foutput) { fprintf(fpdbg,"ipmilan pong, recvfrom len=%d\n", rv); if (rv > 0) { iana = asf_pkt[15] + (asf_pkt[14] << 8) + (asf_pkt[13] << 16) + (asf_pkt[12] << 24); dump_buf("ping response",asf_pkt, rv,0); printf("ping IANA = %d (%s)\n",iana,get_iana_str(iana)); } } if (rv < 0) return(LAN_ERR_CONNECT); } return(0); } int ping_bmc(char *node, int fdebugcmd) { SOCKADDR_T toaddr; int toaddr_len; SockType sfd; int rv; rv = open_sockfd(node, RMCP_PRI_RMCP_PORT, &sfd, &toaddr, &toaddr_len, fdebugcmd); if (rv != 0) return(rv); rv = rmcp_ping(sfd, (struct sockaddr *)&toaddr,toaddr_len, fdebugcmd); close_sockfd(sfd); return(rv); } static int get_rand(void *data, int len) { int rv = 0; int fd; #if defined(LINUX) fd = open("/dev/urandom", O_RDONLY); if (fd < 0 || len < 0) return errno; rv = read(fd, data, len); close(fd); #else fd = rand(); if (fd == 0) fd = 1; if (len > sizeof(int)) len = sizeof(int); memcpy(data,&fd,len); #endif return rv; } /* * ipmi_open_lan */ int ipmi_open_lan(char *node, int port, char *user, char *pswd, int fdebugcmd) { char *username; uchar priv_level; int rv = -1; #ifndef HAVE_IPV6 char *temp; #endif #ifndef TEST_LAN fdebuglan = fdebugcmd; if (fdebugcmd) fprintf(fpdbg,"ipmi_open_lan: fdebug = %d\n",fdebugcmd); #endif if (fdebugcmd > 2) fdoping = 1; get_mfgid(&vend_id,&prod_id); if (nodeislocal(node)) { fprintf(fpdbg,"ipmi_open_lan: node %s is local!\n",node); rv = LAN_ERR_INVPARAM; goto EXIT; } else { if (fdebugcmd) fprintf(fpdbg,"Opening lan connection to node %s ...\n",node); /* save nodename for sig_abort later */ if (strlen(node) > SZGNODE) { strncpy(nodename, node, SZGNODE); nodename[SZGNODE] = 0; } else strcpy(nodename, node); rv = open_sockfd(node, port, &(pconn->sockfd), &_destaddr, &_destaddr_len, 1); if (fdebugcmd) printf("open_sockfd returned %d, fd=%d\n", rv, pconn->sockfd); if (rv != 0) goto EXIT; #ifdef HAVE_IPV6 strcpy(gnodename,nodename); if (fdebugcmd) fprintf(fpdbg,"Connecting to node %s\n",gnodename); #else #ifdef WIN32 /* check for ws2_32.lib(getnameinfo) resolution */ gnodename[0] = 0; /* int getnameinfo( const struct sockaddr * sa, socklen_t salen, char * host, DWORD hostlen, char * serv, DWORD servlen, int flags); rv = getnameinfo((SOCKADDR *)&_destaddr, _destaddr_len, gnodename,SZGNODE, NULL,0,0); */ #else rv = getnameinfo((struct sockaddr *)&_destaddr, _destaddr_len, gnodename,SZGNODE, NULL,0,0); #endif if (rv != 0) { if (fdebugcmd) fprintf(fpdbg,"ipmi_open_lan: getnameinfo rv = %d\n",rv); gnodename[0] = 0; } temp = inet_ntoa(_destaddr.sin_addr); fprintf(fpdbg,"Connecting to node %s %s\n",gnodename, temp); strncpy(_dest_ip, temp, INET_ADDRSTRLEN); _dest_ip[INET_ADDRSTRLEN] = 0; #endif #ifndef WIN32 /* Linux: Set up signals to handle errors & timeouts. */ signal(SIGINT,sig_abort); signal(SIGALRM,sig_timeout); #endif pconn->connect_state = CONN_STATE_BIND; if (fdoping) { rv = rmcp_ping(pconn->sockfd,(struct sockaddr *)&_destaddr, _destaddr_len, fdebugcmd); if (fdopoke1 && rv != 0) { /* May sometimes need a poke to free up the BMC (cant hurt) */ ipmilan_poke1(pconn->sockfd,(struct sockaddr *)&_destaddr, _destaddr_len); } if (rv != 0) { if (rv == LAN_ERR_CONNECT && frequireping == 0) { /* keep going even if ping/pong failure */ rv = 0; } else { close_sockfd(pconn->sockfd); rv = LAN_ERR_CONNECT; goto EXIT; } } pconn->connect_state = CONN_STATE_PONG; } { auth_type = (uchar)lanp.auth_type; priv_level = (uchar)lanp.priv; username = user; authcode = pswd; authcode_len = (pswd) ? strlen_(authcode) : 0; if ((vend_id == VENDOR_INTEL) || (vend_id == VENDOR_IBM)) pconn->start_out_seq = 1; else { if (fdebugcmd) printf("calling get_rand(%d)\n", pconn->start_out_seq); get_rand(&pconn->start_out_seq,sizeof(pconn->start_out_seq)); } } rv = ipmilan_open_session(pconn->sockfd, (struct sockaddr *)&_destaddr, _destaddr_len, auth_type, username, authcode, authcode_len,priv_level, pconn->start_out_seq, &pconn->in_seq, &pconn->session_id); if (rv == 0) { /* successful (session active) */ pconn->connect_state = CONN_STATE_ACTIVE; /*set connection state to active*/ } else { /* open_session rv != 0 */ if ((gshutdown==0) || fdebugcmd) { if (rv < 0) fprintf(fpdbg,"ipmilan_open_session error, rv = %d\n",rv); else fprintf(fpdbg,"ipmilan_open_session error, rv = 0x%x\n",rv); } close_sockfd(pconn->sockfd); } } EXIT: if (rv != 0) { // if ((gshutdown==0) || fdebugcmd) printf("ipmilan %s\n",decode_rv(rv)); if (rv == -1 && lasterr != 0) show_LastError("ipmilan",lasterr); } return(rv); } int ipmi_flush_lan(char *node) { int rv = 0; /* could match node via pconn = find_conn(node); */ if (!nodeislocal(node)) { /* ipmilan, need to close & cleanup */ if (pconn->sockfd != 0) close_sockfd(pconn->sockfd); } else { /* kcs cleanup */ #ifndef WIN32 alarm(0); signal(SIGALRM,SIG_DFL); #endif } /* endif */ pconn->connect_state = CONN_STATE_INIT; pconn->finsession = 0; pconn->session_id = 0; pconn->sockfd = 0; pconn->in_seq = 1; pconn->start_out_seq = 1; pconn->fMsgAuth = 1; /*1=PerMsgAuth*/ pconn->auth_type = AUTHTYPE_INIT; return (rv); } int ipmi_close_lan(char *node) { int rv = 0; /* could match node via pconn = find_conn(node); */ if (fdebuglan) fprintf(fpdbg,"ipmi_close_lan(%s) entry, sockfd=%d\n", node,pconn->sockfd); if (!nodeislocal(node)) { /* ipmilan, need to close & cleanup */ if (pconn->sockfd != 0) { /* socket is open */ if (gshutdown) pconn->session_id = 0; if (pconn->session_id != 0) { /* session is open */ // cmd_rs = buf_rs; rv = ipmilan_close_session(pconn->sockfd, (struct sockaddr *)&_destaddr, _destaddr_len, ipmi_hdr.sess_id); /* flush session_id even if error, let it time out */ pconn->session_id = 0; } close_sockfd(pconn->sockfd); pconn->sockfd = 0; } pconn->connect_state = CONN_STATE_INIT; pconn->finsession = 0; } else { /* kcs cleanup */ #ifndef WIN32 alarm(0); signal(SIGALRM,SIG_DFL); #endif } /* endif */ if (fdebuglan) fprintf(fpdbg,"ipmi_close_lan(%s) rv=%d sockfd=%d\n", node,rv,pconn->sockfd); return (rv); } /* * ipmicmd_lan * This is called by ipmi_cmd_lan, all commands come through here. */ int ipmicmd_lan(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { uchar rq_data[RQ_LEN_MAX+3]; uchar cmd_rs[RS_LEN_MAX+4]; uchar cc = 0; int rlen; int rv = -1; #ifndef TEST_LAN fdebuglan = fdebugcmd; #endif /* check sdata/sresp against MAX_ */ if (sdata > RQ_LEN_MAX) { if (fdebugcmd) printf("cmd %x sdata(%d) > RQ_LEN_MAX(%d)\n", cmd,sdata,RQ_LEN_MAX); return(LAN_ERR_BADLENGTH); } if (*sresp > RS_LEN_MAX) { if (fdebugcmd) printf("cmd %x sresp(%d) > RS_LEN_MAX(%d), use less\n", cmd,*sresp,RS_LEN_MAX); /* This is ok, just receive up to the max. */ *sresp = RS_LEN_MAX; } if (pdata == NULL) { pdata = rq_data; sdata = 0; } rlen = *sresp; if (nodeislocal(node)) { /*local, use kcs*/ fprintf(fpdbg,"ipmicmd_lan: node %s is local", node); goto EXIT; } else { /* ipmilan */ if (pconn->sockfd == 0) { /* closed, do re-open */ if (fdebugcmd) fprintf(fpdbg,"sockfd==0, node %s needs re-open\n",node); rv = ipmi_open_lan(lanp.node, lanp.port, lanp.user, lanp.pswd, fdebugcmd); if (rv != 0) goto EXIT; } if (fdebugcmd) { fprintf(fpdbg,"lan_cmd(seq=%x) %02x %02x %02x %02x, (dlen=%d): ", ipmi_hdr.seq_num, cmd,netfn,lun,sa,sdata); dump_buf("cmd data",pdata,sdata,0); } if (fdebuglan > 2) dbglog("calling _ipmilan_cmd(%02x,%02x)\n",cmd,netfn); rlen = sizeof(cmd_rs); rv = _ipmilan_cmd(pconn->sockfd, (struct sockaddr *)&_destaddr, _destaddr_len, cmd, netfn, lun, sa, bus, pdata, sdata, cmd_rs, &rlen, fdebugcmd); } cc = cmd_rs[0]; if (rv == 0 && cc == 0) { /* success */ if (fdebugcmd) { fprintf(fpdbg,"lan_rsp rv=0 cc=0 (rlen=%d): ",rlen); dump_buf("cmd rsp",cmd_rs,rlen,0); } rlen--; if (rlen > *sresp) { /*received data > receive buffer*/ if (fdebugcmd) printf("rlen(%d) > sresp(%d), truncated\n",rlen,*sresp); rlen = *sresp; } memcpy(presp,&cmd_rs[1],rlen); *sresp = rlen; } else { /* error */ if (fdebugcmd) fprintf(fpdbg,"ipmicmd_lan: cmd=%02x rv=%d, cc=%02x, rlen=%d\n", cmd,rv,cc,rlen); presp[0] = 0; /*memset(presp,0,*sresp);*/ *sresp = 0; } EXIT: *pcc = cc; return(rv); } /*end ipmicmd_lan()*/ /* * ipmi_cmd_lan * This is the entry point, called from ipmicmd.c */ int ipmi_cmd_lan(char *node, ushort cmd, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, i; uchar mycmd; for (i = 0; i < NCMDS; i++) { if (ipmi_cmds[i].cmdtyp == cmd) break; } if (i >= NCMDS) { fprintf(fperr, "ipmi_cmd_lan: Unknown command %x\n",cmd); return(-1); } if (cmd >= CMDMASK) mycmd = (uchar)(cmd & CMDMASK); /* unmask it */ else mycmd = (uchar)cmd; if (fdebuglan > 2) dbglog("ipmi_cmd_lan: cmd=%04x, mycmd=%02x\n",cmd,mycmd); rc = ipmicmd_lan(node,mycmd,ipmi_cmds[i].netfn,ipmi_cmds[i].lun, ipmi_cmds[i].sa, ipmi_cmds[i].bus, pdata,sdata,presp,sresp,pcc,fdebugcmd); return (rc); } int ipmi_cmdraw_lan(char *node, uchar cmd, uchar netfn, uchar lun, uchar sa, uchar bus, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc; if (fdebuglan > 2) dbglog("ipmi_cmdraw_lan: cmd=%02x, netfn=%02x\n",cmd,netfn); /* bus is not used for lan */ rc = ipmicmd_lan(node, cmd, netfn, lun, sa, bus, pdata,sdata,presp,sresp,pcc,fdebugcmd); return (rc); } SockType lan_get_fd(void) { return(pconn->sockfd); } /* static SOL v1.5 encryption routines */ static void sol15_cipherinit( uchar SeedCount, char *password, uint32 out_seq) { uchar temp[ 40 ]; /* 16 + 4 + 8 + 4 = 32 bytes */ int i; i = SeedCount & 0x0f; srand((unsigned int)time(NULL)); g_Seed[i] = (int32_t)rand(); if (password == NULL) memset(&temp[0], 0, 16); else memcpy(&temp[0], password,16); /*16-byte password*/ h2net(g_Seed[i],&temp[16],4); /*4-byte seed */ memset(&temp[20], 0, 8 ); /*8-byte pad*/ h2net(out_seq,&temp[28],4); /*4-byte seq num */ md5_sum(temp,32, g_Cipher[i]); } #ifdef NOT_USED static void sol15_encrypt( uchar *dst, uchar *src, int len, uchar SeedCount ) { uchar cipher; unsigned int val; int i; SeedCount &= 0x0f; if ( sol_Encryption ) { for (i = 0; i < len; i++, dst++, src++) { cipher = g_Cipher[ SeedCount ][ (i & 0x0f) ]; val = (*src) << (cipher & 0x07); *dst = (uchar)((val | (val >> 8)) ^ cipher); } } else { memcpy( dst, src, len ); } } static void sol15_decrypt( uchar *dst, uchar *src, int len, uchar SeedCount ) { uchar cipher; unsigned int val; int i; SeedCount &= 0x0f; if ( sol_Encryption ) { for (i = 0; i < len; i++, dst++, src++) { cipher = g_Cipher[ SeedCount ][ (i & 0x0f) ]; val = ((*src) ^ cipher) << 8; val >>= (cipher & 0x07); *dst = (uchar)((val >> 8) | val); } } else { memcpy( dst, src, len ); } } #endif /* * lan_get_sol_data * Called before ACTIVATE_SOL1 command */ void lan_get_sol_data(uchar fEnc, uchar seed_cnt, uint32 *seed) { if (seed_cnt != sol_seed_cnt && (seed_cnt < 16)) sol_seed_cnt = seed_cnt; pconn->start_out_seq = ipmi_hdr.seq_num; sol_snd_seq = (uchar)pconn->start_out_seq; sol15_cipherinit(sol_seed_cnt, lanp.pswd, pconn->start_out_seq); *seed = g_Seed[sol_seed_cnt]; if (fdebuglan > 2) dbglog("lan_get_sol_data: %02x %02x %02x\n", /*SOL*/ fEnc, seed_cnt, ipmi_hdr.seq_num); } /* * lan_set_sol_data * Called after ACTIVATE_SOL1 response received */ void lan_set_sol_data(uchar fenc, uchar auth, uchar seed_cnt, int insize, int outsize) { if (fdebuglan > 2) dbglog("lan_set_sol_data: %02x %02x %02x %02x\n", /*SOL*/ auth,seed_cnt,insize,outsize); if (fenc || (auth & 0x07) == 1) { sol_op = 0x80; /*OEM encryption*/ sol_Encryption = 1; } else { sol_op = 0x00; /*no encryption*/ sol_Encryption = 0; } if (seed_cnt != sol_seed_cnt && (seed_cnt < 16)) { /* if seed count changed, re-init the cipher. */ sol_seed_cnt = seed_cnt; sol15_cipherinit(sol_seed_cnt, lanp.pswd, pconn->start_out_seq); } } /* * lan_send_sol * buffer contains characters entered at console. * build an SOL data frame, which ends up * calling _send_lan_cmd(). * * SOL 1.5 Message Format * 0 : Packet Sequence Number * 1 : Packet ack/nak seq num (recvd) * 2 : Character offset (of recvd) * 3 : Seed count * 4 : Operation/Status */ int lan_send_sol( uchar *buffer, int len, SOL_RSP_PKT *rsp) { int rv = -1; int ilen; uchar idata[IPMI_REQBUF_SIZE]; /*=80 bytes*/ uchar *pdata; int hlen, msglen; int sz; IPMI_HDR *phdr; int fdoauth = 1; uchar iauth[16]; uint32 sess_id_tmp; uchar *psessid; int flags; phdr = &ipmi_hdr; hlen = 4 + 10 + 16; // was SOL_HLEN (14); pdata = &idata[0]; memset(pdata,0,hlen); memcpy(&pdata[0], phdr, 4); /* copy RMCP header to buffer */ if (phdr->auth_type == IPMI_SESSION_AUTHTYPE_NONE) fdoauth = 0; else fdoauth = 1; if (fdoauth == 0 && phdr->auth_type != IPMI_SESSION_AUTHTYPE_NONE) pdata[4] = IPMI_SESSION_AUTHTYPE_NONE; else pdata[4] = phdr->auth_type; memcpy(&pdata[5],&phdr->seq_num,4); /*session sequence number*/ sess_id_tmp = phdr->sess_id | SOL_MSG; memcpy(&pdata[9],&sess_id_tmp,4); /*session id*/ if (fdoauth == 0) hlen -= 16; pdata = &idata[hlen]; if (len == 0) { pdata[0] = 0x00; /*ack for keepalive*/ } else { sol_snd_seq = (uchar)inc_sol_seq(sol_snd_seq); pdata[0] = sol_snd_seq; // sol15_encrypt(&pdata[5],buffer,len, sol_seed_cnt); memcpy(&pdata[5],buffer,len); } pdata[1] = sol_rcv_seq; /* seq to ack*/ pdata[2] = sol_rcv_cnt; /* num bytes ack'd */ pdata[3] = sol_seed_cnt; pdata[4] = 0x00; /*Operation/Status*/ msglen = len + 5; { if (fdebuglan > 2) { /*SOL*/ dbg_dump("lan_send_sol input", buffer,len,1); dbglog("auth_type=%x/%x fdoauth=%d hlen=%d seq_num=%x enc=%d\n", phdr->auth_type,lanp.auth_type,fdoauth,hlen,phdr->seq_num, sol_Encryption); dbg_dump("send_sol buf", pdata,msglen,1); } if (fdoauth) { psessid = (uchar *)&sess_id_tmp; do_hash(phdr->password, psessid, &idata[hlen],msglen, phdr->seq_num, phdr->auth_type, iauth); /* copy hashed authcode to header */ memcpy(&pdata[13],iauth,16); } } idata[hlen-1] = (uchar)msglen; ilen = hlen + msglen; // rlen = sizeof(rdata);; if (fdebuglan > 2) dbg_dump("lan_send_sol sendto",idata,ilen,1); flags = 0; sz = ipmilan_sendto(pconn->sockfd,idata,ilen,flags, (struct sockaddr *)&_destaddr,_destaddr_len); if (fdebuglan) dbglog("lan_send_sol, sent %d bytes\n",sz); if (sz < 1) { lasterr = get_LastError(); if (fdebuglan) show_LastError("lan_send_sol",lasterr); rv = LAN_ERR_SEND_FAIL; os_usleep(0,5000); } else { phdr->seq_num = inc_seq_num( phdr->seq_num ); rv = 0; } if (rsp != NULL) { rsp->len = 0; #ifdef RCV_EXTRA if (rv == 0) { /*send was ok, try to receive*/ rv = lan_recv_sol( rsp ); if (fdebuglan) printf("lan_recv_sol ret = %d, len = %d\n",rv,rsp->len); } #endif } return(rv); } int lan_keepalive( uchar bType ) { int rv = 0; #ifdef KAL_OK if (bType == 2) { /* don't try if no data sent yet */ if (sol_snd_seq == 0) return(rv); /* use lan_send_sol, but with 0 length data */ rv = lan_send_sol(NULL,0,NULL); } else #endif { uchar devrec[16]; rv = ipmi_getdeviceid(devrec,16,0); } return(rv); } int lan_recv_sol( SOL_RSP_PKT *rsp ) { static uchar rsdata[MAX_BUFFER_SIZE]; /*LANplus allows 1024*/ uchar rdata[MAX_BUFFER_SIZE]; int rlen, hlen; IPMI_HDR *phdr; uchar *pdata; int itry; int flags; int rv = -1; phdr = &ipmi_hdr; rsp->data = rsdata; hlen = SOL_HLEN; rlen = 0; if (fdebuglan) printf("lan_recv_sol, fdebug=%d, fpdbg=%p\n",fdebuglan,fpdbg); // for (itry = 0; (itry < ipmi_try) && (rlen == 0); itry++) for (itry = 0; (itry < 1) && (rlen == 0); itry++) { /* receive the response */ rv = fd_wait(pconn->sockfd, ipmi_timeout,0); if (rv != 0) { if (fdebuglan) fprintf(fpdbg,"lan_recv_sol timeout\n"); rv = LAN_ERR_RECV_FAIL; os_usleep(0,5000); continue; /* ok to retry */ } flags = RECV_MSG_FLAGS; rlen = ipmilan_recvfrom(pconn->sockfd,rdata,sizeof(rdata),flags, (struct sockaddr *)&_destaddr,&_destaddr_len); if (rlen < 0) { lasterr = get_LastError(); if (fdebuglan) show_LastError("ipmilan_recvfrom",lasterr); rv = rlen; /* -3 = LAN_ERR_RECV_FAIL */ rlen = 0; rsp->len = rlen; if (lasterr == econnrefused) continue; /*try again*/ else break; /* goto EXIT; */ } else { /* successful receive */ rv = 0; if (fdebuglan) { dump_buf("lan_recv_sol rdata",rdata,rlen,1); /*SOL*/ } if (rdata[4] == IPMI_SESSION_AUTHTYPE_NONE) { /* if AUTH_NONE */ /* may have tried with auth, but denied, Dell 1855 */ phdr->auth_type = IPMI_SESSION_AUTHTYPE_NONE; hlen = SOL_HLEN; } net2h(&phdr->iseq_num,&rdata[5],4); /*incoming seq_num from hdr*/ if (rlen >= hlen) { pdata = &rdata[hlen]; if (fdebuglan) dump_buf("lan_recv_sol rsp",rdata,rlen,1); /*SOL*/ rlen -= hlen; if (rlen >= 5) { /*have some data*/ /* 0=seq, 1=ack, 2=cnt, 3=ctl, 4=rsv */ sol_rcv_seq = pdata[0]; sol_rcv_ctl = pdata[3]; pdata = &rdata[hlen+5]; rlen -= 5; /* rlen should match rdata[hlen-1] */ sol_rcv_cnt = (uchar)rlen; } rsp->type = PAYLOAD_TYPE_SOL; rsp->len = rlen; // sol15_decrypt(rsp->data,pdata,rlen, sol_seed_cnt); memcpy(rsp->data,pdata,rlen); } else { if (fdebuglan) printf("lan_recv_sol rlen %d < %d\n",rlen,hlen); /*fpdbg*/ rsp->type = PAYLOAD_TYPE_SOL; rsp->len = 0; } break; } } /*end for*/ return(rv); } #endif uchar cksum(const uchar *buf, register int len) { register uchar csum; register int i; /* 8-bit 2s compliment checksum */ csum = 0; for (i = 0; i < len; i++) csum = (csum + buf[i]) % 256; csum = -csum; return(csum); } /* * ipmi_cmd_ipmb() * This is an entry point for IPMB indirect commands. * Embed the command withn a SendMessage command. * * The iseq value needs to be the same as ipmi_hdr.swseq if * the session is ipmilan, so this routine was moved here. * However, ipmi_cmd_ipmb will also work ok via ipmi_cmdraw * for local commands. */ int ipmi_cmd_ipmb(uchar cmd, uchar netfn, uchar sa, uchar bus, uchar lun, uchar *pdata, int sdata, uchar *presp, int *sresp, uchar *pcc, char fdebugcmd) { int rc, i, j; uchar idata[IPMI_REQBUF_SIZE]; uchar rdata[MAX_BUFFER_SIZE]; uchar ilen; int rlen; uchar iseq; IPMI_HDR *phdr; char *pstr; uchar fneedclear = 0; uchar cc; if (fdebugcmd) printf("ipmi_cmd_ipmb(%02x,%02x,%02x,%02x,%02x) sdata=%d\n", cmd,netfn,sa,bus,lun,sdata); phdr = &ipmi_hdr; iseq = phdr->swseq; i = 0; idata[i++] = bus; j = i; idata[i++] = sa; /*rsAddr (target)*/ idata[i++] = (netfn << 2) | (lun & 0x03); /*metFm/rsLUN*/ idata[i++] = cksum(&idata[j],2); j = i; idata[i++] = bmc_sa; /* rqAddr (main sa) */ idata[i++] = (iseq << 2) | SMS_LUN; /*rqSeq num, SMS Message LUN = 0x02*/ idata[i++] = cmd; if (sdata > 0) { memcpy(&idata[i],pdata,sdata); i += sdata; } idata[i] = cksum(&idata[j],(i - j)); ilen = ++i; rlen = sizeof(rdata); rc = ipmi_cmdraw(IPMB_SEND_MESSAGE,NETFN_APP, bmc_sa,PUBLIC_BUS,BMC_LUN, idata, ilen, rdata, &rlen, pcc, fdebugcmd); if (rc == 0x83 || *pcc == 0x83) { /*retry*/ rlen = sizeof(rdata); rc = ipmi_cmdraw(IPMB_SEND_MESSAGE,NETFN_APP, bmc_sa,PUBLIC_BUS,BMC_LUN, idata, ilen, rdata, &rlen, pcc, fdebugcmd); } if (fdebugcmd) { if (rc == 0 && *pcc == 0) dump_buf("ipmb sendmsg ok",rdata,rlen,0); else { if (*pcc == 0x80) { pstr = "Invalid session handle"; } else if (*pcc == 0x81) pstr = "Lost Arbitration"; else if (*pcc == 0x82) pstr = "Bus Error"; else if (*pcc == 0x83) pstr = "NAK on Write"; else pstr = ""; fprintf(fpdbg,"ipmb sendmsg error %d, cc %x %s\n",rc,*pcc,pstr); } } if (presp == NULL || sresp == NULL) return(LAN_ERR_INVPARAM); if (rc != 0 || *pcc != 0) { *sresp = 0; return(rc); } if (*sresp < 0) return(LAN_ERR_TOO_SHORT); /* sent ok, now issue a GET_MESSAGE command to get the response. */ for (i = 0; i < 10; i++) { rlen = sizeof(rdata); rc = ipmi_cmdraw(IPMB_GET_MESSAGE,NETFN_APP, bmc_sa,PUBLIC_BUS,BMC_LUN, idata, 0, rdata, &rlen, pcc, fdebugcmd); if (fdebugcmd) printf("ipmb get_message rc=%d cc=%x\n",rc,*pcc); if (rc == 0x80 || *pcc == 0x80) /*empty, so retry*/; else if (rc == 0x83 || *pcc == 0x83) /*busy, so retry*/; else break; /* done w success or error */ #ifdef DOS ; /*short wait*/ #else fd_wait(0,0,10); /* wait 1 msec before retry */ #endif /* will retry up to 10 msec for a get_message response on ipmb */ } if (rc == 0 && *pcc == 0) { if (fdebugcmd) dump_buf("ipmb getmsg ok",rdata,rlen,0); i = 0; if (rlen >= 8) { /* strip out the getmsg header */ *pcc = rdata[6]; rlen -= 8; i = 7; } /* copy the data */ if (rlen > *sresp) rlen = *sresp; memcpy(presp,&rdata[i],rlen); } else { if (*pcc == 0x80) pstr = "buffer empty"; else { fneedclear = 1; pstr = ""; } if (fdebugcmd) fprintf(fpdbg,"ipmb getmsg[%d] error %d, cc %x %s\n",i,rc,*pcc,pstr); if (fneedclear) { /* Clear pending message flags */ idata[0] = 0x03; /* clear EvtMsgBuf & RecvMsgQueue */ rlen = 16; rc = ipmi_cmdraw(IPMB_CLEAR_MSGF, NETFN_APP, bmc_sa, PUBLIC_BUS,BMC_LUN, idata, 1, rdata, &rlen, &cc, fdebugcmd); } rlen = 0; } *sresp = rlen; return(rc); } /* end ipmilan.c */ ipmiutil-3.1.9/util/ipicmg.c0000644000000000000000000015236314144515623014466 0ustar rootroot/* * ipicmg.c * * This module handles PICMG extended IPMI commands. * * Change History: * 06/03/2010 ARCress - new, included in source tree * 08/15/2011 ARCress - updated with PICMG 2.3 * *---------------------------------------------------------------------- * Copyright (c) 2010 Kontron. All right reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Kontron, or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * THE COPYRIGHT HOLDER AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL THE * COPYRIGHT HOLDER OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR * DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. *---------------------------------------------------------------------- */ #ifdef WIN32 #include #include #include #include #include "getopt.h" #else #include #include #include #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include "ipmicmd.h" #include "ipicmg.h" /* Misc PICMG defines */ #define PICMG_EXTENSION_ATCA_MAJOR_VERSION 2 #define PICMG_EXTENSION_AMC0_MAJOR_VERSION 4 #define PICMG_EXTENSION_UTCA_MAJOR_VERSION 5 #define PICMG_EKEY_MODE_QUERY 0 #define PICMG_EKEY_MODE_PRINT_ALL 1 #define PICMG_EKEY_MODE_PRINT_ENABLED 2 #define PICMG_EKEY_MODE_PRINT_DISABLED 3 #define PICMG_EKEY_MAX_CHANNEL 16 #define PICMG_EKEY_MAX_FABRIC_CHANNEL 15 #define PICMG_EKEY_MAX_INTERFACE 3 #define PICMG_EKEY_AMC_MAX_CHANNEL 16 #define PICMG_EKEY_AMC_MAX_DEVICE 15 /* 4 bits */ /* Global data */ #ifdef METACOMMAND extern char * progver; /*from ipmiutil.c*/ static char * progname = "ipmiutil picmg"; #else static char * progver = "3.08"; static char * progname = "ipicmg"; #endif static char fdebug = 0; static char fset_mc = 0; static uint8_t g_bus = PUBLIC_BUS; static uint8_t g_sa = BMC_SA; static uint8_t g_lun = BMC_LUN; static uint8_t g_addrtype = ADDR_SMI; static uint8_t g_fruid = 0; static unsigned char PicmgExtMajorVersion; /* the LED color capabilities */ static const char* led_color_str[] = { //__attribute__((unused)) = { "reserved", "BLUE", "RED", "GREEN", "AMBER", "ORANGE", "WHITE", "reserved" }; static const char* amc_link_type_str[] = { // __attribute__((unused)) = { "RESERVED", "RESERVED1", "PCI EXPRESS", "ADVANCED SWITCHING1", "ADVANCED SWITCHING2", "ETHERNET", "RAPIDIO", "STORAGE", }; static const char* amc_link_type_ext_str[][16]= { // __attribute__((unused)) /* FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED */ { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_RESERVED1 */ { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_PCI_EXPRESS */ { "Gen 1 - NSSC", "Gen 1 - SSC", "Gen 2 - NSSC", "Gen 2 - SSC", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING1 */ { "Gen 1 - NSSC", "Gen 1 - SSC", "Gen 2 - NSSC", "Gen 2 - SSC", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_ADVANCED_SWITCHING2 */ { "Gen 1 - NSSC", "Gen 1 - SSC", "Gen 2 - NSSC", "Gen 2 - SSC", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_ETHERNET */ { "1000BASE-BX (SerDES Gigabit)", "10GBASE-BX410 Gigabit XAUI", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_RAPIDIO */ { "1.25 Gbaud transmission rate", "2.5 Gbaud transmission rate", "3.125 Gbaud transmission rate", "", "", "", "", "", "", "", "", "", "", "", "", "" }, /* FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE */ { "Fibre Channel", "Serial ATA", "Serial Attached SCSI", "", "", "", "", "", "", "", "", "", "", "", "", "" } }; typedef enum picmg_bused_resource_mode { PICMG_BUSED_RESOURCE_SUMMARY, } t_picmg_bused_resource_mode ; typedef enum picmg_card_type { PICMG_CARD_TYPE_CPCI, PICMG_CARD_TYPE_ATCA, PICMG_CARD_TYPE_AMC, PICMG_CARD_TYPE_RESERVED } t_picmg_card_type ; /* This is the version of the PICMG Extenstion */ static t_picmg_card_type PicmgCardType = PICMG_CARD_TYPE_RESERVED; const struct valstr picmg_frucontrol_vals[] = { { 0, "Cold Reset" }, { 1, "Warm Reset" }, { 2, "Graceful Reboot" }, { 3, "Issue Diagnostic Interrupt" }, { 4, "Quiesce" }, { 5, NULL }, }; const struct valstr picmg_clk_family_vals[] = { { 0x00, "Unspecified" }, { 0x01, "SONET/SDH/PDH" }, { 0x02, "Reserved for PCI Express" }, { 0x03, "Reserved" }, /* from 03h to C8h */ { 0xC9, "Vendor defined clock family" }, /* from C9h to FFh */ { 0x00, NULL }, }; const struct oemvalstr picmg_clk_accuracy_vals[] = { { 0x01, 10, "PRS" }, { 0x01, 20, "STU" }, { 0x01, 30, "ST2" }, { 0x01, 40, "TNC" }, { 0x01, 50, "ST3E" }, { 0x01, 60, "ST3" }, { 0x01, 70, "SMC" }, { 0x01, 80, "ST4" }, { 0x01, 90, "DUS" }, { 0x02, 0xE0, "PCI Express Generation 2" }, { 0x02, 0xF0, "PCI Express Generation 1" }, { 0xffffff, 0x00, NULL } }; const struct oemvalstr picmg_clk_resource_vals[] = { { 0x0, 0, "On-Carrier Device 0" }, { 0x0, 1, "On-Carrier Device 1" }, { 0x1, 1, "AMC Site 1 - A1" }, { 0x1, 2, "AMC Site 1 - A2" }, { 0x1, 3, "AMC Site 1 - A3" }, { 0x1, 4, "AMC Site 1 - A4" }, { 0x1, 5, "AMC Site 1 - B1" }, { 0x1, 6, "AMC Site 1 - B2" }, { 0x1, 7, "AMC Site 1 - B3" }, { 0x1, 8, "AMC Site 1 - B4" }, { 0x2, 0, "ATCA Backplane" }, { 0xffffff, 0x00, NULL } }; const struct oemvalstr picmg_clk_id_vals[] = { { 0x0, 0, "Clock 0" }, { 0x0, 1, "Clock 1" }, { 0x0, 2, "Clock 2" }, { 0x0, 3, "Clock 3" }, { 0x0, 4, "Clock 4" }, { 0x0, 5, "Clock 5" }, { 0x0, 6, "Clock 6" }, { 0x0, 7, "Clock 7" }, { 0x0, 8, "Clock 8" }, { 0x0, 9, "Clock 9" }, { 0x0, 10, "Clock 10" }, { 0x0, 11, "Clock 11" }, { 0x0, 12, "Clock 12" }, { 0x0, 13, "Clock 13" }, { 0x0, 14, "Clock 14" }, { 0x0, 15, "Clock 15" }, { 0x1, 1, "TCLKA" }, { 0x1, 2, "TCLKB" }, { 0x1, 3, "TCLKC" }, { 0x1, 4, "TCLKD" }, { 0x1, 5, "FLCKA" }, { 0x2, 1, "CLK1A" }, { 0x2, 2, "CLK1A" }, { 0x2, 3, "CLK1A" }, { 0x2, 4, "CLK1A" }, { 0x2, 5, "CLK1A" }, { 0x2, 6, "CLK1A" }, { 0x2, 7, "CLK1A" }, { 0x2, 8, "CLK1A" }, { 0x2, 9, "CLK1A" }, { 0xffffff, 0x00, NULL } }; const struct valstr picmg_busres_id_vals[] = { { 0x0, "Metallic Test Bus pair #1" }, { 0x1, "Metallic Test Bus pair #2" }, { 0x2, "Synch clock group 1 (CLK1)" }, { 0x3, "Synch clock group 2 (CLK2)" }, { 0x4, "Synch clock group 3 (CLK3)" }, { 0x5, NULL } }; const struct valstr picmg_busres_board_cmd_vals[] = { { 0x0, "Query" }, { 0x1, "Release" }, { 0x2, "Force" }, { 0x3, "Bus Free" }, { 0x4, NULL } }; const struct valstr picmg_busres_shmc_cmd_vals[] = { { 0x0, "Request" }, { 0x1, "Relinquish" }, { 0x2, "Notify" }, { 0x3, NULL } }; const struct oemvalstr picmg_busres_board_status_vals[] = { { 0x0, 0x0, "In control" }, { 0x0, 0x1, "No control" }, { 0x1, 0x0, "Ack" }, { 0x1, 0x1, "Refused" }, { 0x1, 0x2, "No control" }, { 0x2, 0x0, "Ack" }, { 0x2, 0x1, "No control" }, { 0x3, 0x0, "Accept" }, { 0x3, 0x1, "Not Needed" }, { 0xffffff, 0x00, NULL } }; const struct oemvalstr picmg_busres_shmc_status_vals[] = { { 0x0, 0x0, "Grant" }, { 0x0, 0x1, "Busy" }, { 0x0, 0x2, "Defer" }, { 0x0, 0x3, "Deny" }, { 0x1, 0x0, "Ack" }, { 0x1, 0x1, "Error" }, { 0x2, 0x0, "Ack" }, { 0x2, 0x1, "Error" }, { 0x2, 0x2, "Deny" }, { 0xffffff, 0x00, NULL } }; void ipmi_picmg_help (void) { printf(" properties - get PICMG properties\n"); printf(" frucontrol - FRU control\n"); printf(" addrinfo - get address information\n"); printf(" activate - activate a FRU\n"); printf(" deactivate - deactivate a FRU\n"); printf(" policy get - get the FRU activation policy\n"); printf(" policy set - set the FRU activation policy\n"); printf(" portstate get - get port state \n"); printf(" portstate getdenied - get all denied[disabled] port description\n"); printf(" portstate getgranted - get all granted[enabled] port description\n"); printf(" portstate getall - get all port state description\n"); printf(" portstate set - set port state \n"); printf(" amcportstate get - get port state \n"); printf(" amcportstate set - set port state \n"); printf(" led prop - get led properties\n"); printf(" led cap - get led color capabilities\n"); printf(" led get - get led state\n"); printf(" led set - set led state\n"); printf(" power get - get power level info\n"); printf(" power set - set power level\n"); printf(" clk get - get clk state\n"); printf(" clk getdenied - get all(up to 16) denied[disabled] clock descriptions\n"); printf(" clk getgranted - get all(up to 16) granted[enabled] clock descriptions\n"); printf(" clk getall - get all(up to 16) clock descriptions\n"); printf(" clk set - set clk state\n"); printf(" busres summary - display brief bused resource status info \n"); } struct sAmcAddrMap { unsigned char ipmbLAddr; char* amcBayId; unsigned char siteNum; } amcAddrMap[] = { {0xFF, "reserved", 0}, {0x72, "A1" , 1}, {0x74, "A2" , 2}, {0x76, "A3" , 3}, {0x78, "A4" , 4}, {0x7A, "B1" , 5}, {0x7C, "B2" , 6}, {0x7E, "B3" , 7}, {0x80, "B4" , 8}, {0x82, "reserved", 0}, {0x84, "reserved", 0}, {0x86, "reserved", 0}, {0x88, "reserved", 0}, }; int ipmi_picmg_getaddr(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[5]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_ADDRESS_INFO_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0; /* picmg identifier */ msg_data[1] = 0; /* default fru id */ if(argc > 0) { msg_data[1] = (uint8_t)strtoul(argv[0], NULL,0); /* FRU ID */ } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error getting address information CC: 0x%02x\n", rv); return rv; } printf("Hardware Address : 0x%02x\n", rsp[1]); printf("IPMB-0 Address : 0x%02x\n", rsp[2]); printf("FRU ID : 0x%02x\n", rsp[4]); printf("Site ID : 0x%02x\n", rsp[5]); printf("Site Type : "); switch (rsp[6]) { case PICMG_ATCA_BOARD: printf("ATCA board\n"); break; case PICMG_POWER_ENTRY: printf("Power Entry Module\n"); break; case PICMG_SHELF_FRU: printf("Shelf FRU\n"); break; case PICMG_DEDICATED_SHMC: printf("Dedicated Shelf Manager\n"); break; case PICMG_FAN_TRAY: printf("Fan Tray\n"); break; case PICMG_FAN_FILTER_TRAY: printf("Fan Filter Tray\n"); break; case PICMG_ALARM: printf("Alarm module\n"); break; case PICMG_AMC: printf("AMC"); printf(" -> IPMB-L Address: 0x%02x\n", amcAddrMap[rsp[5]].ipmbLAddr); break; case PICMG_PMC: printf("PMC\n"); break; case PICMG_RTM: printf("RTM\n"); break; default: if (rsp[6] >= 0xc0 && rsp[6] <= 0xcf) { printf("OEM\n"); } else { printf("unknown\n"); } } return 0; } int ipmi_picmg_properties(void * intf, int show ) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; unsigned char PicmgExtMajorVersion; struct ipmi_rq req; unsigned char msg_data; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD; req.msg.data = &msg_data; req.msg.data_len = 1; msg_data = 0; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error %d getting picmg properties\n", rv); return rv; } if( show ) { printf("PICMG identifier : 0x%02x\n", rsp[0]); printf("PICMG Ext. Version : %i.%i\n", rsp[1]&0x0f, (rsp[1]&0xf0) >> 4); printf("Max FRU Device ID : 0x%02x\n", rsp[2]); printf("FRU Device ID : 0x%02x\n", rsp[3]); } /* We cache the major extension version ... to know how to format some commands */ PicmgExtMajorVersion = rsp[1]&0x0f; if( PicmgExtMajorVersion == PICMG_CPCI_MAJOR_VERSION ) { PicmgCardType = PICMG_CARD_TYPE_CPCI; } else if( PicmgExtMajorVersion == PICMG_ATCA_MAJOR_VERSION) { PicmgCardType = PICMG_CARD_TYPE_ATCA; } else if( PicmgExtMajorVersion == PICMG_AMC_MAJOR_VERSION) { PicmgCardType = PICMG_CARD_TYPE_AMC; } return 0; } #define PICMG_FRU_DEACTIVATE (unsigned char) 0x00 #define PICMG_FRU_ACTIVATE (unsigned char) 0x01 int ipmi_picmg_fru_activation(void * intf, int argc, char ** argv, unsigned char state) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; struct picmg_set_fru_activation_cmd cmd; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_FRU_ACTIVATION_CMD; req.msg.data = (unsigned char*) &cmd; req.msg.data_len = 3; cmd.picmg_id = 0; /* PICMG identifier */ cmd.fru_id = atob(argv[0]); /* FRU ID */ cmd.fru_state = state; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { printf("Error %d on activation/deactivation of FRU\n",rv); return rv; } if (rsp[0] != 0x00) { printf("Error, invalid response\n"); } return 0; } int ipmi_picmg_fru_activation_policy_get(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_FRU_POLICY_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf(" %s\n", ((rsp[1] & 0x01) == 0x01) ? "activation locked" : "activation not locked"); printf(" %s\n", ((rsp[1] & 0x02) == 0x02) ? "deactivation locked" : "deactivation not locked"); return 0; } int ipmi_picmg_fru_activation_policy_set(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_FRU_POLICY_CMD; req.msg.data = msg_data; req.msg.data_len = 4; msg_data[0] = 0; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU ID */ msg_data[2] = atob(argv[1])& 0x03; /* FRU act policy mask */ msg_data[3] = atob(argv[2])& 0x03; /* FRU act policy set bits */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } #define PICMG_MAX_LINK_PER_CHANNEL 4 int ipmi_picmg_portstate_get(void * intf, int interfc, uchar channel, int mode) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; struct fru_picmgext_link_desc* d; /* descriptor pointer for rec. data */ memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_PORT_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (interfc & 0x3)<<6; /* interface */ msg_data[1] |= (channel & 0x3F); /* channel number */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else if( mode == PICMG_EKEY_MODE_QUERY ) printf("returned Completion Code 0x%02x\n", rv); return rv; } if (rsp_len >= 6) { int index; /* add support for more than one link per channel */ for(index=0;index (1+ (index*5))){ d = (struct fru_picmgext_link_desc *) &(rsp[1 + (index*5)]); if ( mode == PICMG_EKEY_MODE_PRINT_ALL || mode == PICMG_EKEY_MODE_QUERY || ( mode == PICMG_EKEY_MODE_PRINT_ENABLED && rsp[5 + (index*5) ] == 0x01 ) || ( mode == PICMG_EKEY_MODE_PRINT_DISABLED && rsp[5 + (index*5) ] == 0x00 ) ) { printf(" Link Grouping ID: 0x%02x\n", d->grouping); printf(" Link Type Extension: 0x%02x\n", d->ext); printf(" Link Type: 0x%02x ", d->type); if (d->type == 0 || d->type == 0xff) { printf("Reserved %d\n",d->type); } else if (d->type >= 0x06 && d->type <= 0xef) { printf("Reserved %d\n",d->type); } else if (d->type >= 0xf0 && d->type <= 0xfe) { printf("OEM GUID Definition %d\n",d->type); } else { switch (d->type) { case FRU_PICMGEXT_LINK_TYPE_BASE: printf("PICMG 3.0 Base Interface 10/100/1000\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET: printf("PICMG 3.1 Ethernet Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND: printf("PICMG 3.2 Infiniband Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR: printf("PICMG 3.3 Star Fabric Interface\n"); break; case FRU_PICMGEXT_LINK_TYPE_PCIE: printf("PCI Express Fabric Interface\n"); break; default: printf("Invalid\n"); break; } } printf(" Link Designator: \n"); printf(" Port Flag: 0x%02x\n", d->desig_port); printf(" Interface: 0x%02x - ", d->desig_if); switch (d->desig_if) { case FRU_PICMGEXT_DESIGN_IF_BASE: printf("Base Interface\n"); break; case FRU_PICMGEXT_DESIGN_IF_FABRIC: printf("Fabric Interface\n"); break; case FRU_PICMGEXT_DESIGN_IF_UPDATE_CHANNEL: printf("Update Channel\n"); break; case FRU_PICMGEXT_DESIGN_IF_RESERVED: printf("Reserved\n"); break; default: printf("Invalid"); break; } printf(" Channel Number: 0x%02x\n", d->desig_channel); printf(" STATE: %s\n", ( rsp[5 +(index*5)] == 0x01) ?"enabled":"disabled"); printf("\n"); } } } } else { printf("Unexpected answer len %d, can't print result\n",rsp_len); } return 0; } int ipmi_picmg_portstate_set(void * intf, int interfc, uchar channel, uchar port, int type, int typeext, int group, int enable) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; // struct fru_picmgext_link_desc* d; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_PORT_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 6; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (channel & 0x3f) | ((interfc & 3) << 6); msg_data[2] = (port & 0xf) | ((type & 0xf) << 4); msg_data[3] = ((type >> 4) & 0xf) | ((typeext & 0xf) << 4); msg_data[4] = group & 0xff; msg_data[5] = (unsigned char) (enable & 0x01); /* en/dis */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } /* AMC.0 commands */ #define PICMG_AMC_MAX_LINK_PER_CHANNEL 4 int ipmi_picmg_amc_portstate_get(void * intf,int device,uchar channel, int mode) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[4]; struct fru_picmgext_amc_link_info* d; /* descriptor pointer for rec. data */ memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_GET_PORT_STATE_CMD; req.msg.data = msg_data; /* FIXME : add check for AMC or carrier device */ if(device == -1 || PicmgCardType != PICMG_CARD_TYPE_ATCA ){ req.msg.data_len = 2; /* for amc only channel */ }else{ req.msg.data_len = 3; /* for carrier channel and device */ } msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = channel ; msg_data[2] = (uchar)device ; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else if ( mode == PICMG_EKEY_MODE_QUERY ) printf("returned Completion Code 0x%02x\n", rv); return rv; } if (rsp_len >= 5) { int index; /* add support for more than one link per channel */ for(index=0;index (1+ (index*4))){ unsigned char type; unsigned char ext; unsigned char grouping; unsigned char port; unsigned char enabled; d = (struct fru_picmgext_amc_link_info *)&(rsp[1 + (index*4)]); /* Removed endianness check here, probably not required as we dont use bitfields */ port = d->linkInfo[0] & 0x0F; type = ((d->linkInfo[0] & 0xF0) >> 4 )|(d->linkInfo[1] & 0x0F ); ext = ((d->linkInfo[1] & 0xF0) >> 4 ); grouping = d->linkInfo[2]; enabled = rsp[4 + (index*4) ]; if ( mode == PICMG_EKEY_MODE_PRINT_ALL || mode == PICMG_EKEY_MODE_QUERY || ( mode == PICMG_EKEY_MODE_PRINT_ENABLED && enabled == 0x01 ) || ( mode == PICMG_EKEY_MODE_PRINT_DISABLED && enabled == 0x00 ) ) { if(device == -1 || PicmgCardType != PICMG_CARD_TYPE_ATCA ){ printf(" Link device : AMC\n"); }else{ printf(" Link device : 0x%02x\n", device ); } printf(" Link Grouping ID: 0x%02x\n", grouping); if (type == 0 || type == 1 ||type == 0xff) { printf(" Link Type Extension: 0x%02x\n", ext); printf(" Link Type: Reserved\n"); } else if (type >= 0xf0 && type <= 0xfe) { printf(" Link Type Extension: 0x%02x\n", ext); printf(" Link Type: OEM GUID Definition\n"); } else { if (type <= FRU_PICMGEXT_AMC_LINK_TYPE_STORAGE ) { printf(" Link Type Extension: %s\n", amc_link_type_ext_str[type][ext]); printf(" Link Type: %s\n", amc_link_type_str[type]); } else{ printf(" Link Type Extension: 0x%02x\n", ext); printf(" Link Type: undefined\n"); } } printf(" Link Designator: \n"); printf(" Channel Number: 0x%02x\n", channel); printf(" Port Flag: 0x%02x\n", port ); printf(" STATE: %s\n", ( enabled == 0x01 )?"enabled":"disabled"); printf("\n"); } } } } else { printf("ipmi_picmg_amc_portstate_get: " "Unexpected answer, can't print result\n"); } return 0; } int ipmi_picmg_amc_portstate_set(void * intf, uchar channel, uchar port, int type, int typeext, int group, int enable, int device) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[7]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_SET_PORT_STATE_CMD; req.msg.data = msg_data; msg_data[0] = 0x00; /* PICMG identifier*/ msg_data[1] = channel; /* channel id */ msg_data[2] = port & 0xF; /* port flags */ msg_data[2] |= (type & 0x0F)<<4; /* type */ msg_data[3] = (type & 0xF0)>>4; /* type */ msg_data[3] |= (typeext & 0x0F)<<4; /* extension */ msg_data[4] = (group & 0xFF); /* group */ msg_data[5] = (enable & 0x01); /* state */ req.msg.data_len = 6; /* device id - only for carrier needed */ if (device >= 0) { msg_data[6] = (uchar)device; req.msg.data_len = 7; } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } int ipmi_picmg_get_led_properties(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_FRU_LED_PROPERTIES_CMD; req.msg.data = msg_data; req.msg.data_len = 2; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("General Status LED Properties: 0x%2x\n\r", rsp[1] ); printf("App. Specific LED Count: 0x%2x\n\r", rsp[2] ); return 0; } int ipmi_picmg_get_led_capabilities(void * intf, int argc, char ** argv) { int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_LED_COLOR_CAPABILITIES_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* LED-ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("LED Color Capabilities: %02x", rsp[1] ); for ( i=0 ; i<8 ; i++ ) { if ( rsp[1] & (0x01 << i) ) { printf("%s, ", led_color_str[ i ]); } } printf("\n\r"); printf("Default LED Color in\n\r"); printf(" LOCAL control: %s\n\r", led_color_str[ rsp[2] ] ); printf(" OVERRIDE state: %s\n\r", led_color_str[ rsp[3] ] ); return 0; } int ipmi_picmg_get_led_state(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_FRU_LED_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* LED-ID */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("LED states: %x ", rsp[1] ); if (rsp[1] == 0x1) printf("[LOCAL CONTROL]\n\r"); else if (rsp[1] == 0x2) printf("[OVERRIDE]\n\r"); else if (rsp[1] == 0x4) printf("[LAMPTEST]\n\r"); else printf("\n\r"); printf(" Local Control function: %x ", rsp[2] ); if (rsp[2] == 0x0) printf("[OFF]\n\r"); else if (rsp[2] == 0xff) printf("[ON]\n\r"); else printf("[BLINKING]\n\r"); printf(" Local Control On-Duration: %x\n\r", rsp[3] ); printf(" Local Control Color: %x [%s]\n\r", rsp[4], led_color_str[ rsp[4] ]); /* override state or lamp test */ if (rsp[1] == 0x02) { printf(" Override function: %x ", rsp[5] ); if (rsp[2] == 0x0) printf("[OFF]\n\r"); else if (rsp[2] == 0xff) printf("[ON]\n\r"); else printf("[BLINKING]\n\r"); printf(" Override On-Duration: %x\n\r", rsp[6] ); printf(" Override Color: %x [%s]\n\r", rsp[7], led_color_str[ rsp[7] ]); }else if (rsp[1] == 0x06) { printf(" Override function: %x ", rsp[5] ); if (rsp[2] == 0x0) printf("[OFF]\n\r"); else if (rsp[2] == 0xff) printf("[ON]\n\r"); else printf("[BLINKING]\n\r"); printf(" Override On-Duration: %x\n\r", rsp[6] ); printf(" Override Color: %x [%s]\n\r", rsp[7], led_color_str[ rsp[7] ]); printf(" Lamp test duration: %x\n\r", rsp[8] ); } return 0; } int ipmi_picmg_set_led_state(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_FRU_LED_STATE_CMD; req.msg.data = msg_data; req.msg.data_len = 6; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* LED-ID */ msg_data[3] = atob(argv[2]); /* LED function */ msg_data[4] = atob(argv[3]); /* LED on duration */ msg_data[5] = atob(argv[4]); /* LED color */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } int ipmi_picmg_get_power_level(void * intf, int argc, char ** argv) { int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_GET_POWER_LEVEL_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* Power type */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } printf("Dynamic Power Configuration: %s\n", (rsp[1]&0x80)==0x80?"enabled":"disabled" ); printf("Actual Power Level: %i\n", (rsp[1] & 0xf)); printf("Delay to stable Power: %i\n", rsp[2]); printf("Power Multiplier: %i\n", rsp[3]); for ( i = 1; i+3 < rsp_len ; i++ ) { printf(" Power Draw %i: %i\n", i, (rsp[i+3]) * rsp[3] / 10); } return 0; } int ipmi_picmg_set_power_level(void * intf, int argc, char ** argv) { // int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_SET_POWER_LEVEL_CMD; req.msg.data = msg_data; req.msg.data_len = 4; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* power level */ msg_data[3] = atob(argv[2]); /* present to desired */ rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } int ipmi_picmg_bused_resource(void * intf, t_picmg_bused_resource_mode mode) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); switch ( mode ) { case PICMG_BUSED_RESOURCE_SUMMARY: { t_picmg_busres_resource_id resource; t_picmg_busres_board_cmd_types cmd =PICMG_BUSRES_BOARD_CMD_QUERY; req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_BUSED_RESOURCE_CMD; req.msg.data = msg_data; req.msg.data_len = 3; /* IF BOARD query for all resources */ for( resource=PICMG_BUSRES_METAL_TEST_BUS_1;resource<=PICMG_BUSRES_SYNC_CLOCK_GROUP_3;resource+=(t_picmg_busres_resource_id)1 ) { msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (unsigned char) cmd; msg_data[2] = (unsigned char) resource; rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("bused resource control: no response\n"); else printf("bused resource control: returned Completion Code 0x%02x\n",rv); return rv; } else { printf("Resource 0x%02x '%-26s' : 0x%02x [%s] \n" , resource, val2str(resource,picmg_busres_id_vals), rsp[1], oemval2str(cmd,rsp[1], picmg_busres_board_status_vals)); } } } break; default: rv = -1; break; } return rv; } int ipmi_picmg_fru_control(void * intf, int argc, char ** argv) { uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_FRU_CONTROL_CMD; req.msg.data = msg_data; req.msg.data_len = 3; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = atob(argv[0]); /* FRU-ID */ msg_data[2] = atob(argv[1]); /* control option */ printf("FRU Device Id: %d FRU Control Option: %s\n\r", msg_data[1], \ val2str( msg_data[2], picmg_frucontrol_vals)); rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("frucontrol: no response\n"); else printf("frucontrol: returned Completion Code 0x%02x\n",rv); return rv; } else { printf("frucontrol: ok\n"); } return 0; } int ipmi_picmg_clk_get(void * intf, int clk_id,int clk_res,int mode) { // int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char enabled; unsigned char direction; unsigned char msg_data[6]; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_GET_CLK_STATE_CMD; req.msg.data = msg_data; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = clk_id; if(clk_res == -1 || PicmgCardType != PICMG_CARD_TYPE_ATCA ){ req.msg.data_len = 2; /* for amc only channel */ }else{ req.msg.data_len = 3; /* for carrier channel and device */ msg_data[2] = clk_res; } rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } { enabled = (rsp[1]&0x8)!=0; direction = (rsp[1]&0x4)!=0; if ( mode == PICMG_EKEY_MODE_QUERY || mode == PICMG_EKEY_MODE_PRINT_ALL || ( mode == PICMG_EKEY_MODE_PRINT_DISABLED && enabled == 0 ) || ( mode == PICMG_EKEY_MODE_PRINT_ENABLED && enabled == 1 ) ) { if( PicmgCardType != PICMG_CARD_TYPE_AMC ) { printf("CLK resource id : %3d [ %s ]\n", clk_res , oemval2str( ((clk_res>>6)&0x03), (clk_res&0x0F), picmg_clk_resource_vals)); } else { printf("CLK resource id : N/A [ AMC Module ]\n"); clk_res = 0x40; /* Set */ } printf("CLK id : %3d [ %s ]\n", clk_id, oemval2str( ((clk_res>>6)&0x03), clk_id , picmg_clk_id_vals)); printf("CLK setting : 0x%02x\n", rsp[1]); printf(" - state: %s\n", (enabled)?"enabled":"disabled"); printf(" - direction: %s\n", (direction)?"Source":"Receiver"); printf(" - PLL ctrl: 0x%x\n", rsp[1]&0x3); if(enabled){ unsigned long freq = 0; freq = ( rsp[5] << 0 | rsp[6] << 8 | rsp[7] << 16 | rsp[8] << 24 ); printf(" - Index: %3d\n", rsp[2]); printf(" - Family: %3d [ %s ]\n", rsp[3], val2str( rsp[3], picmg_clk_family_vals)); printf(" - AccLVL: %3d [ %s ]\n", rsp[4], oemval2str(rsp[3],rsp[4],picmg_clk_accuracy_vals)); printf(" - Freq: %lu\n", freq); } } } return 0; } int ipmi_picmg_clk_set(void * intf, int argc, char ** argv) { // int i; uint8_t rsp[IPMI_RSPBUF_SIZE]; int rsp_len, rv; struct ipmi_rq req; unsigned char msg_data[11]; unsigned long freq=0; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = PICMG_AMC_SET_CLK_STATE_CMD; req.msg.data = msg_data; msg_data[0] = 0x00; /* PICMG identifier */ msg_data[1] = (uchar)strtoul(argv[0], NULL,0); /* clk id */ msg_data[2] = (uchar)strtoul(argv[1], NULL,0); /* clk index */ msg_data[3] = (uchar)strtoul(argv[2], NULL,0); /* setting */ msg_data[4] = (uchar)strtoul(argv[3], NULL,0); /* family */ msg_data[5] = (uchar)strtoul(argv[4], NULL,0); /* acc */ freq = strtoul(argv[5], NULL,0); msg_data[6] = (uchar)((freq >> 0)& 0xFF); /* freq */ msg_data[7] = (uchar)((freq >> 8)& 0xFF); /* freq */ msg_data[8] = (uchar)((freq >>16)& 0xFF); /* freq */ msg_data[9] = (uchar)((freq >>24)& 0xFF); /* freq */ req.msg.data_len = 10; if( PicmgCardType == PICMG_CARD_TYPE_ATCA ) { if( argc > 7) { req.msg.data_len = 11; msg_data[10] = (uchar)strtoul(argv[6], NULL,0); /* resource id */ } else { printf("missing resource id for atca board\n"); return -1; } } #if 1 printf("## ID: %d\n", msg_data[1]); printf("## index: %d\n", msg_data[2]); printf("## setting: 0x%02x\n", msg_data[3]); printf("## family: %d\n", msg_data[4]); printf("## acc: %d\n", msg_data[5]); printf("## freq: %lu\n", freq ); printf("## res: %d\n", msg_data[10]); #endif rv = ipmi_sendrecv(&req, &rsp[0], &rsp_len); if (rv) { if (rv < 0) printf("no response\n"); else printf("returned Completion Code 0x%02x\n", rv); return rv; } return 0; } #ifdef METACOMMAND int i_picmg(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { int rc = 0; int showProperties = 0; void *intf = NULL; int c, i; char *s1; printf("%s ver %s\n", progname,progver); while ( (c = getopt( argc, argv,"m:i:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } fset_mc = 1; ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'i': /*specify a fru id*/ if (strncmp(optarg,"0x",2) == 0) g_fruid = htoi(&optarg[2]); else g_fruid = htoi(optarg); printf("Using FRU ID 0x%02x\n",g_fruid); break; case 'x': fdebug = 1; break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': ipmi_picmg_help(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } /* Get PICMG properties is called to obtain version information */ if (argc !=0 && !strncmp(argv[0], "properties", 10)) { showProperties =1; } if (argc == 0 || (!strncmp(argv[0], "help", 4))) { ipmi_picmg_help(); return ERR_USAGE; } rc = ipmi_picmg_properties(intf,showProperties); if (rc < 0) { /*cannot contact MC, so exit*/ goto do_exit; } /* address info command */ else if (!strncmp(argv[0], "addrinfo", 8)) { rc = ipmi_picmg_getaddr(intf, argc-1, &argv[1]); } else if (!strncmp(argv[0], "busres", 6)) { if (argc > 1) { if (!strncmp(argv[1], "summary", 7)) { ipmi_picmg_bused_resource(intf, PICMG_BUSED_RESOURCE_SUMMARY ); } } else { printf("usage: busres summary\n"); } } /* fru control command */ else if (!strncmp(argv[0], "frucontrol", 10)) { if (argc > 2) { rc = ipmi_picmg_fru_control(intf, argc-1, &(argv[1])); } else { printf("usage: frucontrol