From a9ee361f27e0439530387765924574e5358c8a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sat, 10 Sep 2022 15:44:41 +0200 Subject: New upstream version 1.8.19 --- lib/Makefile.am | 3 +- lib/Makefile.in | 717 ---------------------- lib/dimm_spd.c | 49 +- lib/helper.c | 221 +++++-- lib/ipmi_cfgp.c | 36 +- lib/ipmi_channel.c | 464 +++++++++------ lib/ipmi_chassis.c | 1575 +++++++++++++++++++++++++++++++++++-------------- lib/ipmi_dcmi.c | 1265 +++++++++++++++++++++------------------ lib/ipmi_delloem.c | 727 +++++++++++------------ lib/ipmi_ekanalyzer.c | 384 +++++++----- lib/ipmi_event.c | 184 +++--- lib/ipmi_firewall.c | 94 +-- lib/ipmi_fru.c | 949 +++++++++++++++-------------- lib/ipmi_fwum.c | 64 +- lib/ipmi_gendev.c | 65 +- lib/ipmi_hpmfwupg.c | 179 +++--- lib/ipmi_ime.c | 90 ++- lib/ipmi_isol.c | 51 +- lib/ipmi_kontronoem.c | 75 ++- lib/ipmi_lanp.c | 596 +++++++++++-------- lib/ipmi_lanp6.c | 16 +- lib/ipmi_main.c | 206 ++++--- lib/ipmi_mc.c | 774 +++++++++++++++++++----- lib/ipmi_oem.c | 49 +- lib/ipmi_pef.c | 429 +++++++++++--- lib/ipmi_picmg.c | 278 ++++++--- lib/ipmi_quantaoem.c | 184 ++++++ lib/ipmi_raw.c | 33 +- lib/ipmi_sdr.c | 735 +++++++++++++---------- lib/ipmi_sdradd.c | 34 +- lib/ipmi_sel.c | 442 +++++++------- lib/ipmi_sensor.c | 390 +++++++----- lib/ipmi_session.c | 40 +- lib/ipmi_sol.c | 106 ++-- lib/ipmi_strings.c | 1117 +++++++++++++++++++++++++++++++++-- lib/ipmi_sunoem.c | 205 ++++--- lib/ipmi_time.c | 243 ++++++++ lib/ipmi_tsol.c | 33 +- lib/ipmi_user.c | 138 +++-- lib/ipmi_vita.c | 86 +-- lib/log.c | 16 +- 41 files changed, 8092 insertions(+), 5250 deletions(-) delete mode 100644 lib/Makefile.in mode change 100755 => 100644 lib/ipmi_dcmi.c mode change 100755 => 100644 lib/ipmi_ime.c create mode 100644 lib/ipmi_quantaoem.c create mode 100644 lib/ipmi_time.c (limited to 'lib') diff --git a/lib/Makefile.am b/lib/Makefile.am index cc69a8f..49f5a8a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -41,8 +41,7 @@ libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.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 ipmi_vita.c \ - ipmi_lanp6.c ipmi_cfgp.c \ - ../src/plugins/lan/md5.c ../src/plugins/lan/md5.h + ipmi_lanp6.c ipmi_cfgp.c ipmi_quantaoem.c ipmi_time.c libipmitool_la_LDFLAGS = -export-dynamic libipmitool_la_LIBADD = -lm diff --git a/lib/Makefile.in b/lib/Makefile.in deleted file mode 100644 index 0e2b6b2..0000000 --- a/lib/Makefile.in +++ /dev/null @@ -1,717 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 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@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -target_triplet = @target@ -subdir = lib -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -am__dirstamp = $(am__leading_dot)dirstamp -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 ipmi_vita.lo ipmi_lanp6.lo ipmi_cfgp.lo \ - ../src/plugins/lan/md5.lo -libipmitool_la_OBJECTS = $(am_libipmitool_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libipmitool_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(libipmitool_la_LDFLAGS) $(LDFLAGS) -o \ - $@ -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libipmitool_la_SOURCES) -DIST_SOURCES = $(libipmitool_la_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -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@ -INTF_USB = @INTF_USB@ -INTF_USB_LIB = @INTF_USB_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@ -AUTOMAKE_OPTIONS = subdir-objects -AM_CPPFLAGS = -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 ipmi_vita.c \ - ipmi_lanp6.c ipmi_cfgp.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)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } -../src/plugins/lan/$(am__dirstamp): - @$(MKDIR_P) ../src/plugins/lan - @: > ../src/plugins/lan/$(am__dirstamp) -../src/plugins/lan/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) ../src/plugins/lan/$(DEPDIR) - @: > ../src/plugins/lan/$(DEPDIR)/$(am__dirstamp) -../src/plugins/lan/md5.lo: ../src/plugins/lan/$(am__dirstamp) \ - ../src/plugins/lan/$(DEPDIR)/$(am__dirstamp) - -libipmitool.la: $(libipmitool_la_OBJECTS) $(libipmitool_la_DEPENDENCIES) $(EXTRA_libipmitool_la_DEPENDENCIES) - $(AM_V_CCLD)$(libipmitool_la_LINK) $(libipmitool_la_OBJECTS) $(libipmitool_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -rm -f ../src/plugins/lan/*.$(OBJEXT) - -rm -f ../src/plugins/lan/*.lo - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@../src/plugins/lan/$(DEPDIR)/md5.Plo@am__quote@ -@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_cfgp.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_lanp6.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)/ipmi_vita.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -rm -rf ../src/plugins/lan/.libs ../src/plugins/lan/_libs - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: ctags-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(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) - -rm -f ../src/plugins/lan/$(DEPDIR)/$(am__dirstamp) - -rm -f ../src/plugins/lan/$(am__dirstamp) - -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 ../src/plugins/lan/$(DEPDIR) ./$(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 ../src/plugins/lan/$(DEPDIR) ./$(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 TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ - ctags-am distclean distclean-compile distclean-generic \ - distclean-libtool distclean-tags distdir dvi dvi-am html \ - html-am info info-am install install-am install-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 tags-am 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 index 41e30db..d496184 100644 --- a/lib/dimm_spd.c +++ b/lib/dimm_spd.c @@ -1620,8 +1620,10 @@ 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, msg_data[4]; - int len, offset; + uint8_t *spd_data = NULL; + uint8_t msg_data[4]; + uint32_t len, offset; + int rc = -1; msg_data[0] = id; @@ -1632,14 +1634,14 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id) req.msg.data_len = 1; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { printf(" Device not present (No Response)\n"); - return -1; + goto end; } - if (rsp->ccode > 0) { + if (rsp->ccode) { printf(" Device not present (%s)\n", val2str(rsp->ccode, completion_code_vals)); - return -1; + goto end; } fru.size = (rsp->data[1] << 8) | rsp->data[0]; @@ -1651,15 +1653,15 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id) if (fru.size < 1) { lprintf(LOG_ERR, " Invalid FRU size %d", fru.size); - return -1; + goto end; } spd_data = malloc(fru.size); - if (spd_data == NULL) { + if (!spd_data) { printf(" Unable to malloc memory for spd array of size=%d\n", fru.size); - return -1; + goto end; } memset(&req, 0, sizeof(req)); @@ -1677,34 +1679,39 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id) msg_data[3] = FRU_DATA_RQST_SIZE; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { printf(" Device not present (No Response)\n"); - free(spd_data); - spd_data = NULL; - return -1; + goto end; } - if (rsp->ccode > 0) { + if (rsp->ccode) { printf(" Device not present (%s)\n", val2str(rsp->ccode, completion_code_vals)); - free(spd_data); - spd_data = NULL; /* Timeouts are acceptable. No DIMM in the socket */ if (rsp->ccode == 0xc3) - return 1; + rc = 1; - return -1; + goto end; } len = rsp->data[0]; + if(rsp->data_len < 1 + || len > rsp->data_len - 1 + || len > fru.size - offset) + { + printf(" Not enough buffer size"); + goto end; + } memcpy(&spd_data[offset], rsp->data + 1, len); offset += len; } while (offset < fru.size); /* now print spd info */ ipmi_spd_print(spd_data, offset); - free(spd_data); - spd_data = NULL; + rc = 0; - return 0; +end: + free_n(&spd_data); + + return rc; } diff --git a/lib/helper.c b/lib/helper.c index de91438..b547123 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -29,12 +29,6 @@ * 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. */ -#define _POSIX_SOURCE -#define /* glibc 2.19 and earlier */ _BSD_SOURCE || \ - /* Since glibc 2.20 */_DEFAULT_SOURCE || \ - _XOPEN_SOURCE >= 500 || \ - _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || \ - /* Since glibc 2.10: */ _POSIX_C_SOURCE >= 200112L \ #include #include @@ -60,7 +54,7 @@ #ifdef HAVE_PATHS_H # include #else -# define _PATH_VARRUN "/var/run/" +# define _PATH_RUN "/run/" #endif #include @@ -100,7 +94,7 @@ buf2str_extended(const uint8_t *buf, int len, const char *sep) int left; int sep_len; - if (buf == NULL) { + if (!buf) { snprintf(str, sizeof(str), ""); return (const char *)str; } @@ -180,7 +174,7 @@ ipmi_parse_hex(const char *str, uint8_t *out, int size) } len /= 2; /* out bytes */ - if (out == NULL) { + if (!out) { return -2; } @@ -234,6 +228,50 @@ void printbuf(const uint8_t * buf, int len, const char * desc) fprintf(stderr, "\n"); } +/* + * Unconditionally reverse the order of arbitrarily long strings of bytes + */ +uint8_t *array_byteswap(uint8_t *buffer, size_t length) +{ + size_t i; + uint8_t temp; + size_t max = length - 1; + + for (i = 0; i < length / 2; ++i) { + temp = buffer[i]; + buffer[i] = buffer[max - i]; + buffer[max - i] = temp; + } + + return buffer; +} + +/* Convert data array from network (big-endian) to host byte order */ +uint8_t *array_ntoh(uint8_t *buffer, size_t length) +{ +#if WORDS_BIGENDIAN + /* Big-endian host doesn't need conversion from big-endian network */ + (void)length; /* Silence the compiler */ + return buffer; +#else + /* Little-endian host needs conversion from big-endian network */ + return array_byteswap(buffer, length); +#endif +} + +/* Convert data array from little-endian to host byte order */ +uint8_t *array_letoh(uint8_t *buffer, size_t length) +{ +#if WORDS_BIGENDIAN + /* Big-endian host needs conversion from little-endian IPMI */ + return array_byteswap(buffer, length); +#else + /* Little-endian host doesn't need conversion from little-endian IPMI */ + (void)length; /* Silence the compiler */ + return buffer; +#endif +} + /* str2mac - parse-out MAC address from given string and store it * into buffer. * @@ -281,29 +319,77 @@ mac2str(const uint8_t *buf) return buf2str_extended(buf, 6, ":"); } -const char * val2str(uint16_t val, const struct valstr *vs) +/** + * Find the index of value in a valstr array + * + * @param[in] val The value to search for + * @param[in] vs The valstr array to search in + * @return >=0 The index into \p vs + * @return -1 Error: value \p val was not found in \p vs + */ +static +inline +off_t find_val_idx(uint32_t val, const struct valstr *vs) { - static char un_str[32]; - int i; - - for (i = 0; vs[i].str != NULL; i++) { - if (vs[i].val == val) - return vs[i].str; + if (vs) { + for (off_t i = 0; vs[i].str; ++i) { + if (vs[i].val == val) { + return i; + } + } } + return -1; +} + +/** + * Generate a statically allocated 'Unknown' string for the provided value. + * The function is not thread-safe (as most of ipmitool). + * + * @param[in] val The value to put into the string + * @returns A pointer to a statically allocated string + */ +static +inline +const char *unknown_val_str(uint32_t val) +{ + static char un_str[32]; memset(un_str, 0, 32); snprintf(un_str, 32, "Unknown (0x%02X)", val); return un_str; } -const char * oemval2str(uint32_t oem, uint16_t val, - const struct oemvalstr *vs) +const char * +specific_val2str(uint32_t val, + const struct valstr *specific, + const struct valstr *generic) +{ + int i; + + if (0 <= (i = find_val_idx(val, specific))) { + return specific[i].str; + } + + if (0 <= (i = find_val_idx(val, generic))) { + return generic[i].str; + } + + return unknown_val_str(val); +} + +const char *val2str(uint32_t val, const struct valstr *vs) +{ + return specific_val2str(val, NULL, vs); +} + + +const char *oemval2str(uint32_t oem, uint32_t val, + const struct oemvalstr *vs) { - static char un_str[32]; int i; - for (i = 0; vs[i].oem != 0xffffff && vs[i].str != NULL; i++) { + for (i = 0; vs[i].oem != 0xffffff && vs[i].str; i++) { /* FIXME: for now on we assume PICMG capability on all IANAs */ if ( (vs[i].oem == oem || vs[i].oem == IPMI_OEM_PICMG) && vs[i].val == val ) { @@ -311,10 +397,7 @@ const char * oemval2str(uint32_t oem, uint16_t val, } } - memset(un_str, 0, 32); - snprintf(un_str, 32, "Unknown (0x%X)", val); - - return un_str; + return unknown_val_str(val); } /* str2double - safely convert string to double @@ -559,12 +642,12 @@ int str2uchar(const char * str, uint8_t * uchr_ptr) return 0; } /* str2uchar(...) */ -uint16_t str2val(const char *str, const struct valstr *vs) +uint32_t str2val32(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) + for (i = 0; vs[i].str; i++) { + if (strcasecmp(vs[i].str, str) == 0) return vs[i].val; } @@ -582,10 +665,10 @@ print_valstr(const struct valstr * vs, const char * title, int loglevel) { int i; - if (vs == NULL) + if (!vs) return; - if (title != NULL) { + if (title) { if (loglevel < 0) printf("\n%s:\n\n", title); else @@ -600,7 +683,7 @@ print_valstr(const struct valstr * vs, const char * title, int loglevel) lprintf(loglevel, "=============================================="); } - for (i = 0; vs[i].str != NULL; i++) { + for (i = 0; vs[i].str; 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); @@ -631,18 +714,18 @@ print_valstr_2col(const struct valstr * vs, const char * title, int loglevel) { int i; - if (vs == NULL) + if (!vs) return; - if (title != NULL) { + if (title) { 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) { + for (i = 0; vs[i].str; i++) { + if (!vs[i+1].str) { /* last one */ if (loglevel < 0) { printf(" %4d %-32s\n", vs[i].val, vs[i].str); @@ -696,12 +779,12 @@ ipmi_open_file(const char * file, int rw) struct stat st1, st2; FILE * fp; - /* verify existance */ + /* verify existence */ if (lstat(file, &st1) < 0) { if (rw) { /* does not exist, ok to create */ fp = fopen(file, "w"); - if (fp == NULL) { + if (!fp) { lperror(LOG_ERR, "Unable to open file %s " "for write", file); return NULL; @@ -718,7 +801,7 @@ ipmi_open_file(const char * file, int rw) if (!rw) { /* on read skip the extra checks */ fp = fopen(file, "r"); - if (fp == NULL) { + if (!fp) { lperror(LOG_ERR, "Unable to open file %s", file); return NULL; } @@ -741,7 +824,7 @@ ipmi_open_file(const char * file, int rw) } fp = fopen(file, rw ? "w+" : "r"); - if (fp == NULL) { + if (!fp) { lperror(LOG_ERR, "Unable to open file %s", file); return NULL; } @@ -785,6 +868,7 @@ ipmi_start_daemon(struct ipmi_intf *intf) { pid_t pid; int fd; + int ret; #ifdef SIGHUP sigset_t sighup; #endif @@ -828,7 +912,11 @@ ipmi_start_daemon(struct ipmi_intf *intf) exit(0); #endif - chdir("/"); + ret = chdir("/"); + if (ret) { + lprintf(LOG_ERR, "chdir failed: %s (%d)", strerror(errno), errno); + exit(1); + } umask(0); for (fd=0; fd<64; fd++) { @@ -837,9 +925,20 @@ ipmi_start_daemon(struct ipmi_intf *intf) } fd = open("/dev/null", O_RDWR); - assert(0 == fd); - dup(fd); - dup(fd); + if (fd != STDIN_FILENO) { + lprintf(LOG_ERR, "failed to reset stdin: %s (%d)", strerror(errno), errno); + exit(1); + } + ret = dup(fd); + if (ret != STDOUT_FILENO) { + lprintf(LOG_ERR, "failed to reset stdout: %s (%d)", strerror(errno), errno); + exit(1); + } + ret = dup(fd); + if (ret != STDERR_FILENO) { + lprintf(LOG_ERR, "failed to reset stderr: %s (%d)", strerror(errno), errno); + exit(1); + } } /* eval_ccode - evaluate return value of _ipmi_* functions and print error error @@ -852,7 +951,7 @@ ipmi_start_daemon(struct ipmi_intf *intf) int eval_ccode(const int ccode) { - if (ccode == 0) { + if (!ccode) { return 0; } else if (ccode < 0) { switch (ccode) { @@ -1012,11 +1111,11 @@ ipmi_get_oem_id(struct ipmi_intf *intf) req.msg.data_len = 0; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Get Board ID command failed"); return 0; } - if (rsp->ccode > 0) { + if (rsp->ccode) { lprintf(LOG_ERR, "Get Board ID command failed: %#x %s", rsp->ccode, val2str(rsp->ccode, completion_code_vals)); return 0; @@ -1026,3 +1125,35 @@ ipmi_get_oem_id(struct ipmi_intf *intf) return oem_id; } + +/** Parse command line arguments as numeric byte values (dec or hex) + * and store them in a \p len sized buffer \p out. + * + * @param[in] argc Number of arguments + * @param[in] argv Array of arguments + * @param[out] out The output buffer + * @param[in] len Length of the output buffer in bytes (no null-termination + * is assumed, the input data is treated as raw byte values, + * not as a string. + * + * @returns A success status indicator + * @return false Error + * @return true Success + */ +bool +args2buf(int argc, char *argv[], uint8_t *out, size_t len) +{ + size_t i; + + for (i = 0; i < len && i < (size_t)argc; ++i) { + uint8_t byte; + + if (str2uchar(argv[i], &byte)) { + lprintf(LOG_ERR, "Bad byte value: %s", argv[i]); + return false; + } + + out[i] = byte; + } + return true; +} diff --git a/lib/ipmi_cfgp.c b/lib/ipmi_cfgp.c index b8af80d..4131a65 100644 --- a/lib/ipmi_cfgp.c +++ b/lib/ipmi_cfgp.c @@ -30,7 +30,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include +#ifdef HAVE_MALLOC_H +# include +#else +# include +#endif #include #include @@ -49,7 +53,7 @@ ipmi_cfgp_init(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp *set, unsigned int count, const char *cmdname, ipmi_cfgp_handler_t handler, void *priv) { - if (ctx == NULL || set == NULL || handler == NULL || !cmdname) { + if (!ctx || !set || !handler || !cmdname) { return -1; } @@ -74,7 +78,7 @@ ipmi_cfgp_uninit(struct ipmi_cfgp_ctx *ctx) { struct ipmi_cfgp_data *d; - if (ctx == NULL) { + if (!ctx) { return -1; } @@ -123,7 +127,7 @@ ipmi_cfgp_parse_sel(struct ipmi_cfgp_ctx *ctx, { const struct ipmi_cfgp *p; - if (ctx == NULL || argv == NULL || sel == NULL) { + if (!ctx || !argv || !sel) { return -1; } @@ -137,7 +141,7 @@ ipmi_cfgp_parse_sel(struct ipmi_cfgp_ctx *ctx, } p = lookup_cfgp(ctx, argv[0]); - if (p == NULL) { + if (!p) { lprintf(LOG_ERR, "invalid parameter"); return -1; } @@ -201,11 +205,11 @@ cfgp_add_data(struct ipmi_cfgp_ctx *ctx, struct ipmi_cfgp_data *data) static void cfgp_usage(const struct ipmi_cfgp *p, int write) { - if (p->name == NULL) { + if (!p->name) { return; } - if (write && p->format == NULL) { + if (write && !p->format) { return; } @@ -227,7 +231,7 @@ ipmi_cfgp_usage(const struct ipmi_cfgp *set, int count, int write) const struct ipmi_cfgp *p; int i; - if (set == NULL) { + if (!set) { return; } @@ -263,7 +267,7 @@ ipmi_cfgp_parse_data(struct ipmi_cfgp_ctx *ctx, struct ipmi_cfgp_data *data; struct ipmi_cfgp_action action; - if (ctx == NULL || sel == NULL || argv == NULL) { + if (!ctx || !sel || !argv) { return -1; } @@ -290,7 +294,7 @@ ipmi_cfgp_parse_data(struct ipmi_cfgp_ctx *ctx, } data = malloc(sizeof(struct ipmi_cfgp_data) + p->size); - if (data == NULL) { + if (!data) { return -1; } @@ -370,7 +374,7 @@ cfgp_get_param(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp *p, do { data = malloc(sizeof(struct ipmi_cfgp_data) + p->size); - if (data == NULL) { + if (!data) { return -1; } @@ -422,7 +426,7 @@ ipmi_cfgp_get(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp_sel *sel) int i; int ret; - if (ctx == NULL || sel == NULL) { + if (!ctx || !sel) { return -1; } @@ -461,7 +465,7 @@ cfgp_do_action(struct ipmi_cfgp_ctx *ctx, int action_type, struct ipmi_cfgp_action action; int ret; - if (ctx == NULL || sel == NULL) { + if (!ctx || !sel) { return -1; } @@ -470,7 +474,7 @@ cfgp_do_action(struct ipmi_cfgp_ctx *ctx, int action_type, action.argv = NULL; action.file = file; - for (data = ctx->v; data != NULL; data = data->next) { + for (data = ctx->v; data; data = data->next) { if (sel->param != -1 && sel->param != data->sel.param) { continue; } @@ -523,7 +527,7 @@ int ipmi_cfgp_save(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp_sel *sel, FILE *file) { - if (file == NULL) { + if (!file) { return -1; } @@ -534,7 +538,7 @@ int ipmi_cfgp_print(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp_sel *sel, FILE *file) { - if (file == NULL) { + if (!file) { return -1; } diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c index fab2e54..bb7e60a 100644 --- a/lib/ipmi_channel.c +++ b/lib/ipmi_channel.c @@ -75,7 +75,7 @@ _ipmi_get_channel_access(struct ipmi_intf *intf, struct ipmi_rq req = {0}; uint8_t data[2]; - if (channel_access == NULL) { + if (!channel_access) { return (-3); } data[0] = channel_access->channel & 0x0F; @@ -87,9 +87,9 @@ _ipmi_get_channel_access(struct ipmi_intf *intf, req.msg.data_len = 2; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { return (-1); - } else if (rsp->ccode != 0) { + } else if (rsp->ccode) { return rsp->ccode; } else if (rsp->data_len != 2) { return (-2); @@ -118,7 +118,7 @@ _ipmi_get_channel_info(struct ipmi_intf *intf, struct ipmi_rq req = {0}; uint8_t data[1]; - if (channel_info == NULL) { + if (!channel_info) { return (-3); } data[0] = channel_info->channel & 0x0F; @@ -128,9 +128,9 @@ _ipmi_get_channel_info(struct ipmi_intf *intf, req.msg.data_len = 1; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { return (-1); - } else if (rsp->ccode != 0) { + } else if (rsp->ccode) { return rsp->ccode; } else if (rsp->data_len != 9) { return (-2); @@ -202,7 +202,7 @@ _ipmi_set_channel_access(struct ipmi_intf *intf, req.msg.data_len = 3; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { return (-1); } return rsp->ccode; @@ -225,7 +225,7 @@ iana_string(uint32_t iana) * ipmi_1_5_authtypes * * Create a string describing the supported authentication types as - * specificed by the parameter n + * specified by the parameter n */ static const char * ipmi_1_5_authtypes(uint8_t n) @@ -244,10 +244,28 @@ ipmi_1_5_authtypes(uint8_t n) return supportedTypes; } -uint8_t -ipmi_current_channel_medium(struct ipmi_intf *intf) +void +ipmi_current_channel_info(struct ipmi_intf *intf, + struct channel_info_t *chinfo) { - return ipmi_get_channel_medium(intf, 0xE); + int ccode = 0; + + chinfo->channel = CH_CURRENT; + ccode = _ipmi_get_channel_info(intf, chinfo); + if (ccode) { + if (ccode != IPMI_CC_INV_DATA_FIELD_IN_REQ) { + if (ccode > 0) { + lprintf(LOG_ERR, "Get Channel Info command failed: %s", + val2str(ccode, completion_code_vals)); + } + else { + eval_ccode(ccode); + } + } + chinfo->channel = CH_UNKNOWN; + chinfo->medium = IPMI_CHANNEL_MEDIUM_RESERVED; + } + return; } /** @@ -276,7 +294,7 @@ ipmi_get_channel_auth_cap(struct ipmi_intf *intf, uint8_t channel, uint8_t priv) rsp = intf->sendrecv(intf, &req); - if ((rsp == NULL) || (rsp->ccode > 0)) { + if (!rsp || rsp->ccode) { /* * It's very possible that this failed because we asked for IPMI v2 data * Ask again, without requesting IPMI v2 data @@ -284,11 +302,11 @@ ipmi_get_channel_auth_cap(struct ipmi_intf *intf, uint8_t channel, uint8_t priv) msg_data[0] &= 0x7F; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Unable to Get Channel Authentication Capabilities"); return (-1); } - if (rsp->ccode > 0) { + if (rsp->ccode) { lprintf(LOG_ERR, "Get Channel Authentication Capabilities failed: %s", val2str(rsp->ccode, completion_code_vals)); return (-1); @@ -342,86 +360,152 @@ ipmi_get_channel_auth_cap(struct ipmi_intf *intf, uint8_t channel, uint8_t priv) return 0; } -static int -ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type, - uint8_t channel) +static inline size_t parse_cipher_suite(uint8_t *cipher_suite_data, + size_t data_len, + uint32_t *iana, + uint8_t *auth_alg, + uint8_t *integrity_alg, + uint8_t *crypt_alg, + enum cipher_suite_ids *cipher_suite_id) +{ + size_t size = 0; + const char *incomplete = "Incomplete data record in cipher suite data"; + + if (*cipher_suite_data == STANDARD_CIPHER_SUITE) { + struct std_cipher_suite_record_t *record = + (struct std_cipher_suite_record_t*)cipher_suite_data; + + /* Verify that we have at least a full record left; id + 3 algs */ + if (data_len < sizeof(*record)) { + lprintf(LOG_INFO, "%s", incomplete); + goto out; + } + + /* IANA code remains default (0) */ + *cipher_suite_id = record->cipher_suite_id; + *auth_alg = CIPHER_ALG_MASK & record->auth_alg; + *integrity_alg = CIPHER_ALG_MASK & record->integrity_alg; + *crypt_alg = CIPHER_ALG_MASK & record->crypt_alg; + size = sizeof(*record); + } else if (*cipher_suite_data == OEM_CIPHER_SUITE) { + /* OEM record type */ + struct oem_cipher_suite_record_t *record = + (struct oem_cipher_suite_record_t*)cipher_suite_data; + /* Verify that we have at least a full record left + * id + iana + 3 algs + */ + if (data_len < sizeof(*record)) { + lprintf(LOG_INFO, "%s", incomplete); + goto out; + } + + /* Grab the IANA */ + *iana = ipmi24toh(record->iana); + *cipher_suite_id = record->cipher_suite_id; + *auth_alg = CIPHER_ALG_MASK & record->auth_alg; + *integrity_alg = CIPHER_ALG_MASK & record->integrity_alg; + *crypt_alg = CIPHER_ALG_MASK & record->crypt_alg; + size = sizeof(*record); + } else { + lprintf(LOG_INFO, "Bad start of record byte in cipher suite data " + "(value %x)", *cipher_suite_data); + } + +out: + return size; +} + +static size_t +parse_channel_cipher_suite_data(uint8_t *cipher_suite_data, size_t data_len, + struct cipher_suite_info* suites, + size_t nr_suites) +{ + size_t count = 0; + size_t offset = 0; + + /* Default everything to zeroes */ + memset(suites, 0, sizeof(*suites) * nr_suites); + + while (offset < data_len && count < nr_suites) { + size_t suite_size; + + /* Set non-zero defaults */ + suites[count].auth_alg = IPMI_AUTH_RAKP_NONE; + suites[count].integrity_alg = IPMI_INTEGRITY_NONE; + suites[count].crypt_alg = IPMI_CRYPT_NONE; + + /* Update fields from cipher suite data */ + suite_size = parse_cipher_suite(cipher_suite_data + offset, + data_len - offset, + &suites[count].iana, + &suites[count].auth_alg, + &suites[count].integrity_alg, + &suites[count].crypt_alg, + &suites[count].cipher_suite_id); + + if (!suite_size) { + lprintf(LOG_INFO, + "Failed to parse cipher suite data at offset %d", + offset); + break; + } + + offset += suite_size; + count++; + } + return count; +} + +int +ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, + const char *payload_type, + uint8_t channel, + struct cipher_suite_info *suites, + size_t *count) { struct ipmi_rs *rsp; struct ipmi_rq req; 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; /* 0x40 sets * 16 bytes per set */ - uint8_t cipher_suite_data[1024]; - uint16_t offset = 0; - /* how much was returned, total */ - uint16_t cipher_suite_data_length = 0; + uint8_t cipher_suite_data[MAX_CIPHER_SUITE_RECORD_OFFSET * + MAX_CIPHER_SUITE_DATA_LEN]; + size_t offset = 0; + size_t nr_suites = 0; + + if (!suites || !count || !*count) + return -1; + nr_suites = *count; + *count = 0; memset(cipher_suite_data, 0, sizeof(cipher_suite_data)); - + memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = IPMI_GET_CHANNEL_CIPHER_SUITES; req.msg.data = rqdata; - req.msg.data_len = 3; + req.msg.data_len = sizeof(rqdata); rqdata[0] = channel; - rqdata[1] = ((strncmp(payload_type, "ipmi", 4) == 0)? 0: 1); - /* Always ask for cipher suite format */ - rqdata[2] = 0x80; - - 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; + rqdata[1] = strcmp(payload_type, "ipmi") ? 1 : 0; + do { + /* Always ask for cipher suite format */ + rqdata[2] = LIST_ALGORITHMS_BY_CIPHER_SUITE | list_index; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites"); return -1; } - if (rsp->ccode > 0) { + if (rsp->ccode + || rsp->data_len < 1 + || rsp->data_len > sizeof(uint8_t) + MAX_CIPHER_SUITE_DATA_LEN) + { 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); @@ -429,88 +513,49 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type, */ 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; + /* + * Increment our list for the next call + */ + ++list_index; + } while ((rsp->data_len == (sizeof(uint8_t) + MAX_CIPHER_SUITE_DATA_LEN)) + && (list_index < MAX_CIPHER_SUITE_RECORD_OFFSET)); - 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) { - /* standard type */ - iana = 0; + *count = parse_channel_cipher_suite_data(cipher_suite_data, offset, suites, + nr_suites); + return 0; +} - /* Verify that we have at least a full record left; id + 3 algs */ - if ((cipher_suite_data_length - offset) < 4) { - 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 type */ - /* Verify that we have at least a full record left - * id + iana + 3 algs - */ - if ((cipher_suite_data_length - offset) < 4) { - lprintf(LOG_ERR, "Incomplete data record in cipher suite data"); - return -1; - } +static int +ipmi_print_channel_cipher_suites(struct ipmi_intf *intf, + const char *payload_type, + uint8_t channel) +{ + int rc; + size_t i = 0; + struct cipher_suite_info suites[MAX_CIPHER_SUITE_COUNT]; + size_t nr_suites = sizeof(*suites); + const char *header_str = +"ID IANA Auth Alg Integrity Alg Confidentiality Alg"; - cipher_suite_id = cipher_suite_data[offset++]; + rc = ipmi_get_channel_cipher_suites(intf, payload_type, channel, + suites, &nr_suites); - /* 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; - } + if (rc < 0) + return rc; - /* - * 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; - } - } + if (!csv_output) { + printf("%s\n", header_str); + } + for (i = 0; i < nr_suites; i++) { /* 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)); + printf(csv_output ? "%d,%s,%s,%s,%s\n" + : "%-4d %-7s %-15s %-15s %-15s\n", + suites[i].cipher_suite_id, + iana_string(suites[i].iana), + val2str(suites[i].auth_alg, ipmi_auth_algorithms), + val2str(suites[i].integrity_alg, ipmi_integrity_algorithms), + val2str(suites[i].crypt_alg, ipmi_encryption_algorithms)); } return 0; } @@ -648,8 +693,9 @@ ipmi_get_channel_info(struct ipmi_intf *intf, uint8_t channel) * * @channel - IPMI Channel * - * returns - IPMI Channel Medium, IPMI_CHANNEL_MEDIUM_RESERVED if ccode > 0, - * 0 on error. + * @returns IPMI Channel Medium + * @retval IPMI_CHANNEL_MEDIUM_RESERVED if ccode was not IPMI_CC_OK + * @retval 0 on error */ uint8_t ipmi_get_channel_medium(struct ipmi_intf *intf, uint8_t channel) @@ -659,13 +705,16 @@ ipmi_get_channel_medium(struct ipmi_intf *intf, uint8_t channel) channel_info.channel = channel; ccode = _ipmi_get_channel_info(intf, &channel_info); - if (ccode == 0xCC) { - return IPMI_CHANNEL_MEDIUM_RESERVED; - } else if (ccode < 0 && eval_ccode(ccode) != 0) { - return 0; - } else if (ccode > 0) { - lprintf(LOG_ERR, "Get Channel Info command failed: %s", - val2str(ccode, completion_code_vals)); + if (ccode) { + if (ccode != IPMI_CC_INV_DATA_FIELD_IN_REQ) { + if (ccode > 0) { + lprintf(LOG_ERR, "Get Channel Info command failed: %s", + val2str(ccode, completion_code_vals)); + } + else { + eval_ccode(ccode); + } + } return IPMI_CHANNEL_MEDIUM_RESERVED; } lprintf(LOG_DEBUG, "Channel type: %s", @@ -754,9 +803,27 @@ ipmi_set_user_access(struct ipmi_intf *intf, int argc, char **argv) int ccode = 0; int i = 0; uint8_t channel = 0; - uint8_t priv = 0; uint8_t user_id = 0; - if (argc > 0 && strncmp(argv[0], "help", 4) == 0) { + struct { + const char *option; + enum { + UA_INTEGER, /* direct integer value */ + UA_BOOLEAN, /* off/disable = false, on/enable = true */ + UA_BOOLEAN_INVERSE /* off/disable = true, on/enable = false */ + } type; + uint8_t *val; + uint8_t min; /* minimum value for UA_INTEGER options */ + uint8_t max; /* maximum value for UA_INTEGER options */ + } options[] = { + { "callin=", UA_BOOLEAN_INVERSE, &user_access.callin_callback, 0, 0}, + { "link=", UA_BOOLEAN, &user_access.link_auth, 0, 0}, + { "ipmi=", UA_BOOLEAN, &user_access.ipmi_messaging, 0, 0}, + { "privilege=", UA_INTEGER, &user_access.privilege_limit + , IPMI_SESSION_PRIV_CALLBACK + , IPMI_SESSION_PRIV_NOACCESS }, + }; + + if (argc > 0 && !strcmp(argv[0], "help")) { printf_channel_usage(); return 0; } else if (argc < 3) { @@ -778,33 +845,46 @@ ipmi_set_user_access(struct ipmi_intf *intf, int argc, char **argv) return (-1); } for (i = 2; i < argc; i ++) { - if (strncmp(argv[i], "callin=", 7) == 0) { - if (strncmp(argv[i] + 7, "off", 3) == 0) { - user_access.callin_callback = 1; - } else { - user_access.callin_callback = 0; - } - } else if (strncmp(argv[i], "link=", 5) == 0) { - if (strncmp(argv[i] + 5, "off", 3) == 0) { - user_access.link_auth = 0; - } else { - user_access.link_auth = 1; - } - } else if (strncmp(argv[i], "ipmi=", 5) == 0) { - if (strncmp(argv[i] + 5, "off", 3) == 0) { - user_access.ipmi_messaging = 0; - } else { - user_access.ipmi_messaging = 1; - } - } else if (strncmp(argv[i], "privilege=", 10) == 0) { - if (str2uchar(argv[i] + 10, &priv) != 0) { - lprintf(LOG_ERR, - "Numeric value expected, but '%s' given.", - argv[i] + 10); - return (-1); + size_t j; + for (j = 0; j < ARRAY_SIZE(options); ++j) { + const char *opt = argv[i]; + const int optlen = strlen(options[j].option); + if (!strncmp(opt, options[j].option, optlen)) { + const char *optval = opt + optlen; + uint16_t val; + + if (UA_INTEGER != options[j].type) { + bool boolval = (UA_BOOLEAN_INVERSE == options[j].type) + ? false + : true; + *options[j].val = boolval; + if (!strcmp(optval, "off") + || !strcmp(optval, "disable") + || !strcmp(optval, "no")) + { + boolval = !boolval; + } + } else if (UINT8_MAX + != (val = str2val(optval, ipmi_privlvl_vals))) + { + *options[j].val = (uint8_t)val; + } else if (str2uchar(optval, options[j].val)) { + lprintf(LOG_ERR + , "Numeric [%hhu-%hhu] value expected, " + "but '%s' given." + , options[j].min + , options[j].max + , optval); + return (-1); + } + lprintf(LOG_DEBUG + , "Option %s=%hhu" + , options[j].option + , *options[j].val); + break; } - user_access.privilege_limit = priv; - } else { + } + if (ARRAY_SIZE(options) == j) { lprintf(LOG_ERR, "Invalid option: %s\n", argv[i]); return (-1); } @@ -831,10 +911,10 @@ ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv) lprintf(LOG_ERR, "Not enough parameters given."); printf_channel_usage(); return (-1); - } else if (strncmp(argv[0], "help", 4) == 0) { + } else if (!strcmp(argv[0], "help")) { printf_channel_usage(); return 0; - } else if (strncmp(argv[0], "authcap", 7) == 0) { + } else if (!strcmp(argv[0], "authcap")) { if (argc != 3) { printf_channel_usage(); return (-1); @@ -844,7 +924,7 @@ ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv) return (-1); } retval = ipmi_get_channel_auth_cap(intf, channel, priv); - } else if (strncmp(argv[0], "getaccess", 10) == 0) { + } else if (!strcmp(argv[0], "getaccess")) { uint8_t user_id = 0; if ((argc < 2) || (argc > 3)) { lprintf(LOG_ERR, "Not enough parameters given."); @@ -860,9 +940,9 @@ ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv) } } retval = ipmi_get_user_access(intf, channel, user_id); - } else if (strncmp(argv[0], "setaccess", 9) == 0) { + } else if (!strcmp(argv[0], "setaccess")) { return ipmi_set_user_access(intf, (argc - 1), &(argv[1])); - } else if (strncmp(argv[0], "info", 4) == 0) { + } else if (!strcmp(argv[0], "info")) { channel = 0xE; if (argc > 2) { printf_channel_usage(); @@ -874,11 +954,11 @@ ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv) } } retval = ipmi_get_channel_info(intf, channel); - } else if (strncmp(argv[0], "getciphers", 10) == 0) { + } else if (!strcmp(argv[0], "getciphers")) { /* channel getciphers [channel] */ channel = 0xE; if ((argc < 2) || (argc > 3) || - (strncmp(argv[1], "ipmi", 4) && strncmp(argv[1], "sol", 3))) { + (strcmp(argv[1], "ipmi") && strcmp(argv[1], "sol"))) { printf_channel_usage(); return (-1); } @@ -887,9 +967,9 @@ ipmi_channel_main(struct ipmi_intf *intf, int argc, char **argv) return (-1); } } - retval = ipmi_get_channel_cipher_suites(intf, - argv[1], /* ipmi | sol */ - channel); + retval = ipmi_print_channel_cipher_suites(intf, + argv[1], /* ipmi | sol */ + channel); } else { lprintf(LOG_ERR, "Invalid CHANNEL command: %s\n", argv[0]); printf_channel_usage(); diff --git a/lib/ipmi_chassis.c b/lib/ipmi_chassis.c index 7b5c2a8..7ac6770 100644 --- a/lib/ipmi_chassis.c +++ b/lib/ipmi_chassis.c @@ -29,13 +29,13 @@ * 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. */ -#define _SVID_SOURCE || _BSD_SOURCE || _POSIX_C_SOURCE >= 1 || \ - _XOPEN_SOURCE || _POSIX_SOURCE #include #include #include #include +#include +#include #include #include @@ -44,9 +44,132 @@ #include #include #include +#include + +#define CHASSIS_BOOT_MBOX_IANA_SZ 3 +#define CHASSIS_BOOT_MBOX_BLOCK_SZ 16 +#define CHASSIS_BOOT_MBOX_BLOCK0_SZ \ + (CHASSIS_BOOT_MBOX_BLOCK_SZ - CHASSIS_BOOT_MBOX_IANA_SZ) +#define CHASSIS_BOOT_MBOX_MAX_BLOCK 0xFF +#define CHASSIS_BOOT_MBOX_MAX_BLOCKS (CHASSIS_BOOT_MBOX_MAX_BLOCK + 1) + +/* Get/Set system boot option boot flags bit definitions */ +/* Boot flags byte 1 bits */ +#define BF1_VALID_SHIFT 7 +#define BF1_INVALID 0 +#define BF1_VALID (1 << BF1_VALID_SHIFT) +#define BF1_VALID_MASK BF1_VALID + +#define BF1_PERSIST_SHIFT 6 +#define BF1_ONCE 0 +#define BF1_PERSIST (1 << BF1_PERSIST_SHIFT) +#define BF1_PERSIST_MASK BF1_PERSIST + +#define BF1_BOOT_TYPE_SHIFT 5 +#define BF1_BOOT_TYPE_LEGACY 0 +#define BF1_BOOT_TYPE_EFI (1 << BF1_BOOT_TYPE_SHIFT) +#define BF1_BOOT_TYPE_MASK BF1_BOOT_TYPE_EFI + +/* Boot flags byte 2 bits */ +#define BF2_CMOS_CLEAR_SHIFT 7 +#define BF2_CMOS_CLEAR (1 << BF2_CMOS_CLEAR_SHIFT) +#define BF2_CMOS_CLEAR_MASK BF2_CMOS_CLEAR + +#define BF2_KEYLOCK_SHIFT 6 +#define BF2_KEYLOCK (1 << BF2_KEYLOCK_SHIFT) +#define BF2_KEYLOCK_MASK BF2_KEYLOCK + +#define BF2_BOOTDEV_SHIFT 2 +#define BF2_BOOTDEV_DEFAULT (0 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_PXE (1 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_HDD (2 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_HDD_SAFE (3 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_DIAG_PART (4 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_CDROM (5 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_SETUP (6 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_REMOTE_FDD (7 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_REMOTE_CDROM (8 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_REMOTE_PRIMARY_MEDIA (9 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_REMOTE_HDD (11 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_FDD (15 << BF2_BOOTDEV_SHIFT) +#define BF2_BOOTDEV_MASK (0xF << BF2_BOOTDEV_SHIFT) + +#define BF2_BLANK_SCREEN_SHIFT 1 +#define BF2_BLANK_SCREEN (1 << BF2_BLANK_SCREEN_SHIFT) +#define BF2_BLANK_SCREEN_MASK BF2_BLANK_SCREEN + +#define BF2_RESET_LOCKOUT_SHIFT 0 +#define BF2_RESET_LOCKOUT (1 << BF2_RESET_LOCKOUT_SHIFT) +#define BF2_RESET_LOCKOUT_MASK BF2_RESET_LOCKOUT + +/* Boot flags byte 3 bits */ +#define BF3_POWER_LOCKOUT_SHIFT 7 +#define BF3_POWER_LOCKOUT (1 << BF3_POWER_LOCKOUT_SHIFT) +#define BF3_POWER_LOCKOUT_MASK BF3_POWER_LOCKOUT + +#define BF3_VERBOSITY_SHIFT 5 +#define BF3_VERBOSITY_DEFAULT (0 << BF3_VERBOSITY_SHIFT) +#define BF3_VERBOSITY_QUIET (1 << BF3_VERBOSITY_SHIFT) +#define BF3_VERBOSITY_VERBOSE (2 << BF3_VERBOSITY_SHIFT) +#define BF3_VERBOSITY_MASK (3 << BF3_VERBOSITY_SHIFT) + +#define BF3_EVENT_TRAPS_SHIFT 4 +#define BF3_EVENT_TRAPS (1 << BF3_EVENT_TRAPS_SHIFT) +#define BF3_EVENT_TRAPS_MASK BF3_EVENT_TRAPS + +#define BF3_PASSWD_BYPASS_SHIFT 3 +#define BF3_PASSWD_BYPASS (1 << BF3_PASSWD_BYPASS_SHIFT) +#define BF3_PASSWD_BYPASS_MASK BF3_PASSWD_BYPASS + +#define BF3_SLEEP_LOCKOUT_SHIFT 2 +#define BF3_SLEEP_LOCKOUT (1 << BF3_SLEEP_LOCKOUT_SHIFT) +#define BF3_SLEEP_LOCKOUT_MASK BF3_SLEEP_LOCKOUT + +#define BF3_CONSOLE_REDIR_SHIFT 0 +#define BF3_CONSOLE_REDIR_DEFAULT (0 << BF3_CONSOLE_REDIR_SHIFT) +#define BF3_CONSOLE_REDIR_SUPPRESS (1 << BF3_CONSOLE_REDIR_SHIFT) +#define BF3_CONSOLE_REDIR_ENABLE (2 << BF3_CONSOLE_REDIR_SHIFT) +#define BF3_CONSOLE_REDIR_MASK (3 << BF3_CONSOLE_REDIR_SHIFT) + +/* Boot flags byte 4 bits */ +#define BF4_SHARED_MODE_SHIFT 3 +#define BF4_SHARED_MODE (1 << BF4_SHARED_MODE_SHIFT) +#define BF4_SHARED_MODE_MASK BF4_SHARED_MODE + +#define BF4_BIOS_MUX_SHIFT 0 +#define BF4_BIOS_MUX_DEFAULT (0 << BF4_BIOS_MUX_SHIFT) +#define BF4_BIOS_MUX_BMC (1 << BF4_BIOS_MUX_SHIFT) +#define BF4_BIOS_MUX_SYSTEM (2 << BF4_BIOS_MUX_SHIFT) +#define BF4_BIOS_MUX_MASK (7 << BF4_BIOS_MUX_SHIFT) + + +typedef struct { + uint8_t iana[CHASSIS_BOOT_MBOX_IANA_SZ]; + uint8_t data[CHASSIS_BOOT_MBOX_BLOCK0_SZ]; +} mbox_b0_data_t; + +typedef struct { + uint8_t block; + union { + uint8_t data[CHASSIS_BOOT_MBOX_BLOCK_SZ]; + mbox_b0_data_t b0; + }; +} mbox_t; extern int verbose; +static const struct valstr get_bootparam_cc_vals[] = { + { 0x80, "Unsupported parameter" }, + { 0x00, NULL } +}; + +static const struct valstr set_bootparam_cc_vals[] = { + { 0x80, "Unsupported parameter" }, + { 0x81, "Attempt to set 'in progress' while not in 'complete' state" }, + { 0x82, "Parameter is read-only" }, + { 0x00, NULL } +}; + int ipmi_chassis_power_status(struct ipmi_intf * intf) { @@ -59,11 +182,11 @@ ipmi_chassis_power_status(struct ipmi_intf * intf) req.msg.data_len = 0; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Unable to get Chassis Power Status"); return -1; } - if (rsp->ccode > 0) { + if (rsp->ccode) { lprintf(LOG_ERR, "Get Chassis Power Status failed: %s", val2str(rsp->ccode, completion_code_vals)); return -1; @@ -98,12 +221,12 @@ ipmi_chassis_power_control(struct ipmi_intf * intf, uint8_t ctl) req.msg.data_len = 1; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Unable to set Chassis Power Control to %s", val2str(ctl, ipmi_chassis_power_control_vals)); return -1; } - if (rsp->ccode > 0) { + if (rsp->ccode) { lprintf(LOG_ERR, "Set Chassis Power Control to %s failed: %s", val2str(ctl, ipmi_chassis_power_control_vals), val2str(rsp->ccode, completion_code_vals)); @@ -131,8 +254,8 @@ ipmi_chassis_identify(struct ipmi_intf * intf, char * arg) req.msg.netfn = IPMI_NETFN_CHASSIS; req.msg.cmd = 0x4; - if (arg != NULL) { - if (strncmp(arg, "force", 5) == 0) { + if (arg) { + if (!strcmp(arg, "force")) { identify_data.force_on = 1; } else { if ( (rc = str2uchar(arg, &identify_data.interval)) != 0) { @@ -154,11 +277,11 @@ ipmi_chassis_identify(struct ipmi_intf * intf, char * arg) } rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Unable to set Chassis Identify"); return -1; } - if (rsp->ccode > 0) { + if (rsp->ccode) { lprintf(LOG_ERR, "Set Chassis Identify failed: %s", val2str(rsp->ccode, completion_code_vals)); if (identify_data.force_on != 0) { @@ -172,7 +295,7 @@ ipmi_chassis_identify(struct ipmi_intf * intf, char * arg) } printf("Chassis identify interval: "); - if (arg == NULL) { + if (!arg) { printf("default (15 seconds)\n"); } else { if (identify_data.force_on != 0) { @@ -202,11 +325,11 @@ ipmi_chassis_poh(struct ipmi_intf * intf) req.msg.cmd = 0xf; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Unable to get Chassis Power-On-Hours"); return -1; } - if (rsp->ccode > 0) { + if (rsp->ccode) { lprintf(LOG_ERR, "Get Chassis Power-On-Hours failed: %s", val2str(rsp->ccode, completion_code_vals)); return -1; @@ -245,52 +368,18 @@ ipmi_chassis_restart_cause(struct ipmi_intf * intf) req.msg.cmd = 0x7; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Unable to get Chassis Restart Cause"); return -1; } - if (rsp->ccode > 0) { + if (rsp->ccode) { 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"); - } + printf("System restart cause: %s\n", + val2str(rsp->data[0] & 0xf, ipmi_chassis_restart_cause_vals)); return 0; } @@ -306,11 +395,11 @@ ipmi_chassis_status(struct ipmi_intf * intf) req.msg.cmd = 0x1; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Error sending Chassis Status command"); return -1; } - if (rsp->ccode > 0) { + if (rsp->ccode) { lprintf(LOG_ERR, "Error sending Chassis Status command: %s", val2str(rsp->ccode, completion_code_vals)); return -1; @@ -389,11 +478,11 @@ ipmi_chassis_selftest(struct ipmi_intf * intf) req.msg.cmd = 0x4; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Error sending Get Self Test command"); return -1; } - if (rsp->ccode > 0) { + if (rsp->ccode) { lprintf(LOG_ERR, "Error sending Get Self Test command: %s", val2str(rsp->ccode, completion_code_vals)); return -1; @@ -447,61 +536,166 @@ ipmi_chassis_selftest(struct ipmi_intf * intf) } static int -ipmi_chassis_set_bootparam(struct ipmi_intf * intf, uint8_t param, uint8_t * data, int len) +ipmi_chassis_set_bootparam(struct ipmi_intf * intf, + uint8_t param, void *data, int len) { struct ipmi_rs * rsp; struct ipmi_rq req; - uint8_t msg_data[16]; + struct { + uint8_t param; + uint8_t data[]; + } *msg_data; + int rc = -1; + size_t msgsize = 1 + len; /* Single-byte parameter plus the data */ + static const uint8_t BOOTPARAM_MASK = 0x7F; + + msg_data = malloc(msgsize); + if (!msg_data) { + goto out; + } + memset(msg_data, 0, msgsize); - memset(msg_data, 0, 16); - msg_data[0] = param & 0x7f; - memcpy(msg_data+1, data, len); + msg_data->param = param & BOOTPARAM_MASK; + memcpy(msg_data->data, 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; + req.msg.data = (uint8_t *)msg_data; + req.msg.data_len = msgsize; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Error setting Chassis Boot Parameter %d", param); return -1; } - if (rsp->ccode > 0) { + + rc = rsp->ccode; + if (rc) { if (param != 0) { - lprintf(LOG_ERR, "Set Chassis Boot Parameter %d failed: %s", - param, val2str(rsp->ccode, completion_code_vals)); + lprintf(LOG_ERR, + "Set Chassis Boot Parameter %d failed: %s", + param, + specific_val2str(rsp->ccode, + set_bootparam_cc_vals, + completion_code_vals)); } - return -1; + goto out; } lprintf(LOG_DEBUG, "Chassis Set Boot Parameter %d to %s", param, buf2str(data, len)); - return 0; + +out: + free_n(&msg_data); + return rc; +} + +/* Flags to ipmi_chassis_get_bootparam() */ +typedef enum { + PARAM_NO_GENERIC_INFO, /* Do not print generic boot parameter info */ + PARAM_NO_DATA_DUMP, /* Do not dump parameter data */ + PARAM_NO_RANGE_ERROR, /* Do not report out of range info to user */ + PARAM_SPECIFIC /* Parameter-specific flags start with this */ +} chassis_bootparam_flags_t; + +/* Flags to ipmi_chassis_get_bootparam() for Boot Mailbox parameter (7) */ +typedef enum { + MBOX_PARSE_USE_TEXT = PARAM_SPECIFIC, /* Use text output vs. hex */ + MBOX_PARSE_ALLBLOCKS /* Parse all blocks, not just one */ +} chassis_bootmbox_parse_t; + +#define BP_FLAG(x) (1 << (x)) + +static +void +chassis_bootmailbox_parse(void *buf, size_t len, int flags) +{ + void *blockdata; + size_t datalen; + bool use_text = flags & BP_FLAG(MBOX_PARSE_USE_TEXT); + bool all_blocks = flags & BP_FLAG(MBOX_PARSE_ALLBLOCKS); + + mbox_t *mbox; + + if (!buf || !len) { + return; + } + + mbox = buf; + blockdata = mbox->data; + datalen = len - sizeof(mbox->block); + if (!all_blocks) { + /* Print block selector only if a single block is printed */ + printf(" Selector : %d\n", mbox->block); + } + if (!mbox->block) { + uint32_t iana = ipmi24toh(mbox->b0.iana); + /* For block zero print the IANA Private Enterprise Number */ + printf(" IANA PEN : %" PRIu32 " [%s]\n", + iana, + val2str(iana, ipmi_oem_info)); + blockdata = mbox->b0.data; + datalen -= sizeof(mbox->b0.iana); + } + + printf(" Block "); + if (all_blocks) { + printf("%3" PRIu8 " Data : ", mbox->block); + } + else { + printf("Data : "); + } + if (use_text) { + /* Ensure the data string is null-terminated */ + unsigned char text[CHASSIS_BOOT_MBOX_BLOCK_SZ + 1] = { 0 }; + memcpy(text, blockdata, datalen); + printf("'%s'\n", text); + } + else { + printf("%s\n", buf2str(blockdata, datalen)); + } } static int -ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg) +ipmi_chassis_get_bootparam(struct ipmi_intf * intf, + int argc, char *argv[], int flags) { struct ipmi_rs * rsp; struct ipmi_rq req; uint8_t msg_data[3]; uint8_t param_id = 0; + bool skip_generic = flags & BP_FLAG(PARAM_NO_GENERIC_INFO); + bool skip_data = flags & BP_FLAG(PARAM_NO_DATA_DUMP); + bool skip_range = flags & BP_FLAG(PARAM_NO_RANGE_ERROR); + int rc = -1; - if (arg == NULL) - return -1; + if (argc < 1 || !argv[0]) { + goto out; + } - if (str2uchar(arg, ¶m_id) != 0) { - lprintf(LOG_ERR, "Invalid parameter '%s' given instead of bootparam.", - arg); - return (-1); + if (str2uchar(argv[0], ¶m_id)) { + lprintf(LOG_ERR, + "Invalid parameter '%s' given instead of bootparam.", + argv[0]); + goto out; } + --argc; + ++argv; + memset(msg_data, 0, 3); msg_data[0] = param_id & 0x7f; - msg_data[1] = 0; - msg_data[2] = 0; + + if (argc) { + if (str2uchar(argv[0], &msg_data[1])) { + lprintf(LOG_ERR, + "Invalid argument '%s' given to" + " bootparam %" PRIu8, + argv[0], msg_data[1]); + goto out; + } + } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_CHASSIS; @@ -510,13 +704,22 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg) req.msg.data_len = 3; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { - lprintf(LOG_ERR, "Error Getting Chassis Boot Parameter %s", arg); + if (!rsp) { + lprintf(LOG_ERR, + "Error Getting Chassis Boot Parameter %" PRIu8, + msg_data[0]); return -1; } - if (rsp->ccode > 0) { - lprintf(LOG_ERR, "Get Chassis Boot Parameter %s failed: %s", - arg, val2str(rsp->ccode, completion_code_vals)); + if (IPMI_CC_PARAM_OUT_OF_RANGE == rsp->ccode && skip_range) { + return -1; + } + if (rsp->ccode) { + lprintf(LOG_ERR, + "Get Chassis Boot Parameter %" PRIu8 " failed: %s", + msg_data[0], + specific_val2str(rsp->ccode, + get_bootparam_cc_vals, + completion_code_vals)); return -1; } @@ -526,10 +729,17 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg) 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)); + if (!skip_generic) { + 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"); + if (!skip_data) { + printf("Boot parameter data: %s\n", + buf2str(rsp->data+2, rsp->data_len - 2)); + } + } switch(param_id) { @@ -622,132 +832,181 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg) { printf( " Boot Flags :\n"); - if((rsp->data[2]&0x80) == 0x80) + if(rsp->data[2] & BF1_VALID) printf(" - Boot Flag Valid\n"); else printf(" - Boot Flag Invalid\n"); - if((rsp->data[2]&0x40) == 0x40) + if(rsp->data[2] & BF1_PERSIST) printf(" - Options apply to all future boots\n"); else printf(" - Options apply to only next boot\n"); - if((rsp->data[2]&0x20) == 0x20) + if(rsp->data[2] & BF1_BOOT_TYPE_EFI) printf(" - BIOS EFI boot \n"); else printf(" - BIOS PC Compatible (legacy) boot \n"); - if((rsp->data[3]&0x80) == 0x80) + if(rsp->data[3] & BF2_CMOS_CLEAR) printf(" - CMOS Clear\n"); - if((rsp->data[3]&0x40) == 0x40) + if(rsp->data[3] & BF2_KEYLOCK) printf(" - Lock Keyboard\n"); printf(" - Boot Device Selector : "); - switch( ((rsp->data[3]>>2)&0x0f)) + switch(rsp->data[3] & BF2_BOOTDEV_MASK) { - 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; + case BF2_BOOTDEV_DEFAULT: + printf("No override\n"); + break; + case BF2_BOOTDEV_PXE: + printf("Force PXE\n"); + break; + case BF2_BOOTDEV_HDD: + printf("Force Boot from default Hard-Drive\n"); + break; + case BF2_BOOTDEV_HDD_SAFE: + printf("Force Boot from default Hard-Drive, " + "request Safe-Mode\n"); + break; + case BF2_BOOTDEV_DIAG_PART: + printf("Force Boot from Diagnostic Partition\n"); + break; + case BF2_BOOTDEV_CDROM: + printf("Force Boot from CD/DVD\n"); + break; + case BF2_BOOTDEV_SETUP: + printf("Force Boot into BIOS Setup\n"); + break; + case BF2_BOOTDEV_REMOTE_FDD: + printf("Force Boot from remotely connected " + "Floppy/primary removable media\n"); + break; + case BF2_BOOTDEV_REMOTE_CDROM: + printf("Force Boot from remotely connected " + "CD/DVD\n"); + break; + case BF2_BOOTDEV_REMOTE_PRIMARY_MEDIA: + printf("Force Boot from primary remote media\n"); + break; + case BF2_BOOTDEV_REMOTE_HDD: + printf("Force Boot from remotely connected " + "Hard-Drive\n"); + break; + case BF2_BOOTDEV_FDD: + printf("Force Boot from Floppy/primary " + "removable media\n"); + break; + default: + printf("Flag error\n"); + break; } - if((rsp->data[3]&0x02) == 0x02) + if(rsp->data[3] & BF2_BLANK_SCREEN) printf(" - Screen blank\n"); - if((rsp->data[3]&0x01) == 0x01) + if(rsp->data[3] & BF2_RESET_LOCKOUT) 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)) + if(rsp->data[4] & BF3_POWER_LOCKOUT) + printf(" - Lock out (power off/sleep " + "request) via Power Button\n"); + + printf(" - BIOS verbosity : "); + switch(rsp->data[4] & BF3_VERBOSITY_MASK) { - 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; + case BF3_VERBOSITY_DEFAULT: + printf("System Default\n"); + break; + case BF3_VERBOSITY_QUIET: + printf("Request Quiet Display\n"); + break; + case BF3_VERBOSITY_VERBOSE: + printf("Request Verbose Display\n"); + break; + default: + printf("Flag error\n"); + break; } - if((rsp->data[4]&0x10) == 0x10) + if(rsp->data[4] & BF3_EVENT_TRAPS) printf(" - Force progress event traps\n"); - if((rsp->data[4]&0x08) == 0x08) + if(rsp->data[4] & BF3_PASSWD_BYPASS) printf(" - User password bypass\n"); - if((rsp->data[4]&0x04) == 0x04) + if(rsp->data[4] & BF3_SLEEP_LOCKOUT) 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)) + printf(" - Console Redirection control : "); + switch(rsp->data[4] & BF3_CONSOLE_REDIR_MASK) { - 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; + case BF3_CONSOLE_REDIR_DEFAULT: + printf( + "Console redirection occurs per BIOS " + "configuration setting (default)\n"); + break; + case BF3_CONSOLE_REDIR_SUPPRESS: + printf("Suppress (skip) console redirection " + "if enabled\n"); + break; + case BF3_CONSOLE_REDIR_ENABLE: + printf("Request console redirection be " + "enabled\n"); + break; + default: + printf("Flag error\n"); + break; } - if((rsp->data[5]&0x08) == 0x08) + if(rsp->data[5] & BF4_SHARED_MODE) 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; + switch (rsp->data[5] & BF4_BIOS_MUX_MASK) { + case BF4_BIOS_MUX_DEFAULT: + printf("BIOS uses recommended setting of the " + "mux at the end of POST\n"); + break; + case BF4_BIOS_MUX_BMC: + printf( + "Requests BIOS to force mux to BMC at " + "conclusion of POST/start of OS boot\n"); + break; + case BF4_BIOS_MUX_SYSTEM: + 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; + uint32_t timestamp; 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) - ); + timestamp = ipmi32toh(&rsp->data[7]); 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); - } - + printf(" Timestamp : %s\n", ipmi_timestamp_numeric(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; + chassis_bootmailbox_parse(rsp->data + 2, + rsp->data_len - 2, + flags); + break; default: - printf(" Undefined byte\n"); + printf(" Unsupported parameter %" PRIu8 "\n", param_id); break; } - return 0; + rc = IPMI_CC_OK; +out: + return rc; } static int @@ -777,24 +1036,25 @@ get_bootparam_options(char *optstring, {NULL} /* End marker */ }, *op; + const char *optkw = "options="; - if (strncmp(optstring, "options=", 8) != 0) { + if (strncmp(optstring, optkw, strlen(optkw))) { lprintf(LOG_ERR, "No options= keyword found \"%s\"", optstring); return -1; } token = strtok_r(optstring + 8, ",", &saveptr); - while (token != NULL) { + while (token) { int setbit = 0; - if (strcmp(token, "help") == 0) { + if (!strcmp(token, "help")) { optionError = 1; break; } - if (strncmp(token, "no-", 3) == 0) { + if (!strcmp(token, "no-")) { setbit = 1; token += 3; } - for (op = options; op->name != NULL; ++op) { - if (strncmp(token, op->name, strlen(op->name)) == 0) { + for (op = options; op->name; ++op) { + if (!strcmp(token, op->name)) { if (setbit) { *set_flag |= op->value; } else { @@ -803,7 +1063,7 @@ get_bootparam_options(char *optstring, break; } } - if (op->name == NULL) { + if (!op->name) { /* Option not found */ optionError = 1; if (setbit) { @@ -816,7 +1076,7 @@ get_bootparam_options(char *optstring, if (optionError) { lprintf(LOG_NOTICE, " Legal options are:"); lprintf(LOG_NOTICE, " %-8s: print this message", "help"); - for (op = options; op->name != NULL; ++op) { + for (op = options; op->name; ++op) { lprintf(LOG_NOTICE, " %-8s: %s", op->name, op->desc); } lprintf(LOG_NOTICE, " Any Option may be prepended with no-" @@ -846,14 +1106,17 @@ ipmi_chassis_get_bootvalid(struct ipmi_intf * intf) req.msg.data_len = 3; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Error Getting Chassis Boot Parameter %d", param_id); return -1; } - if (rsp->ccode > 0) { + if (rsp->ccode) { lprintf(LOG_ERR, "Get Chassis Boot Parameter %d failed: %s", - param_id, val2str(rsp->ccode, completion_code_vals)); + param_id, + specific_val2str(rsp->ccode, + get_bootparam_cc_vals, + completion_code_vals)); return -1; } @@ -863,77 +1126,97 @@ ipmi_chassis_get_bootvalid(struct ipmi_intf * intf) return(rsp->data[2]); } +typedef enum { + SET_COMPLETE, + SET_IN_PROGRESS, + COMMIT_WRITE, + RESERVED +} progress_t; + + +static +void +chassis_bootparam_set_in_progress(struct ipmi_intf *intf, progress_t progress) +{ + /* + * By default try to set/clear set-in-progress parameter before/after + * changing any boot parameters. If setting fails, the code will set + * this flag to false and stop trying to fiddle with it for future + * requests. + */ + static bool use_progress = true; + uint8_t flag = progress; + int rc; + + if (!use_progress) { + return; + } + + rc = ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, + &flag, 1); + + /* + * Only disable future checks if set in progress status setting failed. + * Setting of other statuses may fail legitimately. + */ + if (rc && SET_IN_PROGRESS == progress) { + use_progress = false; + } +} + +typedef enum { + BIOS_POST_ACK = 1 << 0, + OS_LOADER_ACK = 1 << 1, + OS_SERVICE_PARTITION_ACK = 1 << 2, + SMS_ACK = 1 << 3, + OEM_ACK = 1 << 4, + RESERVED_ACK_MASK = 7 << 5 +} bootinfo_ack_t; + +static +int +chassis_bootparam_clear_ack(struct ipmi_intf *intf, bootinfo_ack_t flag) +{ + uint8_t flags[2] = { flag & ~RESERVED_ACK_MASK, + flag & ~RESERVED_ACK_MASK }; + + return ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_INFO_ACK, + flags, 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; + uint8_t flags[2]; + int rc; - 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); + chassis_bootparam_set_in_progress(intf, SET_IN_PROGRESS); + rc = chassis_bootparam_clear_ack(intf, BIOS_POST_ACK); - 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 (rc) { + goto out; } 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); - } + lprintf(LOG_ERR, "Failed to read boot valid flag"); + rc = bootvalid; + goto out; } - 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); + flags[0] = (bootvalid & ~clr_flag) | set_flag; + rc = ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_FLAG_VALID, + flags, 1); + if (IPMI_CC_OK == rc) { + chassis_bootparam_set_in_progress(intf, COMMIT_WRITE); } +out: + chassis_bootparam_set_in_progress(intf, SET_COMPLETE); return rc; } @@ -941,107 +1224,372 @@ 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; + int rc; - 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); + chassis_bootparam_set_in_progress(intf, SET_IN_PROGRESS); + rc = chassis_bootparam_clear_ack(intf, BIOS_POST_ACK); 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; + goto out; } - if (iflags == NULL) - memset(flags, 0, 5); + if (!iflags) + memset(flags, 0, sizeof(flags)); else memcpy(flags, iflags, sizeof (flags)); - if (arg == NULL) + if (!arg) flags[1] |= 0x00; - else if (strncmp(arg, "none", 4) == 0) + else if (!strcmp(arg, "none")) flags[1] |= 0x00; - else if (strncmp(arg, "pxe", 3) == 0 || - strncmp(arg, "force_pxe", 9) == 0) + else if (!strcmp(arg, "pxe") || + !strcmp(arg, "force_pxe")) + { flags[1] |= 0x04; - else if (strncmp(arg, "disk", 4) == 0 || - strncmp(arg, "force_disk", 10) == 0) + } + else if (!strcmp(arg, "disk") || + !strcmp(arg, "force_disk")) + { flags[1] |= 0x08; - else if (strncmp(arg, "safe", 4) == 0 || - strncmp(arg, "force_safe", 10) == 0) + } + else if (!strcmp(arg, "safe") || + !strcmp(arg, "force_safe")) + { flags[1] |= 0x0c; - else if (strncmp(arg, "diag", 4) == 0 || - strncmp(arg, "force_diag", 10) == 0) + } + else if (!strcmp(arg, "diag") || + !strcmp(arg, "force_diag")) + { flags[1] |= 0x10; - else if (strncmp(arg, "cdrom", 5) == 0 || - strncmp(arg, "force_cdrom", 11) == 0) + } + else if (!strcmp(arg, "cdrom") || + !strcmp(arg, "force_cdrom")) + { flags[1] |= 0x14; - else if (strncmp(arg, "floppy", 6) == 0 || - strncmp(arg, "force_floppy", 12) == 0) + } + else if (!strcmp(arg, "floppy") || + !strcmp(arg, "force_floppy")) + { flags[1] |= 0x3c; - else if (strncmp(arg, "bios", 4) == 0 || - strncmp(arg, "force_bios", 10) == 0) + } + else if (!strcmp(arg, "bios") || + !strcmp(arg, "force_bios")) + { 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; + rc = -1; + goto out; } /* 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); + rc = ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_BOOT_FLAGS, + flags, 5); + if (IPMI_CC_OK == rc) { + chassis_bootparam_set_in_progress(intf, COMMIT_WRITE); + printf("Set Boot Device to %s\n", arg); + } + +out: + chassis_bootparam_set_in_progress(intf, SET_COMPLETE); + return rc; +} + +static void chassis_bootmailbox_help() +{ + lprintf(LOG_NOTICE, +"bootmbox get [text] [block ]\n" +" Read the entire Boot Initiator Mailbox or the specified .\n" +" If 'text' option is specified, the data is output as plain text, otherwise\n" +" hex dump mode is used.\n" +"\n" +"bootmbox set text [block ] \"\"\n" +"bootmbox set [block ] [ ...]\n" +" Write the specified or the entire Boot Initiator Mailbox.\n" +" It is required to specify a decimal IANA Enterprise Number recognized\n" +" by the boot initiator on the target system. Refer to your target system\n" +" manufacturer for details. The rest of the arguments are either separate\n" +" data byte values separated by spaces, or a single text string argument.\n" +"\n" +" When single block write is requested, the total length of may not\n" +" exceed 13 bytes for block 0, or 16 bytes otherwise.\n" +"\n" +"bootmbox help\n" +" Show this help."); +} + +static +int +chassis_set_bootmailbox(struct ipmi_intf *intf, int16_t block, bool use_text, + int argc, char *argv[]) +{ + int rc = -1; + int32_t iana = 0; + size_t blocks = 0; + size_t datasize = 0; + off_t string_offset = 0; + + lprintf(LOG_INFO, "Writing Boot Mailbox..."); + + if (argc < 1 || str2int(argv[0], &iana)) { + lprintf(LOG_ERR, + "No valid IANA PEN specified!\n"); + chassis_bootmailbox_help(); + goto out; + } + ++argv; + --argc; + + if (argc < 1) { + lprintf(LOG_ERR, + "No data provided!\n"); + chassis_bootmailbox_help(); + goto out; + } + + /* + * Initialize the data size. For text mode it is just the + * single argument string length plus one byte for \0 termination. + * For byte mode the length is the number of byte arguments without + * any additional termination. + */ + if (!use_text) { + datasize = argc; + } + else { + datasize = strlen(argv[0]) + 1; /* Include the terminator */ + } + + lprintf(LOG_INFO, "Data size: %u", datasize); + + /* Decide how many blocks we will be writing */ + if (block >= 0) { + blocks = 1; + } + else { + /* + * We need to write all data, so calculate the data + * size in blocks and set the starting block to zero. + */ + blocks = CHASSIS_BOOT_MBOX_IANA_SZ; + blocks += datasize; + blocks += CHASSIS_BOOT_MBOX_BLOCK_SZ - 1; + blocks /= CHASSIS_BOOT_MBOX_BLOCK_SZ; + + block = 0; + } + + lprintf(LOG_INFO, "Blocks to write: %d", blocks); + + if (blocks > CHASSIS_BOOT_MBOX_MAX_BLOCKS) { + lprintf(LOG_ERR, + "Data size %zu exceeds maximum (%d)", + datasize, + (CHASSIS_BOOT_MBOX_BLOCK_SZ + * CHASSIS_BOOT_MBOX_MAX_BLOCKS) + - CHASSIS_BOOT_MBOX_IANA_SZ); + goto out; + } + + /* Indicate that we're touching the boot parameters */ + chassis_bootparam_set_in_progress(intf, SET_IN_PROGRESS); + + for (size_t bindex = 0; + datasize > 0 && bindex < blocks; + ++bindex, ++block) + { + /* The request data structure */ + mbox_t mbox = { .block = block, {{0}} }; + + /* Destination for input data */ + uint8_t *data = mbox.data; + + /* The maximum amount of data this block may hold */ + size_t maxblocksize = sizeof(mbox.data); + + /* The actual amount of data in this block */ + size_t blocksize; + off_t unused = 0; + + /* Block 0 needs special care as it has IANA PEN specifier */ + if (!block) { + data = mbox.b0.data; + maxblocksize = sizeof(mbox.b0.data); + htoipmi24(iana, mbox.b0.iana); } - printf("Set Boot Device to %s\n", arg); + /* + * Find out how many bytes we are going to write to this + * block. + */ + if (datasize > maxblocksize) { + blocksize = maxblocksize; + } + else { + blocksize = datasize; + } + + /* Remember how much data remains */ + datasize -= blocksize; + + if (!use_text) { + args2buf(argc, argv, data, blocksize); + argc -= blocksize; + argv += blocksize; + } + else { + memcpy(data, argv[0] + string_offset, blocksize); + string_offset += blocksize; + } + + lprintf(LOG_INFO, "Block %3" PRId16 ": %s", block, + buf2str_extended(data, blocksize, " ")); + + unused = maxblocksize - blocksize; + rc = ipmi_chassis_set_bootparam(intf, + IPMI_CHASSIS_BOOTPARAM_INIT_MBOX, + &mbox, + sizeof(mbox) - unused); + if (IPMI_CC_PARAM_OUT_OF_RANGE == rc) { + lprintf(LOG_ERR, + "Hit end of mailbox writing block %" PRId16, + block); + } + if (rc) { + goto complete; + } } - 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); + lprintf(LOG_INFO, + "Wrote %zu blocks of Boot Initiator Mailbox", + blocks); + chassis_bootparam_set_in_progress(intf, COMMIT_WRITE); + + rc = chassis_bootparam_clear_ack(intf, BIOS_POST_ACK | OS_LOADER_ACK); + +complete: + chassis_bootparam_set_in_progress(intf, SET_COMPLETE); +out: + return rc; +} + +static +int +chassis_get_bootmailbox(struct ipmi_intf *intf, + int16_t block, bool use_text) +{ + int rc = IPMI_CC_UNSPECIFIED_ERROR; + char param_str[2]; /* Max "7" */ + char block_str[4]; /* Max "255" */ + char *bpargv[] = { param_str, block_str }; + int flags; + + flags = use_text ? BP_FLAG(MBOX_PARSE_USE_TEXT) : 0; + + snprintf(param_str, sizeof(param_str), + "%" PRIu8, IPMI_CHASSIS_BOOTPARAM_INIT_MBOX); + + if (block >= 0) { + snprintf(block_str, sizeof(block_str), + "%" PRIu8, (uint8_t)block); + + rc = ipmi_chassis_get_bootparam(intf, + ARRAY_SIZE(bpargv), + bpargv, + flags); + } + else { + int currblk; + + flags |= BP_FLAG(MBOX_PARSE_ALLBLOCKS); + for (currblk = 0; currblk <= UCHAR_MAX; ++currblk) { + snprintf(block_str, sizeof(block_str), + "%" PRIu8, (uint8_t)currblk); + + if (currblk) { + /* + * If block 0 succeeded, we don't want to + * print generic info for each next block, + * and we don't want range error to be + * reported when we hit the end of blocks. + */ + flags |= BP_FLAG(PARAM_NO_GENERIC_INFO); + flags |= BP_FLAG(PARAM_NO_RANGE_ERROR); + } + + rc = ipmi_chassis_get_bootparam(intf, + ARRAY_SIZE(bpargv), + bpargv, + flags); + + if (rc) { + if (currblk) { + rc = IPMI_CC_OK; + } + break; + } + } } return rc; } +static +int +chassis_bootmailbox(struct ipmi_intf *intf, int argc, char *argv[]) +{ + int rc = IPMI_CC_UNSPECIFIED_ERROR; + bool use_text = false; /* Default to data dump I/O mode */ + int16_t block = -1; /* By default print all blocks */ + const char *cmd; + + if ((argc < 1) || !strcmp(argv[0], "help")) { + chassis_bootmailbox_help(); + goto out; + } else { + cmd = argv[0]; + ++argv; + --argc; + + if (argc > 0 && !strcmp(argv[0], "text")) { + use_text = true; + ++argv; + --argc; + } + + if (argc > 0 && !strcmp(argv[0], "block")) { + if (argc < 2) { + chassis_bootmailbox_help(); + goto out; + } + if(str2short(argv[1], &block)) { + lprintf(LOG_ERR, + "Invalid block %s", argv[1]); + goto out; + } + argv += 2; + argc -= 2; + + } + + if (!strcmp(cmd, "get")) { + rc = chassis_get_bootmailbox(intf, block, use_text); + } + else if (!strcmp(cmd, "set")) { + rc = chassis_set_bootmailbox(intf, block, use_text, + argc, argv); + } + } + +out: + return rc; +} + + static int ipmi_chassis_power_policy(struct ipmi_intf * intf, uint8_t policy) { @@ -1055,11 +1603,11 @@ ipmi_chassis_power_policy(struct ipmi_intf * intf, uint8_t policy) req.msg.data_len = 1; rsp = intf->sendrecv(intf, &req); - if (rsp == NULL) { + if (!rsp) { lprintf(LOG_ERR, "Error in Power Restore Policy command"); return -1; } - if (rsp->ccode > 0) { + if (rsp->ccode) { lprintf(LOG_ERR, "Power Restore Policy command failed: %s", val2str(rsp->ccode, completion_code_vals)); return -1; @@ -1100,25 +1648,25 @@ ipmi_power_main(struct ipmi_intf * intf, int argc, char ** argv) int rc = 0; uint8_t ctl = 0; - if ((argc < 1) || (strncmp(argv[0], "help", 4) == 0)) { + if (argc < 1 || !strcmp(argv[0], "help")) { lprintf(LOG_NOTICE, "chassis power Commands: status, on, off, cycle, reset, diag, soft"); return 0; } - if (strncmp(argv[0], "status", 6) == 0) { + if (!strcmp(argv[0], "status")) { rc = ipmi_chassis_print_power_status(intf); return rc; } - if ((strncmp(argv[0], "up", 2) == 0) || (strncmp(argv[0], "on", 2) == 0)) + if (!strcmp(argv[0], "up") || !strcmp(argv[0], "on")) ctl = IPMI_CHASSIS_CTL_POWER_UP; - else if ((strncmp(argv[0], "down", 4) == 0) || (strncmp(argv[0], "off", 3) == 0)) + else if (!strcmp(argv[0], "down") || !strcmp(argv[0], "off")) ctl = IPMI_CHASSIS_CTL_POWER_DOWN; - else if (strncmp(argv[0], "cycle", 5) == 0) + else if (!strcmp(argv[0], "cycle")) ctl = IPMI_CHASSIS_CTL_POWER_CYCLE; - else if (strncmp(argv[0], "reset", 5) == 0) + else if (!strcmp(argv[0], "reset")) ctl = IPMI_CHASSIS_CTL_HARD_RESET; - else if (strncmp(argv[0], "diag", 4) == 0) + else if (!strcmp(argv[0], "diag")) ctl = IPMI_CHASSIS_CTL_PULSE_DIAG; - else if ((strncmp(argv[0], "acpi", 4) == 0) || (strncmp(argv[0], "soft", 4) == 0)) + else if (!strcmp(argv[0], "acpi") || !strcmp(argv[0], "soft")) ctl = IPMI_CHASSIS_CTL_ACPI_SOFT; else { lprintf(LOG_ERR, "Invalid chassis power command: %s", argv[0]); @@ -1146,55 +1694,270 @@ ipmi_chassis_set_bootflag_help() get_bootparam_options("options=help", &set_flag, &clr_flag); } +/* + * Sugar. Macros for internal use by bootdev_parse_options() to make + * the structure initialization look better. Can't use scope-limited + * static consts for initializers with gcc5, alas. + */ +#define BF1_OFFSET 0 +#define BF2_OFFSET 1 +#define BF3_OFFSET 2 +#define BF4_OFFSET 3 +#define BF_BYTE_COUNT 5 + +/* A helper for ipmi_chassis_main() to parse bootdev options */ +static +bool +bootdev_parse_options(char *optstring, uint8_t flags[]) +{ + char *token; + char *saveptr = NULL; + int optionError = 0; + + static const struct bootdev_opt_s { + char *name; + off_t offset; + unsigned char mask; + unsigned char value; + char *desc; + } *op; + static const struct bootdev_opt_s options[] = { + /* data 1 */ + { + "valid", + BF1_OFFSET, + BF1_VALID_MASK, + BF1_VALID, + "Boot flags valid" + }, + { + "persistent", + BF1_OFFSET, + BF1_PERSIST_MASK, + BF1_PERSIST, + "Changes are persistent for " + "all future boots" + }, + { + "efiboot", + BF1_OFFSET, + BF1_BOOT_TYPE_MASK, + BF1_BOOT_TYPE_EFI, + "Extensible Firmware Interface " + "Boot (EFI)" + }, + /* data 2 */ + { + "clear-cmos", + BF2_OFFSET, + BF2_CMOS_CLEAR_MASK, + BF2_CMOS_CLEAR, + "CMOS clear" + }, + { + "lockkbd", + BF2_OFFSET, + BF2_KEYLOCK_MASK, + BF2_KEYLOCK, + "Lock Keyboard" + }, + /* data2[5:2] is parsed elsewhere */ + { + "screenblank", + BF2_OFFSET, + BF2_BLANK_SCREEN_MASK, + BF2_BLANK_SCREEN, + "Screen Blank" + }, + { + "lockoutreset", + BF2_OFFSET, + BF2_RESET_LOCKOUT_MASK, + BF2_RESET_LOCKOUT, + "Lock out Reset buttons" + }, + /* data 3 */ + { + "lockout_power", + BF3_OFFSET, + BF3_POWER_LOCKOUT_MASK, + BF3_POWER_LOCKOUT, + "Lock out (power off/sleep " + "request) via Power Button" + }, + { + "verbose=default", + BF3_OFFSET, + BF3_VERBOSITY_MASK, + BF3_VERBOSITY_DEFAULT, + "Request quiet BIOS display" + }, + { + "verbose=no", + BF3_OFFSET, + BF3_VERBOSITY_MASK, + BF3_VERBOSITY_QUIET, + "Request quiet BIOS display" + }, + { + "verbose=yes", + BF3_OFFSET, + BF3_VERBOSITY_MASK, + BF3_VERBOSITY_VERBOSE, + "Request verbose BIOS display" + }, + { + "force_pet", + BF3_OFFSET, + BF3_EVENT_TRAPS_MASK, + BF3_EVENT_TRAPS, + "Force progress event traps" + }, + { + "upw_bypass", + BF3_OFFSET, + BF3_PASSWD_BYPASS_MASK, + BF3_PASSWD_BYPASS, + "User password bypass" + }, + { + "lockout_sleep", + BF3_OFFSET, + BF3_SLEEP_LOCKOUT_MASK, + BF3_SLEEP_LOCKOUT, + "Lock out the Sleep button" + }, + { + "cons_redirect=default", + BF3_OFFSET, + BF3_CONSOLE_REDIR_MASK, + BF3_CONSOLE_REDIR_DEFAULT, + "Console redirection occurs per " + "BIOS configuration setting" + }, + { + "cons_redirect=skip", + BF3_OFFSET, + BF3_CONSOLE_REDIR_MASK, + BF3_CONSOLE_REDIR_SUPPRESS, + "Suppress (skip) console " + "redirection if enabled" + }, + { + "cons_redirect=enable", + BF3_OFFSET, + BF3_CONSOLE_REDIR_MASK, + BF3_CONSOLE_REDIR_ENABLE, + "Request console redirection " + "be enabled" + }, + /* data 4 */ + /* data4[7:4] reserved */ + /* data4[3] BIOS Shared Mode Override, not implemented here */ + /* data4[2:0] BIOS Mux Control Override, not implemented here */ + + /* data5 reserved */ + + {NULL} /* End marker */ + }; + + memset(&flags[0], 0, BF_BYTE_COUNT); + token = strtok_r(optstring, ",", &saveptr); + while (token) { + if (!strcmp(token, "help")) { + optionError = 1; + break; + } + for (op = options; op->name; ++op) { + if (!strcmp(token, op->name)) { + flags[op->offset] &= ~(op->mask); + flags[op->offset] |= op->value; + break; + } + } + if (!op->name) { + /* Option not found */ + optionError = 1; + lprintf(LOG_ERR, "Invalid option: %s", token); + } + token = strtok_r(NULL, ",", &saveptr); + } + if (optionError) { + lprintf(LOG_NOTICE, "Legal options settings are:"); + lprintf(LOG_NOTICE, " %-22s: %s", + "help", + "print this message"); + for (op = options; op->name; ++op) { + lprintf(LOG_NOTICE, " %-22s: %s", op->name, op->desc); + } + return false; + } + + return true; +} + int ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv) { - int rc = 0; + int rc = -1; - if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) { - lprintf(LOG_NOTICE, "Chassis Commands: status, power, identify, policy, restart_cause, poh, bootdev, bootparam, selftest"); + if (!argc || !strcmp(argv[0], "help")) { + lprintf(LOG_NOTICE, "Chassis Commands:\n" + " status, power, policy, restart_cause\n" + " poh, identify, selftest,\n" + " bootdev, bootparam, bootmbox"); } - else if (strncmp(argv[0], "status", 6) == 0) { + else if (!strcmp(argv[0], "status")) { rc = ipmi_chassis_status(intf); } - else if (strncmp(argv[0], "selftest", 8) == 0) { + else if (!strcmp(argv[0], "selftest")) { rc = ipmi_chassis_selftest(intf); } - else if (strncmp(argv[0], "power", 5) == 0) { + else if (!strcmp(argv[0], "power")) { uint8_t ctl = 0; - if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) { + if (argc < 2 || !strcmp(argv[1], "help")) { lprintf(LOG_NOTICE, "chassis power Commands: status, on, off, cycle, reset, diag, soft"); - return 0; + rc = 0; + goto out; } - if (strncmp(argv[1], "status", 6) == 0) { + if (!strcmp(argv[1], "status")) { rc = ipmi_chassis_print_power_status(intf); - return rc; + goto out; } - if ((strncmp(argv[1], "up", 2) == 0) || (strncmp(argv[1], "on", 2) == 0)) + if (!strcmp(argv[1], "up") || + !strcmp(argv[1], "on")) + { ctl = IPMI_CHASSIS_CTL_POWER_UP; - else if ((strncmp(argv[1], "down", 4) == 0) || (strncmp(argv[1], "off", 3) == 0)) + } + else if (!strcmp(argv[1], "down") || + !strcmp(argv[1], "off")) + { ctl = IPMI_CHASSIS_CTL_POWER_DOWN; - else if (strncmp(argv[1], "cycle", 5) == 0) + } + else if (!strcmp(argv[1], "cycle")) ctl = IPMI_CHASSIS_CTL_POWER_CYCLE; - else if (strncmp(argv[1], "reset", 5) == 0) + else if (!strcmp(argv[1], "reset")) ctl = IPMI_CHASSIS_CTL_HARD_RESET; - else if (strncmp(argv[1], "diag", 4) == 0) + else if (!strcmp(argv[1], "diag")) ctl = IPMI_CHASSIS_CTL_PULSE_DIAG; - else if ((strncmp(argv[1], "acpi", 4) == 0) || (strncmp(argv[1], "soft", 4) == 0)) + else if (!strcmp(argv[1], "acpi") || + !strcmp(argv[1], "soft")) + { ctl = IPMI_CHASSIS_CTL_ACPI_SOFT; + } else { lprintf(LOG_ERR, "Invalid chassis power command: %s", argv[1]); - return -1; + goto out; } rc = ipmi_chassis_power_control(intf, ctl); } - else if (strncmp(argv[0], "identify", 8) == 0) { + else if (!strcmp(argv[0], "identify")) { if (argc < 2) { rc = ipmi_chassis_identify(intf, NULL); } - else if (strncmp(argv[1], "help", 4) == 0) { + else if (!strcmp(argv[1], "help")) { lprintf(LOG_NOTICE, "chassis identify "); lprintf(LOG_NOTICE, " default is 15 seconds"); lprintf(LOG_NOTICE, " 0 to turn off"); @@ -1203,14 +1966,14 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv) rc = ipmi_chassis_identify(intf, argv[1]); } } - else if (strncmp(argv[0], "poh", 3) == 0) { + else if (!strcmp(argv[0], "poh")) { rc = ipmi_chassis_poh(intf); } - else if (strncmp(argv[0], "restart_cause", 13) == 0) { + else if (!strcmp(argv[0], "restart_cause")) { rc = ipmi_chassis_restart_cause(intf); } - else if (strncmp(argv[0], "policy", 4) == 0) { - if ((argc < 2) || (strncmp(argv[1], "help", 4) == 0)) { + else if (!strcmp(argv[0], "policy")) { + if (argc < 2 || !strcmp(argv[1], "help")) { lprintf(LOG_NOTICE, "chassis policy "); lprintf(LOG_NOTICE, " list : return supported policies"); lprintf(LOG_NOTICE, " always-on : turn on when power is restored"); @@ -1218,13 +1981,13 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv) lprintf(LOG_NOTICE, " always-off : stay off after power is restored"); } else { uint8_t ctl; - if (strncmp(argv[1], "list", 4) == 0) + if (!strcmp(argv[1], "list")) ctl = IPMI_CHASSIS_POLICY_NO_CHANGE; - else if (strncmp(argv[1], "always-on", 9) == 0) + else if (!strcmp(argv[1], "always-on")) ctl = IPMI_CHASSIS_POLICY_ALWAYS_ON; - else if (strncmp(argv[1], "previous", 8) == 0) + else if (!strcmp(argv[1], "previous")) ctl = IPMI_CHASSIS_POLICY_PREVIOUS; - else if (strncmp(argv[1], "always-off", 10) == 0) + else if (!strcmp(argv[1], "always-off")) ctl = IPMI_CHASSIS_POLICY_ALWAYS_OFF; else { lprintf(LOG_ERR, "Invalid chassis policy: %s", argv[1]); @@ -1233,21 +1996,26 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv) rc = ipmi_chassis_power_policy(intf, ctl); } } - else if (strncmp(argv[0], "bootparam", 9) == 0) { - if ((argc < 3) || (strncmp(argv[1], "help", 4) == 0)) { + else if (!strcmp(argv[0], "bootparam")) { + if (argc < 3 || !strcmp(argv[1], "help")) { 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]); + if (!strcmp(argv[1], "get")) { + rc = ipmi_chassis_get_bootparam(intf, + argc - 2, + argv + 2, + 0); } - else if (strncmp(argv[1], "set", 3) == 0) { + else if (!strcmp(argv[1], "set")) { 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)) { + if (!strcmp(argv[2], "help") + || argc < 4 + || (argc >= 4 + && strcmp(argv[2], "bootflag"))) + { ipmi_chassis_set_bootflag_help(); } else { if (argc == 5) { @@ -1263,8 +2031,8 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv) lprintf(LOG_NOTICE, "bootparam get|set