From b32d92e890caac903491116e9d817aa780c0323b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Wed, 23 Jul 2014 15:03:00 +0200 Subject: Imported Upstream version 1.8.14 --- lib/Makefile.am | 48 + lib/Makefile.in | 601 ++++++ lib/dimm_spd.c | 943 +++++++++ lib/helper.c | 789 ++++++++ lib/hpm2.c | 289 +++ lib/ipmi_channel.c | 903 +++++++++ lib/ipmi_chassis.c | 1393 +++++++++++++ lib/ipmi_dcmi.c | 2193 +++++++++++++++++++++ lib/ipmi_delloem.c | 4225 +++++++++++++++++++++++++++++++++++++++ lib/ipmi_ekanalyzer.c | 4195 +++++++++++++++++++++++++++++++++++++++ lib/ipmi_event.c | 642 ++++++ lib/ipmi_firewall.c | 1191 +++++++++++ lib/ipmi_fru.c | 5209 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/ipmi_fwum.c | 1132 +++++++++++ lib/ipmi_gendev.c | 640 ++++++ lib/ipmi_hpmfwupg.c | 2624 +++++++++++++++++++++++++ lib/ipmi_ime.c | 1044 ++++++++++ lib/ipmi_isol.c | 828 ++++++++ lib/ipmi_kontronoem.c | 808 ++++++++ lib/ipmi_lanp.c | 2352 ++++++++++++++++++++++ lib/ipmi_main.c | 1063 ++++++++++ lib/ipmi_mc.c | 1112 +++++++++++ lib/ipmi_oem.c | 168 ++ lib/ipmi_pef.c | 890 +++++++++ lib/ipmi_picmg.c | 2371 ++++++++++++++++++++++ lib/ipmi_raw.c | 432 ++++ lib/ipmi_sdr.c | 4835 +++++++++++++++++++++++++++++++++++++++++++++ lib/ipmi_sdradd.c | 668 +++++++ lib/ipmi_sel.c | 3094 +++++++++++++++++++++++++++++ lib/ipmi_sensor.c | 964 +++++++++ lib/ipmi_session.c | 459 +++++ lib/ipmi_sol.c | 2098 ++++++++++++++++++++ lib/ipmi_strings.c | 578 ++++++ lib/ipmi_sunoem.c | 2434 +++++++++++++++++++++++ lib/ipmi_tsol.c | 608 ++++++ lib/ipmi_user.c | 836 ++++++++ lib/log.c | 156 ++ 37 files changed, 54815 insertions(+) create mode 100644 lib/Makefile.am create mode 100644 lib/Makefile.in create mode 100644 lib/dimm_spd.c create mode 100644 lib/helper.c create mode 100644 lib/hpm2.c create mode 100644 lib/ipmi_channel.c create mode 100644 lib/ipmi_chassis.c create mode 100755 lib/ipmi_dcmi.c create mode 100644 lib/ipmi_delloem.c create mode 100644 lib/ipmi_ekanalyzer.c create mode 100644 lib/ipmi_event.c create mode 100644 lib/ipmi_firewall.c create mode 100644 lib/ipmi_fru.c create mode 100644 lib/ipmi_fwum.c create mode 100644 lib/ipmi_gendev.c create mode 100644 lib/ipmi_hpmfwupg.c create mode 100755 lib/ipmi_ime.c create mode 100644 lib/ipmi_isol.c create mode 100644 lib/ipmi_kontronoem.c create mode 100644 lib/ipmi_lanp.c create mode 100644 lib/ipmi_main.c create mode 100644 lib/ipmi_mc.c create mode 100644 lib/ipmi_oem.c create mode 100644 lib/ipmi_pef.c create mode 100644 lib/ipmi_picmg.c create mode 100644 lib/ipmi_raw.c create mode 100644 lib/ipmi_sdr.c create mode 100644 lib/ipmi_sdradd.c create mode 100644 lib/ipmi_sel.c create mode 100644 lib/ipmi_sensor.c create mode 100644 lib/ipmi_session.c create mode 100644 lib/ipmi_sol.c create mode 100644 lib/ipmi_strings.c create mode 100644 lib/ipmi_sunoem.c create mode 100644 lib/ipmi_tsol.c create mode 100644 lib/ipmi_user.c create mode 100644 lib/log.c (limited to 'lib') diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..d878b11 --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,48 @@ +# 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. + +INCLUDES = -I$(top_srcdir)/include +MAINTAINERCLEANFILES = Makefile.in + +noinst_LTLIBRARIES = libipmitool.la +libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \ + ipmi_lanp.c ipmi_fru.c ipmi_chassis.c ipmi_mc.c log.c \ + dimm_spd.c ipmi_sensor.c ipmi_channel.c ipmi_event.c \ + ipmi_session.c ipmi_strings.c ipmi_user.c ipmi_raw.c \ + ipmi_oem.c ipmi_isol.c ipmi_sunoem.c ipmi_fwum.c ipmi_picmg.c \ + ipmi_main.c ipmi_tsol.c ipmi_firewall.c ipmi_kontronoem.c \ + ipmi_hpmfwupg.c ipmi_sdradd.c ipmi_ekanalyzer.c ipmi_gendev.c \ + ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c hpm2.c \ + ../src/plugins/lan/md5.c ../src/plugins/lan/md5.h + +libipmitool_la_LDFLAGS = -export-dynamic +libipmitool_la_LIBADD = -lm +libipmitool_la_DEPENDENCIES = + diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 0000000..0925a1f --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,601 @@ +# Makefile.in generated by automake 1.11.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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@ + +# 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. + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = lib +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am_libipmitool_la_OBJECTS = helper.lo ipmi_sdr.lo ipmi_sel.lo \ + ipmi_sol.lo ipmi_pef.lo ipmi_lanp.lo ipmi_fru.lo \ + ipmi_chassis.lo ipmi_mc.lo log.lo dimm_spd.lo ipmi_sensor.lo \ + ipmi_channel.lo ipmi_event.lo ipmi_session.lo ipmi_strings.lo \ + ipmi_user.lo ipmi_raw.lo ipmi_oem.lo ipmi_isol.lo \ + ipmi_sunoem.lo ipmi_fwum.lo ipmi_picmg.lo ipmi_main.lo \ + ipmi_tsol.lo ipmi_firewall.lo ipmi_kontronoem.lo \ + ipmi_hpmfwupg.lo ipmi_sdradd.lo ipmi_ekanalyzer.lo \ + ipmi_gendev.lo ipmi_ime.lo ipmi_delloem.lo ipmi_dcmi.lo \ + hpm2.lo md5.lo +libipmitool_la_OBJECTS = $(am_libipmitool_la_OBJECTS) +libipmitool_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libipmitool_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libipmitool_la_SOURCES) +DIST_SOURCES = $(libipmitool_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +ARCH = @ARCH@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASEDIR = @BASEDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTRO = @DISTRO@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTF_BMC = @INTF_BMC@ +INTF_BMC_LIB = @INTF_BMC_LIB@ +INTF_DUMMY = @INTF_DUMMY@ +INTF_DUMMY_LIB = @INTF_DUMMY_LIB@ +INTF_FREE = @INTF_FREE@ +INTF_FREE_LIB = @INTF_FREE_LIB@ +INTF_IMB = @INTF_IMB@ +INTF_IMB_LIB = @INTF_IMB_LIB@ +INTF_LAN = @INTF_LAN@ +INTF_LANPLUS = @INTF_LANPLUS@ +INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@ +INTF_LAN_LIB = @INTF_LAN_LIB@ +INTF_LIPMI = @INTF_LIPMI@ +INTF_LIPMI_LIB = @INTF_LIPMI_LIB@ +INTF_OPEN = @INTF_OPEN@ +INTF_OPEN_LIB = @INTF_OPEN_LIB@ +INTF_SERIAL = @INTF_SERIAL@ +INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OS = @OS@ +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@ +POW_LIB = @POW_LIB@ +PSTAMP = @PSTAMP@ +RANLIB = @RANLIB@ +RPMBUILD = @RPMBUILD@ +RPM_RELEASE = @RPM_RELEASE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_configure_args = @ac_configure_args@ +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@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -I$(top_srcdir)/include +MAINTAINERCLEANFILES = Makefile.in +noinst_LTLIBRARIES = libipmitool.la +libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \ + ipmi_lanp.c ipmi_fru.c ipmi_chassis.c ipmi_mc.c log.c \ + dimm_spd.c ipmi_sensor.c ipmi_channel.c ipmi_event.c \ + ipmi_session.c ipmi_strings.c ipmi_user.c ipmi_raw.c \ + ipmi_oem.c ipmi_isol.c ipmi_sunoem.c ipmi_fwum.c ipmi_picmg.c \ + ipmi_main.c ipmi_tsol.c ipmi_firewall.c ipmi_kontronoem.c \ + ipmi_hpmfwupg.c ipmi_sdradd.c ipmi_ekanalyzer.c ipmi_gendev.c \ + ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c hpm2.c \ + ../src/plugins/lan/md5.c ../src/plugins/lan/md5.h + +libipmitool_la_LDFLAGS = -export-dynamic +libipmitool_la_LIBADD = -lm +libipmitool_la_DEPENDENCIES = +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 lib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign lib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libipmitool.la: $(libipmitool_la_OBJECTS) $(libipmitool_la_DEPENDENCIES) $(EXTRA_libipmitool_la_DEPENDENCIES) + $(libipmitool_la_LINK) $(libipmitool_la_OBJECTS) $(libipmitool_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dimm_spd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hpm2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_channel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_chassis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_dcmi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_delloem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_ekanalyzer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_event.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_firewall.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_fru.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_fwum.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_gendev.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_hpmfwupg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_ime.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_isol.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_kontronoem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_lanp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_main.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_mc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_oem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_pef.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_picmg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_raw.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sdr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sdradd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sensor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_session.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sol.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_strings.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_sunoem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_tsol.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_user.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +md5.lo: ../src/plugins/lan/md5.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md5.lo -MD -MP -MF $(DEPDIR)/md5.Tpo -c -o md5.lo `test -f '../src/plugins/lan/md5.c' || echo '$(srcdir)/'`../src/plugins/lan/md5.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/md5.Tpo $(DEPDIR)/md5.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../src/plugins/lan/md5.c' object='md5.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md5.lo `test -f '../src/plugins/lan/md5.c' || echo '$(srcdir)/'`../src/plugins/lan/md5.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +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: + +clean-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." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-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 \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/dimm_spd.c b/lib/dimm_spd.c new file mode 100644 index 0000000..1f27de2 --- /dev/null +++ b/lib/dimm_spd.c @@ -0,0 +1,943 @@ +/* + * 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 +#include + +#include +#include + +extern int verbose; + +/* + * Also, see ipmi_fru.c. + * + * Apparently some systems have problems with FRU access greater than 16 bytes + * at a time, even when using byte (not word) access. In order to ensure we + * work with the widest variety of hardware request size is capped at 16 bytes. + * Since this may result in slowdowns on some systems with lots of FRU data you + * can change this define to enable larger (up to 32 bytes at a time) access. + */ +#define FRU_DATA_RQST_SIZE 16; + +const struct valstr spd_memtype_vals[] = { + { 0x01, "STD FPM DRAM" }, + { 0x02, "EDO" }, + { 0x04, "SDRAM" }, + { 0x05, "ROM" }, + { 0x06, "DDR SGRAM" }, + { 0x07, "DDR SDRAM" }, + { 0x08, "DDR2 SDRAM" }, + { 0x09, "DDR2 SDRAM FB-DIMM" }, + { 0x0A, "DDR2 SDRAM FB-DIMM Probe" }, + { 0x0B, "DDR3 SDRAM" }, + { 0x00, NULL }, +}; + +const struct valstr ddr3_density_vals[] = +{ + { 0, "256 Mb" }, + { 1, "512 Mb" }, + { 2, "1 Gb" }, + { 3, "2 Gb" }, + { 4, "4 Gb" }, + { 5, "8 Gb" }, + { 6, "16 Gb" }, + { 0x00, NULL }, +}; + +const struct valstr ddr3_banks_vals[] = +{ + { 0, "3 (8 Banks)" }, + { 1, "4 (16 Banks)" }, + { 2, "5 (32 Banks)" }, + { 3, "6 (64 Banks)" }, + { 0x00, NULL }, +}; + +const struct valstr ddr3_ecc_vals[] = +{ + { 0, "0 bits" }, + { 1, "8 bits" }, + { 0x00, NULL }, +}; + +const struct valstr spd_config_vals[] = { + { 0x00, "None" }, + { 0x01, "Parity" }, + { 0x02, "ECC" }, + { 0x04, "Addr Cmd Parity" }, + { 0x00, NULL }, +}; + +const struct valstr spd_voltage_vals[] = { + { 0x00, "5.0V TTL" }, + { 0x01, "LVTTL" }, + { 0x02, "HSTL 1.5V" }, + { 0x03, "SSTL 3.3V" }, + { 0x04, "SSTL 2.5V" }, + { 0x05, "SSTL 1.8V" }, + { 0x00, NULL }, +}; + +/* + * JEDEC Standard Manufacturers Identification Code + * publication JEP106N, December 2003 + */ + +const struct valstr jedec_id1_vals[] = { + { 0x01, "AMD" }, + { 0x02, "AMI" }, + { 0x83, "Fairchild" }, + { 0x04, "Fujitsu" }, + { 0x85, "GTE" }, + { 0x86, "Harris" }, + { 0x07, "Hitachi" }, + { 0x08, "Inmos" }, + { 0x89, "Intel" }, + { 0x8a, "I.T.T." }, + { 0x0b, "Intersil" }, + { 0x8c, "Monolithic Memories" }, + { 0x0d, "Mostek" }, + { 0x0e, "Motorola" }, + { 0x8f, "National" }, + { 0x10, "NEC" }, + { 0x91, "RCA" }, + { 0x92, "Raytheon" }, + { 0x13, "Conexant (Rockwell)" }, + { 0x94, "Seeq" }, + { 0x15, "Philips Semi. (Signetics)" }, + { 0x16, "Synertek" }, + { 0x97, "Texas Instruments" }, + { 0x98, "Toshiba" }, + { 0x19, "Xicor" }, + { 0x1a, "Zilog" }, + { 0x9b, "Eurotechnique" }, + { 0x1c, "Mitsubishi" }, + { 0x9d, "Lucent (AT&T)" }, + { 0x9e, "Exel" }, + { 0x1f, "Atmel" }, + { 0x20, "SGS/Thomson" }, + { 0xa1, "Lattice Semi." }, + { 0xa2, "NCR" }, + { 0x23, "Wafer Scale Integration" }, + { 0xa4, "IBM" }, + { 0x25, "Tristar" }, + { 0x26, "Visic" }, + { 0xa7, "Intl. CMOS Technology" }, + { 0xa8, "SSSI" }, + { 0x29, "Microchip Technology" }, + { 0x2a, "Ricoh Ltd." }, + { 0xab, "VLSI" }, + { 0x2c, "Micron Technology" }, + { 0xad, "Hyundai Electronics" }, + { 0xae, "OKI Semiconductor" }, + { 0x2f, "ACTEL" }, + { 0xb0, "Sharp" }, + { 0x31, "Catalyst" }, + { 0x32, "Panasonic" }, + { 0xb3, "IDT" }, + { 0x34, "Cypress" }, + { 0xb5, "DEC" }, + { 0xb6, "LSI Logic" }, + { 0x37, "Zarlink" }, + { 0x38, "UTMC" }, + { 0xb9, "Thinking Machine" }, + { 0xba, "Thomson CSF" }, + { 0x3b, "Integrated CMOS(Vertex)" }, + { 0xbc, "Honeywell" }, + { 0x3d, "Tektronix" }, + { 0x3e, "Sun Microsystems" }, + { 0xbf, "SST" }, + { 0x40, "MOSEL" }, + { 0xc1, "Infineon" }, + { 0xc2, "Macronix" }, + { 0x43, "Xerox" }, + { 0xc4, "Plus Logic" }, + { 0x45, "SunDisk" }, + { 0x46, "Elan Circuit Tech." }, + { 0xc7, "European Silicon Str." }, + { 0xc8, "Apple Computer" }, + { 0xc9, "Xilinx" }, + { 0x4a, "Compaq" }, + { 0xcb, "Protocol Engines" }, + { 0x4c, "SCI" }, + { 0xcd, "Seiko Instruments" }, + { 0xce, "Samsung" }, + { 0x4f, "I3 Design System" }, + { 0xd0, "Klic" }, + { 0x51, "Crosspoint Solutions" }, + { 0x52, "Alliance Semiconductor" }, + { 0xd3, "Tandem" }, + { 0x54, "Hewlett-Packard" }, + { 0xd5, "Intg. Silicon Solutions" }, + { 0xd6, "Brooktree" }, + { 0x57, "New Media" }, + { 0x58, "MHS Electronic" }, + { 0xd9, "Performance Semi." }, + { 0xda, "Winbond Electronic" }, + { 0x5b, "Kawasaki Steel" }, + { 0xdc, "Bright Micro" }, + { 0x5d, "TECMAR" }, + { 0x5e, "Exar" }, + { 0xdf, "PCMCIA" }, + { 0xe0, "LG Semiconductor" }, + { 0x61, "Northern Telecom" }, + { 0x62, "Sanyo" }, + { 0xe3, "Array Microsystems" }, + { 0x64, "Crystal Semiconductor" }, + { 0xe5, "Analog Devices" }, + { 0xe6, "PMC-Sierra" }, + { 0x67, "Asparix" }, + { 0x68, "Convex Computer" }, + { 0xe9, "Quality Semiconductor" }, + { 0xea, "Nimbus Technology" }, + { 0x6b, "Transwitch" }, + { 0xec, "Micronas (ITT Intermetall)" }, + { 0x6d, "Cannon" }, + { 0x6e, "Altera" }, + { 0xef, "NEXCOM" }, + { 0x70, "QUALCOMM" }, + { 0xf1, "Sony" }, + { 0xf2, "Cray Research" }, + { 0x73, "AMS (Austria Micro)" }, + { 0xf4, "Vitesse" }, + { 0x75, "Aster Electronics" }, + { 0x76, "Bay Networks (Synoptic)" }, + { 0xf7, "Zentrum" }, + { 0xf8, "TRW" }, + { 0x79, "Thesys" }, + { 0x7a, "Solbourne Computer" }, + { 0xfb, "Allied-Signal" }, + { 0x7c, "Dialog" }, + { 0xfd, "Media Vision" }, + { 0xfe, "Level One Communication" }, + { 0x00, NULL }, +}; + +const struct valstr jedec_id2_vals[] = { + { 0x01, "Cirrus Logic" }, + { 0x02, "National Instruments" }, + { 0x83, "ILC Data Device" }, + { 0x04, "Alcatel Mietec" }, + { 0x85, "Micro Linear" }, + { 0x86, "Univ. of NC" }, + { 0x07, "JTAG Technologies" }, + { 0x08, "Loral" }, + { 0x89, "Nchip" }, + { 0x8A, "Galileo Tech" }, + { 0x0B, "Bestlink Systems" }, + { 0x8C, "Graychip" }, + { 0x0D, "GENNUM" }, + { 0x0E, "VideoLogic" }, + { 0x8F, "Robert Bosch" }, + { 0x10, "Chip Express" }, + { 0x91, "DATARAM" }, + { 0x92, "United Microelec Corp." }, + { 0x13, "TCSI" }, + { 0x94, "Smart Modular" }, + { 0x15, "Hughes Aircraft" }, + { 0x16, "Lanstar Semiconductor" }, + { 0x97, "Qlogic" }, + { 0x98, "Kingston" }, + { 0x19, "Music Semi" }, + { 0x1A, "Ericsson Components" }, + { 0x9B, "SpaSE" }, + { 0x1C, "Eon Silicon Devices" }, + { 0x9D, "Programmable Micro Corp" }, + { 0x9E, "DoD" }, + { 0x1F, "Integ. Memories Tech." }, + { 0x20, "Corollary Inc." }, + { 0xA1, "Dallas Semiconductor" }, + { 0xA2, "Omnivision" }, + { 0x23, "EIV(Switzerland)" }, + { 0xA4, "Novatel Wireless" }, + { 0x25, "Zarlink (formerly Mitel)" }, + { 0x26, "Clearpoint" }, + { 0xA7, "Cabletron" }, + { 0xA8, "Silicon Technology" }, + { 0x29, "Vanguard" }, + { 0x2A, "Hagiwara Sys-Com" }, + { 0xAB, "Vantis" }, + { 0x2C, "Celestica" }, + { 0xAD, "Century" }, + { 0xAE, "Hal Computers" }, + { 0x2F, "Rohm Company Ltd." }, + { 0xB0, "Juniper Networks" }, + { 0x31, "Libit Signal Processing" }, + { 0x32, "Enhanced Memories Inc." }, + { 0xB3, "Tundra Semiconductor" }, + { 0x34, "Adaptec Inc." }, + { 0xB5, "LightSpeed Semi." }, + { 0xB6, "ZSP Corp." }, + { 0x37, "AMIC Technology" }, + { 0x38, "Adobe Systems" }, + { 0xB9, "Dynachip" }, + { 0xBA, "PNY Electronics" }, + { 0x3B, "Newport Digital" }, + { 0xBC, "MMC Networks" }, + { 0x3D, "T Square" }, + { 0x3E, "Seiko Epson" }, + { 0xBF, "Broadcom" }, + { 0x40, "Viking Components" }, + { 0xC1, "V3 Semiconductor" }, + { 0xC2, "Flextronics (formerly Orbit)" }, + { 0x43, "Suwa Electronics" }, + { 0xC4, "Transmeta" }, + { 0x45, "Micron CMS" }, + { 0x46, "American Computer & Digital Components Inc" }, + { 0xC7, "Enhance 3000 Inc" }, + { 0xC8, "Tower Semiconductor" }, + { 0x49, "CPU Design" }, + { 0x4A, "Price Point" }, + { 0xCB, "Maxim Integrated Product" }, + { 0x4C, "Tellabs" }, + { 0xCD, "Centaur Technology" }, + { 0xCE, "Unigen Corporation" }, + { 0x4F, "Transcend Information" }, + { 0xD0, "Memory Card Technology" }, + { 0x51, "CKD Corporation Ltd." }, + { 0x52, "Capital Instruments, Inc." }, + { 0xD3, "Aica Kogyo, Ltd." }, + { 0x54, "Linvex Technology" }, + { 0xD5, "MSC Vertriebs GmbH" }, + { 0xD6, "AKM Company, Ltd." }, + { 0x57, "Dynamem, Inc." }, + { 0x58, "NERA ASA" }, + { 0xD9, "GSI Technology" }, + { 0xDA, "Dane-Elec (C Memory)" }, + { 0x5B, "Acorn Computers" }, + { 0xDC, "Lara Technology" }, + { 0x5D, "Oak Technology, Inc." }, + { 0x5E, "Itec Memory" }, + { 0xDF, "Tanisys Technology" }, + { 0xE0, "Truevision" }, + { 0x61, "Wintec Industries" }, + { 0x62, "Super PC Memory" }, + { 0xE3, "MGV Memory" }, + { 0x64, "Galvantech" }, + { 0xE5, "Gadzoox Nteworks" }, + { 0xE6, "Multi Dimensional Cons." }, + { 0x67, "GateField" }, + { 0x68, "Integrated Memory System" }, + { 0xE9, "Triscend" }, + { 0xEA, "XaQti" }, + { 0x6B, "Goldenram" }, + { 0xEC, "Clear Logic" }, + { 0x6D, "Cimaron Communications" }, + { 0x6E, "Nippon Steel Semi. Corp." }, + { 0xEF, "Advantage Memory" }, + { 0x70, "AMCC" }, + { 0xF1, "LeCroy" }, + { 0xF2, "Yamaha Corporation" }, + { 0x73, "Digital Microwave" }, + { 0xF4, "NetLogic Microsystems" }, + { 0x75, "MIMOS Semiconductor" }, + { 0x76, "Advanced Fibre" }, + { 0xF7, "BF Goodrich Data." }, + { 0xF8, "Epigram" }, + { 0x79, "Acbel Polytech Inc." }, + { 0x7A, "Apacer Technology" }, + { 0xFB, "Admor Memory" }, + { 0x7C, "FOXCONN" }, + { 0xFD, "Quadratics Superconductor" }, + { 0xFE, "3COM" }, + { 0x00, NULL }, +}; + +const struct valstr jedec_id3_vals[] = { + { 0x01, "Camintonn Corporation" }, + { 0x02, "ISOA Incorporated" }, + { 0x83, "Agate Semiconductor" }, + { 0x04, "ADMtek Incorporated" }, + { 0x85, "HYPERTEC" }, + { 0x86, "Adhoc Technologies" }, + { 0x07, "MOSAID Technologies" }, + { 0x08, "Ardent Technologies" }, + { 0x89, "Switchcore" }, + { 0x8A, "Cisco Systems, Inc." }, + { 0x0B, "Allayer Technologies" }, + { 0x8C, "WorkX AG" }, + { 0x0D, "Oasis Semiconductor" }, + { 0x0E, "Novanet Semiconductor" }, + { 0x8F, "E-M Solutions" }, + { 0x10, "Power General" }, + { 0x91, "Advanced Hardware Arch." }, + { 0x92, "Inova Semiconductors GmbH" }, + { 0x13, "Telocity" }, + { 0x94, "Delkin Devices" }, + { 0x15, "Symagery Microsystems" }, + { 0x16, "C-Port Corporation" }, + { 0x97, "SiberCore Technologies" }, + { 0x98, "Southland Microsystems" }, + { 0x19, "Malleable Technologies" }, + { 0x1A, "Kendin Communications" }, + { 0x9B, "Great Technology Microcomputer" }, + { 0x1C, "Sanmina Corporation" }, + { 0x9D, "HADCO Corporation" }, + { 0x9E, "Corsair" }, + { 0x1F, "Actrans System Inc." }, + { 0x20, "ALPHA Technologies" }, + { 0xA1, "Cygnal Integrated Products Incorporated" }, + { 0xA2, "Artesyn Technologies" }, + { 0x23, "Align Manufacturing" }, + { 0xA4, "Peregrine Semiconductor" }, + { 0x25, "Chameleon Systems" }, + { 0x26, "Aplus Flash Technology" }, + { 0xA7, "MIPS Technologies" }, + { 0xA8, "Chrysalis ITS" }, + { 0x29, "ADTEC Corporation" }, + { 0x2A, "Kentron Technologies" }, + { 0xAB, "Win Technologies" }, + { 0x2C, "ASIC Designs Inc" }, + { 0xAD, "Extreme Packet Devices" }, + { 0xAE, "RF Micro Devices" }, + { 0x2F, "Siemens AG" }, + { 0xB0, "Sarnoff Corporation" }, + { 0x31, "Itautec Philco SA" }, + { 0x32, "Radiata Inc." }, + { 0xB3, "Benchmark Elect. (AVEX)" }, + { 0x34, "Legend" }, + { 0xB5, "SpecTek Incorporated" }, + { 0xB6, "Hi/fn" }, + { 0x37, "Enikia Incorporated" }, + { 0x38, "SwitchOn Networks" }, + { 0xB9, "AANetcom Incorporated" }, + { 0xBA, "Micro Memory Bank" }, + { 0x3B, "ESS Technology" }, + { 0xBC, "Virata Corporation" }, + { 0x3D, "Excess Bandwidth" }, + { 0x3E, "West Bay Semiconductor" }, + { 0xBF, "DSP Group" }, + { 0x40, "Newport Communications" }, + { 0xC1, "Chip2Chip Incorporated" }, + { 0xC2, "Phobos Corporation" }, + { 0x43, "Intellitech Corporation" }, + { 0xC4, "Nordic VLSI ASA" }, + { 0x45, "Ishoni Networks" }, + { 0x46, "Silicon Spice" }, + { 0xC7, "Alchemy Semiconductor" }, + { 0xC8, "Agilent Technologies" }, + { 0x49, "Centillium Communications" }, + { 0x4A, "W.L. Gore" }, + { 0xCB, "HanBit Electronics" }, + { 0x4C, "GlobeSpan" }, + { 0xCD, "Element 14" }, + { 0xCE, "Pycon" }, + { 0x4F, "Saifun Semiconductors" }, + { 0xD0, "Sibyte, Incorporated" }, + { 0x51, "MetaLink Technologies" }, + { 0x52, "Feiya Technology" }, + { 0xD3, "I & C Technology" }, + { 0x54, "Shikatronics" }, + { 0xD5, "Elektrobit" }, + { 0xD6, "Megic" }, + { 0x57, "Com-Tier" }, + { 0x58, "Malaysia Micro Solutions" }, + { 0xD9, "Hyperchip" }, + { 0xDA, "Gemstone Communications" }, + { 0x5B, "Anadyne Microelectronics" }, + { 0xDC, "3ParData" }, + { 0x5D, "Mellanox Technologies" }, + { 0x5E, "Tenx Technologies" }, + { 0xDF, "Helix AG" }, + { 0xE0, "Domosys" }, + { 0x61, "Skyup Technology" }, + { 0x62, "HiNT Corporation" }, + { 0xE3, "Chiaro" }, + { 0x64, "MCI Computer GMBH" }, + { 0xE5, "Exbit Technology A/S" }, + { 0xE6, "Integrated Technology Express" }, + { 0x67, "AVED Memory" }, + { 0x68, "Legerity" }, + { 0xE9, "Jasmine Networks" }, + { 0xEA, "Caspian Networks" }, + { 0x6B, "nCUBE" }, + { 0xEC, "Silicon Access Networks" }, + { 0x6D, "FDK Corporation" }, + { 0x6E, "High Bandwidth Access" }, + { 0xEF, "MultiLink Technology" }, + { 0x70, "BRECIS" }, + { 0xF1, "World Wide Packets" }, + { 0xF2, "APW" }, + { 0x73, "Chicory Systems" }, + { 0xF4, "Xstream Logic" }, + { 0x75, "Fast-Chip" }, + { 0x76, "Zucotto Wireless" }, + { 0xF7, "Realchip" }, + { 0xF8, "Galaxy Power" }, + { 0x79, "eSilicon" }, + { 0x7A, "Morphics Technology" }, + { 0xFB, "Accelerant Networks" }, + { 0x7C, "Silicon Wave" }, + { 0xFD, "SandCraft" }, + { 0xFE, "Elpida" }, + { 0x00, NULL }, +}; + +const struct valstr jedec_id4_vals[] = { + { 0x01, "Solectron" }, + { 0x02, "Optosys Technologies" }, + { 0x83, "Buffalo (Formerly Melco)" }, + { 0x04, "TriMedia Technologies" }, + { 0x85, "Cyan Technologies" }, + { 0x86, "Global Locate" }, + { 0x07, "Optillion" }, + { 0x08, "Terago Communications" }, + { 0x89, "Ikanos Communications" }, + { 0x8A, "Princeton Technology" }, + { 0x0B, "Nanya Technology" }, + { 0x8C, "Elite Flash Storage" }, + { 0x0D, "Mysticom" }, + { 0x0E, "LightSand Communications" }, + { 0x8F, "ATI Technologies" }, + { 0x10, "Agere Systems" }, + { 0x91, "NeoMagic" }, + { 0x92, "AuroraNetics" }, + { 0x13, "Golden Empire" }, + { 0x94, "Muskin" }, + { 0x15, "Tioga Technologies" }, + { 0x16, "Netlist" }, + { 0x97, "TeraLogic" }, + { 0x98, "Cicada Semiconductor" }, + { 0x19, "Centon Electronics" }, + { 0x1A, "Tyco Electronics" }, + { 0x9B, "Magis Works" }, + { 0x1C, "Zettacom" }, + { 0x9D, "Cogency Semiconductor" }, + { 0x9E, "Chipcon AS" }, + { 0x1F, "Aspex Technology" }, + { 0x20, "F5 Networks" }, + { 0xA1, "Programmable Silicon Solutions" }, + { 0xA2, "ChipWrights" }, + { 0x23, "Acorn Networks" }, + { 0xA4, "Quicklogic" }, + { 0x25, "Kingmax Semiconductor" }, + { 0x26, "BOPS" }, + { 0xA7, "Flasys" }, + { 0xA8, "BitBlitz Communications" }, + { 0x29, "eMemory Technology" }, + { 0x2A, "Procket Networks" }, + { 0xAB, "Purple Ray" }, + { 0x2C, "Trebia Networks" }, + { 0xAD, "Delta Electronics" }, + { 0xAE, "Onex Communications" }, + { 0x2F, "Ample Communications" }, + { 0xB0, "Memory Experts Intl" }, + { 0x31, "Astute Networks" }, + { 0x32, "Azanda Network Devices" }, + { 0xB3, "Dibcom" }, + { 0x34, "Tekmos" }, + { 0xB5, "API NetWorks" }, + { 0xB6, "Bay Microsystems" }, + { 0x37, "Firecron Ltd" }, + { 0x38, "Resonext Communications" }, + { 0xB9, "Tachys Technologies" }, + { 0xBA, "Equator Technology" }, + { 0x3B, "Concept Computer" }, + { 0xBC, "SILCOM" }, + { 0x3D, "3Dlabs" }, + { 0x3E, "ct Magazine" }, + { 0xBF, "Sanera Systems" }, + { 0x40, "Silicon Packets" }, + { 0xC1, "Viasystems Group" }, + { 0xC2, "Simtek" }, + { 0x43, "Semicon Devices Singapore" }, + { 0xC4, "Satron Handelsges" }, + { 0x45, "Improv Systems" }, + { 0x46, "INDUSYS GmbH" }, + { 0xC7, "Corrent" }, + { 0xC8, "Infrant Technologies" }, + { 0x49, "Ritek Corp" }, + { 0x4A, "empowerTel Networks" }, + { 0xCB, "Hypertec" }, + { 0x4C, "Cavium Networks" }, + { 0xCD, "PLX Technology" }, + { 0xCE, "Massana Design" }, + { 0x4F, "Intrinsity" }, + { 0xD0, "Valence Semiconductor" }, + { 0x51, "Terawave Communications" }, + { 0x52, "IceFyre Semiconductor" }, + { 0xD3, "Primarion" }, + { 0x54, "Picochip Designs Ltd" }, + { 0xD5, "Silverback Systems" }, + { 0xD6, "Jade Star Technologies" }, + { 0x57, "Pijnenburg Securealink" }, + { 0x58, "MemorySolutioN" }, + { 0xD9, "Cambridge Silicon Radio" }, + { 0xDA, "Swissbit" }, + { 0x5B, "Nazomi Communications" }, + { 0xDC, "eWave System" }, + { 0x5D, "Rockwell Collins" }, + { 0x5E, "PAION" }, + { 0xDF, "Alphamosaic Ltd" }, + { 0xE0, "Sandburst" }, + { 0x61, "SiCon Video" }, + { 0x62, "NanoAmp Solutions" }, + { 0xE3, "Ericsson Technology" }, + { 0x64, "PrairieComm" }, + { 0xE5, "Mitac International" }, + { 0xE6, "Layer N Networks" }, + { 0x67, "Atsana Semiconductor" }, + { 0x68, "Allegro Networks" }, + { 0xE9, "Marvell Semiconductors" }, + { 0xEA, "Netergy Microelectronic" }, + { 0x6B, "NVIDIA" }, + { 0xEC, "Internet Machines" }, + { 0x6D, "Peak Electronics" }, + { 0xEF, "Accton Technology" }, + { 0x70, "Teradiant Networks" }, + { 0xF1, "Europe Technologies" }, + { 0xF2, "Cortina Systems" }, + { 0x73, "RAM Components" }, + { 0xF4, "Raqia Networks" }, + { 0x75, "ClearSpeed" }, + { 0x76, "Matsushita Battery" }, + { 0xF7, "Xelerated" }, + { 0xF8, "SimpleTech" }, + { 0x79, "Utron Technology" }, + { 0x7A, "Astec International" }, + { 0xFB, "AVM gmbH" }, + { 0x7C, "Redux Communications" }, + { 0xFD, "Dot Hill Systems" }, + { 0xFE, "TeraChip" }, + { 0x00, NULL }, +}; + +const struct valstr jedec_id5_vals[] = { + { 0x01, "T-RAM Incorporated" }, + { 0x02, "Innovics Wireless" }, + { 0x83, "Teknovus" }, + { 0x04, "KeyEye Communications" }, + { 0x85, "Runcom Technologies" }, + { 0x86, "RedSwitch" }, + { 0x07, "Dotcast" }, + { 0x08, "Silicon Mountain Memory" }, + { 0x89, "Signia Technologies" }, + { 0x8A, "Pixim" }, + { 0x0B, "Galazar Networks" }, + { 0x8C, "White Electronic Designs" }, + { 0x0D, "Patriot Scientific" }, + { 0x0E, "Neoaxiom Corporation" }, + { 0x8F, "3Y Power Technology" }, + { 0x10, "Europe Technologies" }, + { 0x91, "Potentia Power Systems" }, + { 0x92, "C-guys Incorporated" }, + { 0x13, "Digital Communications Technology Incorporated" }, + { 0x94, "Silicon-Based Technology" }, + { 0x15, "Fulcrum Microsystems" }, + { 0x16, "Positivo Informatica Ltd" }, + { 0x97, "XIOtech Corporation" }, + { 0x98, "PortalPlayer" }, + { 0x19, "Zhiying Software" }, + { 0x1A, "Direct2Data" }, + { 0x9B, "Phonex Broadband" }, + { 0x1C, "Skyworks Solutions" }, + { 0x9D, "Entropic Communications" }, + { 0x9E, "Pacific Force Technology" }, + { 0x1F, "Zensys A/S" }, + { 0x20, "Legend Silicon Corp." }, + { 0xA1, "sci-worx GmbH" }, + { 0xA2, "Oasis Silicon Systems" }, + { 0x23, "Renesas Technology" }, + { 0xA4, "Raza Microelectronics" }, + { 0x25, "Phyworks" }, + { 0x26, "MediaTek" }, + { 0xA7, "Non-cents Productions" }, + { 0xA8, "US Modular" }, + { 0x29, "Wintegra Ltd" }, + { 0x2A, "Mathstar" }, + { 0xAB, "StarCore" }, + { 0x2C, "Oplus Technologies" }, + { 0xAD, "Mindspeed" }, + { 0xAE, "Just Young Computer" }, + { 0x2F, "Radia Communications" }, + { 0xB0, "OCZ" }, + { 0x31, "Emuzed" }, + { 0x32, "LOGIC Devices" }, + { 0xB3, "Inphi Corporation" }, + { 0x34, "Quake Technologies" }, + { 0xB5, "Vixel" }, + { 0xB6, "SolusTek" }, + { 0x37, "Kongsberg Maritime" }, + { 0x38, "Faraday Technology" }, + { 0xB9, "Altium Ltd." }, + { 0xBA, "Insyte" }, + { 0x3B, "ARM Ltd." }, + { 0xBC, "DigiVision" }, + { 0x3D, "Vativ Technologies" }, + { 0x3E, "Endicott Interconnect Technologies" }, + { 0xBF, "Pericom" }, + { 0x40, "Bandspeed" }, + { 0xC1, "LeWiz Communications" }, + { 0xC2, "CPU Technology" }, + { 0x43, "Ramaxel Technology" }, + { 0xC4, "DSP Group" }, + { 0x45, "Axis Communications" }, + { 0x46, "Legacy Electronics" }, + { 0xC7, "Chrontel" }, + { 0xC8, "Powerchip Semiconductor" }, + { 0x49, "MobilEye Technologies" }, + { 0x4A, "Excel Semiconductor" }, + { 0xCB, "A-DATA Technology" }, + { 0x4C, "VirtualDigm" }, + { 0x00, NULL }, +}; + +int +ipmi_spd_print(uint8_t *spd_data, int len) +{ + int k = 0; + int ii = 0; + + if (len < 92) + return -1; /* we need first 91 bytes to do our thing */ + + printf(" Memory Type : %s\n", + val2str(spd_data[2], spd_memtype_vals)); + + if (spd_data[2] == 0x0B) /* DDR3 SDRAM */ + { + int iPN; + char *pchPN = spd_data+128; + int sdram_cap = 0; + int pri_bus_width = 0; + int sdram_width = 0; + int ranks = 0; + int mem_size = 0; + + if (len < 148) + return -1; /* we need first 91 bytes to do our thing */ + + + sdram_cap = ldexp(256,(spd_data[4]&15)); + pri_bus_width = ldexp(8,(spd_data[8]&7)); + sdram_width = ldexp(4,(spd_data[7]&7)); + ranks = ldexp(1,((spd_data[7]&0x3F)>>3)); + mem_size = (sdram_cap/8) * (pri_bus_width/sdram_width) * ranks; + printf(" SDRAM Capacity : %d MB\n", sdram_cap ); + printf(" Memory Banks : %s\n", val2str(spd_data[4]>>4, ddr3_banks_vals)); + printf(" Primary Bus Width : %d bits\n", pri_bus_width ); + printf(" SDRAM Device Width : %d bits\n", sdram_width ); + printf(" Number of Ranks : %d\n", ranks ); + printf(" Memory size : %d MB\n", mem_size ); + + /* printf(" Memory Density : %s\n", val2str(spd_data[4]&15, ddr3_density_vals)); */ + printf(" 1.5 V Nominal Op : %s\n", (((spd_data[6]&1) != 0) ? "No":"Yes" ) ); + printf(" 1.35 V Nominal Op : %s\n", (((spd_data[6]&2) != 0) ? "No":"Yes" ) ); + printf(" 1.2X V Nominal Op : %s\n", (((spd_data[6]&4) != 0) ? "No":"Yes" ) ); + printf(" Error Detect/Cor : %s\n", val2str(spd_data[8]>>3, ddr3_ecc_vals)); + + printf(" Manufacturer : "); + switch (spd_data[117]&127) + { + case 0: + printf("%s\n", val2str(spd_data[118], jedec_id1_vals)); + break; + + case 1: + printf("%s\n", val2str(spd_data[118], jedec_id2_vals)); + break; + + case 2: + printf("%s\n", val2str(spd_data[118], jedec_id3_vals)); + break; + + case 3: + printf("%s\n", val2str(spd_data[118], jedec_id4_vals)); + break; + + case 4: + printf("%s\n", val2str(spd_data[118], jedec_id5_vals)); + break; + + default: + printf("%s\n", "JEDEC JEP106 update required" ); + + } + + printf(" Manufacture Date : year %c%c week %c%c\n", + '0'+(spd_data[120]>>4), '0'+(spd_data[120]&15), '0'+(spd_data[121]>>4), '0'+(spd_data[121]&15) ); + + printf(" Serial Number : %02x%02x%02x%02x\n", + spd_data[122], spd_data[123], spd_data[124], spd_data[125]); + + printf(" Part Number : "); + for (iPN=0; iPN < 19; iPN++) + { + printf( "%c", *pchPN++ ); + } + printf("\n"); + } + else + { + ii = (spd_data[3] & 0x0f) + (spd_data[4] & 0x0f) - 17; + k = ((spd_data[5] & 0x7) + 1) * spd_data[17]; + + if(ii > 0 && ii <= 12 && k > 0) { + printf(" Memory Size : %d MB\n", ((1 << ii) * k)); + } else { + printf(" Memory Size INVALID: %d, %d, %d, %d\n", spd_data[3], + spd_data[4], spd_data[5], spd_data[17]); + } + printf(" Voltage Intf : %s\n", + val2str(spd_data[8], spd_voltage_vals)); + printf(" Error Detect/Cor : %s\n", + val2str(spd_data[11], spd_config_vals)); + + /* handle jedec table bank continuation values */ + printf(" Manufacturer : "); + if (spd_data[64] != 0x7f) + printf("%s\n", + val2str(spd_data[64], jedec_id1_vals)); + else { + if (spd_data[65] != 0x7f) + printf("%s\n", + val2str(spd_data[65], jedec_id2_vals)); + else { + if (spd_data[66] != 0x7f) + printf("%s\n", + val2str(spd_data[66], jedec_id3_vals)); + else { + if (spd_data[67] != 0x7f) + printf("%s\n", + val2str(spd_data[67], + jedec_id4_vals)); + else + printf("%s\n", + val2str(spd_data[68], + jedec_id5_vals)); + } + } + } + + if (spd_data[73]) { + char part[19]; + memcpy(part, spd_data+73, 18); + part[18] = 0; + printf(" Part Number : %s\n", part); + } + + printf(" Serial Number : %02x%02x%02x%02x\n", + spd_data[95], spd_data[96], spd_data[97], spd_data[98]); + } + + if (verbose) { + printf("\n"); + printbuf(spd_data, len, "SPD DATA"); + } + + return 0; +} + +int +ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + struct fru_info fru; + uint8_t spd_data[256], msg_data[4]; + int len, offset; + + msg_data[0] = id; + + 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; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + printf(" Device not present (No Response)\n"); + return -1; + } + if (rsp->ccode > 0) { + printf(" Device not present (%s)\n", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + fru.size = (rsp->data[1] << 8) | rsp->data[0]; + fru.access = rsp->data[2] & 0x1; + + lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)", + fru.size, fru.access ? "words" : "bytes"); + + if (fru.size < 1) { + lprintf(LOG_ERR, " Invalid FRU size %d", fru.size); + return -1; + } + + 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; + + offset = 0; + memset(spd_data, 0, 256); + do { + msg_data[0] = id; + msg_data[1] = offset; + msg_data[2] = 0; + msg_data[3] = FRU_DATA_RQST_SIZE; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + printf(" Device not present (No Response)\n"); + return -1; + } + if (rsp->ccode > 0) { + printf(" Device not present (%s)\n", + val2str(rsp->ccode, completion_code_vals)); + + /* Timeouts are acceptable. No DIMM in the socket */ + if (rsp->ccode == 0xc3) + return 1; + + return -1; + } + + len = rsp->data[0]; + memcpy(&spd_data[offset], rsp->data + 1, len); + offset += len; + } while (offset < fru.size); + + /* now print spd info */ + ipmi_spd_print(spd_data, offset); + + return 0; +} diff --git a/lib/helper.c b/lib/helper.c new file mode 100644 index 0000000..4b903b0 --- /dev/null +++ b/lib/helper.c @@ -0,0 +1,789 @@ +/* + * 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 /* For TIOCNOTTY */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_PATHS_H +# include +#else +# define _PATH_VARRUN "/var/run/" +#endif + +#include +#include +#include +#include + +extern int verbose; + +uint32_t buf2long(uint8_t * buf) +{ + return (uint32_t)(buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]); +} + +uint16_t buf2short(uint8_t * buf) +{ + return (uint16_t)(buf[1] << 8 | buf[0]); +} + +const char * buf2str(uint8_t * buf, int len) +{ + static char str[2049]; + int i; + + if (len <= 0 || len > 1024) + return NULL; + + memset(str, 0, 2049); + + for (i=0; i INT32_MAX) + return (-3); + + *int_ptr = (int32_t)arg_long; + return 0; +} /* str2int(...) */ + +/* str2uint - safely convert string to uint32_t + * + * @str: source string to convert from + * @uint_ptr: pointer where to store result + * + * returns zero on success + * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow + */ +int str2uint(const char * str, uint32_t * uint_ptr) +{ + int rc = 0; + uint64_t arg_ulong = 0; + if (!str || !uint_ptr) + return (-1); + + if ( (rc = str2ulong(str, &arg_ulong)) != 0) { + *uint_ptr = 0; + return rc; + } + + if (arg_ulong > UINT32_MAX) + return (-3); + + *uint_ptr = (uint32_t)arg_ulong; + return 0; +} /* str2uint(...) */ + +/* str2short - safely convert string to int16_t + * + * @str: source string to convert from + * @shrt_ptr: pointer where to store result + * + * returns zero on success + * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow + */ +int str2short(const char * str, int16_t * shrt_ptr) +{ + int rc = (-3); + int64_t arg_long = 0; + if (!str || !shrt_ptr) + return (-1); + + if ( (rc = str2long(str, &arg_long)) != 0 ) { + *shrt_ptr = 0; + return rc; + } + + if (arg_long < INT16_MIN || arg_long > INT16_MAX) + return (-3); + + *shrt_ptr = (int16_t)arg_long; + return 0; +} /* str2short(...) */ + +/* str2ushort - safely convert string to uint16_t + * + * @str: source string to convert from + * @ushrt_ptr: pointer where to store result + * + * returns zero on success + * returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow + */ +int str2ushort(const char * str, uint16_t * ushrt_ptr) +{ + int rc = (-3); + uint64_t arg_ulong = 0; + if (!str || !ushrt_ptr) + return (-1); + + if ( (rc = str2ulong(str, &arg_ulong)) != 0 ) { + *ushrt_ptr = 0; + return rc; + } + + if (arg_ulong > UINT16_MAX) + return (-3); + + *ushrt_ptr = (uint16_t)arg_ulong; + return 0; +} /* str2ushort(...) */ + +/* str2char - safely convert string to int8 + * + * @str: source string to convert from + * @chr_ptr: pointer where to store result + * + * returns zero on success + * returns (-1) if one of args is NULL, (-2) or (-3) if conversion fails + */ +int str2char(const char *str, int8_t * chr_ptr) +{ + int rc = (-3); + int64_t arg_long = 0; + if (!str || !chr_ptr) { + return (-1); + } + if ((rc = str2long(str, &arg_long)) != 0) { + *chr_ptr = 0; + return rc; + } + if (arg_long < INT8_MIN || arg_long > INT8_MAX) { + return (-3); + } + return 0; +} /* str2char(...) */ + +/* str2uchar - safely convert string to uint8 + * + * @str: source string to convert from + * @uchr_ptr: pointer where to store result + * + * returns zero on success + * returns (-1) if one of args is NULL, (-2) or (-3) if conversion fails + */ +int str2uchar(const char * str, uint8_t * uchr_ptr) +{ + int rc = (-3); + uint64_t arg_ulong = 0; + if (!str || !uchr_ptr) + return (-1); + + if ( (rc = str2ulong(str, &arg_ulong)) != 0 ) { + *uchr_ptr = 0; + return rc; + } + + if (arg_ulong > UINT8_MAX) + return (-3); + + *uchr_ptr = (uint8_t)arg_ulong; + return 0; +} /* str2uchar(...) */ + +uint16_t str2val(const char *str, const struct valstr *vs) +{ + int i; + + for (i = 0; vs[i].str != NULL; i++) { + if (strncasecmp(vs[i].str, str, __maxlen(str, vs[i].str)) == 0) + return vs[i].val; + } + + return vs[i].val; +} + +/* print_valstr - print value string list to log or stdout + * + * @vs: value string list to print + * @title: name of this value string list + * @loglevel: what log level to print, -1 for stdout + */ +void +print_valstr(const struct valstr * vs, const char * title, int loglevel) +{ + int i; + + if (vs == NULL) + return; + + if (title != NULL) { + if (loglevel < 0) + printf("\n%s:\n\n", title); + else + lprintf(loglevel, "\n%s:\n", title); + } + + if (loglevel < 0) { + printf(" VALUE\tHEX\tSTRING\n"); + printf("==============================================\n"); + } else { + lprintf(loglevel, " VAL\tHEX\tSTRING"); + lprintf(loglevel, "=============================================="); + } + + for (i = 0; vs[i].str != NULL; i++) { + if (loglevel < 0) { + if (vs[i].val < 256) + printf(" %d\t0x%02x\t%s\n", vs[i].val, vs[i].val, vs[i].str); + else + printf(" %d\t0x%04x\t%s\n", vs[i].val, vs[i].val, vs[i].str); + } else { + if (vs[i].val < 256) + lprintf(loglevel, " %d\t0x%02x\t%s", vs[i].val, vs[i].val, vs[i].str); + else + lprintf(loglevel, " %d\t0x%04x\t%s", vs[i].val, vs[i].val, vs[i].str); + } + } + + if (loglevel < 0) + printf("\n"); + else + lprintf(loglevel, ""); +} + +/* print_valstr_2col - print value string list in two columns to log or stdout + * + * @vs: value string list to print + * @title: name of this value string list + * @loglevel: what log level to print, -1 for stdout + */ +void +print_valstr_2col(const struct valstr * vs, const char * title, int loglevel) +{ + int i; + + if (vs == NULL) + return; + + if (title != NULL) { + if (loglevel < 0) + printf("\n%s:\n\n", title); + else + lprintf(loglevel, "\n%s:\n", title); + } + + for (i = 0; vs[i].str != NULL; i++) { + if (vs[i+1].str == NULL) { + /* last one */ + if (loglevel < 0) { + printf(" %4d %-32s\n", vs[i].val, vs[i].str); + } else { + lprintf(loglevel, " %4d %-32s\n", vs[i].val, vs[i].str); + } + } + else { + if (loglevel < 0) { + printf(" %4d %-32s %4d %-32s\n", + vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str); + } else { + lprintf(loglevel, " %4d %-32s %4d %-32s\n", + vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str); + } + i++; + } + } + + if (loglevel < 0) + printf("\n"); + else + lprintf(loglevel, ""); +} + +/* ipmi_csum - calculate an ipmi checksum + * + * @d: buffer to check + * @s: position in buffer to start checksum from + */ +uint8_t +ipmi_csum(uint8_t * d, int s) +{ + uint8_t c = 0; + for (; s > 0; s--, d++) + c += *d; + return -c; +} + +/* ipmi_open_file - safely open a file for reading or writing + * + * @file: filename + * @rw: read-write flag, 1=write + * + * returns pointer to file handler on success + * returns NULL on error + */ +FILE * +ipmi_open_file(const char * file, int rw) +{ + struct stat st1, st2; + FILE * fp; + + /* verify existance */ + if (lstat(file, &st1) < 0) { + if (rw) { + /* does not exist, ok to create */ + fp = fopen(file, "w"); + if (fp == NULL) { + lperror(LOG_ERR, "Unable to open file %s " + "for write", file); + return NULL; + } + /* created ok, now return the descriptor */ + return fp; + } else { + lprintf(LOG_ERR, "File %s does not exist", file); + return NULL; + } + } + +#ifndef ENABLE_FILE_SECURITY + if (!rw) { + /* on read skip the extra checks */ + fp = fopen(file, "r"); + if (fp == NULL) { + lperror(LOG_ERR, "Unable to open file %s", file); + return NULL; + } + return fp; + } +#endif + + /* it exists - only regular files, not links */ + if (S_ISREG(st1.st_mode) == 0) { + lprintf(LOG_ERR, "File %s has invalid mode: %d", + file, st1.st_mode); + return NULL; + } + + /* allow only files with 1 link (itself) */ + if (st1.st_nlink != 1) { + lprintf(LOG_ERR, "File %s has invalid link count: %d != 1", + file, (int)st1.st_nlink); + return NULL; + } + + fp = fopen(file, rw ? "w+" : "r"); + if (fp == NULL) { + lperror(LOG_ERR, "Unable to open file %s", file); + return NULL; + } + + /* stat again */ + if (fstat(fileno(fp), &st2) < 0) { + lperror(LOG_ERR, "Unable to stat file %s", file); + fclose(fp); + return NULL; + } + + /* verify inode */ + if (st1.st_ino != st2.st_ino) { + lprintf(LOG_ERR, "File %s has invalid inode: %d != %d", + file, st1.st_ino, st2.st_ino); + fclose(fp); + return NULL; + } + + /* verify owner */ + if (st1.st_uid != st2.st_uid) { + lprintf(LOG_ERR, "File %s has invalid user id: %d != %d", + file, st1.st_uid, st2.st_uid); + fclose(fp); + return NULL; + } + + /* verify inode */ + if (st2.st_nlink != 1) { + lprintf(LOG_ERR, "File %s has invalid link count: %d != 1", + file, st2.st_nlink); + fclose(fp); + return NULL; + } + + return fp; +} + +void +ipmi_start_daemon(struct ipmi_intf *intf) +{ + pid_t pid; + int fd; +#ifdef SIGHUP + sigset_t sighup; +#endif + +#ifdef SIGHUP + sigemptyset(&sighup); + sigaddset(&sighup, SIGHUP); + if (sigprocmask(SIG_UNBLOCK, &sighup, NULL) < 0) + fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n"); + signal(SIGHUP, SIG_IGN); +#endif +#ifdef SIGTTOU + signal(SIGTTOU, SIG_IGN); +#endif +#ifdef SIGTTIN + signal(SIGTTIN, SIG_IGN); +#endif +#ifdef SIGQUIT + signal(SIGQUIT, SIG_IGN); +#endif +#ifdef SIGTSTP + signal(SIGTSTP, SIG_IGN); +#endif + + pid = (pid_t) fork(); + if (pid < 0 || pid > 0) + exit(0); + +#if defined(SIGTSTP) && defined(TIOCNOTTY) + if (setpgid(0, getpid()) == -1) + exit(1); + if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) { + ioctl(fd, TIOCNOTTY, NULL); + close(fd); + } +#else + if (setpgid(0, 0) == -1) + exit(1); + pid = (pid_t) fork(); + if (pid < 0 || pid > 0) + exit(0); +#endif + + chdir("/"); + umask(0); + + for (fd=0; fd<64; fd++) { + if (fd != intf->fd) + close(fd); + } + + fd = open("/dev/null", O_RDWR); + assert(0 == fd); + dup(fd); + dup(fd); +} + +/* is_fru_id - wrapper for str-2-int FRU ID conversion. Message is printed + * on error. + * FRU ID range: <0..255> + * + * @argv_ptr: source string to convert from; usually argv + * @fru_id_ptr: pointer where to store result + * + * returns zero on success + * returns (-1) on error and message is printed on STDERR + */ +int +is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr) +{ + if (!argv_ptr || !fru_id_ptr) { + lprintf(LOG_ERR, "is_fru_id(): invalid argument(s)."); + return (-1); + } + + if (str2uchar(argv_ptr, fru_id_ptr) == 0) { + return 0; + } + lprintf(LOG_ERR, "FRU ID '%s' is either invalid or out of range.", + argv_ptr); + return (-1); +} /* is_fru_id(...) */ + +/* is_ipmi_channel_num - wrapper for str-2-int Channel conversion. Message is + * printed on error. + * + * 6.3 Channel Numbers, p. 45, IPMIv2 spec. + * Valid channel numbers are: <0..7>, + * Reserved channel numbers: <8-D> + * + * @argv_ptr: source string to convert from; usually argv + * @channel_ptr: pointer where to store result + * + * returns zero on success + * returns (-1) on error and message is printed on STDERR + */ +int +is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr) +{ + if (!argv_ptr || !channel_ptr) { + lprintf(LOG_ERR, + "is_ipmi_channel_num(): invalid argument(s)."); + return (-1); + } + if ((str2uchar(argv_ptr, channel_ptr) == 0) + && ((*channel_ptr >= 0x0 && *channel_ptr <= 0x7) + || (*channel_ptr >= 0xE && *channel_ptr <= 0xF))) { + return 0; + } + lprintf(LOG_ERR, + "Given Channel number '%s' is either invalid or out of range.", + argv_ptr); + lprintf(LOG_ERR, "Channel number must be from ranges: <0..7>, <0xE..0xF>"); + return (-1); +} + +/* is_ipmi_user_id() - wrapper for str-2-uint IPMI UID conversion. Message is + * printed on error. + * + * @argv_ptr: source string to convert from; usually argv + * @ipmi_uid_ptr: pointer where to store result + * + * returns zero on success + * returns (-1) on error and message is printed on STDERR + */ +int +is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr) +{ + if (!argv_ptr || !ipmi_uid_ptr) { + lprintf(LOG_ERR, + "is_ipmi_user_id(): invalid argument(s)."); + return (-1); + } + if ((str2uchar(argv_ptr, ipmi_uid_ptr) == 0) + && *ipmi_uid_ptr >= IPMI_UID_MIN + && *ipmi_uid_ptr <= IPMI_UID_MAX) { + return 0; + } + lprintf(LOG_ERR, + "Given User ID '%s' is either invalid or out of range.", + argv_ptr); + lprintf(LOG_ERR, "User ID is limited to range <%i..%i>.", + IPMI_UID_MIN, IPMI_UID_MAX); + return (-1); +} + +uint16_t +ipmi_get_oem_id(struct ipmi_intf *intf) +{ + /* Execute a Get Board ID command to determine the board */ + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint16_t oem_id; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_TSOL; + req.msg.cmd = 0x21; + req.msg.data_len = 0; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Get Board ID command failed"); + return 0; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Board ID command failed: %#x %s", + rsp->ccode, val2str(rsp->ccode, completion_code_vals)); + return 0; + } + oem_id = rsp->data[0] | (rsp->data[1] << 8); + lprintf(LOG_DEBUG,"Board ID: %x", oem_id); + + return oem_id; +} diff --git a/lib/hpm2.c b/lib/hpm2.c new file mode 100644 index 0000000..e7d6c03 --- /dev/null +++ b/lib/hpm2.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2012 Pigeon Point Systems. 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 Pigeon Point Systems 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 "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. + * PIGEON POINT SYSTEMS ("PPS") 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 + * PPS 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 PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#if HAVE_PRAGMA_PACK +# pragma pack(push, 1) +#endif + +/* HPM.x Get Capabilities request */ +struct hpmx_cmd_get_capabilities_rq { + uint8_t picmg_id; + uint8_t hpmx_id; +} ATTRIBUTE_PACKING; + +/* HPM.2 Get Capabilities response */ +struct hpm2_cmd_get_capabilities_rp { + uint8_t picmg_id; + struct hpm2_lan_attach_capabilities caps; +} ATTRIBUTE_PACKING; + +#if HAVE_PRAGMA_PACK +# pragma pack(pop) +#endif + +/* IPMI Get LAN Configuration Parameters command */ +#define IPMI_LAN_GET_CONFIG 0x02 + +int hpm2_get_capabilities(struct ipmi_intf * intf, + struct hpm2_lan_attach_capabilities * caps) +{ + struct ipmi_rq req; + struct ipmi_rs * rsp; + struct hpmx_cmd_get_capabilities_rq rq; + + /* reset result */ + memset(caps, 0, sizeof(struct hpm2_lan_attach_capabilities)); + + /* prepare request */ + rq.picmg_id = 0; + rq.hpmx_id = 2; + + /* prepare request */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_PICMG; + req.msg.cmd = HPM2_GET_LAN_ATTACH_CAPABILITIES; + req.msg.data = (uint8_t *)&rq; + req.msg.data_len = sizeof(rq); + + + /* send */ + rsp = intf->sendrecv(intf, &req); + + if (!rsp) { + lprintf(LOG_NOTICE, "Error sending request."); + return -1; + } + + if (rsp->ccode == 0xC1) { + lprintf(LOG_DEBUG, "IPM Controller is not HPM.2 compatible"); + return rsp->ccode; + } else if (rsp->ccode) { + lprintf(LOG_NOTICE, "Get HPM.x Capabilities request failed," + " compcode = %x", rsp->ccode); + return rsp->ccode; + } + + /* check response length */ + if (rsp->data_len < 2 || rsp->data_len > 10) { + lprintf(LOG_NOTICE, "Bad response length, len=%d", rsp->data_len); + return -1; + } + + /* check HPM.x identifier */ + if (rsp->data[1] != 2) { + lprintf(LOG_NOTICE, "Bad HPM.x ID, id=%d", rsp->data[1]); + return rsp->ccode; + } + + /* + * this hardly can happen, since completion code is already checked. + * but check for safety + */ + if (rsp->data_len < 4) { + lprintf(LOG_NOTICE, "Bad response length, len=%d", rsp->data_len); + return -1; + } + + /* copy HPM.2 capabilities */ + memcpy(caps, rsp->data + 2, rsp->data_len - 2); + +#if WORDS_BIGENDIAN + /* swap bytes to convert from little-endian format */ + caps->lan_channel_mask = BSWAP_16(caps->lan_channel_mask); +#endif + + /* check HPM.2 revision */ + if (caps->hpm2_revision_id != HPM2_REVISION) { + lprintf(LOG_NOTICE, "Bad HPM.2 revision, rev=%d", + caps->hpm2_revision_id); + return -1; + } + + if (!caps->lan_channel_mask) { + return -1; + } + + /* check response length */ + if (rsp->data_len < 8) { + lprintf(LOG_NOTICE, "Bad response length, len=%d", rsp->data_len); + return -1; + } + + /* check HPM.2 LAN parameters start */ + if (caps->hpm2_lan_params_start < 0xC0) { + lprintf(LOG_NOTICE, "Bad HPM.2 LAN params start, start=%x", + caps->hpm2_lan_params_start); + return -1; + } + + /* check HPM.2 LAN parameters revision */ + if (caps->hpm2_lan_params_rev != HPM2_LAN_PARAMS_REV) { + lprintf(LOG_NOTICE, "Bad HPM.2 LAN params revision, rev=%d", + caps->hpm2_lan_params_rev); + return -1; + } + + /* check for HPM.2 SOL extension */ + if (!(caps->hpm2_caps & HPM2_CAPS_SOL_EXTENSION)) { + /* no further checks */ + return 0; + } + + /* check response length */ + if (rsp->data_len < 10) { + lprintf(LOG_NOTICE, "Bad response length, len=%d", rsp->data_len); + return -1; + } + + /* check HPM.2 SOL parameters start */ + if (caps->hpm2_sol_params_start < 0xC0) { + lprintf(LOG_NOTICE, "Bad HPM.2 SOL params start, start=%x", + caps->hpm2_sol_params_start); + return -1; + } + + /* check HPM.2 SOL parameters revision */ + if (caps->hpm2_sol_params_rev != HPM2_SOL_PARAMS_REV) { + lprintf(LOG_NOTICE, "Bad HPM.2 SOL params revision, rev=%d", + caps->hpm2_sol_params_rev); + return -1; + } + + return 0; +} + +int hpm2_get_lan_channel_capabilities(struct ipmi_intf * intf, + uint8_t hpm2_lan_params_start, + struct hpm2_lan_channel_capabilities * caps) +{ + struct ipmi_rq req; + struct ipmi_rs * rsp; + uint8_t rq[4]; + + /* reset result */ + memset(caps, 0, sizeof(struct hpm2_lan_channel_capabilities)); + + /* prepare request */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_TRANSPORT; + req.msg.cmd = IPMI_LAN_GET_CONFIG; + req.msg.data = (uint8_t *)&rq; + req.msg.data_len = sizeof(rq); + + /* prepare request data */ + rq[0] = 0xE; /* sending channel */ + rq[1] = hpm2_lan_params_start; /* HPM.2 Channel Caps */ + rq[2] = rq[3] = 0; + + /* send */ + rsp = intf->sendrecv(intf, &req); + + if (rsp) { + lprintf(LOG_NOTICE, "Error sending request"); + return -1; + } + + if (rsp->ccode == 0x80) { + lprintf(LOG_DEBUG, "HPM.2 Channel Caps parameter is not supported"); + return rsp->ccode; + } else if (rsp->ccode) { + lprintf(LOG_NOTICE, "Get LAN Configuration Parameters request failed," + " compcode = %x", rsp->ccode); + return rsp->ccode; + } + + /* check response length */ + if (rsp->data_len != sizeof (struct hpm2_lan_channel_capabilities) + 1) { + lprintf(LOG_NOTICE, "Bad response length, len=%d", rsp->data_len); + return -1; + } + + /* check parameter revision */ + if (rsp->data[0] != HPM2_LAN_PARAMS_REV) { + lprintf(LOG_NOTICE, "Bad HPM.2 LAN parameter revision, rev=%d", + rsp->data[0]); + return -1; + } + + /* copy parameter data */ + memcpy(caps, &rsp->data[1], sizeof (struct hpm2_lan_channel_capabilities)); + +#if WORDS_BIGENDIAN + /* swap bytes to convert from little-endian format */ + caps->max_inbound_pld_size = BSWAP_16(caps->max_inbound_pld_size); + caps->max_outbound_pld_size = BSWAP_16(caps->max_outbound_pld_size); +#endif + + return 0; +} + +int hpm2_detect_max_payload_size(struct ipmi_intf * intf) +{ + struct hpm2_lan_attach_capabilities attach_caps; + struct hpm2_lan_channel_capabilities channel_caps; + int err; + + /* query HPM.2 support */ + err = hpm2_get_capabilities(intf, &attach_caps); + + /* check if HPM.2 is supported */ + if (err != 0 || !attach_caps.lan_channel_mask) { + return err; + } + + /* query channel capabilities */ + err = hpm2_get_lan_channel_capabilities(intf, + attach_caps.hpm2_lan_params_start, &channel_caps); + + /* check if succeeded */ + if (err != 0) { + return err; + } + + /* update request and response sizes */ + ipmi_intf_set_max_request_data_size(intf, + channel_caps.max_inbound_pld_size - 7); + ipmi_intf_set_max_response_data_size(intf, + channel_caps.max_outbound_pld_size - 8); + + /* print debug info */ + lprintf(LOG_DEBUG, "Set maximum request size to %d\n" + "Set maximum response size to %d", + intf->max_request_data_size, intf->max_response_data_size); + + return 0; +} diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c new file mode 100644 index 0000000..43db338 --- /dev/null +++ b/lib/ipmi_channel.c @@ -0,0 +1,903 @@ +/* -*-mode: C; indent-tabs-mode: t; -*- + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +extern int csv_output; +extern int verbose; + +void printf_channel_usage (void); + +/** + * ipmi_1_5_authtypes + * + * Create a string describing the supported authentication types as + * specificed by the parameter n + */ +static const char * +ipmi_1_5_authtypes(uint8_t n) +{ + uint32_t i; + static char supportedTypes[128]; + + bzero(supportedTypes, 128); + + for (i = 0; ipmi_authtype_vals[i].val != 0; i++) { + if (n & ipmi_authtype_vals[i].val) { + strcat(supportedTypes, ipmi_authtype_vals[i].str); + strcat(supportedTypes, " "); + } + } + + return supportedTypes; +} + + + +/** + * ipmi_get_channel_auth_cap + * + * return 0 on success + * -1 on failure + */ +int +ipmi_get_channel_auth_cap(struct ipmi_intf * intf, + uint8_t channel, + uint8_t priv) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + struct get_channel_auth_cap_rsp auth_cap; + uint8_t msg_data[2]; + + msg_data[0] = channel | 0x80; // Ask for IPMI v2 data as well + msg_data[1] = priv; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_APP; // 0x06 + req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP; // 0x38 + req.msg.data = msg_data; + req.msg.data_len = 2; + + rsp = intf->sendrecv(intf, &req); + + if ((rsp == NULL) || (rsp->ccode > 0)) { + /* + * It's very possible that this failed because we asked for IPMI v2 data + * Ask again, without requesting IPMI v2 data + */ + msg_data[0] &= 0x7F; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to Get Channel Authentication Capabilities"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Channel Authentication Capabilities failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + } + + memcpy(&auth_cap, rsp->data, sizeof(struct get_channel_auth_cap_rsp)); + + printf("Channel number : %d\n", + auth_cap.channel_number); + printf("IPMI v1.5 auth types : %s\n", + ipmi_1_5_authtypes(auth_cap.enabled_auth_types)); + + if (auth_cap.v20_data_available) + printf("KG status : %s\n", + (auth_cap.kg_status) ? "non-zero" : "default (all zeroes)"); + + printf("Per message authentication : %sabled\n", + (auth_cap.per_message_auth) ? "dis" : "en"); + printf("User level authentication : %sabled\n", + (auth_cap.user_level_auth) ? "dis" : "en"); + + printf("Non-null user names exist : %s\n", + (auth_cap.non_null_usernames) ? "yes" : "no"); + printf("Null user names exist : %s\n", + (auth_cap.null_usernames) ? "yes" : "no"); + printf("Anonymous login enabled : %s\n", + (auth_cap.anon_login_enabled) ? "yes" : "no"); + + if (auth_cap.v20_data_available) { + printf("Channel supports IPMI v1.5 : %s\n", + (auth_cap.ipmiv15_support) ? "yes" : "no"); + printf("Channel supports IPMI v2.0 : %s\n", + (auth_cap.ipmiv20_support) ? "yes" : "no"); + } + + /* + * If there is support for an OEM authentication type, there is some + * information. + */ + if (auth_cap.enabled_auth_types & IPMI_1_5_AUTH_TYPE_BIT_OEM) { + printf("IANA Number for OEM : %d\n", + auth_cap.oem_id[0] | + auth_cap.oem_id[1] << 8 | + auth_cap.oem_id[2] << 16); + printf("OEM Auxiliary Data : 0x%x\n", + auth_cap.oem_aux_data); + } + + return 0; +} + + + +/** + * ipmi_get_channel_info + * + * returns 0 on success + * -1 on failure + * + */ +int +ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + uint8_t rqdata[2]; + uint8_t medium; + struct get_channel_info_rsp channel_info; + struct get_channel_access_rsp channel_access; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_APP; // 0x06 + req.msg.cmd = IPMI_GET_CHANNEL_INFO; // 0x42 + req.msg.data = &channel; + req.msg.data_len = 1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to Get Channel Info"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Channel Info failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + memcpy(&channel_info, rsp->data, sizeof(struct get_channel_info_rsp)); + + printf("Channel 0x%x info:\n", channel_info.channel_number); + + printf(" Channel Medium Type : %s\n", + val2str(channel_info.channel_medium, ipmi_channel_medium_vals)); + + printf(" Channel Protocol Type : %s\n", + val2str(channel_info.channel_protocol, ipmi_channel_protocol_vals)); + + printf(" Session Support : "); + switch (channel_info.session_support) { + case 0x0: + printf("session-less\n"); + break; + case 0x1: + printf("single-session\n"); + break; + case 0x2: + printf("multi-session\n"); + break; + case 0x3: + default: + printf("session-based\n"); + break; + } + + printf(" Active Session Count : %d\n", + channel_info.active_sessions); + + printf(" Protocol Vendor ID : %d\n", + channel_info.vendor_id[0] | + channel_info.vendor_id[1] << 8 | + channel_info.vendor_id[2] << 16); + + + /* only proceed if this is LAN channel */ + medium = ipmi_get_channel_medium(intf, channel); + if (medium != IPMI_CHANNEL_MEDIUM_LAN && + medium != IPMI_CHANNEL_MEDIUM_LAN_OTHER) { + return 0; + } + + memset(&req, 0, sizeof(req)); + rqdata[0] = channel & 0xf; + + /* get volatile settings */ + + rqdata[1] = 0x80; /* 0x80=active */ + req.msg.netfn = IPMI_NETFN_APP; // 0x06 + req.msg.cmd = IPMI_GET_CHANNEL_ACCESS; // 0x41 + req.msg.data = rqdata; + req.msg.data_len = 2; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to Get Channel Access (volatile)"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Channel Access (volatile) failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + memcpy(&channel_access, rsp->data, sizeof(struct get_channel_access_rsp)); + + + printf(" Volatile(active) Settings\n"); + printf(" Alerting : %sabled\n", + (channel_access.alerting) ? "dis" : "en"); + printf(" Per-message Auth : %sabled\n", + (channel_access.per_message_auth) ? "dis" : "en"); + printf(" User Level Auth : %sabled\n", + (channel_access.user_level_auth) ? "dis" : "en"); + + printf(" Access Mode : "); + switch (channel_access.access_mode) { + case 0: + printf("disabled\n"); + break; + case 1: + printf("pre-boot only\n"); + break; + case 2: + printf("always available\n"); + break; + case 3: + printf("shared\n"); + break; + default: + printf("unknown\n"); + break; + } + + /* get non-volatile settings */ + + rqdata[1] = 0x40; /* 0x40=non-volatile */ + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to Get Channel Access (non-volatile)"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Channel Access (non-volatile) failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + memcpy(&channel_access, rsp->data, sizeof(struct get_channel_access_rsp)); + + printf(" Non-Volatile Settings\n"); + printf(" Alerting : %sabled\n", + (channel_access.alerting) ? "dis" : "en"); + printf(" Per-message Auth : %sabled\n", + (channel_access.per_message_auth) ? "dis" : "en"); + printf(" User Level Auth : %sabled\n", + (channel_access.user_level_auth) ? "dis" : "en"); + + printf(" Access Mode : "); + switch (channel_access.access_mode) { + case 0: + printf("disabled\n"); + break; + case 1: + printf("pre-boot only\n"); + break; + case 2: + printf("always available\n"); + break; + case 3: + printf("shared\n"); + break; + default: + printf("unknown\n"); + break; + } + + return 0; +} + +static int +ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req1, req2; + uint8_t rqdata[2]; + struct get_user_access_rsp user_access; + int curr_uid, max_uid = 0, init = 1; + + curr_uid = userid ? : 1; + + memset(&req1, 0, sizeof(req1)); + req1.msg.netfn = IPMI_NETFN_APP; + req1.msg.cmd = IPMI_GET_USER_ACCESS; + req1.msg.data = rqdata; + req1.msg.data_len = 2; + + memset(&req2, 0, sizeof(req2)); + req2.msg.netfn = IPMI_NETFN_APP; + req2.msg.cmd = IPMI_GET_USER_NAME; + req2.msg.data = rqdata; + req2.msg.data_len = 1; + + do + { + rqdata[0] = channel & 0xf; + rqdata[1] = curr_uid & 0x3f; + + rsp = intf->sendrecv(intf, &req1); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to Get User Access (channel %d id %d)", + rqdata[0], rqdata[1]); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get User Access (channel %d id %d) failed: %s", + rqdata[0], rqdata[1], + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp)); + + rqdata[0] = curr_uid & 0x3f; + + rsp = intf->sendrecv(intf, &req2); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to Get User Name (id %d)", rqdata[0]); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get User Name (id %d) failed: %s", + rqdata[0], val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + if (init) { + printf("Maximum User IDs : %d\n", user_access.max_user_ids); + printf("Enabled User IDs : %d\n", user_access.enabled_user_ids); + max_uid = user_access.max_user_ids; + init = 0; + } + + printf("\n"); + printf("User ID : %d\n", curr_uid); + printf("User Name : %s\n", rsp->data); + printf("Fixed Name : %s\n", + (curr_uid <= user_access.fixed_user_ids) ? "Yes" : "No"); + printf("Access Available : %s\n", + (user_access.callin_callback) ? "callback" : "call-in / callback"); + printf("Link Authentication : %sabled\n", + (user_access.link_auth) ? "en" : "dis"); + printf("IPMI Messaging : %sabled\n", + (user_access.ipmi_messaging) ? "en" : "dis"); + printf("Privilege Level : %s\n", + val2str(user_access.privilege_limit, ipmi_privlvl_vals)); + + curr_uid ++; + + } while (!userid && curr_uid <= max_uid); + + return 0; +} + +static int +ipmi_set_user_access(struct ipmi_intf * intf, int argc, char ** argv) +{ + uint8_t channel, privilege_limit, userid; + struct ipmi_rs * rsp; + struct ipmi_rq req; + uint8_t rqdata[2]; + struct get_user_access_rsp user_access; + struct set_user_access_data set_access; + int i; + + if ((argc < 3) || (strncmp(argv[0], "help", 4) == 0)) { + printf_channel_usage(); + return 0; + } + + if (str2uchar(argv[0], &channel) != 0) { + lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[0]); + return (-1); + } + if (str2uchar(argv[1], &userid) != 0) { + lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]); + return (-1); + } + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_APP; + req.msg.cmd = IPMI_GET_USER_ACCESS; + req.msg.data = rqdata; + req.msg.data_len = 2; + + rqdata[0] = channel & 0xf; + rqdata[1] = userid & 0x3f; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to Get User Access (channel %d id %d)", + rqdata[0], rqdata[1]); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get User Access (channel %d id %d) failed: %s", + rqdata[0], rqdata[1], + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp)); + + memset(&set_access, 0, sizeof(set_access)); + set_access.change_bits = 1; + set_access.callin_callback = user_access.callin_callback; + set_access.link_auth = user_access.link_auth; + set_access.ipmi_messaging = user_access.ipmi_messaging; + set_access.channel = channel; + set_access.user_id = userid; + set_access.privilege_limit = user_access.privilege_limit; + set_access.session_limit = 0; + + for (i = 2; i < argc; i ++) + { + if (strncmp(argv[i], "callin=", 7) == 0) { + set_access.callin_callback = !(strncmp (argv[i]+7, "off", 3)); + } + else if (strncmp(argv[i], "link=", 5) == 0) { + set_access.link_auth = strncmp (argv[i]+5, "off", 3); + } + else if (strncmp(argv[i], "ipmi=", 5) == 0) { + set_access.ipmi_messaging = strncmp (argv[i]+5, "off", 3); + } + else if (strncmp(argv[i], "privilege=", 10) == 0) { + if (str2uchar(argv[i]+10, &privilege_limit) != 0) { + lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[i]+10); + return (-1); + } + set_access.privilege_limit = privilege_limit; + } + else { + printf ("Invalid option: %s\n", argv [i]); + return -1; + } + } + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_APP; + req.msg.cmd = IPMI_SET_USER_ACCESS; + req.msg.data = (uint8_t *) &set_access; + req.msg.data_len = 4; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to Set User Access (channel %d id %d)", + set_access.channel, set_access.user_id); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Set User Access (channel %d id %d) failed: %s", + set_access.channel, set_access.user_id, + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + return 0; +} + + +static const char * +iana_string(uint32_t iana) +{ + static char s[10]; + + if (iana) + { + sprintf(s, "%06x", iana); + return s; + } + else + return "N/A"; +} + + +static int +ipmi_get_channel_cipher_suites(struct ipmi_intf * intf, + const char * payload_type, + uint8_t channel) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + + uint8_t oem_record; + uint8_t rqdata[3]; + uint32_t iana; + uint8_t auth_alg, integrity_alg, crypt_alg; + uint8_t cipher_suite_id; + uint8_t list_index = 0; + uint8_t cipher_suite_data[1024]; // 0x40 sets * 16 bytes per set + uint16_t offset = 0; + uint16_t cipher_suite_data_length = 0; // how much was returned, total + + memset(cipher_suite_data, 0, sizeof(cipher_suite_data)); + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_APP; // 0x06 + req.msg.cmd = IPMI_GET_CHANNEL_CIPHER_SUITES; // 0x54 + req.msg.data = rqdata; + req.msg.data_len = 3; + + rqdata[0] = channel; + rqdata[1] = ((strncmp(payload_type, "ipmi", 4) == 0)? 0: 1); + rqdata[2] = 0x80; // Always ask for cipher suite format + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + + // Grab the returned channel number once. We assume it's the same + // in future calls. + if (rsp->data_len >= 1) + channel = rsp->data[0]; + + while ((rsp->data_len > 1) && (rsp->data_len == 17) && (list_index < 0x3F)) + { + // + // We got back cipher suite data -- store it. + //printf("copying data to offset %d\n", offset); + //printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data"); + memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1); + offset += rsp->data_len - 1; + + // + // Increment our list for the next call + // + ++list_index; + rqdata[2] = (rqdata[2] & 0x80) + list_index; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + } + + /* Copy last chunk */ + if(rsp->data_len > 1) + { + // + // We got back cipher suite data -- store it. + //printf("copying data to offset %d\n", offset); + //printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data"); + memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1); + offset += rsp->data_len - 1; + } + + // + // We can chomp on all our data now. + // + cipher_suite_data_length = offset; + offset = 0; + + if (! csv_output) + printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n"); + + while (offset < cipher_suite_data_length) + { + if (cipher_suite_data[offset++] == 0xC0) + { + oem_record = 0; // standard type + iana = 0; + + // Verify that we have at least a full record left + if ((cipher_suite_data_length - offset) < 4) // id + 3 algs + { + lprintf(LOG_ERR, "Incomplete data record in cipher suite data"); + return -1; + } + + cipher_suite_id = cipher_suite_data[offset++]; + + } + else if (cipher_suite_data[offset++] == 0xC1) + { + oem_record = 1; // OEM record type + + // Verify that we have at least a full record left + if ((cipher_suite_data_length - offset) < 4) // id + iana + 3 algs + { + lprintf(LOG_ERR, "Incomplete data record in cipher suite data"); + return -1; + } + + cipher_suite_id = cipher_suite_data[offset++]; + + // + // Grab the IANA + // + iana = + cipher_suite_data[offset] | + (cipher_suite_data[offset + 1] << 8) | + (cipher_suite_data[offset + 2] << 16); + offset += 3; + } + else + { + lprintf(LOG_ERR, "Bad start of record byte in cipher suite data"); + return -1; + } + + // + // Grab the algorithms for this cipher suite. I guess we can't be + // sure of what order they'll come in. Also, I suppose we default + // to the NONE algorithm if one were absent. This part of the spec is + // poorly written -- I have read the errata document. For now, I'm only + // allowing one algorithm per type (auth, integrity, crypt) because I + // don't I understand how it could be otherwise. + // + auth_alg = IPMI_AUTH_RAKP_NONE; + integrity_alg = IPMI_INTEGRITY_NONE; + crypt_alg = IPMI_CRYPT_NONE; + + while (((cipher_suite_data[offset] & 0xC0) != 0xC0) && + ((cipher_suite_data_length - offset) > 0)) + { + switch (cipher_suite_data[offset] & 0xC0) + { + case 0x00: + // Authentication algorithm specifier + auth_alg = cipher_suite_data[offset++] & 0x3F; + break; + case 0x40: + // Interity algorithm specifier + integrity_alg = cipher_suite_data[offset++] & 0x3F; + break; + case 0x80: + // Confidentiality algorithm specifier + crypt_alg = cipher_suite_data[offset++] & 0x3F; + break; + } + } + + + // + // We have everything we need to spit out a cipher suite record + // + printf((csv_output? "%d,%s,%s,%s,%s\n" : + "%-4d %-7s %-15s %-15s %-15s\n"), + cipher_suite_id, + iana_string(iana), + val2str(auth_alg, ipmi_auth_algorithms), + val2str(integrity_alg, ipmi_integrity_algorithms), + val2str(crypt_alg, ipmi_encryption_algorithms)); + } + + + return 0; +} + + + +uint8_t +ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + struct get_channel_info_rsp info; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_APP; + req.msg.cmd = IPMI_GET_CHANNEL_INFO; + req.msg.data = &channel; + req.msg.data_len = 1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Get Channel Info command failed"); + return 0; + } + if (rsp->ccode > 0) { + if (rsp->ccode == 0xcc) + return IPMI_CHANNEL_MEDIUM_RESERVED; + lprintf(LOG_INFO, "Get Channel Info command failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return IPMI_CHANNEL_MEDIUM_RESERVED; + } + + memcpy(&info, rsp->data, sizeof(struct get_channel_info_rsp)); + + lprintf(LOG_DEBUG, "Channel type: %s", + val2str(info.channel_medium, ipmi_channel_medium_vals)); + + return info.channel_medium; +} + +uint8_t +ipmi_current_channel_medium(struct ipmi_intf * intf) +{ + return ipmi_get_channel_medium(intf, 0xE); +} + +void +printf_channel_usage() +{ + lprintf(LOG_NOTICE, "Channel Commands: authcap "); + lprintf(LOG_NOTICE, " getaccess [user id]"); + lprintf(LOG_NOTICE, " setaccess " + " [callin=on|off] [ipmi=on|off] [link=on|off] [privilege=level]"); + lprintf(LOG_NOTICE, " info [channel number]"); + lprintf(LOG_NOTICE, " getciphers [channel]\n"); + lprintf(LOG_NOTICE, "Possible privilege levels are:"); + lprintf(LOG_NOTICE, " 1 Callback level"); + lprintf(LOG_NOTICE, " 2 User level"); + lprintf(LOG_NOTICE, " 3 Operator level"); + lprintf(LOG_NOTICE, " 4 Administrator level"); + lprintf(LOG_NOTICE, " 5 OEM Proprietary level"); + lprintf(LOG_NOTICE, " 15 No access"); +} + + +int +ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv) +{ + int retval = 0; + uint8_t channel, priv = 0; + + if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) + { + printf_channel_usage(); + } + else if (strncmp(argv[0], "authcap", 7) == 0) + { + if (argc != 3) { + printf_channel_usage(); + return (-1); + } else { + if (str2uchar(argv[1], &channel) != 0) { + lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]); + return (-1); + } + if (str2uchar(argv[2], &priv) != 0) { + lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]); + return (-1); + } + retval = ipmi_get_channel_auth_cap(intf, channel, priv); + } + } + else if (strncmp(argv[0], "getaccess", 10) == 0) + { + if ((argc < 2) || (argc > 3)) + printf_channel_usage(); + else { + uint8_t ch = 0; + uint8_t id = 0; + if (str2uchar(argv[1], &ch) != 0) { + lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]); + return (-1); + } + if (argc == 3) { + if (str2uchar(argv[2], &id) != 0) { + lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]); + return (-1); + } + } + retval = ipmi_get_user_access(intf, ch, id); + } + } + else if (strncmp(argv[0], "setaccess", 9) == 0) + { + retval = ipmi_set_user_access(intf, argc-1, &(argv[1])); + } + else if (strncmp(argv[0], "info", 4) == 0) + { + if (argc > 2) + printf_channel_usage(); + else { + uint8_t ch = 0xe; + if (argc == 2) { + if (str2uchar(argv[1], &ch) != 0) { + lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]); + return (-1); + } + } + retval = ipmi_get_channel_info(intf, ch); + } + } + + // it channel getciphers [channel] + else if (strncmp(argv[0], "getciphers", 10) == 0) + { + if ((argc < 2) || (argc > 3) || + (strncmp(argv[1], "ipmi", 4) && strncmp(argv[1], "sol", 3))) + printf_channel_usage(); + else + { + uint8_t ch = 0xe; + if (argc == 3) { + if (str2uchar(argv[2], &ch) != 0) { + lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]); + return (-1); + } + } + retval = ipmi_get_channel_cipher_suites(intf, + argv[1], // ipmi | sol + ch); + } + } + else + { + printf("Invalid CHANNEL command: %s\n", argv[0]); + printf_channel_usage(); + retval = -1; + } + + return retval; +} diff --git a/lib/ipmi_chassis.c b/lib/ipmi_chassis.c new file mode 100644 index 0000000..d4e88ee --- /dev/null +++ b/lib/ipmi_chassis.c @@ -0,0 +1,1393 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include + +extern int verbose; + +int +ipmi_chassis_power_status(struct ipmi_intf * intf) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_CHASSIS; + req.msg.cmd = 0x1; + req.msg.data_len = 0; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to get Chassis Power Status"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Chassis Power Status failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + return rsp->data[0] & 1; +} + +static int +ipmi_chassis_print_power_status(struct ipmi_intf * intf) +{ + int ps = ipmi_chassis_power_status(intf); + + if (ps < 0) + return -1; + + printf("Chassis Power is %s\n", ps ? "on" : "off"); + + return 0; +} + +int +ipmi_chassis_power_control(struct ipmi_intf * intf, uint8_t ctl) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_CHASSIS; + req.msg.cmd = 0x2; + req.msg.data = &ctl; + req.msg.data_len = 1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to set Chassis Power Control to %s", + val2str(ctl, ipmi_chassis_power_control_vals)); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Set Chassis Power Control to %s failed: %s", + val2str(ctl, ipmi_chassis_power_control_vals), + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + printf("Chassis Power Control: %s\n", + val2str(ctl, ipmi_chassis_power_control_vals)); + +#if 0 /* this can cause sessions to hang around after power commands */ + /* sessions often get lost when changing chassis power */ + intf->abort = 1; +#endif + + return 0; +} + +static int +ipmi_chassis_identify(struct ipmi_intf * intf, char * arg) +{ + struct ipmi_rq req; + struct ipmi_rs * rsp; + int rc = (-3); + + struct { + uint8_t interval; + uint8_t force_on; + } identify_data = { .interval = 0, .force_on = 0 }; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_CHASSIS; + req.msg.cmd = 0x4; + + if (arg != NULL) { + if (strncmp(arg, "force", 5) == 0) { + identify_data.force_on = 1; + } else { + if ( (rc = str2uchar(arg, &identify_data.interval)) != 0) { + if (rc == (-2)) { + lprintf(LOG_ERR, "Invalid interval given."); + } else { + lprintf(LOG_ERR, "Given interval is too big."); + } + return (-1); + } + } + req.msg.data = (uint8_t *)&identify_data; + /* The Force Identify On byte is optional and not + * supported by all devices-- if force is not specified, + * we pass only one data byte; if specified, we pass two + * data bytes and check for an error completion code + */ + req.msg.data_len = (identify_data.force_on) ? 2 : 1; + } + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to set Chassis Identify"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Set Chassis Identify failed: %s", + val2str(rsp->ccode, completion_code_vals)); + if (identify_data.force_on != 0) { + /* Intel SE7501WV2 F/W 1.2 returns CC 0xC7, but + * the IPMI v1.5 spec does not standardize a CC + * if unsupported, so we warn + */ + lprintf(LOG_WARNING, "Chassis may not support Force Identify On\n"); + } + return -1; + } + + printf("Chassis identify interval: "); + if (arg == NULL) { + printf("default (15 seconds)\n"); + } else { + if (identify_data.force_on != 0) { + printf("indefinite\n"); + } else { + if (identify_data.interval == 0) + printf("off\n"); + else + printf("%i seconds\n", identify_data.interval); + } + } + return 0; +} + +static int +ipmi_chassis_poh(struct ipmi_intf * intf) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + uint8_t mins_per_count; + uint32_t count; + float minutes; + uint32_t days, hours; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_CHASSIS; + req.msg.cmd = 0xf; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to get Chassis Power-On-Hours"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Chassis Power-On-Hours failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + mins_per_count = rsp->data[0]; + memcpy(&count, rsp->data+1, 4); +#if WORDS_BIGENDIAN + count = BSWAP_32(count); +#endif + + minutes = (float)count * mins_per_count; + days = minutes / 1440; + minutes -= (float)days * 1440; + hours = minutes / 60; + minutes -= hours * 60; + + if (mins_per_count < 60) { + printf("POH Counter : %i days, %i hours, %li minutes\n", + days, hours, (long)minutes); + } else { + printf("POH Counter : %i days, %i hours\n", days, hours); + } + + return 0; +} + +static int +ipmi_chassis_restart_cause(struct ipmi_intf * intf) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_CHASSIS; + req.msg.cmd = 0x7; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Unable to get Chassis Restart Cause"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Chassis Restart Cause failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + printf("System restart cause: "); + + switch (rsp->data[0] & 0xf) { + case 0: + printf("unknown\n"); + break; + case 1: + printf("chassis power control command\n"); + break; + case 2: + printf("reset via pushbutton\n"); + break; + case 3: + printf("power-up via pushbutton\n"); + break; + case 4: + printf("watchdog expired\n"); + break; + case 5: + printf("OEM\n"); + break; + case 6: + printf("power-up due to always-restore power policy\n"); + break; + case 7: + printf("power-up due to restore-previous power policy\n"); + break; + case 8: + printf("reset via PEF\n"); + break; + case 9: + printf("power-cycle via PEF\n"); + break; + default: + printf("invalid\n"); + } + + return 0; +} + +int +ipmi_chassis_status(struct ipmi_intf * intf) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_CHASSIS; + req.msg.cmd = 0x1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Error sending Chassis Status command"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Error sending Chassis Status command: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + /* byte 1 */ + printf("System Power : %s\n", (rsp->data[0] & 0x1) ? "on" : "off"); + printf("Power Overload : %s\n", (rsp->data[0] & 0x2) ? "true" : "false"); + printf("Power Interlock : %s\n", (rsp->data[0] & 0x4) ? "active" : "inactive"); + printf("Main Power Fault : %s\n", (rsp->data[0] & 0x8) ? "true" : "false"); + printf("Power Control Fault : %s\n", (rsp->data[0] & 0x10) ? "true" : "false"); + printf("Power Restore Policy : "); + switch ((rsp->data[0] & 0x60) >> 5) { + case 0x0: + printf("always-off\n"); + break; + case 0x1: + printf("previous\n"); + break; + case 0x2: + printf("always-on\n"); + break; + case 0x3: + default: + printf("unknown\n"); + } + + /* byte 2 */ + printf("Last Power Event : "); + if (rsp->data[1] & 0x1) + printf("ac-failed "); + if (rsp->data[1] & 0x2) + printf("overload "); + if (rsp->data[1] & 0x4) + printf("interlock "); + if (rsp->data[1] & 0x8) + printf("fault "); + if (rsp->data[1] & 0x10) + printf("command"); + printf("\n"); + + /* byte 3 */ + printf("Chassis Intrusion : %s\n", (rsp->data[2] & 0x1) ? "active" : "inactive"); + printf("Front-Panel Lockout : %s\n", (rsp->data[2] & 0x2) ? "active" : "inactive"); + printf("Drive Fault : %s\n", (rsp->data[2] & 0x4) ? "true" : "false"); + printf("Cooling/Fan Fault : %s\n", (rsp->data[2] & 0x8) ? "true" : "false"); + + if (rsp->data_len > 3) { + /* optional byte 4 */ + if (rsp->data[3] == 0) { + printf("Front Panel Control : none\n"); + } else { + printf("Sleep Button Disable : %s\n", (rsp->data[3] & 0x80) ? "allowed" : "not allowed"); + printf("Diag Button Disable : %s\n", (rsp->data[3] & 0x40) ? "allowed" : "not allowed"); + printf("Reset Button Disable : %s\n", (rsp->data[3] & 0x20) ? "allowed" : "not allowed"); + printf("Power Button Disable : %s\n", (rsp->data[3] & 0x10) ? "allowed" : "not allowed"); + printf("Sleep Button Disabled: %s\n", (rsp->data[3] & 0x08) ? "true" : "false"); + printf("Diag Button Disabled : %s\n", (rsp->data[3] & 0x04) ? "true" : "false"); + printf("Reset Button Disabled: %s\n", (rsp->data[3] & 0x02) ? "true" : "false"); + printf("Power Button Disabled: %s\n", (rsp->data[3] & 0x01) ? "true" : "false"); + } + } + + return 0; +} + + +static int +ipmi_chassis_selftest(struct ipmi_intf * intf) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_APP; + req.msg.cmd = 0x4; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Error sending Get Self Test command"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Error sending Get Self Test command: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + printf("Self Test Results : "); + switch (rsp->data[0]) { + case 0x55: + printf("passed\n"); + break; + + case 0x56: + printf("not implemented\n"); + break; + + case 0x57: + { + int i; + const struct valstr broken_dev_vals[] = { + { 0, "firmware corrupted" }, + { 1, "boot block corrupted" }, + { 2, "FRU Internal Use Area corrupted" }, + { 3, "SDR Repository empty" }, + { 4, "IPMB not responding" }, + { 5, "cannot access BMC FRU" }, + { 6, "cannot access SDR Repository" }, + { 7, "cannot access SEL Device" }, + { 0xff, NULL }, + }; + printf("device error\n"); + for (i=0; i<8; i++) { + if (rsp->data[1] & (1<data[1]); + break; + + default: + printf("Device-specific failure %02xh:%02xh\n", + rsp->data[0], rsp->data[1]); + break; + } + + return 0; +} + +static int +ipmi_chassis_set_bootparam(struct ipmi_intf * intf, uint8_t param, uint8_t * data, int len) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + uint8_t msg_data[16]; + + memset(msg_data, 0, 16); + msg_data[0] = param & 0x7f; + memcpy(msg_data+1, data, len); + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_CHASSIS; + req.msg.cmd = 0x8; + req.msg.data = msg_data; + req.msg.data_len = len + 1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Error setting Chassis Boot Parameter %d", param); + return -1; + } + if (rsp->ccode > 0) { + if (param != 0) { + lprintf(LOG_ERR, "Set Chassis Boot Parameter %d failed: %s", + param, val2str(rsp->ccode, completion_code_vals)); + } + return -1; + } + + lprintf(LOG_DEBUG, "Chassis Set Boot Parameter %d to %s", param, buf2str(data, len)); + return 0; +} + +static int +ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + uint8_t msg_data[3]; + uint8_t param_id = 0; + + if (arg == NULL) + return -1; + + if (str2uchar(arg, ¶m_id) != 0) { + lprintf(LOG_ERR, "Invalid parameter '%s' given instead of bootparam.", + arg); + return (-1); + } + + memset(msg_data, 0, 3); + + msg_data[0] = param_id & 0x7f; + msg_data[1] = 0; + msg_data[2] = 0; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_CHASSIS; + req.msg.cmd = 0x9; + req.msg.data = msg_data; + req.msg.data_len = 3; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Error Getting Chassis Boot Parameter %s", arg); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Chassis Boot Parameter %s failed: %s", + arg, val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + if (verbose > 2) + printbuf(rsp->data, rsp->data_len, "Boot Option"); + + param_id = 0; + param_id = (rsp->data[1] & 0x7f); + + printf("Boot parameter version: %d\n", rsp->data[0]); + printf("Boot parameter %d is %s\n", rsp->data[1] & 0x7f, + (rsp->data[1] & 0x80) ? "invalid/locked" : "valid/unlocked"); + printf("Boot parameter data: %s\n", buf2str(rsp->data+2, rsp->data_len - 2)); + + switch(param_id) + { + case 0: + { + printf(" Set In Progress : "); + switch((rsp->data[2]) &0x03) + { + case 0: printf("set complete\n"); break; + case 1: printf("set in progress\n"); break; + case 2: printf("commit write\n"); break; + default: printf("error, reserved bit\n"); break; + } + } + break; + case 1: + { + printf(" Service Partition Selector : "); + if((rsp->data[2]) == 0) + { + printf("unspecified\n"); + } + else + { + printf("%d\n",(rsp->data[2])); + } + } + break; + case 2: + { + printf( " Service Partition Scan :\n"); + if((rsp->data[2]&0x03) != 0) + { + if((rsp->data[2]&0x01) == 0x01) + printf(" - Request BIOS to scan\n"); + if((rsp->data[2]&0x02) == 0x02) + printf(" - Service Partition Discovered\n"); + } + else + { + printf(" No flag set\n"); + } + } + break; + case 3: + { + printf( " BMC boot flag valid bit clearing :\n"); + if((rsp->data[2]&0x1f) != 0) + { + if((rsp->data[2]&0x10) == 0x10) + printf(" - Don't clear valid bit on reset/power cycle cause by PEF\n"); + if((rsp->data[2]&0x08) == 0x08) + printf(" - Don't automatically clear boot flag valid bit on timeout\n"); + if((rsp->data[2]&0x04) == 0x04) + printf(" - Don't clear valid bit on reset/power cycle cause by watchdog\n"); + if((rsp->data[2]&0x02) == 0x02) + printf(" - Don't clear valid bit on push button reset // soft reset\n"); + if((rsp->data[2]&0x01) == 0x01) + printf(" - Don't clear valid bit on power up via power push button or wake event\n"); + } + else + { + printf(" No flag set\n"); + } + } + break; + case 4: + { + printf( " Boot Info Acknowledge :\n"); + if((rsp->data[3]&0x1f) != 0) + { + if((rsp->data[3]&0x10) == 0x10) + printf(" - OEM has handled boot info\n"); + if((rsp->data[3]&0x08) == 0x08) + printf(" - SMS has handled boot info\n"); + if((rsp->data[3]&0x04) == 0x04) + printf(" - OS // service partition has handled boot info\n"); + if((rsp->data[3]&0x02) == 0x02) + printf(" - OS Loader has handled boot info\n"); + if((rsp->data[3]&0x01) == 0x01) + printf(" - BIOS/POST has handled boot info\n"); + } + else + { + printf(" No flag set\n"); + } + } + break; + case 5: + { + printf( " Boot Flags :\n"); + + if((rsp->data[2]&0x80) == 0x80) + printf(" - Boot Flag Valid\n"); + else + printf(" - Boot Flag Invalid\n"); + + if((rsp->data[2]&0x40) == 0x40) + printf(" - Options apply to all future boots\n"); + else + printf(" - Options apply to only next boot\n"); + + if((rsp->data[2]&0x20) == 0x20) + printf(" - BIOS EFI boot \n"); + else + printf(" - BIOS PC Compatible (legacy) boot \n"); + + if((rsp->data[3]&0x80) == 0x80) + printf(" - CMOS Clear\n"); + if((rsp->data[3]&0x40) == 0x40) + printf(" - Lock Keyboard\n"); + printf(" - Boot Device Selector : "); + switch( ((rsp->data[3]>>2)&0x0f)) + { + case 0: printf("No override\n"); break; + case 1: printf("Force PXE\n"); break; + case 2: printf("Force Boot from default Hard-Drive\n"); break; + case 3: printf("Force Boot from default Hard-Drive, request Safe-Mode\n"); break; + case 4: printf("Force Boot from Diagnostic Partition\n"); break; + case 5: printf("Force Boot from CD/DVD\n"); break; + case 6: printf("Force Boot into BIOS Setup\n"); break; + case 15: printf("Force Boot from Floppy/primary removable media\n"); break; + default: printf("Flag error\n"); break; + } + if((rsp->data[3]&0x02) == 0x02) + printf(" - Screen blank\n"); + if((rsp->data[3]&0x01) == 0x01) + printf(" - Lock out Reset buttons\n"); + + if((rsp->data[4]&0x80) == 0x80) + printf(" - Lock out (power off/sleep request) vi Power Button\n"); + printf(" - Console Redirection control : "); + switch( ((rsp->data[4]>>5)&0x03)) + { + case 0: printf("System Default\n"); break; + case 1: printf("Request Quiet Display\n"); break; + case 2: printf("Request Verbose Display\n"); break; + default: printf("Flag error\n"); break; + } + if((rsp->data[4]&0x10) == 0x10) + printf(" - Force progress event traps\n"); + if((rsp->data[4]&0x08) == 0x08) + printf(" - User password bypass\n"); + if((rsp->data[4]&0x04) == 0x04) + printf(" - Lock Out Sleep Button\n"); + if((rsp->data[4]&0x02) == 0x02) + printf(" - Lock Out Sleep Button\n"); + printf(" - BIOS verbosity : "); + switch( ((rsp->data[4]>>0)&0x03)) + { + case 0: printf("Console redirection occurs per BIOS configuration setting (default)\n"); break; + case 1: printf("Suppress (skip) console redirection if enabled\n"); break; + case 2: printf("Request console redirection be enabled\n"); break; + default: printf("Flag error\n"); break; + } + + if((rsp->data[5]&0x08) == 0x08) + printf(" - BIOS Shared Mode Override\n"); + printf(" - BIOS Mux Control Override : "); + switch( ((rsp->data[5]>>0)&0x07)) + { + case 0: printf("BIOS uses recommended setting of the mux at the end of POST\n"); break; + case 1: printf("Requests BIOS to force mux to BMC at conclusion of POST/start of OS boot\n"); break; + case 2: printf("Requests BIOS to force mux to system at conclusion of POST/start of OS boot\n"); break; + default: printf("Flag error\n"); break; + } + } + break; + case 6: + { + unsigned long session_id; + unsigned long timestamp; + char time_buf[40]; + time_t out_time; + + session_id = ((unsigned long) rsp->data[3]); + session_id |= (((unsigned long) rsp->data[4])<<8); + session_id |= (((unsigned long) rsp->data[5])<<16); + session_id |= (((unsigned long) rsp->data[6])<<24); + + timestamp = ((unsigned long) rsp->data[7]); + timestamp |= (((unsigned long) rsp->data[8])<<8); + timestamp |= (((unsigned long) rsp->data[9])<<16); + timestamp |= (((unsigned long) rsp->data[10])<<24); + + memset(time_buf, 0, 40); + strftime( + time_buf, + sizeof(time_buf), + "%m/%d/%Y %H:%M:%S", localtime(&out_time) + ); + + printf(" Boot Initiator Info :\n"); + printf(" Channel Number : %d\n", (rsp->data[2] & 0x0f)); + printf(" Session Id : %08lXh\n",session_id); + if(timestamp != 0) + { + printf(" Timestamp : %08lXh, %s\n",timestamp,time_buf); + } + else + { + printf(" Timestamp : %08lXh, undefined\n",timestamp); + } + + } + break; + case 7: + { + printf(" Selector : %d\n", rsp->data[2] ); + printf(" Block Data : %s\n", buf2str(rsp->data+3, rsp->data_len - 2)); + } + break; + default: + printf(" Undefined byte\n"); + break; + } + + return 0; +} + +static int +get_bootparam_options(char *optstring, + unsigned char *set_flag, unsigned char *clr_flag) +{ + char *token; + char *saveptr = NULL; + int optionError = 0; + *set_flag = 0; + *clr_flag = 0; + static struct { + char *name; + unsigned char value; + char *desc; + } options[] = { + {"PEF", 0x10, + "Clear valid bit on reset/power cycle cause by PEF"}, + {"timeout", 0x08, + "Automatically clear boot flag valid bit on timeout"}, + {"watchdog", 0x04, + "Clear valid bit on reset/power cycle cause by watchdog"}, + {"reset", 0x02, + "Clear valid bit on push button reset/soft reset"}, + {"power", 0x01, + "Clear valid bit on power up via power push button or wake event"}, + + {NULL} /* End marker */ + }, *op; + + if (strncmp(optstring, "options=", 8) != 0) { + lprintf(LOG_ERR, "No options= keyword found \"%s\"", optstring); + return -1; + } + token = strtok_r(optstring + 8, ",", &saveptr); + while (token != NULL) { + int setbit = 0; + if (strcmp(token, "help") == 0) { + optionError = 1; + break; + } + if (strncmp(token, "no-", 3) == 0) { + setbit = 1; + token += 3; + } + for (op = options; op->name != NULL; ++op) { + if (strncmp(token, op->name, strlen(op->name)) == 0) { + if (setbit) { + *set_flag |= op->value; + } else { + *clr_flag |= op->value; + } + break; + } + } + if (op->name == NULL) { + /* Option not found */ + optionError = 1; + if (setbit) { + token -=3; + } + lprintf(LOG_ERR, "Invalid option: %s", token); + } + token = strtok_r(NULL, ",", &saveptr); + } + if (optionError) { + lprintf(LOG_NOTICE, " Legal options are:"); + lprintf(LOG_NOTICE, " %-8s: print this message", "help"); + for (op = options; op->name != NULL; ++op) { + lprintf(LOG_NOTICE, " %-8s: %s", op->name, op->desc); + } + lprintf(LOG_NOTICE, " Any Option may be prepended with no-" + " to invert sense of operation\n"); + return (-1); + } + return (0); +} + +static int +ipmi_chassis_get_bootvalid(struct ipmi_intf * intf) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + uint8_t msg_data[3]; + uint8_t param_id = IPMI_CHASSIS_BOOTPARAM_FLAG_VALID; + memset(msg_data, 0, 3); + + msg_data[0] = param_id & 0x7f; + msg_data[1] = 0; + msg_data[2] = 0; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_CHASSIS; + req.msg.cmd = 0x9; + req.msg.data = msg_data; + req.msg.data_len = 3; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, + "Error Getting Chassis Boot Parameter %d", param_id); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Get Chassis Boot Parameter %d failed: %s", + param_id, val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + if (verbose > 2) + printbuf(rsp->data, rsp->data_len, "Boot Option"); + + return(rsp->data[2]); +} + +static int +ipmi_chassis_set_bootvalid(struct ipmi_intf *intf, uint8_t set_flag, uint8_t clr_flag) +{ + int bootvalid; + uint8_t flags[5]; + int rc = 0; + int use_progress = 1; + uint8_t param_id = IPMI_CHASSIS_BOOTPARAM_FLAG_VALID; + + if (use_progress) { + /* set set-in-progress flag */ + memset(flags, 0, 5); + flags[0] = 0x01; + rc = ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, flags, 1); + if (rc < 0) + use_progress = 0; + } + + memset(flags, 0, 5); + flags[0] = 0x01; + flags[1] = 0x01; + rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_INFO_ACK, + flags, 2); + + if (rc < 0) { + if (use_progress) { + /* set-in-progress = set-complete */ + memset(flags, 0, 5); + ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, + flags, 1); + } + return -1; + } + + bootvalid = ipmi_chassis_get_bootvalid(intf); + + if (bootvalid < 0) { + if (use_progress) { + /* set-in-progress = set-complete */ + memset(flags, 0, 5); + ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, + flags, 1); + } + return -1; + } + flags[0] = (bootvalid & ~clr_flag) | set_flag; + + rc = ipmi_chassis_set_bootparam(intf, param_id, flags, 1); + + if (rc == 0) { + if (use_progress) { + /* set-in-progress = commit-write */ + memset(flags, 0, 5); + flags[0] = 0x02; + ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, + flags, 1); + } + } + + if (use_progress) { + /* set-in-progress = set-complete */ + memset(flags, 0, 5); + ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, + flags, 1); + } + + return rc; +} + +static int +ipmi_chassis_set_bootdev(struct ipmi_intf * intf, char * arg, uint8_t *iflags) +{ + uint8_t flags[5]; + int rc = 0; + int use_progress = 1; + + if (use_progress) { + /* set set-in-progress flag */ + memset(flags, 0, 5); + flags[0] = 0x01; + rc = ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, flags, 1); + if (rc < 0) + use_progress = 0; + } + + memset(flags, 0, 5); + flags[0] = 0x01; + flags[1] = 0x01; + rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_INFO_ACK, + flags, 2); + + if (rc < 0) { + if (use_progress) { + /* set-in-progress = set-complete */ + memset(flags, 0, 5); + ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, + flags, 1); + } + return -1; + } + + if (iflags == NULL) + memset(flags, 0, 5); + else + memcpy(flags, iflags, sizeof (flags)); + + if (arg == NULL) + flags[1] |= 0x00; + else if (strncmp(arg, "none", 4) == 0) + flags[1] |= 0x00; + else if (strncmp(arg, "pxe", 3) == 0 || + strncmp(arg, "force_pxe", 9) == 0) + flags[1] |= 0x04; + else if (strncmp(arg, "disk", 4) == 0 || + strncmp(arg, "force_disk", 10) == 0) + flags[1] |= 0x08; + else if (strncmp(arg, "safe", 4) == 0 || + strncmp(arg, "force_safe", 10) == 0) + flags[1] |= 0x0c; + else if (strncmp(arg, "diag", 4) == 0 || + strncmp(arg, "force_diag", 10) == 0) + flags[1] |= 0x10; + else if (strncmp(arg, "cdrom", 5) == 0 || + strncmp(arg, "force_cdrom", 11) == 0) + flags[1] |= 0x14; + else if (strncmp(arg, "floppy", 6) == 0 || + strncmp(arg, "force_floppy", 12) == 0) + flags[1] |= 0x3c; + else if (strncmp(arg, "bios", 4) == 0 || + strncmp(arg, "force_bios", 10) == 0) + flags[1] |= 0x18; + else { + lprintf(LOG_ERR, "Invalid argument: %s", arg); + if (use_progress) { + /* set-in-progress = set-complete */ + memset(flags, 0, 5); + ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, + flags, 1); + } + return -1; + } + + /* set flag valid bit */ + flags[0] |= 0x80; + + rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_BOOT_FLAGS, + flags, 5); + if (rc == 0) { + if (use_progress) { + /* set-in-progress = commit-write */ + memset(flags, 0, 5); + flags[0] = 0x02; + ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, + flags, 1); + } + + printf("Set Boot Device to %s\n", arg); + } + + if (use_progress) { + /* set-in-progress = set-complete */ + memset(flags, 0, 5); + ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, + flags, 1); + } + + return rc; +} + +static int +ipmi_chassis_power_policy(struct ipmi_intf * intf, uint8_t policy) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_CHASSIS; + req.msg.cmd = 0x6; + req.msg.data = &policy; + req.msg.data_len = 1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Error in Power Restore Policy command"); + return -1; + } + if (rsp->ccode > 0) { + lprintf(LOG_ERR, "Power Restore Policy command failed: %s", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + if (policy == IPMI_CHASSIS_POLICY_NO_CHANGE) { + printf("Supported chassis power policy: "); + if (rsp->data[0] & (1<data[0] & (1<data[0] & (1< [options=...]"); + lprintf(LOG_NOTICE, " Legal devices are:"); + lprintf(LOG_NOTICE, " none : No override"); + lprintf(LOG_NOTICE, " force_pxe : Force PXE boot"); + lprintf(LOG_NOTICE, " force_disk : Force boot from default Hard-drive"); + lprintf(LOG_NOTICE, " force_safe : Force boot from default Hard-drive, request Safe Mode"); + lprintf(LOG_NOTICE, " force_diag : Force boot from Diagnostic Partition"); + lprintf(LOG_NOTICE, " force_cdrom : Force boot from CD/DVD"); + lprintf(LOG_NOTICE, " force_bios : Force boot into BIOS Setup"); + get_bootparam_options("options=help", &set_flag, &clr_flag); +} + +int +ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv) +{ + int rc = 0; + + if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) { + lprintf(LOG_NOTICE, "Chassis Commands: status, power, identify, policy, restart_cause, poh, bootdev, bootparam, selftest"); + } + else if (strncmp(argv[0], "status", 6) == 0) { + rc = ipmi_chassis_status(intf); + } + else if (strncmp(argv[0], "selftest", 8) == 0) { + rc = ipmi_chassis_selftest(intf); + } + else if (strncmp(argv[0], "power", 5) == 0) { + uint8_t ctl = 0; + + if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) { + lprintf(LOG_NOTICE, "chassis power Commands: status, on, off, cycle, reset, diag, soft"); + return 0; + } + if (strncmp(argv[1], "status", 6) == 0) { + rc = ipmi_chassis_print_power_status(intf); + return rc; + } + if ((strncmp(argv[1], "up", 2) == 0) || (strncmp(argv[1], "on", 2) == 0)) + ctl = IPMI_CHASSIS_CTL_POWER_UP; + else if ((strncmp(argv[1], "down", 4) == 0) || (strncmp(argv[1], "off", 3) == 0)) + ctl = IPMI_CHASSIS_CTL_POWER_DOWN; + else if (strncmp(argv[1], "cycle", 5) == 0) + ctl = IPMI_CHASSIS_CTL_POWER_CYCLE; + else if (strncmp(argv[1], "reset", 5) == 0) + ctl = IPMI_CHASSIS_CTL_HARD_RESET; + else if (strncmp(argv[1], "diag", 4) == 0) + ctl = IPMI_CHASSIS_CTL_PULSE_DIAG; + else if ((strncmp(argv[1], "acpi", 4) == 0) || (strncmp(argv[1], "soft", 4) == 0)) + ctl = IPMI_CHASSIS_CTL_ACPI_SOFT; + else { + lprintf(LOG_ERR, "Invalid chassis power command: %s", argv[1]); + return -1; + } + + rc = ipmi_chassis_power_control(intf, ctl); + } + else if (strncmp(argv[0], "identify", 8) == 0) { + if (argc < 2) { + rc = ipmi_chassis_identify(intf, NULL); + } + else if (strncmp(argv[1], "help", 4) == 0) { + lprintf(LOG_NOTICE, "chassis identify "); + lprintf(LOG_NOTICE, " default is 15 seconds"); + lprintf(LOG_NOTICE, " 0 to turn off"); + lprintf(LOG_NOTICE, " force to turn on indefinitely"); + } else { + rc = ipmi_chassis_identify(intf, argv[1]); + } + } + else if (strncmp(argv[0], "poh", 3) == 0) { + rc = ipmi_chassis_poh(intf); + } + else if (strncmp(argv[0], "restart_cause", 13) == 0) { + rc = ipmi_chassis_restart_cause(intf); + } + else if (strncmp(argv[0], "policy", 4) == 0) { + if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) { + lprintf(LOG_NOTICE, "chassis policy "); + lprintf(LOG_NOTICE, " list : return supported policies"); + lprintf(LOG_NOTICE, " always-on : turn on when power is restored"); + lprintf(LOG_NOTICE, " previous : return to previous state when power is restored"); + lprintf(LOG_NOTICE, " always-off : stay off after power is restored"); + } else { + uint8_t ctl; + if (strncmp(argv[1], "list", 4) == 0) + ctl = IPMI_CHASSIS_POLICY_NO_CHANGE; + else if (strncmp(argv[1], "always-on", 9) == 0) + ctl = IPMI_CHASSIS_POLICY_ALWAYS_ON; + else if (strncmp(argv[1], "previous", 8) == 0) + ctl = IPMI_CHASSIS_POLICY_PREVIOUS; + else if (strncmp(argv[1], "always-off", 10) == 0) + ctl = IPMI_CHASSIS_POLICY_ALWAYS_OFF; + else { + lprintf(LOG_ERR, "Invalid chassis policy: %s", argv[1]); + return -1; + } + rc = ipmi_chassis_power_policy(intf, ctl); + } + } + else if (strncmp(argv[0], "bootparam", 9) == 0) { + if ((argc < 3) || (strncmp(argv[1], "help", 4) == 0)) { + lprintf(LOG_NOTICE, "bootparam get "); + ipmi_chassis_set_bootflag_help(); + } + else { + if (strncmp(argv[1], "get", 3) == 0) { + rc = ipmi_chassis_get_bootparam(intf, argv[2]); + } + else if (strncmp(argv[1], "set", 3) == 0) { + unsigned char set_flag=0; + unsigned char clr_flag=0; + if (strncmp(argv[2], "help", 4) == 0 || + argc < 4 || (argc >= 4 && + strncmp(argv[2], "bootflag", 8) != 0)) { + ipmi_chassis_set_bootflag_help(); + } else { + if (argc == 5) { + get_bootparam_options(argv[4], &set_flag, &clr_flag); + } + rc = ipmi_chassis_set_bootdev(intf, argv[3], NULL); + if (argc == 5 && (set_flag != 0 || clr_flag != 0)) { + rc = ipmi_chassis_set_bootvalid(intf, set_flag, clr_flag); + } + } + } + else + lprintf(LOG_NOTICE, "bootparam get|set