diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-10-09 09:19:55 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2016-10-09 09:19:55 +0200 |
commit | 7ddeb3781f3d79ef1ae5a765a66f6cdd1ec113ef (patch) | |
tree | 3546836f27de4168559a62d8022626dfb101a133 | |
parent | 5bac665e38a15e6725f9ec17c7f7e80a0506aa08 (diff) | |
parent | 82ac6c87ce0b0af2fb8de25d70442fec406bb742 (diff) |
Merge tag 'upstream/1.8.18'
Upstream version 1.8.18
62 files changed, 6197 insertions, 3484 deletions
@@ -1,3 +1,67 @@ +version 1.8.18 2016-10-08 + * Add mac2str() and str2mac() to print/parse MAC address + * Change formatting, remove commented-out code in + src/plugins/imb/imbapi.c + * Export find_lan_channel() as global + * Expose _ipmi_get_channel_info() + * Extend buf2str to allow separator + * Fix indentation of #define in src/plugins/imb/imbapi.c + * Fix missing `goto out_free;` when ipmi_parse_hex() returns (-1) + * Fix warning for buf2str argument + * ID 408 - fix sel list last X listing + * ID: 38 - Protocol violating SOL retries when talking to + SIMSO-HTC + * ID: 459 - Fix reading FRU on Artesyn (Emerson) shelf manager, + MF105. + * ID: 464 - ipmievd crash fix in log_event + * ID:230 - check return value of malloc() in lib/ipmi_ekanalyzer.c + * ID:261 - Fix err. output consistency for % ipmitool chassis + INV_PARAM; + * ID:287 - Fix print-out of DDR3 SDRAM Serial Number + * ID:287 - Remove trailing white-spaces from dimm_spd.c + * ID:289 - bmx-snmp-proxy: PEF alerting does not work for + multiple destinations + * ID:312 - BREAKING CHANGE - Re-design of PEF user interface + * ID:312 - Fix bitmask in _ipmi_set_pef_policy_entry() + * ID:335 - Check return value of fseek(), prevent segfault + * ID:335 - Check return value of fseek(), prevent segfault + * ID:355 - Comment out statement without effect in lib/ipmi_sel.c + * ID:355 - Fix 'missing initializer' in struct lan_param + * ID:355 - Fix ``warning: ISO C forbids zero-size array 'data''' + * ID:355 - Fix different pointer type in lib/ipmi_picmg.c + * ID:355 - Fix missing struct initializers in lib/ipmi_firewall.c + * ID:355 - Fix printf format in lib/ipmi_sunoem.c + * ID:355 - Fix printf() related warnings in lib/ipmi_delloem.c + * ID:355 - Fix signedness warnings in lib/ipmi_sdr.c + * ID:355 - Fix statements without effect in lib/ipmi_ekanalyzer.c + * ID:355 - Move section_id from ipmi_fru. to ipmi_fru.c + * ID:355 - Replace DEBUG() macro with lprintf(LOG_DEBUG, ...) + * ID:375 - Add lan6 subcommand to handle IPv6 LAN parameters + * ID:400 - Add support for VITA-specific sensor types and events. + * ID:441 - Add support for HMAC_MD5 and HMAC_SHA256 + * ID:443 - Disable USB driver by default on non-Linux systems + * ID:444 - Cleanup of defaults in configure.ac + * ID:445 - Fix of compilation on FreeBSD + * ID:446 - Fix broken firewall reset iterator + * ID:447 - Fix access beyond array limits in serial_terminal + * ID:449 - ipmitool close console session for sol deactivate + command + * ID:451 - Modify the memory ecc error display of SEL for new + supermicro motherboards. + * ID:452 - Add PICMG extension 5.x for PICMG extension check + * ID:454 - Add support for PICMG 3.1 R2.0 Link Types and Link + Classes. + * ID:456 - Unable to disable the VLAN ID using ipmitool + * ID:457 - Display User ID enable/disable status + * ID:463 - Removal of Nokia Siemens Networks + * ID:465 - Supermicro memory ecc Modify the memory ecc error + display of SEL for new supermicro boards. + * Moved ipmi_parse_hex() to helper.c + * Re-work ipmi_mc_get_guid() and turn it into reusable code + * Revert "ID:335 - Check return value of fseek(), prevent + segfault" + * Rewrite code with the notion that Kg is binary data, not string + version 1.8.17 2016-05-01 * Add INSTALL and NEWS, mandated by autoconf * Added missing ipmi_sel_supermicro.h to template Makefile.am diff --git a/config.h.in b/config.h.in index dc91f49..c955c6e 100644 --- a/config.h.in +++ b/config.h.in @@ -27,6 +27,9 @@ /* Define to 1 if libcrypto supports MD5. */ #undef HAVE_CRYPTO_MD5 +/* Define to 1 if libcrypto supports SHA256. */ +#undef HAVE_CRYPTO_SHA256 + /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for ipmitool 1.8.17. +# Generated by GNU Autoconf 2.69 for ipmitool 1.8.18. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ipmitool' PACKAGE_TARNAME='ipmitool' -PACKAGE_VERSION='1.8.17' -PACKAGE_STRING='ipmitool 1.8.17' +PACKAGE_VERSION='1.8.18' +PACKAGE_STRING='ipmitool 1.8.18' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1359,7 +1359,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures ipmitool 1.8.17 to adapt to many kinds of systems. +\`configure' configures ipmitool 1.8.18 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1430,7 +1430,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ipmitool 1.8.17:";; + short | recursive ) echo "Configuration of ipmitool 1.8.18:";; esac cat <<\_ACEOF @@ -1558,7 +1558,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ipmitool configure 1.8.17 +ipmitool configure 1.8.18 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1923,7 +1923,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by ipmitool $as_me 1.8.17, which was +It was created by ipmitool $as_me 1.8.18, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2898,7 +2898,7 @@ fi # Define the identity of the package. PACKAGE='ipmitool' - VERSION='1.8.17' + VERSION='1.8.18' cat >>confdefs.h <<_ACEOF @@ -12556,14 +12556,14 @@ if test "x$exec_prefix" = "xNONE"; then fi +xenable_all_options=yes xenable_intf_bmc=no +xenable_intf_dummy=no xenable_intf_imb=yes -xenable_intf_open=yes -xenable_intf_usb=yes xenable_intf_lipmi=yes +xenable_intf_open=yes #xenable_intf_serial=yes -xenable_intf_dummy=no -xenable_all_options=yes +xenable_intf_usb=no xenable_ipmishell=yes case "$host_os" in @@ -12587,33 +12587,29 @@ solaris*) xenable_intf_imb=no xenable_intf_open=no xenable_intf_lipmi=no - xenable_intf_bmc=no - xenable_intf_usb=no ;; *darwin*|aix*) # disable the linux and solaris-specific interfaces xenable_intf_imb=no xenable_intf_open=no xenable_intf_lipmi=no - xenable_intf_bmc=no xenable_ipmishell=no - xenable_intf_usb=no ;; *freebsd*) xenable_intf_imb=no xenable_intf_lipmi=no - xenable_intf_bmc=no + CFLAGS="$CFLAGS -D__BSD_VISIBLE" ;; *netbsd*) xenable_intf_imb=no xenable_intf_lipmi=no - xenable_intf_bmc=no xenable_intf_open=no ;; gnu*) # disable the linux and solaris-specific interfaces on Hurd xenable_intf_imb=no xenable_intf_open=no + xenable_intf_usb=yes ;; esac @@ -12725,6 +12721,55 @@ else fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_sha256 in -lcrypto" >&5 +$as_echo_n "checking for EVP_sha256 in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_EVP_sha256+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto -lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char EVP_sha256 (); +int +main () +{ +return EVP_sha256 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_crypto_EVP_sha256=yes +else + ac_cv_lib_crypto_EVP_sha256=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EVP_sha256" >&5 +$as_echo "$ac_cv_lib_crypto_EVP_sha256" >&6; } +if test "x$ac_cv_lib_crypto_EVP_sha256" = xyes; then : + if test "x$xenable_internal_sha256" != "xyes"; then + if test "x$have_crypto" != "xyes"; then + LIBS="$LIBS -lcrypto" + have_sha256=yes + fi + +$as_echo "#define HAVE_CRYPTO_SHA256 1" >>confdefs.h + + fi +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MD5_Init in -lcrypto" >&5 $as_echo_n "checking for MD5_Init in -lcrypto... " >&6; } if ${ac_cv_lib_crypto_MD5_Init+:} false; then : @@ -14469,7 +14514,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by ipmitool $as_me 1.8.17, which was +This file was extended by ipmitool $as_me 1.8.18, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14535,7 +14580,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -ipmitool config.status 1.8.17 +ipmitool config.status 1.8.18 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 16c8305..f2fe1f3 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ dnl dnl autoconf for ipmitool dnl -AC_INIT([ipmitool], [1.8.17]) +AC_INIT([ipmitool], [1.8.18]) AC_CONFIG_SRCDIR([src/ipmitool.c]) AC_CANONICAL_SYSTEM AM_INIT_AUTOMAKE @@ -56,14 +56,14 @@ dnl dnl set default option values dnl +xenable_all_options=yes xenable_intf_bmc=no +xenable_intf_dummy=no xenable_intf_imb=yes -xenable_intf_open=yes -xenable_intf_usb=yes xenable_intf_lipmi=yes +xenable_intf_open=yes #xenable_intf_serial=yes -xenable_intf_dummy=no -xenable_all_options=yes +xenable_intf_usb=no xenable_ipmishell=yes dnl set some things so we build with GNU tools on Solaris @@ -88,33 +88,29 @@ solaris*) xenable_intf_imb=no xenable_intf_open=no xenable_intf_lipmi=no - xenable_intf_bmc=no - xenable_intf_usb=no ;; *darwin*|aix*) # disable the linux and solaris-specific interfaces xenable_intf_imb=no xenable_intf_open=no xenable_intf_lipmi=no - xenable_intf_bmc=no xenable_ipmishell=no - xenable_intf_usb=no ;; *freebsd*) xenable_intf_imb=no xenable_intf_lipmi=no - xenable_intf_bmc=no + CFLAGS="$CFLAGS -D__BSD_VISIBLE" ;; *netbsd*) xenable_intf_imb=no xenable_intf_lipmi=no - xenable_intf_bmc=no xenable_intf_open=no ;; gnu*) # disable the linux and solaris-specific interfaces on Hurd xenable_intf_imb=no xenable_intf_open=no + xenable_intf_usb=yes ;; esac @@ -164,6 +160,16 @@ AC_CHECK_LIB([crypto], [EVP_aes_128_cbc], fi], [have_crypto=no], [-lcrypto]) +AC_CHECK_LIB([crypto], [EVP_sha256], + [if test "x$xenable_internal_sha256" != "xyes"; then + if test "x$have_crypto" != "xyes"; then + LIBS="$LIBS -lcrypto" + have_sha256=yes + fi + AC_DEFINE(HAVE_CRYPTO_SHA256, [1], [Define to 1 if libcrypto supports SHA256.]) + fi], + [], [-lcrypto]) + AC_CHECK_LIB([crypto], [MD5_Init], [if test "x$xenable_internal_md5" != "xyes"; then if test "x$have_crypto" != "xyes"; then diff --git a/contrib/bmc-snmp-proxy b/contrib/bmc-snmp-proxy index 1704ef3..fcb2ab8 100644 --- a/contrib/bmc-snmp-proxy +++ b/contrib/bmc-snmp-proxy @@ -3,7 +3,7 @@ # # bmc-snmp-proxy: Set SNMP proxy to BMC (Baseboard Management Controller) # -# version: 0.6 +# version: 0.62 # # Authors: Charles Rose <charles_rose@dell.com> # Jordan Hargrave <jordan_hargrave@dell.com> @@ -20,9 +20,9 @@ SYSCONF_DIR="/etc/sysconfig" CONFIG="${SYSCONF_DIR}/bmc-snmp-proxy" -SNMPD_LOCAL_CONF_DIR="/etc/snmp/bmc" -SNMPD_LOCAL_CONF="${SNMPD_LOCAL_CONF_DIR}/snmpd.local.conf" -TRAPD_LOCAL_CONF="${SNMPD_LOCAL_CONF_DIR}/snmptrapd.local.conf" +SNMPD_BMC_CONF_DIR="/etc/snmp/bmc" +SNMPD_BMC_CONF="${SNMPD_BMC_CONF_DIR}/snmpd.local.conf" +TRAPD_BMC_CONF="${SNMPD_BMC_CONF_DIR}/snmptrapd.local.conf" TRAPD_CONF="/etc/snmp/snmptrapd.conf" @@ -57,14 +57,16 @@ bmc_info_exists() else RETVAL=2 fi + return $RETVAL } check_snmp() { - if [ ! -d /etc/snmp ] && [ ! -x /usr/sbin/snmpd ]; then + if [ ! -d /etc/snmp ] || [ ! -x /usr/sbin/snmpd ]; then RETVAL=12 fi + return $RETVAL } @@ -77,11 +79,12 @@ write_snmp_conf() printf "###############################################\n" printf "# Automatically created by %s #\n" "${SCRIPT_NAME}" printf "###############################################\n" - printf "view bmcview included %s 80\n" "${BMC_OID}" - printf "com2sec -Cn bmc_ctx bmc_sec default bmc_cmty\n" - printf "group bmc_grp v1 bmc_sec\n" - printf "access bmc_grp bmc_ctx any noauth exact bmcview none none\n" - printf "proxy -Cn bmc_ctx -v 1 %s\n" "${PROXY_TOKEN}" + printf "#view bmcview included %s 80\n" "${BMC_OID}" + printf "#com2sec -Cn bmc_ctx bmc_sec default bmc_cmty\n" + printf "#group bmc_grp v1 bmc_sec\n" + printf "#access bmc_grp bmc_ctx any noauth exact bmcview none none\n" + printf "#proxy -Cn bmc_ctx -v 1 %s\n" "${PROXY_TOKEN}" + printf "proxy -v 1 %s\n" "${PROXY_TOKEN}" printf "###############################################\n" } @@ -92,6 +95,7 @@ valid_ip() printf -- "%s" "${1}"| grep -Eq \ "^${octet}\\.${octet}\\.${octet}\\.${octet}$" + return $? } @@ -112,37 +116,38 @@ set_snmp_proxy() if check_vars; then PROXY_TOKEN="-c ${BMC_COMMUNITY} ${BMC_IPv4} ${BMC_OID}" - if [ ! -d ${SNMPD_LOCAL_CONF_DIR} ] && \ - mkdir ${SNMPD_LOCAL_CONF_DIR}; then - write_snmp_conf > ${SNMPD_LOCAL_CONF} - [ $? -ne 0 ] && RETVAL=4 + if [ -d ${SNMPD_BMC_CONF_DIR} ]; then + write_snmp_conf > ${SNMPD_BMC_CONF} || RETVAL=4 fi else RETVAL=3 fi } - set_snmpd_conf_path() { - for SYSCONF in ${SYSCONF_DIR}/snmp*d; + if [ ! -d ${SNMPD_BMC_CONF_DIR} ]; then + mkdir ${SNMPD_BMC_CONF_DIR} || RETVAL=7 + fi + + # We need SNMPCONFPATH set for both snmpd and snmptrapd + for sysconf in ${SYSCONF_DIR}/snmp*d; do - if grep -q "${SNMPD_LOCAL_CONF_DIR}" "${SYSCONF}" > \ - /dev/null 2>&1; then - continue - else - printf "SNMPCONFPATH=%s\n" "${SNMPD_LOCAL_CONF_DIR}" \ - >> ${SYSCONF} || RETVAL=7 + if ! grep -q "^SNMPCONFPATH.*${SNMPD_BMC_CONF_DIR}" \ + "${sysconf}" > /dev/null 2>&1; then + printf "SNMPCONFPATH=/etc/snmp:%s\n" \ + "${SNMPD_BMC_CONF_DIR}" >> ${sysconf} || \ + RETVAL=7 fi done + return $RETVAL } disable_snmp_proxy() { - if [ -f ${SNMPD_LOCAL_CONF} ]; then - rm -f ${SNMPD_LOCAL_CONF} - [ $? -ne 0 ] && RETVAL=5 + if [ -f ${SNMPD_BMC_CONF} ]; then + rm -f ${SNMPD_BMC_CONF} || RETVAL=5 fi } ############################################################################# @@ -152,6 +157,7 @@ disable_snmp_proxy() pick_alert_dest() { test_ip="$1" + # We have 4 IPv4 and 4 IPv6 alert dest. We will set IPv4 for now. for ALERT_DEST in `seq 1 4` do temp_ip=$(${IPMITOOL} lan alert print ${CHANNEL} ${ALERT_DEST}\ @@ -165,12 +171,12 @@ pick_alert_dest() set_alert_dest_ip() { ${IPMITOOL} lan alert set ${CHANNEL} ${ALERT_DEST} ipaddr ${1} \ - retry 4 type pet >/dev/null 2>&1 - [ $? -ne 0 ] && RETVAL=8 + retry 4 type pet >/dev/null 2>&1 || RETVAL=8 } -bmc_alert_dest() +config_bmc_alert_dest() { + # call with enable|disable # Pick the first active LAN channel for CHANNEL in `seq 1 14` do @@ -180,12 +186,12 @@ bmc_alert_dest() # If TRAPD_IP is already set as an alert dest, if pick_alert_dest "${TRAPD_IP}"; then - # reset: reset it if we are called with reset - [ "${1}" = "reset" ] && \ + # disable: reset it if we are called with disable + [ "${1}" = "disable" ] && \ set_alert_dest_ip "0.0.0.0" # else, find the next free alert dest, elif pick_alert_dest "0.0.0.0"; then - [ "${1}" = "reset" ] && \ + [ "${1}" = "disable" ] && \ return $RETVAL # set: the TRAPD_IP set_alert_dest_ip "${TRAPD_IP}" @@ -193,42 +199,54 @@ bmc_alert_dest() # No free alert destinations RETVAL=9 fi + return $RETVAL } -set_ipmi_alert() +set_ipmi_pef() { - ${IPMITOOL} lan set ${CHANNEL} alert "${1}" >/dev/null 2>&1 - [ $? -ne 0 ] && RETVAL=10 + # Needs ipmitool-1.8.13 + patches + ${IPMITOOL} pef policy set ${ALERT_DEST} "${1}" >/dev/null 2>&1 || \ + RETVAL=10 } get_host_ip() { - # Get host's IP that the BMC can reach. + # Get host's IP that the BMC can reach. This is at best a hack. IFACE=$(/usr/sbin/ip -o -f inet address |awk '!/: lo/ {print $2}') + for dev in ${IFACE} do - ping -c 1 -I ${dev} ${BMC_IPv4} > /dev/null 2>&1 + temp_ping=$(ping -c 1 -I ${dev} ${BMC_IPv4}) + [ $? -ne 0 ] && continue + + printf -- "%s" "$temp_ping"| awk 'NR==1{print $5}' && break done } config_bmc_alert() { + # Do two things + # Set/Reset TRAP IP in BMC + # Enable/Disable PEF alerting in BMC for TRAP + # Get Host's IP that the BMC can send traps to TRAPD_IP=$(get_host_ip) # Set Host's IP as the alert destination in the BMC - valid_ip ${TRAPD_IP} && bmc_alert_dest "${ACTION}" + valid_ip ${TRAPD_IP} && config_bmc_alert_dest "${ACTION}" + + # Enable/Disable alerting on the LAN channel + [ $RETVAL -eq 0 ] && set_ipmi_pef "${ACTION}" - # Enable alerting on the LAN channel - [ $RETVAL -eq 0 ] && set_ipmi_alert "${ACTION}" + return $RETVAL } write_trapd_conf() { printf "###############################################\n" printf "# Automatically created by %s #\n" "${SCRIPT_NAME}" - printf "forward %s %s\n" "${BMC_OID}*" "${FORWARD_HOST}" + printf "forward default %s\n" "${FORWARD_HOST}" printf "###############################################\n" } @@ -236,10 +254,9 @@ config_trapd() { # Proceed only if snmptrapd is available on the system if [ -f ${TRAPD_CONF} ]; then - write_trapd_conf > ${TRAPD_LOCAL_CONF} - [ $? -ne 0 ] && RETVAL=11 + write_trapd_conf > ${TRAPD_BMC_CONF} || RETVAL=11 else - return 1 + RETVAL=11 fi } @@ -249,6 +266,7 @@ trap_sink_exists() # multiple FORWARD_HOST=$(awk '/^trap.*sink/{print $2}; /^informsink/{print $2}' \ /etc/snmp/snmpd*conf | head -1) + if [ -z "${FORWARD_HOST}" ]; then # there is no trapsink setup. return 1 @@ -261,19 +279,20 @@ trap_sink_exists() trap_forward() { NO_TRAP=0 - ACTION=${1} # set or reset + ACTION=${1} # enable or disable - if [ "${ACTION}" = "set" ]; then + if [ "${ACTION}" = "enable" ]; then # Get trapd config, if trap_sink_exists; then - config_trapd && config_bmc_alert + config_bmc_alert && config_trapd else # exit silently if there is no sink NO_TRAP=1 fi else - if [ -f ${TRAPD_LOCAL_CONF} ]; then - rm -f ${TRAPD_LOCAL_CONF} >/dev/null 2>&1 + if [ -f ${TRAPD_BMC_CONF} ]; then + rm -f ${TRAPD_BMC_CONF} >/dev/null 2>&1 + config_bmc_alert else NO_TRAP=1 fi @@ -288,7 +307,6 @@ service_reload() service $1 reload [ $? -ne 0 ] && RETVAL=6 fi - return } ############################################################################# @@ -296,11 +314,12 @@ start() { if bmc_info_exists && check_snmp; then touch ${LOCKFILE} + set_snmpd_conf_path && set_snmp_proxy [ $RETVAL -eq 0 ] && service_reload snmpd if [ "${TRAP_FORWARD}" = "yes" ]; then - trap_forward "set" + trap_forward "enable" [ $RETVAL -eq 0 ] && [ $NO_TRAP -eq 0 ] && \ service_reload snmptrapd fi @@ -316,10 +335,11 @@ stop() [ $RETVAL -eq 0 ] && service_reload snmpd if [ "${TRAP_FORWARD}" = "yes" ]; then - trap_forward "reset" + trap_forward "disable" [ $RETVAL -eq 0 ] && [ $NO_TRAP -eq 0 ] && \ service_reload snmptrapd fi + rm -f ${LOCKFILE} fi } @@ -329,12 +349,13 @@ status() { eval_gettext "${SCRIPT_NAME}: snmp proxy to BMC is " # Checking for lockfile is better. - #if grep -q "^proxy" "${SNMPD_LOCAL_CONF}" > /dev/null 2>&1 ; then + #if grep -q "^proxy" "${SNMPD_BMC_CONF}" > /dev/null 2>&1 ; then if [ -f ${LOCKFILE} ]; then eval_gettext "set" else eval_gettext "not set" fi + echo RETVAL=0 } @@ -360,10 +381,10 @@ case "$RETVAL" in 0|1) ;; 2) eval_gettext "${SCRIPT_NAME}: failed to read ${BMC_INFO} " 1>&2 ;; 3) eval_gettext "${SCRIPT_NAME}: failed to get proxy config." 1>&2 ;; - 4) eval_gettext "${SCRIPT_NAME}: failed to set ${SNMPD_LOCAL_CONF}." 1>&2 ;; + 4) eval_gettext "${SCRIPT_NAME}: failed to set ${SNMPD_BMC_CONF}." 1>&2 ;; 5) eval_gettext "${SCRIPT_NAME}: failed to disable snmp proxy." 1>&2 ;; 6) eval_gettext "${SCRIPT_NAME}: failed to reload snmpd." 1>&2 ;; - 7) eval_gettext "${SCRIPT_NAME}: failed to update ${SYSCONF}." 1>&2 ;; + 7) eval_gettext "${SCRIPT_NAME}: failed to set snmpd config." 1>&2 ;; 8) eval_gettext "${SCRIPT_NAME}: failed to set IPMI alert dest." 1>&2 ;; 9) eval_gettext "${SCRIPT_NAME}: no free IPMI alert dest." 1>&2 ;; 10) eval_gettext "${SCRIPT_NAME}: failed to set IPMI PEF." 1>&2 ;; @@ -375,6 +396,7 @@ esac if [ ${RETVAL} -gt 1 ]; then eval_gettext " Return code: ${RETVAL}"; echo fi + exit ${RETVAL} ############################################################################# # end of file diff --git a/include/ipmitool/Makefile.am b/include/ipmitool/Makefile.am index 160e354..9093a56 100644 --- a/include/ipmitool/Makefile.am +++ b/include/ipmitool/Makefile.am @@ -38,5 +38,5 @@ noinst_HEADERS = log.h bswap.h hpm2.h helper.h ipmi.h ipmi_cc.h ipmi_intf.h \ ipmi_oem.h ipmi_sdradd.h ipmi_isol.h ipmi_sunoem.h ipmi_picmg.h \ ipmi_fwum.h ipmi_main.h ipmi_tsol.h ipmi_firewall.h \ ipmi_kontronoem.h ipmi_ekanalyzer.h ipmi_gendev.h ipmi_ime.h \ - ipmi_delloem.h ipmi_dcmi.h ipmi_vita.h ipmi_sel_supermicro.h - + ipmi_delloem.h ipmi_dcmi.h ipmi_vita.h ipmi_sel_supermicro.h \ + ipmi_cfgp.h ipmi_lanp6.h diff --git a/include/ipmitool/Makefile.in b/include/ipmitool/Makefile.in index 5c55d42..96e0624 100644 --- a/include/ipmitool/Makefile.in +++ b/include/ipmitool/Makefile.in @@ -317,7 +317,8 @@ noinst_HEADERS = log.h bswap.h hpm2.h helper.h ipmi.h ipmi_cc.h ipmi_intf.h \ ipmi_oem.h ipmi_sdradd.h ipmi_isol.h ipmi_sunoem.h ipmi_picmg.h \ ipmi_fwum.h ipmi_main.h ipmi_tsol.h ipmi_firewall.h \ ipmi_kontronoem.h ipmi_ekanalyzer.h ipmi_gendev.h ipmi_ime.h \ - ipmi_delloem.h ipmi_dcmi.h ipmi_vita.h ipmi_sel_supermicro.h + ipmi_delloem.h ipmi_dcmi.h ipmi_vita.h ipmi_sel_supermicro.h \ + ipmi_cfgp.h ipmi_lanp6.h all: all-am diff --git a/include/ipmitool/helper.h b/include/ipmitool/helper.h index b7ad628..bfaf284 100644 --- a/include/ipmitool/helper.h +++ b/include/ipmitool/helper.h @@ -97,7 +97,12 @@ void print_valstr_2col(const struct valstr * vs, const char * title, int logleve uint16_t buf2short(uint8_t * buf); uint32_t buf2long(uint8_t * buf); -const char * buf2str(uint8_t * buf, int len); +#define BUF2STR_MAXIMUM_OUTPUT_SIZE (3*1024 + 1) +const char * buf2str_extended(const uint8_t *buf, int len, const char *sep); +const char * buf2str(const uint8_t *buf, int len); +int str2mac(const char *arg, uint8_t *buf); +const char * mac2str(const uint8_t *buf); +int ipmi_parse_hex(const char *str, uint8_t *out, int size); void printbuf(const uint8_t * buf, int len, const char * desc); uint8_t ipmi_csum(uint8_t * d, int s); FILE * ipmi_open_file(const char * file, int rw); diff --git a/include/ipmitool/ipmi.h b/include/ipmitool/ipmi.h index e978bfc..6e42d06 100644 --- a/include/ipmitool/ipmi.h +++ b/include/ipmitool/ipmi.h @@ -46,6 +46,7 @@ #endif #define IPMI_BUF_SIZE 1024 +#define IPMI_MAX_MD_SIZE 0x20 #if HAVE_PRAGMA_PACK #define ATTRIBUTE_PACKING @@ -211,13 +212,13 @@ struct ipmi_rs { uint32_t console_id; uint8_t bmc_rand[16]; /* Random number generated by the BMC */ uint8_t bmc_guid[16]; - uint8_t key_exchange_auth_code[20]; + uint8_t key_exchange_auth_code[IPMI_MAX_MD_SIZE]; } rakp2_message; struct { uint8_t message_tag; uint8_t rakp_return_code; uint32_t console_id; - uint8_t integrity_check_value[20]; + uint8_t integrity_check_value[IPMI_MAX_MD_SIZE]; } rakp4_message; struct { uint8_t packet_sequence_number; @@ -298,6 +299,7 @@ typedef enum IPMI_OEM { /* 24339 for [ADLINK TECHNOLOGY INC.] */ IPMI_OEM_ADLINK_24339 = 24339, IPMI_OEM_NOKIA_SOLUTIONS_AND_NETWORKS = 28458, + IPMI_OEM_VITA = 33196, IPMI_OEM_SUPERMICRO_47488 = 47488 } IPMI_OEM; diff --git a/include/ipmitool/ipmi_cfgp.h b/include/ipmitool/ipmi_cfgp.h new file mode 100644 index 0000000..ab8acb3 --- /dev/null +++ b/include/ipmitool/ipmi_cfgp.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2016 Pentair Technical Products. All right reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Pentair Technical Products 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * PENTAIR TECHNICAL SOLUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef IPMI_CFGP_H +#define IPMI_CFGP_H + +#include <stdio.h> + +/* Forward declarations. */ +struct ipmi_cfgp; +struct ipmi_cfgp_ctx; + +/* + * Action types. + */ +enum { + /* parse dumped parameter data */ + CFGP_PARSE, + /* get parameter from BMC */ + CFGP_GET, + /* set parameter to BMC */ + CFGP_SET, + /* output parameter data in form that can be parsed back */ + CFGP_SAVE, + /* print parameter in user-friendly format */ + CFGP_PRINT +}; + +/* + * Action-specific information. + */ +struct ipmi_cfgp_action { + /* Action type. */ + int type; + + /* Set selector. */ + int set; + + /* Block selector. */ + int block; + + /* No error output needed. */ + int quiet; + + /* Number of command line arguments (only for parse action). */ + int argc; + + /* Command line arguments (only for parse action). */ + const char **argv; + + /* Output file (only for dump/print actions). */ + FILE *file; +}; + +/* + * Access types. + */ +enum { + CFGP_RDWR, + CFGP_RDONLY, + CFGP_WRONLY, + CFGP_RESERVED +}; + +/* + * Configuration parameter descriptor. + */ +struct ipmi_cfgp { + /* Parameter name. */ + const char *name; + + /* Parameter format description. */ + const char *format; + + /* Various parameter traits. */ + unsigned int size; /* block size */ + unsigned int access:2; /* read-write/read-only/write-only */ + unsigned int is_set:1; /* takes non-zero set selectors */ + unsigned int first_set:1; /* 1 = 1-based set selector */ + unsigned int has_blocks:1; /* takes non-zero block selectors */ + unsigned int first_block:1; /* 1 = 1-based block selector */ + + /* Parameter-specific data. */ + int specific; +}; + +/* Parameter callback. */ +typedef int (*ipmi_cfgp_handler_t)(void *priv, + const struct ipmi_cfgp *p, const struct ipmi_cfgp_action *action, + unsigned char *data); + +/* + * Parameter selector. + */ +struct ipmi_cfgp_sel { + int param; + int set; + int block; +}; + +/* + * Configuration parameter data. + */ +struct ipmi_cfgp_data { + struct ipmi_cfgp_data *next; + struct ipmi_cfgp_sel sel; + unsigned char data[]; +}; + +/* + * Configuration parameter operation context. + */ +struct ipmi_cfgp_ctx { + /* Set of parameters. */ + const struct ipmi_cfgp *set; + + /* Descriptor count. */ + int count; + + /* Parameter action handler. */ + ipmi_cfgp_handler_t handler; + + /* ipmitool cmd name */ + const char *cmdname; + + /* List of parameter values. */ + struct ipmi_cfgp_data *v; + + /* Private data. */ + void *priv; +}; + +/* Initialize configuration context. */ +extern int 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); + +/* Uninitialize context, free allocated memory. */ +extern int ipmi_cfgp_uninit(struct ipmi_cfgp_ctx *ctx); + +/* Print parameter usage. */ +void ipmi_cfgp_usage(const struct ipmi_cfgp *set, int count, int write); + +/* Parse parameter selector from command line. */ +extern int ipmi_cfgp_parse_sel(struct ipmi_cfgp_ctx *ctx, + int argc, const char **argv, struct ipmi_cfgp_sel *sel); + +/* Parse parameter data from command line. */ +extern int ipmi_cfgp_parse_data(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel, int argc, const char **argv); + +/* Get parameter data from BMC. */ +extern int ipmi_cfgp_get(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel); + +/* Set parameter data to BMC. */ +extern int ipmi_cfgp_set(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel); + +/* Write parameter data to file. */ +extern int ipmi_cfgp_save(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel, FILE *file); + +/* Print parameter data in user-friendly format. */ +extern int ipmi_cfgp_print(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel, FILE *file); + +#endif /* IPMI_CFGP_H */ diff --git a/include/ipmitool/ipmi_channel.h b/include/ipmitool/ipmi_channel.h index 89e4738..b138c26 100644 --- a/include/ipmitool/ipmi_channel.h +++ b/include/ipmitool/ipmi_channel.h @@ -131,6 +131,8 @@ struct get_channel_auth_cap_rsp { int _ipmi_get_channel_access(struct ipmi_intf *intf, struct channel_access_t *channel_access, uint8_t get_volatile_settings); +int _ipmi_get_channel_info(struct ipmi_intf *intf, + struct channel_info_t *channel_info); int _ipmi_set_channel_access(struct ipmi_intf *intf, struct channel_access_t channel_access, uint8_t access_option, uint8_t privilege_option); diff --git a/include/ipmitool/ipmi_constants.h b/include/ipmitool/ipmi_constants.h index 2aad2cf..8f2bc87 100644 --- a/include/ipmitool/ipmi_constants.h +++ b/include/ipmitool/ipmi_constants.h @@ -118,12 +118,14 @@ #define IPMI_AUTH_RAKP_NONE 0x00 #define IPMI_AUTH_RAKP_HMAC_SHA1 0x01 #define IPMI_AUTH_RAKP_HMAC_MD5 0x02 +#define IPMI_AUTH_RAKP_HMAC_SHA256 0x03 /* From table 13-18 of the IPMI v2 specification */ #define IPMI_INTEGRITY_NONE 0x00 #define IPMI_INTEGRITY_HMAC_SHA1_96 0x01 #define IPMI_INTEGRITY_HMAC_MD5_128 0x02 #define IPMI_INTEGRITY_MD5_128 0x03 +#define IPMI_INTEGRITY_HMAC_SHA256_128 0x04 /* From table 13-19 of the IPMI v2 specfication */ #define IPMI_CRYPT_NONE 0x00 diff --git a/include/ipmitool/ipmi_fru.h b/include/ipmitool/ipmi_fru.h index 4d255a8..65696ba 100644 --- a/include/ipmitool/ipmi_fru.h +++ b/include/ipmitool/ipmi_fru.h @@ -297,22 +297,24 @@ struct fru_picmgext_link_desc { unsigned int desig_channel:6; unsigned int desig_if:2; unsigned int desig_port:4; -#define FRU_PICMGEXT_LINK_TYPE_BASE 0x01 +#define FRU_PICMGEXT_LINK_TYPE_BASE 0x01 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET 0x02 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND 0x03 -#define FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR 0x04 -#define FRU_PICMGEXT_LINK_TYPE_PCIE 0x05 +#define FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR 0x04 +#define FRU_PICMGEXT_LINK_TYPE_PCIE 0x05 +#define FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET_10GBD 0x32 unsigned int type:8; unsigned int ext:4; unsigned int grouping:8; #else unsigned int grouping:8; unsigned int ext:4; -#define FRU_PICMGEXT_LINK_TYPE_BASE 0x01 +#define FRU_PICMGEXT_LINK_TYPE_BASE 0x01 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET 0x02 #define FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND 0x03 -#define FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR 0x04 -#define FRU_PICMGEXT_LINK_TYPE_PCIE 0x05 +#define FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR 0x04 +#define FRU_PICMGEXT_LINK_TYPE_PCIE 0x05 +#define FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET_10GBD 0x32 unsigned int type:8; unsigned int desig_port:4; unsigned int desig_if:2; @@ -610,13 +612,6 @@ typedef struct ipmi_fru_bloc { uint8_t blocId[32]; } t_ipmi_fru_bloc; -static const char *section_id[4] = { - "Internal Use Section", - "Chassis Section", - "Board Section", - "Product Section" -}; - int ipmi_fru_main(struct ipmi_intf *intf, int argc, char **argv); int ipmi_fru_print(struct ipmi_intf *intf, struct sdr_record_fru_locator *fru); diff --git a/include/ipmitool/ipmi_hpmfwupg.h b/include/ipmitool/ipmi_hpmfwupg.h index 71ec565..de65292 100644 --- a/include/ipmitool/ipmi_hpmfwupg.h +++ b/include/ipmitool/ipmi_hpmfwupg.h @@ -437,7 +437,7 @@ struct HpmfwupgInitiateUpgradeActionCtx { struct HpmfwupgUploadFirmwareBlockReq { unsigned char picmgId; unsigned char blockNumber; - unsigned char data[0]; + unsigned char data[]; } ATTRIBUTE_PACKING; #ifdef HAVE_PRAGMA_PACK # pragma pack(0) diff --git a/include/ipmitool/ipmi_intf.h b/include/ipmitool/ipmi_intf.h index 67f6019..982f645 100644 --- a/include/ipmitool/ipmi_intf.h +++ b/include/ipmitool/ipmi_intf.h @@ -59,7 +59,7 @@ enum LANPLUS_SESSION_STATE { #define IPMI_AUTHCODE_BUFFER_SIZE 20 -#define IPMI_SIK_BUFFER_SIZE 20 +#define IPMI_SIK_BUFFER_SIZE IPMI_MAX_MD_SIZE #define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */ struct ipmi_session_params { @@ -131,10 +131,13 @@ struct ipmi_session { uint8_t requested_role; /* As sent in the RAKP 1 message */ uint8_t rakp2_return_code; - uint8_t sik[IPMI_SIK_BUFFER_SIZE]; /* Session integrity key */ - uint8_t kg[IPMI_KG_BUFFER_SIZE]; /* BMC key */ - uint8_t k1[20]; /* Used for Integrity checking? */ - uint8_t k2[20]; /* First 16 bytes used for AES */ + uint8_t sik[IPMI_SIK_BUFFER_SIZE]; /* Session integrity key */ + uint8_t sik_len; /* Session Integrity key length */ + uint8_t kg[IPMI_KG_BUFFER_SIZE]; /* BMC key */ + uint8_t k1[IPMI_MAX_MD_SIZE]; /* Used for Integrity checking? */ + uint8_t k1_len; /* K1 key length */ + uint8_t k2[IPMI_MAX_MD_SIZE]; /* First 16 bytes used for AES */ + uint8_t k2_len; /* K2 key length */ } v2_data; @@ -217,7 +220,7 @@ void ipmi_intf_session_set_privlvl(struct ipmi_intf * intf, uint8_t privlvl); void ipmi_intf_session_set_lookupbit(struct ipmi_intf * intf, uint8_t lookupbit); void ipmi_intf_session_set_cipher_suite_id(struct ipmi_intf * intf, uint8_t cipher_suite_id); void ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_char); -void ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey); +void ipmi_intf_session_set_kgkey(struct ipmi_intf *intf, const uint8_t *kgkey); void ipmi_intf_session_set_port(struct ipmi_intf * intf, int port); void ipmi_intf_session_set_authtype(struct ipmi_intf * intf, uint8_t authtype); void ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout); diff --git a/include/ipmitool/ipmi_lanp.h b/include/ipmitool/ipmi_lanp.h index ba25582..0ef2d96 100644 --- a/include/ipmitool/ipmi_lanp.h +++ b/include/ipmitool/ipmi_lanp.h @@ -78,6 +78,37 @@ enum { IPMI_LANP_RMCP_PRIV_LEVELS, IPMI_LANP_VLAN_TAGS, IPMI_LANP_BAD_PASS_THRESH, + IPMI_LANP_IP6_SUPPORT=50, + IPMI_LANP_IP6_ENABLES, + IPMI_LANP_IP6_TRAFFIC_CLASS, + IPMI_LANP_IP6_STATIC_HOPS, + IPMI_LANP_IP6_FLOW_LABEL, + IPMI_LANP_IP6_STATUS, + IPMI_LANP_IP6_STATIC_ADDR, + IPMI_LANP_IP6_STATIC_DUID_STG, + IPMI_LANP_IP6_STATIC_DUID, + IPMI_LANP_IP6_DYNAMIC_ADDR, + IPMI_LANP_IP6_DYNAMIC_DUID_STG, + IPMI_LANP_IP6_DYNAMIC_DUID, + IPMI_LANP_IP6_DHCP6_CFG_SUP, + IPMI_LANP_IP6_DHCP6_CFG, + IPMI_LANP_IP6_ROUTER_CFG, + IPMI_LANP_IP6_STATIC_RTR1_ADDR, + IPMI_LANP_IP6_STATIC_RTR1_MAC, + IPMI_LANP_IP6_STATIC_RTR1_PFX_LEN, + IPMI_LANP_IP6_STATIC_RTR1_PFX, + IPMI_LANP_IP6_STATIC_RTR2_ADDR, + IPMI_LANP_IP6_STATIC_RTR2_MAC, + IPMI_LANP_IP6_STATIC_RTR2_PFX_LEN, + IPMI_LANP_IP6_STATIC_RTR2_PFX, + IPMI_LANP_IP6_NUM_DYNAMIC_RTRS, + IPMI_LANP_IP6_DYNAMIC_RTR_ADDR, + IPMI_LANP_IP6_DYNAMIC_RTR_MAC, + IPMI_LANP_IP6_DYNAMIC_RTR_PFX_LEN, + IPMI_LANP_IP6_DYNAMIC_RTR_PFX, + IPMI_LANP_IP6_DYNAMIC_HOPS, + IPMI_LANP_IP6_NDSLAAC_CFG_SUP, + IPMI_LANP_IP6_NDSLAAC_CFG, IPMI_LANP_OEM_ALERT_STRING=96, IPMI_LANP_ALERT_RETRY=97, IPMI_LANP_UTC_OFFSET=98, @@ -127,9 +158,11 @@ static struct lan_param { { IPMI_LANP_DHCP_SERVER_MAC, 6, "DHDP Server MAC", NULL, 0}, { IPMI_LANP_DHCP_ENABLE, 1, "DHCP Enable", NULL, 0 }, /* 30 */ { IPMI_LANP_CHAN_ACCESS_MODE, 2, "Channel Access Mode", NULL, 0 }, - { -1 } + { -1, -1, "", NULL, -1 } }; int ipmi_lanp_main(struct ipmi_intf *, int, char **); +uint8_t find_lan_channel(struct ipmi_intf *intf, uint8_t start); + #endif /*IPMI_LANP_H*/ diff --git a/include/ipmitool/ipmi_lanp6.h b/include/ipmitool/ipmi_lanp6.h new file mode 100644 index 0000000..91799e5 --- /dev/null +++ b/include/ipmitool/ipmi_lanp6.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016 Pentair Technical Products. All right reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Pentair Technical Products 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * PENTAIR TECHNICAL SOLUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef IPMI_LANP6_H +#define IPMI_LANP6_H + +#include <ipmitool/ipmi_intf.h> + +/* + * LAN configuration parameter. + */ +struct ipmi_lanp { + int selector; + const char *name; + int size; +}; + +/* + * Private data for LAN configuration. + */ +struct ipmi_lanp_priv { + struct ipmi_intf *intf; + int channel; +}; + +#endif /* IPMI_LANP6_H */ diff --git a/include/ipmitool/ipmi_mc.h b/include/ipmitool/ipmi_mc.h index a840f78..0e3c59f 100644 --- a/include/ipmitool/ipmi_mc.h +++ b/include/ipmitool/ipmi_mc.h @@ -89,6 +89,25 @@ struct ipm_devid_rsp { #define IPM_DEV_ADTL_SUPPORT_BITS (8) +/* Structure follow the IPMI V.2 Rev 1.0 + * See Table 20-10 */ +#ifdef HAVE_PRAGMA_PACK +#pragma pack(1) +#endif +struct ipmi_guid_t { + uint32_t time_low; /* timestamp low field */ + uint16_t time_mid; /* timestamp middle field */ + uint16_t time_hi_and_version; /* timestamp high field and version number */ + uint8_t clock_seq_hi_variant;/* clock sequence high field and variant */ + uint8_t clock_seq_low; /* clock sequence low field */ + uint8_t node[6]; /* node */ +} ATTRIBUTE_PACKING; +#ifdef HAVE_PRAGMA_PACK +#pragma pack(0) +#endif + +int _ipmi_mc_get_guid(struct ipmi_intf *, struct ipmi_guid_t *); + #ifdef HAVE_PRAGMA_PACK #pragma pack(1) #endif @@ -165,6 +184,8 @@ struct ipm_get_watchdog_rsp { #define IPMI_SYSINFO_OS_NAME 0x04 #define IPMI_SYSINFO_DELL_OS_VERSION 0xe4 #define IPMI_SYSINFO_DELL_URL 0xde +#define IPMI_SYSINFO_DELL_IPV6_COUNT 0xe6 +#define IPMI_SYSINFO_DELL_IPV6_DESTADDR 0xf0 int ipmi_mc_getsysinfo(struct ipmi_intf * intf, int param, int block, int set, int len, void *buffer); diff --git a/include/ipmitool/ipmi_pef.h b/include/ipmitool/ipmi_pef.h index cdea4ec..14c6e18 100644 --- a/include/ipmitool/ipmi_pef.h +++ b/include/ipmitool/ipmi_pef.h @@ -40,7 +40,7 @@ struct pef_capabilities { /* "get pef capabilities" response */ uint8_t version; uint8_t actions; /* mapped by PEF_ACTION_xxx */ - uint8_t tblsize; + uint8_t event_filter_count; }; typedef enum { @@ -336,6 +336,7 @@ pef_b2s_generic_ER[] __attribute__((unused)) = { struct pef_policy_entry { #define PEF_POLICY_ID_MASK 0xf0 #define PEF_POLICY_ID_SHIFT 4 +#define PEF_POLICY_DISABLED 0xF7 #define PEF_POLICY_ENABLED 0x08 #define PEF_POLICY_FLAGS_MASK 0x07 #define PEF_POLICY_FLAGS_MATCH_ALWAYS 0 @@ -510,7 +511,9 @@ struct pef_cfgparm_filter_table_size { #pragma pack(1) #endif struct pef_cfgparm_filter_table_entry { -#define PEF_FILTER_TABLE_ID_MASK 0x7f +# define PEF_FILTER_DISABLED 0x7F +# define PEF_FILTER_ENABLED 0x80 +# define PEF_FILTER_TABLE_ID_MASK 0x7F uint8_t data1; struct pef_table_entry entry; } ATTRIBUTE_PACKING; @@ -522,8 +525,8 @@ struct pef_cfgparm_filter_table_entry { #pragma pack(1) #endif struct pef_cfgparm_filter_table_data_1 { - uint8_t data1; - uint8_t data2; + uint8_t id; + uint8_t cfg; } ATTRIBUTE_PACKING; #ifdef HAVE_PRAGMA_PACK #pragma pack(0) @@ -936,6 +939,7 @@ BIT_DESC_MAP_LIST, #endif #define IPMI_CMD_GET_PEF_CAPABILITIES 0x10 +#define IPMI_CMD_SET_PEF_CONFIG_PARMS 0x12 #define IPMI_CMD_GET_PEF_CONFIG_PARMS 0x13 #define IPMI_CMD_GET_LAST_PROCESSED_EVT_ID 0x15 #define IPMI_CMD_GET_SYSTEM_GUID 0x37 @@ -943,6 +947,13 @@ BIT_DESC_MAP_LIST, #define IPMI_CMD_LAN_GET_CONFIG 0x02 #define IPMI_CMD_SERIAL_GET_CONFIG 0x11 +struct pef_cfgparm_set_policy_table_entry +{ + uint8_t param_selector; + uint8_t policy_id; + struct pef_policy_entry entry; +} ATTRIBUTE_PACKING; + const char * ipmi_pef_bit_desc(struct bit_desc_map * map, uint32_t val); void ipmi_pef_print_flags(struct bit_desc_map * map, flg_e type, uint32_t val); void ipmi_pef_print_dec(const char * text, uint32_t val); diff --git a/include/ipmitool/ipmi_sdr.h b/include/ipmitool/ipmi_sdr.h index ccf0cf0..41bb533 100644 --- a/include/ipmitool/ipmi_sdr.h +++ b/include/ipmitool/ipmi_sdr.h @@ -907,7 +907,6 @@ struct ipmi_rs *ipmi_sdr_get_sensor_thresholds(struct ipmi_intf *intf, struct ipmi_rs *ipmi_sdr_get_sensor_hysteresis(struct ipmi_intf *intf, uint8_t sensor, uint8_t target, uint8_t lun, uint8_t channel); -const char *ipmi_sdr_get_sensor_type_desc(const uint8_t type); int ipmi_sdr_get_reservation(struct ipmi_intf *intf, int use_builtin, uint16_t * reserve_id); @@ -937,10 +936,12 @@ int ipmi_sdr_list_cache(struct ipmi_intf *intf); int ipmi_sdr_list_cache_fromfile(struct ipmi_intf *intf, const char *ifile); void ipmi_sdr_list_empty(struct ipmi_intf *intf); int ipmi_sdr_print_info(struct ipmi_intf *intf); -void ipmi_sdr_print_discrete_state(const char *desc, uint8_t sensor_type, - uint8_t event_type, uint8_t state1, - uint8_t state2); -void ipmi_sdr_print_discrete_state_mini(const char *header, const char *separator, +void ipmi_sdr_print_discrete_state(struct ipmi_intf *intf, + const char *desc, uint8_t sensor_type, + uint8_t event_type, uint8_t state1, + uint8_t state2); +void ipmi_sdr_print_discrete_state_mini(struct ipmi_intf *intf, + const char *header, const char *separator, uint8_t sensor_type, uint8_t event_type, uint8_t state1, uint8_t state2); int ipmi_sdr_print_sensor_event_status(struct ipmi_intf *intf, diff --git a/include/ipmitool/ipmi_sel.h b/include/ipmitool/ipmi_sel.h index 9778784..1c325db 100644 --- a/include/ipmitool/ipmi_sel.h +++ b/include/ipmitool/ipmi_sel.h @@ -142,551 +142,533 @@ struct ipmi_event_sensor_types { uint8_t offset; #define ALL_OFFSETS_SPECIFIED 0xff uint8_t data; - uint8_t class; - const char * type; const char * desc; }; -/* The sel module uses the "iana" number to select the appropriate array at run time - This table if for iana number 15000 ( Kontron ), you can add you own OEM sensor types - using a similar constuct, look for switch(iana) in ipmi_sel.c - */ -static struct ipmi_event_sensor_types oem_kontron_event_types[] __attribute__((unused)) = { - - /* event type details uses an oem event type */ - { 0xC0 , 0xFF , 0xff, IPMI_EVENT_CLASS_DISCRETE , "OEM Firmware Info", NULL }, - { 0xC0 , 0xFF , 0xff, IPMI_EVENT_CLASS_DISCRETE , "OEM Firmware Info", NULL }, - - { 0xC1 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset(cPCI)", "Push Button" }, - { 0xC1 , 0x01 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset(cPCI)", "Bridge Reset" }, - { 0xC1 , 0x02 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset(cPCI)", "Backplane" }, - { 0xC1 , 0x03 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset(cPCI)", "Hotswap Fault" }, - { 0xC1 , 0x04 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset(cPCI)", "Hotswap Healty" }, - { 0xC1 , 0x05 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset(cPCI)", "Unknown" }, - { 0xC1 , 0x06 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset(cPCI)", "ITP" }, - { 0xC1 , 0x07 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset(cPCI)", "Hardware Watchdog" }, - { 0xC1 , 0x08 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset(cPCI)", "Software Reset" }, - - /* Uses standard digital reading type */ - { 0xC2 , 0xFF , 0xff, IPMI_EVENT_CLASS_DIGITAL , "SDRR Init Agent", NULL }, - - /* based on PICMG IPMB-0 Link state sensor */ - { 0xC3 , 0x02 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "IPMB-L Link State", "IPMB L Disabled" }, - { 0xC3 , 0x03 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "IPMB-L Link State", "IPMB L Enabled" }, - - { 0xC4 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset", "Push Button" }, - { 0xC4 , 0x01 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset", "Hardware Power Failure" }, - { 0xC4 , 0x02 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset", "Unknown" }, - { 0xC4 , 0x03 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset", "Hardware Watchdog" }, - { 0xC4 , 0x04 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset", "Soft Reset" }, - { 0xC4 , 0x05 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset", "Warm Reset" }, - { 0xC4 , 0x06 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset", "Cold Reset" }, - { 0xC4 , 0x07 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset", "IPMI Command" }, - { 0xC4 , 0x08 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset", "Setup Reset (Save CMOS)" }, - { 0xC4 , 0x09 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Board Reset", "Power Up Reset" }, - - /* event type details uses a standard */ - { 0xC5 , 0xFF , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FRU Information Agent", NULL }, - - { 0xC6 , 0x0E , 0xff, IPMI_EVENT_CLASS_DISCRETE , "POST Value", "Post Error (see data2)" }, - - { 0xC7 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FWUM Status", "First Boot After Upgrade" }, - { 0xC7 , 0x01 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FWUM Status", "First Boot After Rollback(error)" }, - { 0xC7 , 0x02 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FWUM Status", "First Boot After Errors (watchdog)" }, - { 0xC7 , 0x03 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FWUM Status", "First Boot After Manual Rollback" }, - { 0xC7 , 0x08 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FWUM Status", "Firmware Watchdog Bite, reset occurred" }, - - { 0xC8 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Switch Mngt Software Status", "Not Loaded" }, - { 0xC8 , 0x01 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Switch Mngt Software Status", "Initializing" }, - { 0xC8 , 0x02 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Switch Mngt Software Status", "Ready" }, - { 0xC8 , 0x03 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Switch Mngt Software Status", "Failure (see data2)" }, - - { 0xC9 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Diagnostic Status", "Started" }, - { 0xC9 , 0x01 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Diagnostic Status", "Pass" }, - { 0xC9 , 0x02 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Diagnostic Status", "Fail" }, - - { 0xCA , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Firmware Upgrade Status", "In progress"}, - { 0xCA , 0x01 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Firmware Upgrade Status", "Success"}, - { 0xCA , 0x02 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Firmware Upgrade Status", "Failure"}, - - { 0xCB , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FRU Over Current", "Asserted"}, - { 0xCB , 0x01 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FRU Over Current", "Deasserted"}, - - { 0xCC , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FRU Sensor Error", "Asserted"}, - { 0xCC , 0x01 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FRU Sensor Error", "Deasserted"}, - - { 0xCD , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FRU Power Denied", "Asserted"}, - { 0xCD , 0x01 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "FRU Power Denied", "Deasserted"}, - - { 0xCF , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Reset", "Asserted"}, - { 0xCF , 0x01 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "Reset", "Deasserted"}, - - /* END */ - { 0x00, 0x00, 0xff, 0x00, NULL, NULL }, +static const struct ipmi_event_sensor_types generic_event_types[] = { + /* Threshold Based States */ + { 0x01, 0x00, 0xff, "Lower Non-critical going low " }, + { 0x01, 0x01, 0xff, "Lower Non-critical going high" }, + { 0x01, 0x02, 0xff, "Lower Critical going low " }, + { 0x01, 0x03, 0xff, "Lower Critical going high" }, + { 0x01, 0x04, 0xff, "Lower Non-recoverable going low " }, + { 0x01, 0x05, 0xff, "Lower Non-recoverable going high" }, + { 0x01, 0x06, 0xff, "Upper Non-critical going low " }, + { 0x01, 0x07, 0xff, "Upper Non-critical going high" }, + { 0x01, 0x08, 0xff, "Upper Critical going low " }, + { 0x01, 0x09, 0xff, "Upper Critical going high" }, + { 0x01, 0x0a, 0xff, "Upper Non-recoverable going low " }, + { 0x01, 0x0b, 0xff, "Upper Non-recoverable going high" }, + /* DMI-based "usage state" States */ + { 0x02, 0x00, 0xff, "Transition to Idle" }, + { 0x02, 0x01, 0xff, "Transition to Active" }, + { 0x02, 0x02, 0xff, "Transition to Busy" }, + /* Digital-Discrete Event States */ + { 0x03, 0x00, 0xff, "State Deasserted" }, + { 0x03, 0x01, 0xff, "State Asserted" }, + { 0x04, 0x00, 0xff, "Predictive Failure Deasserted" }, + { 0x04, 0x01, 0xff, "Predictive Failure Asserted" }, + { 0x05, 0x00, 0xff, "Limit Not Exceeded" }, + { 0x05, 0x01, 0xff, "Limit Exceeded" }, + { 0x06, 0x00, 0xff, "Performance Met" }, + { 0x06, 0x01, 0xff, "Performance Lags" }, + /* Severity Event States */ + { 0x07, 0x00, 0xff, "Transition to OK" }, + { 0x07, 0x01, 0xff, "Transition to Non-critical from OK" }, + { 0x07, 0x02, 0xff, "Transition to Critical from less severe" }, + { 0x07, 0x03, 0xff, "Transition to Non-recoverable from less severe" }, + { 0x07, 0x04, 0xff, "Transition to Non-critical from more severe" }, + { 0x07, 0x05, 0xff, "Transition to Critical from Non-recoverable" }, + { 0x07, 0x06, 0xff, "Transition to Non-recoverable" }, + { 0x07, 0x07, 0xff, "Monitor" }, + { 0x07, 0x08, 0xff, "Informational" }, + /* Availability Status States */ + { 0x08, 0x00, 0xff, "Device Absent" }, + { 0x08, 0x01, 0xff, "Device Present" }, + { 0x09, 0x00, 0xff, "Device Disabled" }, + { 0x09, 0x01, 0xff, "Device Enabled" }, + { 0x0a, 0x00, 0xff, "Transition to Running" }, + { 0x0a, 0x01, 0xff, "Transition to In Test" }, + { 0x0a, 0x02, 0xff, "Transition to Power Off" }, + { 0x0a, 0x03, 0xff, "Transition to On Line" }, + { 0x0a, 0x04, 0xff, "Transition to Off Line" }, + { 0x0a, 0x05, 0xff, "Transition to Off Duty" }, + { 0x0a, 0x06, 0xff, "Transition to Degraded" }, + { 0x0a, 0x07, 0xff, "Transition to Power Save" }, + { 0x0a, 0x08, 0xff, "Install Error" }, + /* Redundancy States */ + { 0x0b, 0x00, 0xff, "Fully Redundant" }, + { 0x0b, 0x01, 0xff, "Redundancy Lost" }, + { 0x0b, 0x02, 0xff, "Redundancy Degraded" }, + { 0x0b, 0x03, 0xff, "Non-Redundant: Sufficient from Redundant" }, + { 0x0b, 0x04, 0xff, "Non-Redundant: Sufficient from Insufficient" }, + { 0x0b, 0x05, 0xff, "Non-Redundant: Insufficient Resources" }, + { 0x0b, 0x06, 0xff, "Redundancy Degraded from Fully Redundant" }, + { 0x0b, 0x07, 0xff, "Redundancy Degraded from Non-Redundant" }, + /* ACPI Device Power States */ + { 0x0c, 0x00, 0xff, "D0 Power State" }, + { 0x0c, 0x01, 0xff, "D1 Power State" }, + { 0x0c, 0x02, 0xff, "D2 Power State" }, + { 0x0c, 0x03, 0xff, "D3 Power State" }, + /* END */ + { 0x00, 0x00, 0xff, NULL }, }; -static struct ipmi_event_sensor_types generic_event_types[] __attribute__((unused)) = { - /* Threshold Based States */ - { 0x01, 0x00, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Non-critical going low " }, - { 0x01, 0x01, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Non-critical going high" }, - { 0x01, 0x02, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Critical going low " }, - { 0x01, 0x03, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Critical going high" }, - { 0x01, 0x04, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Non-recoverable going low " }, - { 0x01, 0x05, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Lower Non-recoverable going high" }, - { 0x01, 0x06, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Non-critical going low " }, - { 0x01, 0x07, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Non-critical going high" }, - { 0x01, 0x08, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Critical going low " }, - { 0x01, 0x09, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Critical going high" }, - { 0x01, 0x0a, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Non-recoverable going low " }, - { 0x01, 0x0b, 0xff, IPMI_EVENT_CLASS_THRESHOLD, "Threshold", "Upper Non-recoverable going high" }, - /* DMI-based "usage state" States */ - { 0x02, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Usage State", "Transition to Idle" }, - { 0x02, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Usage State", "Transition to Active" }, - { 0x02, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Usage State", "Transition to Busy" }, - /* Digital-Discrete Event States */ - { 0x03, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "State Deasserted" }, - { 0x03, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "State Asserted" }, - { 0x04, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Predictive Failure Deasserted" }, - { 0x04, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Predictive Failure Asserted" }, - { 0x05, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Limit Not Exceeded" }, - { 0x05, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Limit Exceeded" }, - { 0x06, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Performance Met" }, - { 0x06, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Digital State", "Performance Lags" }, - /* Severity Event States */ - { 0x07, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to OK" }, - { 0x07, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Non-critical from OK" }, - { 0x07, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Critical from less severe" }, - { 0x07, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Non-recoverable from less severe" }, - { 0x07, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Non-critical from more severe" }, - { 0x07, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Critical from Non-recoverable" }, - { 0x07, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Transition to Non-recoverable" }, - { 0x07, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Monitor" }, - { 0x07, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Severity State", "Informational" }, - /* Availability Status States */ - { 0x08, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Availability State", "Device Absent" }, - { 0x08, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Availability State", "Device Present" }, - { 0x09, 0x00, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Availability State", "Device Disabled" }, - { 0x09, 0x01, 0xff, IPMI_EVENT_CLASS_DIGITAL, "Availability State", "Device Enabled" }, - { 0x0a, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Running" }, - { 0x0a, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to In Test" }, - { 0x0a, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Power Off" }, - { 0x0a, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to On Line" }, - { 0x0a, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Off Line" }, - { 0x0a, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Off Duty" }, - { 0x0a, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Degraded" }, - { 0x0a, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Transition to Power Save" }, - { 0x0a, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Availability State", "Install Error" }, - /* Redundancy States */ - { 0x0b, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Fully Redundant" }, - { 0x0b, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Redundancy Lost" }, - { 0x0b, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Redundancy Degraded" }, - { 0x0b, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Non-Redundant: Sufficient from Redundant" }, - { 0x0b, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Non-Redundant: Sufficient from Insufficient" }, - { 0x0b, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Non-Redundant: Insufficient Resources" }, - { 0x0b, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Redundancy Degraded from Fully Redundant" }, - { 0x0b, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Redundancy State", "Redundancy Degraded from Non-Redundant" }, - /* ACPI Device Power States */ - { 0x0c, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "ACPI Device Power State", "D0 Power State" }, - { 0x0c, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "ACPI Device Power State", "D1 Power State" }, - { 0x0c, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "ACPI Device Power State", "D2 Power State" }, - { 0x0c, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "ACPI Device Power State", "D3 Power State" }, - /* END */ - { 0x00, 0x00, 0xff, 0x00, NULL, NULL }, +static const struct ipmi_event_sensor_types sensor_specific_event_types[] = { + /* Physical Security */ + { 0x05, 0x00, 0xff, "General Chassis intrusion" }, + { 0x05, 0x01, 0xff, "Drive Bay intrusion" }, + { 0x05, 0x02, 0xff, "I/O Card area intrusion" }, + { 0x05, 0x03, 0xff, "Processor area intrusion" }, + { 0x05, 0x04, 0xff, "System unplugged from LAN" }, + { 0x05, 0x05, 0xff, "Unauthorized dock" }, + { 0x05, 0x06, 0xff, "FAN area intrusion" }, + /* Platform Security */ + { 0x06, 0x00, 0xff, "Front Panel Lockout violation attempted" }, + { 0x06, 0x01, 0xff, "Pre-boot password violation - user password" }, + { 0x06, 0x02, 0xff, "Pre-boot password violation - setup password" }, + { 0x06, 0x03, 0xff, "Pre-boot password violation - network boot password" }, + { 0x06, 0x04, 0xff, "Other pre-boot password violation" }, + { 0x06, 0x05, 0xff, "Out-of-band access password violation" }, + /* Processor */ + { 0x07, 0x00, 0xff, "IERR" }, + { 0x07, 0x01, 0xff, "Thermal Trip" }, + { 0x07, 0x02, 0xff, "FRB1/BIST failure" }, + { 0x07, 0x03, 0xff, "FRB2/Hang in POST failure" }, + { 0x07, 0x04, 0xff, "FRB3/Processor startup/init failure" }, + { 0x07, 0x05, 0xff, "Configuration Error" }, + { 0x07, 0x06, 0xff, "SM BIOS Uncorrectable CPU-complex Error" }, + { 0x07, 0x07, 0xff, "Presence detected" }, + { 0x07, 0x08, 0xff, "Disabled" }, + { 0x07, 0x09, 0xff, "Terminator presence detected" }, + { 0x07, 0x0a, 0xff, "Throttled" }, + { 0x07, 0x0b, 0xff, "Uncorrectable machine check exception" }, + { 0x07, 0x0c, 0xff, "Correctable machine check error" }, + /* Power Supply */ + { 0x08, 0x00, 0xff, "Presence detected" }, + { 0x08, 0x01, 0xff, "Failure detected" }, + { 0x08, 0x02, 0xff, "Predictive failure" }, + { 0x08, 0x03, 0xff, "Power Supply AC lost" }, + { 0x08, 0x04, 0xff, "AC lost or out-of-range" }, + { 0x08, 0x05, 0xff, "AC out-of-range, but present" }, + { 0x08, 0x06, 0x00, "Config Error: Vendor Mismatch" }, + { 0x08, 0x06, 0x01, "Config Error: Revision Mismatch" }, + { 0x08, 0x06, 0x02, "Config Error: Processor Missing" }, + { 0x08, 0x06, 0x03, "Config Error: Power Supply Rating Mismatch" }, + { 0x08, 0x06, 0x04, "Config Error: Voltage Rating Mismatch" }, + { 0x08, 0x06, 0xff, "Config Error" }, + { 0x08, 0x06, 0xff, "Power Supply Inactive" }, + /* Power Unit */ + { 0x09, 0x00, 0xff, "Power off/down" }, + { 0x09, 0x01, 0xff, "Power cycle" }, + { 0x09, 0x02, 0xff, "240VA power down" }, + { 0x09, 0x03, 0xff, "Interlock power down" }, + { 0x09, 0x04, 0xff, "AC lost" }, + { 0x09, 0x05, 0xff, "Soft-power control failure" }, + { 0x09, 0x06, 0xff, "Failure detected" }, + { 0x09, 0x07, 0xff, "Predictive failure" }, + /* Memory */ + { 0x0c, 0x00, 0xff, "Correctable ECC" }, + { 0x0c, 0x01, 0xff, "Uncorrectable ECC" }, + { 0x0c, 0x02, 0xff, "Parity" }, + { 0x0c, 0x03, 0xff, "Memory Scrub Failed" }, + { 0x0c, 0x04, 0xff, "Memory Device Disabled" }, + { 0x0c, 0x05, 0xff, "Correctable ECC logging limit reached" }, + { 0x0c, 0x06, 0xff, "Presence Detected" }, + { 0x0c, 0x07, 0xff, "Configuration Error" }, + { 0x0c, 0x08, 0xff, "Spare" }, + { 0x0c, 0x09, 0xff, "Throttled" }, + { 0x0c, 0x0a, 0xff, "Critical Overtemperature" }, + /* Drive Slot */ + { 0x0d, 0x00, 0xff, "Drive Present" }, + { 0x0d, 0x01, 0xff, "Drive Fault" }, + { 0x0d, 0x02, 0xff, "Predictive Failure" }, + { 0x0d, 0x03, 0xff, "Hot Spare" }, + { 0x0d, 0x04, 0xff, "Parity Check In Progress" }, + { 0x0d, 0x05, 0xff, "In Critical Array" }, + { 0x0d, 0x06, 0xff, "In Failed Array" }, + { 0x0d, 0x07, 0xff, "Rebuild In Progress" }, + { 0x0d, 0x08, 0xff, "Rebuild Aborted" }, + /* System Firmware Error */ + { 0x0f, 0x00, 0x00, "Unspecified" }, + { 0x0f, 0x00, 0x01, "No system memory installed" }, + { 0x0f, 0x00, 0x02, "No usable system memory" }, + { 0x0f, 0x00, 0x03, "Unrecoverable IDE device failure" }, + { 0x0f, 0x00, 0x04, "Unrecoverable system-board failure" }, + { 0x0f, 0x00, 0x05, "Unrecoverable diskette failure" }, + { 0x0f, 0x00, 0x06, "Unrecoverable hard-disk controller failure" }, + { 0x0f, 0x00, 0x07, "Unrecoverable PS/2 or USB keyboard failure" }, + { 0x0f, 0x00, 0x08, "Removable boot media not found" }, + { 0x0f, 0x00, 0x09, "Unrecoverable video controller failure" }, + { 0x0f, 0x00, 0x0a, "No video device selected" }, + { 0x0f, 0x00, 0x0b, "BIOS corruption detected" }, + { 0x0f, 0x00, 0x0c, "CPU voltage mismatch" }, + { 0x0f, 0x00, 0x0d, "CPU speed mismatch failure" }, + { 0x0f, 0x00, 0xff, "Unknown Error" }, + /* System Firmware Hang */ + { 0x0f, 0x01, 0x00, "Unspecified" }, + { 0x0f, 0x01, 0x01, "Memory initialization" }, + { 0x0f, 0x01, 0x02, "Hard-disk initialization" }, + { 0x0f, 0x01, 0x03, "Secondary CPU Initialization" }, + { 0x0f, 0x01, 0x04, "User authentication" }, + { 0x0f, 0x01, 0x05, "User-initiated system setup" }, + { 0x0f, 0x01, 0x06, "USB resource configuration" }, + { 0x0f, 0x01, 0x07, "PCI resource configuration" }, + { 0x0f, 0x01, 0x08, "Option ROM initialization" }, + { 0x0f, 0x01, 0x09, "Video initialization" }, + { 0x0f, 0x01, 0x0a, "Cache initialization" }, + { 0x0f, 0x01, 0x0b, "SMBus initialization" }, + { 0x0f, 0x01, 0x0c, "Keyboard controller initialization" }, + { 0x0f, 0x01, 0x0d, "Management controller initialization" }, + { 0x0f, 0x01, 0x0e, "Docking station attachment" }, + { 0x0f, 0x01, 0x0f, "Enabling docking station" }, + { 0x0f, 0x01, 0x10, "Docking station ejection" }, + { 0x0f, 0x01, 0x11, "Disabling docking station" }, + { 0x0f, 0x01, 0x12, "Calling operating system wake-up vector" }, + { 0x0f, 0x01, 0x13, "System boot initiated" }, + { 0x0f, 0x01, 0x14, "Motherboard initialization" }, + { 0x0f, 0x01, 0x15, "reserved" }, + { 0x0f, 0x01, 0x16, "Floppy initialization" }, + { 0x0f, 0x01, 0x17, "Keyboard test" }, + { 0x0f, 0x01, 0x18, "Pointing device test" }, + { 0x0f, 0x01, 0x19, "Primary CPU initialization" }, + { 0x0f, 0x01, 0xff, "Unknown Hang" }, + /* System Firmware Progress */ + { 0x0f, 0x02, 0x00, "Unspecified" }, + { 0x0f, 0x02, 0x01, "Memory initialization" }, + { 0x0f, 0x02, 0x02, "Hard-disk initialization" }, + { 0x0f, 0x02, 0x03, "Secondary CPU Initialization" }, + { 0x0f, 0x02, 0x04, "User authentication" }, + { 0x0f, 0x02, 0x05, "User-initiated system setup" }, + { 0x0f, 0x02, 0x06, "USB resource configuration" }, + { 0x0f, 0x02, 0x07, "PCI resource configuration" }, + { 0x0f, 0x02, 0x08, "Option ROM initialization" }, + { 0x0f, 0x02, 0x09, "Video initialization" }, + { 0x0f, 0x02, 0x0a, "Cache initialization" }, + { 0x0f, 0x02, 0x0b, "SMBus initialization" }, + { 0x0f, 0x02, 0x0c, "Keyboard controller initialization" }, + { 0x0f, 0x02, 0x0d, "Management controller initialization" }, + { 0x0f, 0x02, 0x0e, "Docking station attachment" }, + { 0x0f, 0x02, 0x0f, "Enabling docking station" }, + { 0x0f, 0x02, 0x10, "Docking station ejection" }, + { 0x0f, 0x02, 0x11, "Disabling docking station" }, + { 0x0f, 0x02, 0x12, "Calling operating system wake-up vector" }, + { 0x0f, 0x02, 0x13, "System boot initiated" }, + { 0x0f, 0x02, 0x14, "Motherboard initialization" }, + { 0x0f, 0x02, 0x15, "reserved" }, + { 0x0f, 0x02, 0x16, "Floppy initialization" }, + { 0x0f, 0x02, 0x17, "Keyboard test" }, + { 0x0f, 0x02, 0x18, "Pointing device test" }, + { 0x0f, 0x02, 0x19, "Primary CPU initialization" }, + { 0x0f, 0x02, 0xff, "Unknown Progress" }, + /* Event Logging Disabled */ + { 0x10, 0x00, 0xff, "Correctable memory error logging disabled" }, + { 0x10, 0x01, 0xff, "Event logging disabled" }, + { 0x10, 0x02, 0xff, "Log area reset/cleared" }, + { 0x10, 0x03, 0xff, "All event logging disabled" }, + { 0x10, 0x04, 0xff, "Log full" }, + { 0x10, 0x05, 0xff, "Log almost full" }, + /* Watchdog 1 */ + { 0x11, 0x00, 0xff, "BIOS Reset" }, + { 0x11, 0x01, 0xff, "OS Reset" }, + { 0x11, 0x02, 0xff, "OS Shut Down" }, + { 0x11, 0x03, 0xff, "OS Power Down" }, + { 0x11, 0x04, 0xff, "OS Power Cycle" }, + { 0x11, 0x05, 0xff, "OS NMI/Diag Interrupt" }, + { 0x11, 0x06, 0xff, "OS Expired" }, + { 0x11, 0x07, 0xff, "OS pre-timeout Interrupt" }, + /* System Event */ + { 0x12, 0x00, 0xff, "System Reconfigured" }, + { 0x12, 0x01, 0xff, "OEM System boot event" }, + { 0x12, 0x02, 0xff, "Undetermined system hardware failure" }, + { 0x12, 0x03, 0xff, "Entry added to auxiliary log" }, + { 0x12, 0x04, 0xff, "PEF Action" }, + { 0x12, 0x05, 0xff, "Timestamp Clock Sync" }, + /* Critical Interrupt */ + { 0x13, 0x00, 0xff, "NMI/Diag Interrupt" }, + { 0x13, 0x01, 0xff, "Bus Timeout" }, + { 0x13, 0x02, 0xff, "I/O Channel check NMI" }, + { 0x13, 0x03, 0xff, "Software NMI" }, + { 0x13, 0x04, 0xff, "PCI PERR" }, + { 0x13, 0x05, 0xff, "PCI SERR" }, + { 0x13, 0x06, 0xff, "EISA failsafe timeout" }, + { 0x13, 0x07, 0xff, "Bus Correctable error" }, + { 0x13, 0x08, 0xff, "Bus Uncorrectable error" }, + { 0x13, 0x09, 0xff, "Fatal NMI" }, + { 0x13, 0x0a, 0xff, "Bus Fatal Error" }, + { 0x13, 0x0b, 0xff, "Bus Degraded" }, + /* Button */ + { 0x14, 0x00, 0xff, "Power Button pressed" }, + { 0x14, 0x01, 0xff, "Sleep Button pressed" }, + { 0x14, 0x02, 0xff, "Reset Button pressed" }, + { 0x14, 0x03, 0xff, "FRU Latch" }, + { 0x14, 0x04, 0xff, "FRU Service" }, + /* Chip Set */ + { 0x19, 0x00, 0xff, "Soft Power Control Failure" }, + { 0x19, 0x01, 0xff, "Thermal Trip" }, + /* Cable/Interconnect */ + { 0x1b, 0x00, 0xff, "Connected" }, + { 0x1b, 0x01, 0xff, "Config Error" }, + /* System Boot Initiated */ + { 0x1d, 0x00, 0xff, "Initiated by power up" }, + { 0x1d, 0x01, 0xff, "Initiated by hard reset" }, + { 0x1d, 0x02, 0xff, "Initiated by warm reset" }, + { 0x1d, 0x03, 0xff, "User requested PXE boot" }, + { 0x1d, 0x04, 0xff, "Automatic boot to diagnostic" }, + { 0x1d, 0x05, 0xff, "OS initiated hard reset" }, + { 0x1d, 0x06, 0xff, "OS initiated warm reset" }, + { 0x1d, 0x07, 0xff, "System Restart" }, + /* Boot Error */ + { 0x1e, 0x00, 0xff, "No bootable media" }, + { 0x1e, 0x01, 0xff, "Non-bootable disk in drive" }, + { 0x1e, 0x02, 0xff, "PXE server not found" }, + { 0x1e, 0x03, 0xff, "Invalid boot sector" }, + { 0x1e, 0x04, 0xff, "Timeout waiting for selection" }, + /* OS Boot */ + { 0x1f, 0x00, 0xff, "A: boot completed" }, + { 0x1f, 0x01, 0xff, "C: boot completed" }, + { 0x1f, 0x02, 0xff, "PXE boot completed" }, + { 0x1f, 0x03, 0xff, "Diagnostic boot completed" }, + { 0x1f, 0x04, 0xff, "CD-ROM boot completed" }, + { 0x1f, 0x05, 0xff, "ROM boot completed" }, + { 0x1f, 0x06, 0xff, "boot completed - device not specified" }, + { 0x1f, 0x07, 0xff, "Installation started" }, + { 0x1f, 0x08, 0xff, "Installation completed" }, + { 0x1f, 0x09, 0xff, "Installation aborted" }, + { 0x1f, 0x0a, 0xff, "Installation failed" }, + /* OS Stop/Shutdown */ + { 0x20, 0x00, 0xff, "Error during system startup" }, + { 0x20, 0x01, 0xff, "Run-time critical stop" }, + { 0x20, 0x02, 0xff, "OS graceful stop" }, + { 0x20, 0x03, 0xff, "OS graceful shutdown" }, + { 0x20, 0x04, 0xff, "PEF initiated soft shutdown" }, + { 0x20, 0x05, 0xff, "Agent not responding" }, + /* Slot/Connector */ + { 0x21, 0x00, 0xff, "Fault Status" }, + { 0x21, 0x01, 0xff, "Identify Status" }, + { 0x21, 0x02, 0xff, "Device Installed" }, + { 0x21, 0x03, 0xff, "Ready for Device Installation" }, + { 0x21, 0x04, 0xff, "Ready for Device Removal" }, + { 0x21, 0x05, 0xff, "Slot Power is Off" }, + { 0x21, 0x06, 0xff, "Device Removal Request" }, + { 0x21, 0x07, 0xff, "Interlock" }, + { 0x21, 0x08, 0xff, "Slot is Disabled" }, + { 0x21, 0x09, 0xff, "Spare Device" }, + /* System ACPI Power State */ + { 0x22, 0x00, 0xff, "S0/G0: working" }, + { 0x22, 0x01, 0xff, "S1: sleeping with system hw & processor context maintained" }, + { 0x22, 0x02, 0xff, "S2: sleeping, processor context lost" }, + { 0x22, 0x03, 0xff, "S3: sleeping, processor & hw context lost, memory retained" }, + { 0x22, 0x04, 0xff, "S4: non-volatile sleep/suspend-to-disk" }, + { 0x22, 0x05, 0xff, "S5/G2: soft-off" }, + { 0x22, 0x06, 0xff, "S4/S5: soft-off" }, + { 0x22, 0x07, 0xff, "G3: mechanical off" }, + { 0x22, 0x08, 0xff, "Sleeping in S1/S2/S3 state" }, + { 0x22, 0x09, 0xff, "G1: sleeping" }, + { 0x22, 0x0a, 0xff, "S5: entered by override" }, + { 0x22, 0x0b, 0xff, "Legacy ON state" }, + { 0x22, 0x0c, 0xff, "Legacy OFF state" }, + { 0x22, 0x0e, 0xff, "Unknown" }, + /* Watchdog 2 */ + { 0x23, 0x00, 0xff, "Timer expired" }, + { 0x23, 0x01, 0xff, "Hard reset" }, + { 0x23, 0x02, 0xff, "Power down" }, + { 0x23, 0x03, 0xff, "Power cycle" }, + { 0x23, 0x04, 0xff, "reserved" }, + { 0x23, 0x05, 0xff, "reserved" }, + { 0x23, 0x06, 0xff, "reserved" }, + { 0x23, 0x07, 0xff, "reserved" }, + { 0x23, 0x08, 0xff, "Timer interrupt" }, + /* Platform Alert */ + { 0x24, 0x00, 0xff, "Platform generated page" }, + { 0x24, 0x01, 0xff, "Platform generated LAN alert" }, + { 0x24, 0x02, 0xff, "Platform Event Trap generated" }, + { 0x24, 0x03, 0xff, "Platform generated SNMP trap, OEM format" }, + /* Entity Presence */ + { 0x25, 0x00, 0xff, "Present" }, + { 0x25, 0x01, 0xff, "Absent" }, + { 0x25, 0x02, 0xff, "Disabled" }, + /* LAN */ + { 0x27, 0x00, 0xff, "Heartbeat Lost" }, + { 0x27, 0x01, 0xff, "Heartbeat" }, + /* Management Subsystem Health */ + { 0x28, 0x00, 0xff, "Sensor access degraded or unavailable" }, + { 0x28, 0x01, 0xff, "Controller access degraded or unavailable" }, + { 0x28, 0x02, 0xff, "Management controller off-line" }, + { 0x28, 0x03, 0xff, "Management controller unavailable" }, + { 0x28, 0x04, 0xff, "Sensor failure" }, + { 0x28, 0x05, 0xff, "FRU failure" }, + /* Battery */ + { 0x29, 0x00, 0xff, "Low" }, + { 0x29, 0x01, 0xff, "Failed" }, + { 0x29, 0x02, 0xff, "Presence Detected" }, + /* Version Change */ + { 0x2b, 0x00, 0xff, "Hardware change detected" }, + { 0x2b, 0x01, 0x00, "Firmware or software change detected" }, + { 0x2b, 0x01, 0x01, "Firmware or software change detected, Mngmt Ctrl Dev Id" }, + { 0x2b, 0x01, 0x02, "Firmware or software change detected, Mngmt Ctrl Firm Rev" }, + { 0x2b, 0x01, 0x03, "Firmware or software change detected, Mngmt Ctrl Dev Rev" }, + { 0x2b, 0x01, 0x04, "Firmware or software change detected, Mngmt Ctrl Manuf Id" }, + { 0x2b, 0x01, 0x05, "Firmware or software change detected, Mngmt Ctrl IPMI Vers" }, + { 0x2b, 0x01, 0x06, "Firmware or software change detected, Mngmt Ctrl Aux Firm Id" }, + { 0x2b, 0x01, 0x07, "Firmware or software change detected, Mngmt Ctrl Firm Boot Block" }, + { 0x2b, 0x01, 0x08, "Firmware or software change detected, Mngmt Ctrl Other" }, + { 0x2b, 0x01, 0x09, "Firmware or software change detected, BIOS/EFI change" }, + { 0x2b, 0x01, 0x0A, "Firmware or software change detected, SMBIOS change" }, + { 0x2b, 0x01, 0x0B, "Firmware or software change detected, O/S change" }, + { 0x2b, 0x01, 0x0C, "Firmware or software change detected, O/S loader change" }, + { 0x2b, 0x01, 0x0D, "Firmware or software change detected, Service Diag change" }, + { 0x2b, 0x01, 0x0E, "Firmware or software change detected, Mngmt SW agent change" }, + { 0x2b, 0x01, 0x0F, "Firmware or software change detected, Mngmt SW App change" }, + { 0x2b, 0x01, 0x10, "Firmware or software change detected, Mngmt SW Middle" }, + { 0x2b, 0x01, 0x11, "Firmware or software change detected, Prog HW Change (FPGA)" }, + { 0x2b, 0x01, 0x12, "Firmware or software change detected, board/FRU module change" }, + { 0x2b, 0x01, 0x13, "Firmware or software change detected, board/FRU component change" }, + { 0x2b, 0x01, 0x14, "Firmware or software change detected, board/FRU replace equ ver" }, + { 0x2b, 0x01, 0x15, "Firmware or software change detected, board/FRU replace new ver" }, + { 0x2b, 0x01, 0x16, "Firmware or software change detected, board/FRU replace old ver" }, + { 0x2b, 0x01, 0x17, "Firmware or software change detected, board/FRU HW conf change" }, + { 0x2b, 0x02, 0xff, "Hardware incompatibility detected" }, + { 0x2b, 0x03, 0xff, "Firmware or software incompatibility detected" }, + { 0x2b, 0x04, 0xff, "Invalid or unsupported hardware version" }, + { 0x2b, 0x05, 0xff, "Invalid or unsupported firmware or software version" }, + { 0x2b, 0x06, 0xff, "Hardware change success" }, + { 0x2b, 0x07, 0x00, "Firmware or software change success" }, + { 0x2b, 0x07, 0x01, "Firmware or software change success, Mngmt Ctrl Dev Id" }, + { 0x2b, 0x07, 0x02, "Firmware or software change success, Mngmt Ctrl Firm Rev" }, + { 0x2b, 0x07, 0x03, "Firmware or software change success, Mngmt Ctrl Dev Rev" }, + { 0x2b, 0x07, 0x04, "Firmware or software change success, Mngmt Ctrl Manuf Id" }, + { 0x2b, 0x07, 0x05, "Firmware or software change success, Mngmt Ctrl IPMI Vers" }, + { 0x2b, 0x07, 0x06, "Firmware or software change success, Mngmt Ctrl Aux Firm Id" }, + { 0x2b, 0x07, 0x07, "Firmware or software change success, Mngmt Ctrl Firm Boot Block" }, + { 0x2b, 0x07, 0x08, "Firmware or software change success, Mngmt Ctrl Other" }, + { 0x2b, 0x07, 0x09, "Firmware or software change success, BIOS/EFI change" }, + { 0x2b, 0x07, 0x0A, "Firmware or software change success, SMBIOS change" }, + { 0x2b, 0x07, 0x0B, "Firmware or software change success, O/S change" }, + { 0x2b, 0x07, 0x0C, "Firmware or software change success, O/S loader change" }, + { 0x2b, 0x07, 0x0D, "Firmware or software change success, Service Diag change" }, + { 0x2b, 0x07, 0x0E, "Firmware or software change success, Mngmt SW agent change" }, + { 0x2b, 0x07, 0x0F, "Firmware or software change success, Mngmt SW App change" }, + { 0x2b, 0x07, 0x10, "Firmware or software change success, Mngmt SW Middle" }, + { 0x2b, 0x07, 0x11, "Firmware or software change success, Prog HW Change (FPGA)" }, + { 0x2b, 0x07, 0x12, "Firmware or software change success, board/FRU module change" }, + { 0x2b, 0x07, 0x13, "Firmware or software change success, board/FRU component change" }, + { 0x2b, 0x07, 0x14, "Firmware or software change success, board/FRU replace equ ver" }, + { 0x2b, 0x07, 0x15, "Firmware or software change success, board/FRU replace new ver" }, + { 0x2b, 0x07, 0x16, "Firmware or software change success, board/FRU replace old ver" }, + { 0x2b, 0x07, 0x17, "Firmware or software change success, board/FRU HW conf change" }, + /* FRU State */ + { 0x2c, 0x00, 0xff, "Not Installed" }, + { 0x2c, 0x01, 0xff, "Inactive" }, + { 0x2c, 0x02, 0xff, "Activation Requested" }, + { 0x2c, 0x03, 0xff, "Activation in Progress" }, + { 0x2c, 0x04, 0xff, "Active" }, + { 0x2c, 0x05, 0xff, "Deactivation Requested" }, + { 0x2c, 0x06, 0xff, "Deactivation in Progress" }, + { 0x2c, 0x07, 0xff, "Communication lost" }, + /* PICMG FRU Hot Swap */ + { 0xF0, 0x00, 0xFF, "Transition to M0" }, + { 0xF0, 0x01, 0xFF, "Transition to M1" }, + { 0xF0, 0x02, 0xFF, "Transition to M2" }, + { 0xF0, 0x03, 0xFF, "Transition to M3" }, + { 0xF0, 0x04, 0xFF, "Transition to M4" }, + { 0xF0, 0x05, 0xFF, "Transition to M5" }, + { 0xF0, 0x06, 0xFF, "Transition to M6" }, + { 0xF0, 0x07, 0xFF, "Transition to M7" }, + /* PICMG IPMB Physical Link */ + { 0xF1, 0x00, 0xff, "IPMB-A disabled, IPMB-B disabled" }, + { 0xF1, 0x01, 0xff, "IPMB-A enabled, IPMB-B disabled" }, + { 0xF1, 0x02, 0xff, "IPMB-A disabled, IPMB-B enabled" }, + { 0xF1, 0x03, 0xff, "IPMB-A enabled, IPMP-B enabled" }, + /* PICNG Moduke Hot Swap */ + { 0xF2, 0x00, 0xff, "Module Handle Closed" }, + { 0xF2, 0x01, 0xff, "Module Handle Opened" }, + { 0xF2, 0x02, 0xff, "Quiesced" }, + { 0x00, 0x00, 0xff, NULL }, }; -static struct ipmi_event_sensor_types sensor_specific_types[] __attribute__((unused)) = { - { 0x00, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Reserved", NULL }, - { 0x01, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Temperature", NULL }, - { 0x02, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Voltage", NULL }, - { 0x03, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Current", NULL }, - { 0x04, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Fan", NULL }, - - { 0x05, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "General Chassis intrusion" }, - { 0x05, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "Drive Bay intrusion" }, - { 0x05, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "I/O Card area intrusion" }, - { 0x05, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "Processor area intrusion" }, - { 0x05, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "System unplugged from LAN" }, - { 0x05, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "Unauthorized dock" }, - { 0x05, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Physical Security", "FAN area intrusion" }, - - { 0x06, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Front Panel Lockout violation attempted" }, - { 0x06, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Pre-boot password violation - user password" }, - { 0x06, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Pre-boot password violation - setup password" }, - { 0x06, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Pre-boot password violation - network boot password" }, - { 0x06, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Other pre-boot password violation" }, - { 0x06, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Security", "Out-of-band access password violation" }, - - { 0x07, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "IERR" }, - { 0x07, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Thermal Trip" }, - { 0x07, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "FRB1/BIST failure" }, - { 0x07, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "FRB2/Hang in POST failure" }, - { 0x07, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "FRB3/Processor startup/init failure" }, - { 0x07, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Configuration Error" }, - { 0x07, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "SM BIOS Uncorrectable CPU-complex Error" }, - { 0x07, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Presence detected" }, - { 0x07, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Disabled" }, - { 0x07, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Terminator presence detected" }, - { 0x07, 0x0a, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Throttled" }, - { 0x07, 0x0b, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Uncorrectable machine check exception" }, - { 0x07, 0x0c, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Processor", "Correctable machine check error" }, - - { 0x08, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Presence detected" }, - { 0x08, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Failure detected" }, - { 0x08, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Predictive failure" }, - { 0x08, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Power Supply AC lost" }, - { 0x08, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "AC lost or out-of-range" }, - { 0x08, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "AC out-of-range, but present" }, - { 0x08, 0x06, 0x00, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Config Error: Vendor Mismatch" }, - { 0x08, 0x06, 0x01, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Config Error: Revision Mismatch" }, - { 0x08, 0x06, 0x02, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Config Error: Processor Missing" }, - { 0x08, 0x06, 0x03, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Config Error: Power Supply Rating Mismatch" }, - { 0x08, 0x06, 0x04, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Config Error: Voltage Rating Mismatch" }, - { 0x08, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Config Error" }, - { 0x08, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Supply", "Power Supply Inactive" }, - - { 0x09, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Power off/down" }, - { 0x09, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Power cycle" }, - { 0x09, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "240VA power down" }, - { 0x09, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Interlock power down" }, - { 0x09, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "AC lost" }, - { 0x09, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Soft-power control failure" }, - { 0x09, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Failure detected" }, - { 0x09, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Power Unit", "Predictive failure" }, - - { 0x0a, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Cooling Device", NULL }, - { 0x0b, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Other Units-based Sensor", NULL }, - - { 0x0c, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Correctable ECC" }, - { 0x0c, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Uncorrectable ECC" }, - { 0x0c, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Parity" }, - { 0x0c, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Memory Scrub Failed" }, - { 0x0c, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Memory Device Disabled" }, - { 0x0c, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Correctable ECC logging limit reached" }, - { 0x0c, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Presence Detected" }, - { 0x0c, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Configuration Error" }, - { 0x0c, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Spare" }, - { 0x0c, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Throttled" }, - { 0x0c, 0x0a, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Memory", "Critical Overtemperature" }, - - { 0x0d, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Drive Present" }, - { 0x0d, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Drive Fault" }, - { 0x0d, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Predictive Failure" }, - { 0x0d, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Hot Spare" }, - { 0x0d, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Parity Check In Progress" }, - { 0x0d, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "In Critical Array" }, - { 0x0d, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "In Failed Array" }, - { 0x0d, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Rebuild In Progress" }, - { 0x0d, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Drive Slot", "Rebuild Aborted" }, - - { 0x0e, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "POST Memory Resize", NULL }, - - { 0x0f, 0x00, 0x00, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unspecified" }, - { 0x0f, 0x00, 0x01, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "No system memory installed" }, - { 0x0f, 0x00, 0x02, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "No usable system memory" }, - { 0x0f, 0x00, 0x03, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable IDE device failure" }, - { 0x0f, 0x00, 0x04, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable system-board failure" }, - { 0x0f, 0x00, 0x05, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable diskette failure" }, - { 0x0f, 0x00, 0x06, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable hard-disk controller failure" }, - { 0x0f, 0x00, 0x07, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable PS/2 or USB keyboard failure" }, - { 0x0f, 0x00, 0x08, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Removable boot media not found" }, - { 0x0f, 0x00, 0x09, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unrecoverable video controller failure" }, - { 0x0f, 0x00, 0x0a, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "No video device selected" }, - { 0x0f, 0x00, 0x0b, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "BIOS corruption detected" }, - { 0x0f, 0x00, 0x0c, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "CPU voltage mismatch" }, - { 0x0f, 0x00, 0x0d, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "CPU speed mismatch failure" }, - { 0x0f, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Error", "Unknown Error" }, - - { 0x0f, 0x01, 0x00, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Unspecified" }, - { 0x0f, 0x01, 0x01, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Memory initialization" }, - { 0x0f, 0x01, 0x02, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Hard-disk initialization" }, - { 0x0f, 0x01, 0x03, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Secondary CPU Initialization" }, - { 0x0f, 0x01, 0x04, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "User authentication" }, - { 0x0f, 0x01, 0x05, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "User-initiated system setup" }, - { 0x0f, 0x01, 0x06, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "USB resource configuration" }, - { 0x0f, 0x01, 0x07, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "PCI resource configuration" }, - { 0x0f, 0x01, 0x08, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Option ROM initialization" }, - { 0x0f, 0x01, 0x09, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Video initialization" }, - { 0x0f, 0x01, 0x0a, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Cache initialization" }, - { 0x0f, 0x01, 0x0b, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "SMBus initialization" }, - { 0x0f, 0x01, 0x0c, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Keyboard controller initialization" }, - { 0x0f, 0x01, 0x0d, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Management controller initialization" }, - { 0x0f, 0x01, 0x0e, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Docking station attachment" }, - { 0x0f, 0x01, 0x0f, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Enabling docking station" }, - { 0x0f, 0x01, 0x10, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Docking station ejection" }, - { 0x0f, 0x01, 0x11, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Disabling docking station" }, - { 0x0f, 0x01, 0x12, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Calling operating system wake-up vector" }, - { 0x0f, 0x01, 0x13, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "System boot initiated" }, - { 0x0f, 0x01, 0x14, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Motherboard initialization" }, - { 0x0f, 0x01, 0x15, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "reserved" }, - { 0x0f, 0x01, 0x16, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Floppy initialization" }, - { 0x0f, 0x01, 0x17, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Keyboard test" }, - { 0x0f, 0x01, 0x18, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Pointing device test" }, - { 0x0f, 0x01, 0x19, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Primary CPU initialization" }, - { 0x0f, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Hang", "Unknown Hang" }, - - { 0x0f, 0x02, 0x00, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Unspecified" }, - { 0x0f, 0x02, 0x01, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Memory initialization" }, - { 0x0f, 0x02, 0x02, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Hard-disk initialization" }, - { 0x0f, 0x02, 0x03, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Secondary CPU Initialization" }, - { 0x0f, 0x02, 0x04, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "User authentication" }, - { 0x0f, 0x02, 0x05, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "User-initiated system setup" }, - { 0x0f, 0x02, 0x06, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "USB resource configuration" }, - { 0x0f, 0x02, 0x07, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "PCI resource configuration" }, - { 0x0f, 0x02, 0x08, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Option ROM initialization" }, - { 0x0f, 0x02, 0x09, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Video initialization" }, - { 0x0f, 0x02, 0x0a, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Cache initialization" }, - { 0x0f, 0x02, 0x0b, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "SMBus initialization" }, - { 0x0f, 0x02, 0x0c, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Keyboard controller initialization" }, - { 0x0f, 0x02, 0x0d, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Management controller initialization" }, - { 0x0f, 0x02, 0x0e, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Docking station attachment" }, - { 0x0f, 0x02, 0x0f, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Enabling docking station" }, - { 0x0f, 0x02, 0x10, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Docking station ejection" }, - { 0x0f, 0x02, 0x11, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Disabling docking station" }, - { 0x0f, 0x02, 0x12, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Calling operating system wake-up vector" }, - { 0x0f, 0x02, 0x13, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "System boot initiated" }, - { 0x0f, 0x02, 0x14, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Motherboard initialization" }, - { 0x0f, 0x02, 0x15, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "reserved" }, - { 0x0f, 0x02, 0x16, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Floppy initialization" }, - { 0x0f, 0x02, 0x17, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Keyboard test" }, - { 0x0f, 0x02, 0x18, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Pointing device test" }, - { 0x0f, 0x02, 0x19, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Primary CPU initialization" }, - { 0x0f, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Firmware Progress", "Unknown Progress" }, - - { 0x10, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "Correctable memory error logging disabled" }, - { 0x10, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "Event logging disabled" }, - { 0x10, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "Log area reset/cleared" }, - { 0x10, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "All event logging disabled" }, - { 0x10, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "Log full" }, - { 0x10, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Event Logging Disabled", "Log almost full" }, - - { 0x11, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "BIOS Reset" }, - { 0x11, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS Reset" }, - { 0x11, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS Shut Down" }, - { 0x11, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS Power Down" }, - { 0x11, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS Power Cycle" }, - { 0x11, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS NMI/Diag Interrupt" }, - { 0x11, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS Expired" }, - { 0x11, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 1", "OS pre-timeout Interrupt" }, - - { 0x12, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "System Reconfigured" }, - { 0x12, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "OEM System boot event" }, - { 0x12, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "Undetermined system hardware failure" }, - { 0x12, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "Entry added to auxiliary log" }, - { 0x12, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "PEF Action" }, - { 0x12, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Event", "Timestamp Clock Sync" }, - - { 0x13, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "NMI/Diag Interrupt" }, - { 0x13, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Bus Timeout" }, - { 0x13, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "I/O Channel check NMI" }, - { 0x13, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Software NMI" }, - { 0x13, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "PCI PERR" }, - { 0x13, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "PCI SERR" }, - { 0x13, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "EISA failsafe timeout" }, - { 0x13, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Bus Correctable error" }, - { 0x13, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Bus Uncorrectable error" }, - { 0x13, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Fatal NMI" }, - { 0x13, 0x0a, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Bus Fatal Error" }, - { 0x13, 0x0b, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Critical Interrupt", "Bus Degraded" }, - - { 0x14, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Button", "Power Button pressed" }, - { 0x14, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Button", "Sleep Button pressed" }, - { 0x14, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Button", "Reset Button pressed" }, - { 0x14, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Button", "FRU Latch" }, - { 0x14, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Button", "FRU Service" }, - - { 0x15, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Module/Board", NULL }, - { 0x16, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Microcontroller/Coprocessor", NULL }, - { 0x17, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Add-in Card", NULL }, - { 0x18, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Chassis", NULL }, - { 0x19, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Chip Set", NULL }, - { 0x19, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Chip Set", "Thermal Trip" }, - { 0x1a, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Other FRU", NULL }, - - { 0x1b, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Cable/Interconnect", "Connected" }, - { 0x1b, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Cable/Interconnect", "Config Error" }, - - { 0x1c, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Terminator", NULL }, - - { 0x1d, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "Initiated by power up" }, - { 0x1d, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "Initiated by hard reset" }, - { 0x1d, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "Initiated by warm reset" }, - { 0x1d, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "User requested PXE boot" }, - { 0x1d, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "Automatic boot to diagnostic" }, - { 0x1d, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "OS initiated hard reset" }, - { 0x1d, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "OS initiated warm reset" }, - { 0x1d, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System Boot Initiated", "System Restart" }, - - { 0x1e, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Boot Error", "No bootable media" }, - { 0x1e, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Boot Error", "Non-bootable disk in drive" }, - { 0x1e, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Boot Error", "PXE server not found" }, - { 0x1e, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Boot Error", "Invalid boot sector" }, - { 0x1e, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Boot Error", "Timeout waiting for selection" }, - - { 0x1f, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "A: boot completed" }, - { 0x1f, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "C: boot completed" }, - { 0x1f, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "PXE boot completed" }, - { 0x1f, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "Diagnostic boot completed" }, - { 0x1f, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "CD-ROM boot completed" }, - { 0x1f, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "ROM boot completed" }, - { 0x1f, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "boot completed - device not specified" }, - { 0x1f, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "Installation started" }, - { 0x1f, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "Installation completed" }, - { 0x1f, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "Installation aborted" }, - { 0x1f, 0x0a, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Boot", "Installation failed" }, - - { 0x20, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "Error during system startup" }, - { 0x20, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "Run-time critical stop" }, - { 0x20, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "OS graceful stop" }, - { 0x20, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "OS graceful shutdown" }, - { 0x20, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "PEF initiated soft shutdown" }, - { 0x20, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "OS Stop/Shutdown", "Agent not responding" }, - - { 0x21, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Fault Status" }, - { 0x21, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Identify Status" }, - { 0x21, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Device Installed" }, - { 0x21, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Ready for Device Installation" }, - { 0x21, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Ready for Device Removal" }, - { 0x21, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Slot Power is Off" }, - { 0x21, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Device Removal Request" }, - { 0x21, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Interlock" }, - { 0x21, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Slot is Disabled" }, - { 0x21, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Slot/Connector", "Spare Device" }, - - { 0x22, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S0/G0: working" }, - { 0x22, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S1: sleeping with system hw & processor context maintained" }, - { 0x22, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S2: sleeping, processor context lost" }, - { 0x22, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S3: sleeping, processor & hw context lost, memory retained" }, - { 0x22, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S4: non-volatile sleep/suspend-to-disk" }, - { 0x22, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S5/G2: soft-off" }, - { 0x22, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S4/S5: soft-off" }, - { 0x22, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "G3: mechanical off" }, - { 0x22, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "Sleeping in S1/S2/S3 state" }, - { 0x22, 0x09, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "G1: sleeping" }, - { 0x22, 0x0a, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "S5: entered by override" }, - { 0x22, 0x0b, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "Legacy ON state" }, - { 0x22, 0x0c, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "Legacy OFF state" }, - { 0x22, 0x0e, 0xff, IPMI_EVENT_CLASS_DISCRETE, "System ACPI Power State", "Unknown" }, - - { 0x23, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "Timer expired" }, - { 0x23, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "Hard reset" }, - { 0x23, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "Power down" }, - { 0x23, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "Power cycle" }, - { 0x23, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "reserved" }, - { 0x23, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "reserved" }, - { 0x23, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "reserved" }, - { 0x23, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "reserved" }, - { 0x23, 0x08, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Watchdog 2", "Timer interrupt" }, - - { 0x24, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Alert", "Platform generated page" }, - { 0x24, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Alert", "Platform generated LAN alert" }, - { 0x24, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Alert", "Platform Event Trap generated" }, - { 0x24, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Platform Alert", "Platform generated SNMP trap, OEM format" }, - - { 0x25, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Entity Presence", "Present" }, - { 0x25, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Entity Presence", "Absent" }, - { 0x25, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Entity Presence", "Disabled" }, - - { 0x26, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Monitor ASIC/IC", NULL }, - - { 0x27, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "LAN", "Heartbeat Lost" }, - { 0x27, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "LAN", "Heartbeat" }, - - { 0x28, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "Sensor access degraded or unavailable" }, - { 0x28, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "Controller access degraded or unavailable" }, - { 0x28, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "Management controller off-line" }, - { 0x28, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "Management controller unavailable" }, - { 0x28, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "Sensor failure" }, - { 0x28, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Management Subsystem Health", "FRU failure" }, - - { 0x29, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Battery", "Low" }, - { 0x29, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Battery", "Failed" }, - { 0x29, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Battery", "Presence Detected" }, - - { 0x2b, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Hardware change detected" }, - { 0x2b, 0x01, 0x00, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected" }, - { 0x2b, 0x01, 0x01, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt Ctrl Dev Id" }, - { 0x2b, 0x01, 0x02, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt Ctrl Firm Rev" }, - { 0x2b, 0x01, 0x03, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt Ctrl Dev Rev" }, - { 0x2b, 0x01, 0x04, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt Ctrl Manuf Id" }, - { 0x2b, 0x01, 0x05, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt Ctrl IPMI Vers" }, - { 0x2b, 0x01, 0x06, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt Ctrl Aux Firm Id" }, - { 0x2b, 0x01, 0x07, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt Ctrl Firm Boot Block" }, - { 0x2b, 0x01, 0x08, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt Ctrl Other" }, - { 0x2b, 0x01, 0x09, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, BIOS/EFI change" }, - { 0x2b, 0x01, 0x0A, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, SMBIOS change" }, - { 0x2b, 0x01, 0x0B, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, O/S change" }, - { 0x2b, 0x01, 0x0C, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, O/S loader change" }, - { 0x2b, 0x01, 0x0D, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Service Diag change" }, - { 0x2b, 0x01, 0x0E, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt SW agent change" }, - { 0x2b, 0x01, 0x0F, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt SW App change" }, - { 0x2b, 0x01, 0x10, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Mngmt SW Middle" }, - { 0x2b, 0x01, 0x11, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, Prog HW Change (FPGA)" }, - { 0x2b, 0x01, 0x12, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, board/FRU module change" }, - { 0x2b, 0x01, 0x13, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, board/FRU component change" }, - { 0x2b, 0x01, 0x14, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, board/FRU replace equ ver" }, - { 0x2b, 0x01, 0x15, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, board/FRU replace new ver" }, - { 0x2b, 0x01, 0x16, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, board/FRU replace old ver" }, - { 0x2b, 0x01, 0x17, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change detected, board/FRU HW conf change" }, - { 0x2b, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Hardware incompatibility detected" }, - { 0x2b, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software incompatibility detected" }, - { 0x2b, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Invalid or unsupported hardware version" }, - { 0x2b, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Invalid or unsupported firmware or software version" }, - { 0x2b, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Hardware change success" }, - { 0x2b, 0x07, 0x00, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success" }, - { 0x2b, 0x07, 0x01, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt Ctrl Dev Id" }, - { 0x2b, 0x07, 0x02, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt Ctrl Firm Rev" }, - { 0x2b, 0x07, 0x03, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt Ctrl Dev Rev" }, - { 0x2b, 0x07, 0x04, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt Ctrl Manuf Id" }, - { 0x2b, 0x07, 0x05, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt Ctrl IPMI Vers" }, - { 0x2b, 0x07, 0x06, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt Ctrl Aux Firm Id" }, - { 0x2b, 0x07, 0x07, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt Ctrl Firm Boot Block" }, - { 0x2b, 0x07, 0x08, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt Ctrl Other" }, - { 0x2b, 0x07, 0x09, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, BIOS/EFI change" }, - { 0x2b, 0x07, 0x0A, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, SMBIOS change" }, - { 0x2b, 0x07, 0x0B, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, O/S change" }, - { 0x2b, 0x07, 0x0C, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, O/S loader change" }, - { 0x2b, 0x07, 0x0D, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Service Diag change" }, - { 0x2b, 0x07, 0x0E, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt SW agent change" }, - { 0x2b, 0x07, 0x0F, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt SW App change" }, - { 0x2b, 0x07, 0x10, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Mngmt SW Middle" }, - { 0x2b, 0x07, 0x11, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, Prog HW Change (FPGA)" }, - { 0x2b, 0x07, 0x12, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, board/FRU module change" }, - { 0x2b, 0x07, 0x13, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, board/FRU component change" }, - { 0x2b, 0x07, 0x14, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, board/FRU replace equ ver" }, - { 0x2b, 0x07, 0x15, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, board/FRU replace new ver" }, - { 0x2b, 0x07, 0x16, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, board/FRU replace old ver" }, - { 0x2b, 0x07, 0x17, IPMI_EVENT_CLASS_DISCRETE, "Version Change", "Firmware or software change success, board/FRU HW conf change" }, - - { 0x2c, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Not Installed" }, - { 0x2c, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Inactive" }, - { 0x2c, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Activation Requested" }, - { 0x2c, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Activation in Progress" }, - { 0x2c, 0x04, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Active" }, - { 0x2c, 0x05, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Deactivation Requested" }, - { 0x2c, 0x06, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Deactivation in Progress" }, - { 0x2c, 0x07, 0xff, IPMI_EVENT_CLASS_DISCRETE, "FRU State", "Communication lost" }, - - { 0xF0, 0x00, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M0" }, - { 0xF0, 0x01, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M1" }, - { 0xF0, 0x02, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M2" }, - { 0xF0, 0x03, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M3" }, - { 0xF0, 0x04, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M4" }, - { 0xF0, 0x05, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M5" }, - { 0xF0, 0x06, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M6" }, - { 0xF0, 0x07, 0xFF, IPMI_EVENT_CLASS_DISCRETE, "FRU Hot Swap", "Transition to M7" }, - - { 0xF1, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "IPMB-0 Status", "IPMB-A disabled, IPMB-B disabled" }, - { 0xF1, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "IPMB-0 Status", "IPMB-A enabled, IPMB-B disabled" }, - { 0xF1, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "IPMB-0 Status", "IPMB-A disabled, IPMB-B enabled" }, - { 0xF1, 0x03, 0xff, IPMI_EVENT_CLASS_DISCRETE, "IPMB-0 Status", "IPMB-A enabled, IPMP-B enabled" }, - - { 0xF2, 0x00, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Module Hot Swap", "Module Handle Closed" }, - { 0xF2, 0x01, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Module Hot Swap", "Module Handle Opened" }, - { 0xF2, 0x02, 0xff, IPMI_EVENT_CLASS_DISCRETE, "Module Hot Swap", "Quiesced" }, - - { 0xC0, 0x00, 0xff, 0x00, "OEM", "OEM Specific" }, +static const struct ipmi_event_sensor_types vita_sensor_event_types[] = { + /* VITA FRU State */ + { 0xF0, 0x00, 0xFF, "Transition to M0" }, + { 0xF0, 0x01, 0xFF, "Transition to M1" }, + { 0xF0, 0x04, 0xFF, "Transition to M4" }, + { 0xF0, 0x05, 0xFF, "Transition to M5" }, + { 0xF0, 0x06, 0xFF, "Transition to M6" }, + { 0xF0, 0x07, 0xFF, "Transition to M7" }, + /* VITA System IPMB Link */ + { 0xF1, 0x00, 0xFF, "IPMB-A disabled, IPMB-B disabled" }, + { 0xF1, 0x01, 0xFF, "IPMB-A enabled, IPMB-B disabled" }, + { 0xF1, 0x02, 0xFF, "IPMB-A disabled, IPMB-B enabled" }, + { 0xF1, 0x03, 0xFF, "IPMB-A enabled, IPMP-B enabled" }, + /* VITA FRU Temperature */ + { 0xF3, 0x00, 0xff, "At or below Lower Non-critical" }, + { 0xF3, 0x01, 0xff, "At or below Lower Critical" }, + { 0xF3, 0x02, 0xff, "At or below Lower Non-recoverable" }, + { 0xF3, 0x03, 0xff, "At or above Upper Non-critical" }, + { 0xF3, 0x04, 0xff, "At or above Upper Critical" }, + { 0xF3, 0x05, 0xff, "At or above Upper Non-recoverable" }, + { 0x00, 0x00, 0xff, NULL } +}; - { 0x00, 0x00, 0x00, 0x00, NULL, NULL }, +static const struct ipmi_event_sensor_types oem_kontron_event_types[] = { + /* Board Reset(cPCI) */ + { 0xC1, 0x00, 0xff, "Push Button" }, + { 0xC1, 0x01, 0xff, "Bridge Reset" }, + { 0xC1, 0x02, 0xff, "Backplane" }, + { 0xC1, 0x03, 0xff, "Hotswap Fault" }, + { 0xC1, 0x04, 0xff, "Hotswap Healty" }, + { 0xC1, 0x05, 0xff, "Unknown" }, + { 0xC1, 0x06, 0xff, "ITP" }, + { 0xC1, 0x07, 0xff, "Hardware Watchdog" }, + { 0xC1, 0x08, 0xff, "Software Reset" }, + /* IPMB-L Link State, based on PICMG IPMB-0 Link state sensor */ + { 0xC3, 0x02, 0xff, "IPMB L Disabled" }, + { 0xC3, 0x03, 0xff, "IPMB L Enabled" }, + /* Board Reset */ + { 0xC4, 0x00, 0xff, "Push Button" }, + { 0xC4, 0x01, 0xff, "Hardware Power Failure" }, + { 0xC4, 0x02, 0xff, "Unknown" }, + { 0xC4, 0x03, 0xff, "Hardware Watchdog" }, + { 0xC4, 0x04, 0xff, "Soft Reset" }, + { 0xC4, 0x05, 0xff, "Warm Reset" }, + { 0xC4, 0x06, 0xff, "Cold Reset" }, + { 0xC4, 0x07, 0xff, "IPMI Command" }, + { 0xC4, 0x08, 0xff, "Setup Reset (Save CMOS)" }, + { 0xC4, 0x09, 0xff, "Power Up Reset" }, + /* POST Value */ + { 0xC6, 0x0E, 0xff, "Post Error (see data2)" }, + /* FWUM Status */ + { 0xC7, 0x00, 0xff, "First Boot After Upgrade" }, + { 0xC7, 0x01, 0xff, "First Boot After Rollback(error)" }, + { 0xC7, 0x02, 0xff, "First Boot After Errors (watchdog)" }, + { 0xC7, 0x03, 0xff, "First Boot After Manual Rollback" }, + { 0xC7, 0x08, 0xff, "Firmware Watchdog Bite, reset occurred" }, + /* Switch Mngt Software Status */ + { 0xC8, 0x00, 0xff, "Not Loaded" }, + { 0xC8, 0x01, 0xff, "Initializing" }, + { 0xC8, 0x02, 0xff, "Ready" }, + { 0xC8, 0x03, 0xff, "Failure (see data2)" }, + /* Diagnostic Status */ + { 0xC9, 0x00, 0xff, "Started" }, + { 0xC9, 0x01, 0xff, "Pass" }, + { 0xC9, 0x02, 0xff, "Fail" }, + { 0xCA, 0x00, 0xff, "In progress"}, + { 0xCA, 0x01, 0xff, "Success"}, + { 0xCA, 0x02, 0xff, "Failure"}, + /* FRU Over Current */ + { 0xCB, 0x00, 0xff, "Asserted"}, + { 0xCB, 0x01, 0xff, "Deasserted"}, + /* FRU Sensor Error */ + { 0xCC, 0x00, 0xff, "Asserted"}, + { 0xCC, 0x01, 0xff, "Deasserted"}, + /* FRU Power Denied */ + { 0xCD, 0x00, 0xff, "Asserted"}, + { 0xCD, 0x01, 0xff, "Deasserted"}, + /* Reset */ + { 0xCF, 0x00, 0xff, "Asserted"}, + { 0xCF, 0x01, 0xff, "Deasserted"}, + /* END */ + { 0x00, 0x00, 0xff, NULL }, }; int ipmi_sel_main(struct ipmi_intf *, int, char **); @@ -695,12 +677,15 @@ void ipmi_sel_print_std_entry_verbose(struct ipmi_intf * intf, struct sel_event_ void ipmi_sel_print_extended_entry(struct ipmi_intf * intf, struct sel_event_record * evt); void ipmi_sel_print_extended_entry_verbose(struct ipmi_intf * intf, struct sel_event_record * evt); void ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char ** desc); -const char * ipmi_sel_get_sensor_type(uint8_t code); -const char * ipmi_sel_get_sensor_type_offset(uint8_t code, uint8_t offset); +const char * ipmi_get_sensor_type(struct ipmi_intf *intf, uint8_t code); uint16_t ipmi_sel_get_std_entry(struct ipmi_intf * intf, uint16_t id, struct sel_event_record * evt); char * get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec); IPMI_OEM ipmi_get_oem(struct ipmi_intf * intf); char * ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec); int ipmi_sel_oem_init(const char * filename); +const struct ipmi_event_sensor_types * +ipmi_get_first_event_sensor_type(struct ipmi_intf *intf, uint8_t sensor_type, uint8_t event_type); +const struct ipmi_event_sensor_types * +ipmi_get_next_event_sensor_type(const struct ipmi_event_sensor_types *evt); #endif /* IPMI_SEL_H */ diff --git a/include/ipmitool/ipmi_sel_supermicro.h b/include/ipmitool/ipmi_sel_supermicro.h index a058a8c..98960e6 100644 --- a/include/ipmitool/ipmi_sel_supermicro.h +++ b/include/ipmitool/ipmi_sel_supermicro.h @@ -34,6 +34,37 @@ #ifndef IPMI_SEL_SUPERMICRO_H # define IPMI_SEL_SUPERMICRO_H +static uint16_t supermicro_x11[] = { + 0x0958, 0x0955, 0x0953, 0x0952, 0x0941, 0x093A, 0x0939, 0x0938, 0x0937, 0x0930, 0x0927, 0x091D, + 0x091C, 0x0917, 0x090D, 0x0909, 0x0907, 0x0901, 0x089F, 0x089C, 0x089B, 0x089A, 0x0898, 0x0896, + 0x0895, 0x0894, 0x0891, 0x0890, 0x0888, 0x0886, 0x0885, 0x0884, 0xFFFF +}; + +static uint16_t supermicro_b11[] = { + 0xFFFF +}; + +static uint16_t supermicro_b2[] = { + 0x0951, 0x094E, 0x0931, 0x092E, 0x092A, 0x0928, 0x0908, 0xFFFF +}; + +static uint16_t supermicro_x10OBi[] = { + 0x0923, 0xFFFF +}; + +static uint16_t supermicro_x10QRH[] = { + 0x0872, 0xFFFF +}; + +static uint16_t supermicro_x10QBL[] = { + 0x0853, 0xFFFF +}; + +static uint16_t supermicro_brickland[] = { + 0x0726, 0x083A, 0xFFFF +}; + + static uint16_t supermicro_x9dal[] = { 0x0635, 0xFFFF }; @@ -50,38 +81,75 @@ static uint16_t supermicro_x9[] = { 0x0635, 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637, 0x0651, 0xFFFF }; +static uint16_t supermicro_romely[] = { + 0x0841, 0x0732, 0x0731, 0x0730, 0x0727, 0x0725, 0x0724, 0x0723, 0x0720, 0x0718, 0x0717, 0x0715, + 0x0713, 0x0711, 0x070E, 0x070A, 0x0709, 0x0708, 0x0706, 0x0705, 0x0704, 0x0702, 0x0701, 0x0700, + 0x066F, 0x066E, 0x066D, 0x0669, 0x0667, 0x0666, 0x0665, 0x0664, 0x0662, 0x0660, 0x0636, 0x0630, + 0x062F, 0x062C, 0x0628, 0x0626, 0x0827, 0x070F, 0x0707, 0x0840, 0x0729, 0x0719, 0x0712, 0x070D, + 0x066C, 0x066A, 0x0625, 0x0714, 0x0710, 0x070C, 0x070B, 0x0668, 0x0663, 0x0661, 0x062B, 0x062A, + 0x0629, 0x093E, 0x0932, 0x092D, 0x092B, 0x0924, 0x0922, 0x0921, 0x091E, 0x0919, 0x0916, 0x089D, + 0x0899, 0x0893, 0x0892, 0x0882, 0x0881, 0x0880, 0x087F, 0x087D, 0x0879, 0x0877, 0x086F, 0x086E, + 0x086D, 0x086C, 0x086B, 0x085C, 0x085B, 0x084B, 0x0865, 0x0864, 0x0860, 0x0859, 0x0858, 0x0857, + 0x0854, 0x0852, 0x0845, 0x0844, 0x0843, 0x0842, 0x083B, 0x0838, 0x0837, 0x0836, 0x0835, 0x0834, + 0x0833, 0x0832, 0x0831, 0x0830, 0x0826, 0x0825, 0x0824, 0x0822, 0x0821, 0x0819, 0x0818, 0x0817, + 0x0816, 0x0815, 0x0814, 0x0728, 0x0813, 0x0812, 0x0810, 0x0807, 0x0806, 0x0805, 0x0804, 0x0803, + 0x0802, 0x0801, 0x0889, 0x0861, 0x083E, 0x0846, 0x0946, 0x0950, 0xFFFF +}; + static uint16_t supermicro_b8[] = { 0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e, 0xFFFF }; static uint16_t supermicro_h8[] = { 0xa111, 0x0408, 0x0811, 0x1411, 0x0911, 0x1211, 0x1011, 0xcd11, 0x1111, 0xbe11, 0xce11, 0xbd11, - 0xbc11, 0xa911, 0xaa11, 0xbd11, 0xcb11, 0xad11, 0xa811, 0xac11, 0xaf11, 0xa511, 0xa011, 0x1611, - 0x2511, 0xbf11, 0x1511, 0x2211, 0x2411, 0x1911, 0xab11, 0xd011, 0xae11, 0xca11, 0x0409, 0xa211, - 0xa311, 0x1311, 0xba11, 0xa711, 0xd111, 0x1711, 0xcf11, 0x2011, 0x1811, 0xFFFF + 0xbc11, 0xa911, 0xaa11, 0xcb11, 0xad11, 0xa811, 0xac11, 0xaf11, 0xa511, 0xa011, 0x1611, 0x2511, + 0xbf11, 0x1511, 0x2211, 0x2411, 0x1911, 0xab11, 0xd011, 0xae11, 0xca11, 0x0409, 0xa211, 0xa311, + 0x1311, 0xba11, 0xa711, 0xd111, 0x1711, 0xcf11, 0x2011, 0x1811, 0xFFFF }; static uint16_t supermicro_p8[] = { - 0x6480, 0x7380, 0x6280, 0x7480, 0x5980, 0xFFFF + 0x5980, 0x6280, 0x6480, 0x7380, 0x7480, 0x0933, 0x094F, 0xFFFF }; static uint16_t supermicro_x8[] = { 0xa880, 0x0403, 0x0100, 0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006, 0x040a, 0xf280, 0x060f, 0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614, - 0x060c, 0x0003, 0x040b, 0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e, - 0x061a, 0xf580, 0x062e, 0x0009, 0xFFFF + 0x0003, 0x040b, 0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e, 0x061a, + 0xf580, 0x062e, 0x0009, 0xFFFF }; static uint16_t supermicro_X8[] = { 0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e, 0xa111, 0x0408, 0x0811, 0x1411, 0x0911, - 0x1211, 0x1011, 0xcd11, 0x1111, 0xbe11, 0xce11, 0xbd11, 0xbc11, 0xa911, 0xaa11, 0xbd11, 0xcb11, - 0xad11, 0xa811, 0xac11, 0xaf11, 0xa511, 0xa011, 0x1611, 0x2511, 0xbf11, 0x1511, 0x2211, 0x2411, - 0x1911, 0xab11, 0xd011, 0xae11, 0xca11, 0x0409, 0xa211, 0xa311, 0x1311, 0xba11, 0xa711, 0xd111, - 0x1711, 0xcf11, 0x2011, 0x1811, 0x6480, 0x7380, 0x6280, 0x7480, 0x5980, 0xa880, 0x0403, 0x0100, - 0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006, 0x040a, 0xf280, 0x060f, - 0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614, 0x060c, 0x0003, 0x040b, - 0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e, 0x061a, 0xf580, 0x062e, + 0x1211, 0x1011, 0xcd11, 0x1111, 0xbe11, 0xce11, 0xbd11, 0xbc11, 0xa911, 0xaa11, 0xcb11, 0xad11, + 0xa811, 0xac11, 0xaf11, 0xa511, 0xa011, 0x1611, 0x2511, 0xbf11, 0x1511, 0x2211, 0x2411, 0x1911, + 0xab11, 0xd011, 0xae11, 0xca11, 0x0409, 0xa211, 0xa311, 0x1311, 0xba11, 0xa711, 0xd111, 0x1711, + 0xcf11, 0x2011, 0x1811, 0x5980, 0x6280, 0x6480, 0x7380, 0x7480, 0x0933, 0x094F, 0xa880, 0x0403, + 0x0100, 0x0601, 0x0001, 0x0404, 0x0606, 0x0608, 0x0632, 0x0400, 0x0401, 0x0006, 0x040a, 0xf280, + 0x060f, 0x0609, 0x0008, 0x0613, 0x061b, 0x0007, 0x0600, 0x060c, 0x060d, 0x0614, 0x0003, 0x040b, + 0x0621, 0x0610, 0x0638, 0xf380, 0x060b, 0x040d, 0x0605, 0x062d, 0x060e, 0x061a, 0xf580, 0x062e, 0x0009, 0xFFFF }; +static uint16_t supermicro_older[] = { + 0x8080, 0x8180, 0x8280, 0x8480, 0x8580, 0x8680, 0x8780, 0x8880, 0x8980, 0x9080, 0x9180, 0x9280, + 0x9380, 0x9480, 0x9580, 0x9680, 0x9780, 0xA080, 0x9880, 0x9980, 0xB080, 0xB180, 0xB280, 0xB380, + 0xB480, 0xA280, 0xB580, 0xB680, 0xA580, 0xB780, 0xD180, 0xA380, 0xA480, 0xD680, 0xBA80, 0xD280, + 0x2111, 0xD380, 0xBC80, 0xBD80, 0xBE80, 0xC080, 0xC180, 0xAA80, 0xBE80, 0xBF80, 0xAB80, 0xD480, + 0xD580, 0xAF80, 0xAE80, 0xC280, 0xAC80, 0xD080, 0xDA80, 0xDB80, 0xDC80, 0xDD80, 0xA680, 0xDE80, + 0xAA80, 0xDF80, 0xBB80, 0xA780, 0xF080, 0xF180, 0xB880, 0xC380, 0xB780, 0x2311, 0xA980, 0xF480, + 0xB980, 0x0002, 0xba80, 0x0602, 0x0603, 0x0604, 0x0607, 0x0410, 0xA611, 0x060A, 0x0611, 0xBB11, + 0x061D, 0x0622, 0x0623, 0x0624, 0x0627, 0x0631, 0x0633, 0x0634, 0x0690, 0x0691, 0x0640, 0x0641, + 0x0642, 0x066B, 0x0743, 0x0644, 0x0645, 0x0645, 0x0646, 0x0647, 0x0648, 0x0647, 0x0650, 0x0652, + 0x0653, 0x0654, 0x0655, 0x0808, 0x0809, 0x0656, 0x0657, 0x0658, 0x0659, 0x0820, 0x0820, 0x0734, + 0x0823, 0x0828, 0x0829, 0x0839, 0x083C, 0x083D, 0x083F, 0x0847, 0x0848, 0x0849, 0x0850, 0x0851, + 0x0855, 0x0856, 0x0862, 0x0863, 0x0866, 0x0867, 0x0868, 0x0869, 0x084A, 0x084C, 0x084D, 0x084F, + 0x085A, 0x085D, 0x085E, 0x085F, 0x086A, 0x0870, 0x0873, 0x0874, 0x0875, 0x0876, 0x0878, 0x087A, + 0x087B, 0x087C, 0x087E, 0x0883, 0x0887, 0x088A, 0x088B, 0x088C, 0x088D, 0x088E, 0x088F, 0x0897, + 0x089E, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x090A, 0x090B, 0x090C, 0x090E, 0x090F, 0x0910, + 0x0912, 0x0913, 0x0914, 0x0915, 0x0918, 0x091A, 0x091B, 0x091F, 0x0920, 0x0925, 0x0926, 0x0929, + 0x092C, 0x092F, 0x0934, 0x0935, 0x0936, 0x093B, 0x093C, 0x093D, 0x093F, 0x0940, 0x0942, 0x0943, + 0x0944, 0x0945, 0x0947, 0x0948, 0x0949, 0x094A, 0x094B, 0x094C, 0x094D, 0x094E, 0x0954, 0x0956, + 0x0957, 0x0959, 0xFFFF +}; + #endif /* IPMI_SEL_SUPERMICRO_H */ diff --git a/include/ipmitool/ipmi_strings.h b/include/ipmitool/ipmi_strings.h index 10ec430..63bbea9 100644 --- a/include/ipmitool/ipmi_strings.h +++ b/include/ipmitool/ipmi_strings.h @@ -52,6 +52,7 @@ extern const struct valstr ipmi_auth_algorithms[]; extern const struct valstr ipmi_integrity_algorithms[]; extern const struct valstr ipmi_encryption_algorithms[]; extern const struct valstr ipmi_oem_info[]; +extern const struct valstr ipmi_user_enable_status_vals[]; extern const struct valstr picmg_frucontrol_vals[]; extern const struct valstr picmg_clk_family_vals[]; @@ -68,8 +69,7 @@ extern const struct oemvalstr picmg_busres_shmc_status_vals[]; /* these are similar, expect that the lookup takes the IANA number as first parameter */ extern const struct oemvalstr ipmi_oem_product_info[]; -extern const struct oemvalstr ipmi_oem_sdr_type_vals[]; - - +extern const char *ipmi_generic_sensor_type_vals[]; +extern const struct oemvalstr ipmi_oem_sensor_type_vals[]; #endif /*IPMI_STRINGS_H*/ diff --git a/ipmitool.spec b/ipmitool.spec index fbdd549..bbc7c49 100644 --- a/ipmitool.spec +++ b/ipmitool.spec @@ -1,6 +1,6 @@ Name: ipmitool Summary: ipmitool - Utility for IPMI control -Version: 1.8.17 +Version: 1.8.18 Release: 1%{?_distro:.%{_distro}} License: BSD Group: Utilities diff --git a/lib/Makefile.am b/lib/Makefile.am index 359cb30..cc69a8f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -41,6 +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 libipmitool_la_LDFLAGS = -export-dynamic diff --git a/lib/Makefile.in b/lib/Makefile.in index ccb468f..0e2b6b2 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -131,7 +131,8 @@ am_libipmitool_la_OBJECTS = helper.lo ipmi_sdr.lo ipmi_sel.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 ../src/plugins/lan/md5.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@) @@ -362,6 +363,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 libipmitool_la_LDFLAGS = -export-dynamic @@ -436,6 +438,7 @@ distclean-compile: @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@ @@ -451,6 +454,7 @@ distclean-compile: @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@ diff --git a/lib/dimm_spd.c b/lib/dimm_spd.c index 8b6927c..41e30db 100644 --- a/lib/dimm_spd.c +++ b/lib/dimm_spd.c @@ -1340,11 +1340,10 @@ ipmi_spd_print(uint8_t *spd_data, int len) printf(" Memory Type : %s\n", val2str(spd_data[2], spd_memtype_vals)); - + if (spd_data[2] == 0x0B) /* DDR3 SDRAM */ { int iPN; - char *pchPN = spd_data+128; int sdram_cap = 0; int pri_bus_width = 0; int sdram_width = 0; @@ -1353,7 +1352,7 @@ ipmi_spd_print(uint8_t *spd_data, int len) if (len < 148) return -1; /* we need first 91 bytes to do our thing */ - + sdram_cap = ldexp(256,(spd_data[4]&15)); pri_bus_width = ldexp(8,(spd_data[8]&7)); @@ -1366,7 +1365,7 @@ ipmi_spd_print(uint8_t *spd_data, int len) printf(" SDRAM Device Width : %d bits\n", sdram_width ); printf(" Number of Ranks : %d\n", ranks ); printf(" Memory size : %d MB\n", mem_size ); - + /* printf(" Memory Density : %s\n", val2str(spd_data[4]&15, ddr3_density_vals)); */ printf(" 1.5 V Nominal Op : %s\n", (((spd_data[6]&1) != 0) ? "No":"Yes" ) ); printf(" 1.35 V Nominal Op : %s\n", (((spd_data[6]&2) != 0) ? "No":"Yes" ) ); @@ -1417,16 +1416,15 @@ ipmi_spd_print(uint8_t *spd_data, int len) } - printf(" Manufacture Date : year %c%c week %c%c\n", + printf(" Manufacture Date : year %c%c week %c%c\n", '0'+(spd_data[120]>>4), '0'+(spd_data[120]&15), '0'+(spd_data[121]>>4), '0'+(spd_data[121]&15) ); - + printf(" Serial Number : %02x%02x%02x%02x\n", spd_data[122], spd_data[123], spd_data[124], spd_data[125]); - + printf(" Part Number : "); - for (iPN=0; iPN < 19; iPN++) - { - printf( "%c", *pchPN++ ); + for (iPN = 128; iPN < 146; iPN++) { + printf("%c", spd_data[iPN]); } printf("\n"); } else if (spd_data[2] == 0x0C) /* DDR4 SDRAM */ @@ -1552,7 +1550,7 @@ ipmi_spd_print(uint8_t *spd_data, int len) val2str(spd_data[8], spd_voltage_vals)); printf(" Error Detect/Cor : %s\n", val2str(spd_data[11], spd_config_vals)); - + /* handle jedec table bank continuation values */ printf(" Manufacturer : "); if (spd_data[64] != 0x7f) @@ -1603,7 +1601,7 @@ ipmi_spd_print(uint8_t *spd_data, int len) part[18] = 0; printf(" Part Number : %s\n", part); } - + printf(" Serial Number : %02x%02x%02x%02x\n", spd_data[95], spd_data[96], spd_data[97], spd_data[98]); } diff --git a/lib/helper.c b/lib/helper.c index 022a9c9..de91438 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -51,6 +51,7 @@ #include <fcntl.h> #include <errno.h> #include <assert.h> +#include <ctype.h> #if HAVE_CONFIG_H # include <config.h> @@ -79,22 +80,139 @@ uint16_t buf2short(uint8_t * buf) return (uint16_t)(buf[1] << 8 | buf[0]); } -const char * buf2str(uint8_t * buf, int len) +/* buf2str_extended - convert sequence of bytes to hexadecimal string with + * optional separator + * + * @param buf - data to convert + * @param len - size of data + * @param sep - optional separator (can be NULL) + * + * @returns buf representation in hex, possibly truncated to fit + * allocated static memory + */ +const char * +buf2str_extended(const uint8_t *buf, int len, const char *sep) { - static char str[2049]; + static char str[BUF2STR_MAXIMUM_OUTPUT_SIZE]; + char *cur; int i; + int sz; + int left; + int sep_len; - if (len <= 0 || len > 1024) - return NULL; + if (buf == NULL) { + snprintf(str, sizeof(str), "<NULL>"); + return (const char *)str; + } + cur = str; + left = sizeof(str); + if (sep) { + sep_len = strlen(sep); + } else { + sep_len = 0; + } + for (i = 0; i < len; i++) { + /* may return more than 2, depending on locale */ + sz = snprintf(cur, left, "%2.2x", buf[i]); + if (sz >= left) { + /* buffer overflow, truncate */ + break; + } + cur += sz; + left -= sz; + /* do not write separator after last byte */ + if (sep && i != (len - 1)) { + if (sep_len >= left) { + break; + } + strncpy(cur, sep, left - sz); + cur += sep_len; + left -= sep_len; + } + } + *cur = '\0'; - memset(str, 0, 2049); + return (const char *)str; +} - for (i=0; i<len; i++) - sprintf(str+i+i, "%2.2x", buf[i]); +const char * +buf2str(const uint8_t *buf, int len) +{ + return buf2str_extended(buf, len, NULL); +} - str[len*2] = '\0'; +/* ipmi_parse_hex - convert hexadecimal numbers to ascii string + * Input string must be composed of two-characer + * hexadecimal numbers. + * There is no separator between the numbers. Each number + * results in one byte of the converted string. + * + * Example: ipmi_parse_hex("50415353574F5244") + * returns 'PASSWORD' + * + * @param str: input string. It must contain only even number + * of '0'-'9','a'-'f' and 'A-F' characters. + * @param out: pointer to output data + * @param size: size of the output buffer + * @returns 0 for empty input string + * -1 for string with odd length + * -2 if out is NULL + * -3 if there is non-hexadecimal char in string + * >0 length of resulting binary data even if it is > size + */ +int +ipmi_parse_hex(const char *str, uint8_t *out, int size) +{ + const char *p; + uint8_t *q; + uint8_t d = 0; + uint8_t b = 0; + int shift = 4; + int len; + + len = strlen(str); + if (len == 0) { + return 0; + } - return (const char *)str; + if (len % 2 != 0) { + return -1; + } + + len /= 2; /* out bytes */ + if (out == NULL) { + return -2; + } + + for (p = str, q = out; *p; p++) { + if (!isxdigit(*p)) { + return -3; + } + + if (*p < 'A') { + /* it must be 0-9 */ + d = *p - '0'; + } else { + /* it's A-F or a-f */ + /* convert to lowercase and to 10-15 */ + d = (*p | 0x20) - 'a' + 10; + } + + if (q < (out + size)) { + /* there is space, store */ + b += d << shift; + if (shift) { + shift = 0; + } else { + shift = 4; + *q = b; + b = 0; + q++; + } + } + } + + return len; } void printbuf(const uint8_t * buf, int len, const char * desc) @@ -116,6 +234,53 @@ void printbuf(const uint8_t * buf, int len, const char * desc) fprintf(stderr, "\n"); } +/* str2mac - parse-out MAC address from given string and store it + * into buffer. + * + * @arg: string to be parsed. + * @buf: buffer of 6 to hold parsed MAC address. + * + * returns zero on success, (-1) on error and error message is printed-out. + */ +int +str2mac(const char *arg, uint8_t *buf) +{ + unsigned int m1 = 0; + unsigned int m2 = 0; + unsigned int m3 = 0; + unsigned int m4 = 0; + unsigned int m5 = 0; + unsigned int m6 = 0; + if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x", + &m1, &m2, &m3, &m4, &m5, &m6) != 6) { + lprintf(LOG_ERR, "Invalid MAC address: %s", arg); + return -1; + } + if (m1 > UINT8_MAX || m2 > UINT8_MAX + || m3 > UINT8_MAX || m4 > UINT8_MAX + || m5 > UINT8_MAX || m6 > UINT8_MAX) { + lprintf(LOG_ERR, "Invalid MAC address: %s", arg); + return -1; + } + buf[0] = (uint8_t)m1; + buf[1] = (uint8_t)m2; + buf[2] = (uint8_t)m3; + buf[3] = (uint8_t)m4; + buf[4] = (uint8_t)m5; + buf[5] = (uint8_t)m6; + return 0; +} + +/* mac2str -- return MAC address as a string + * + * @buf: buffer of 6 to hold parsed MAC address. + */ +const char * +mac2str(const uint8_t *buf) +{ + return buf2str_extended(buf, 6, ":"); +} + const char * val2str(uint16_t val, const struct valstr *vs) { static char un_str[32]; diff --git a/lib/ipmi_cfgp.c b/lib/ipmi_cfgp.c new file mode 100644 index 0000000..b8af80d --- /dev/null +++ b/lib/ipmi_cfgp.c @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2016 Pentair Technical Products. All right reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Pentair Technical Products 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * PENTAIR TECHNICAL SOLUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <malloc.h> +#include <string.h> + +#include <ipmitool/helper.h> +#include <ipmitool/ipmi_cfgp.h> +#include <ipmitool/log.h> + +/* ipmi_cfgp_init initialize configuration parameter context + * @param ctx context to initialize + * @param set array of parameter descriptors + * @param count amount of descriptors supplied + * @param handler function to do real job on parameters from the set + * @param priv private data for the handler + */ +int +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) { + return -1; + } + + memset(ctx, 0, sizeof(struct ipmi_cfgp_ctx)); + + ctx->set = set; + ctx->count = count; + ctx->cmdname = cmdname; + ctx->handler = handler; + ctx->priv = priv; + + return 0; +} + +/* ipmi_cfgp_uninit destroy data list attached to context + * @param ctx parameter context to clear + * @returns 0 -- list destroyed + * -1 -- ctx is NULL + */ +int +ipmi_cfgp_uninit(struct ipmi_cfgp_ctx *ctx) +{ + struct ipmi_cfgp_data *d; + + if (ctx == NULL) { + return -1; + } + + while (ctx->v) { + d = ctx->v; + ctx->v = d->next; + free(d); + d = NULL; + } + + return 0; +} + +/* lookup_cfgp -- find a parameter in a set*/ +static const struct ipmi_cfgp * +lookup_cfgp(const struct ipmi_cfgp_ctx *ctx, const char *name) +{ + const struct ipmi_cfgp *p; + int i; + + for (i = 0; i < ctx->count; i++) { + p = &ctx->set[i]; + + if (p->name && !strcasecmp(p->name, name)) { + return p; + } + } + + return NULL; +} + +/* ipmi_cfgp_parse_sel parse parameter selector + * (parameter ID, set selector, block selector) from cmdline. + * + * @param ctx configuration parameter context to use + * @param argc elements left in argv + * @param argv array of arguments + * @param sel where to store parsed selector + * + * @returns >=0 number of argv elements used + * <0 error + */ +int +ipmi_cfgp_parse_sel(struct ipmi_cfgp_ctx *ctx, + int argc, const char **argv, struct ipmi_cfgp_sel *sel) +{ + const struct ipmi_cfgp *p; + + if (ctx == NULL || argv == NULL || sel == NULL) { + return -1; + } + + sel->param = -1; + sel->set = -1; + sel->block = -1; + + if (argc == 0) { + /* no parameter specified, good for print, save */ + return 0; + } + + p = lookup_cfgp(ctx, argv[0]); + if (p == NULL) { + lprintf(LOG_ERR, "invalid parameter"); + return -1; + } + + sel->param = p - ctx->set; + sel->set = p->is_set ? -1 : 0; + sel->block = p->has_blocks ? -1 : 0; + + if (argc == 1 || !p->is_set) { + /* No set and block selector applicable or specified */ + return 1; + } + + if (str2int(argv[1], &sel->set) + || sel->set < 0 + || (sel->set == 0 && p->first_set)) { + lprintf(LOG_ERR, "invalid set selector"); + return -1; + } + + if (argc == 2 || !p->has_blocks) { + /* No block selector applicable or specified */ + return 2; + } + + if (str2int(argv[2], &sel->block) + || sel->block < 0 + || (sel->block == 0 && p->first_block)) { + lprintf(LOG_ERR, "invalid block selector"); + return -1; + } + + return 3; +} + +/* cfgp_add_data adds block of data to list in the configuration + * parameter context + * + * @param ctx context to add data to + * @param data parameter data + */ +static void +cfgp_add_data(struct ipmi_cfgp_ctx *ctx, struct ipmi_cfgp_data *data) +{ + struct ipmi_cfgp_data **pprev = &ctx->v; + + data->next = NULL; + + while (*pprev) { + pprev = &(*pprev)->next; + } + + *pprev = data; +} + +/* cfgp_usage prints format for configuration parameter + * + * @param p configuration parameter descriptor + * @param write 0 if no value is expected, !=0 otherwise + */ +static void +cfgp_usage(const struct ipmi_cfgp *p, int write) +{ + if (p->name == NULL) { + return; + } + + if (write && p->format == NULL) { + return; + } + + printf(" %s%s%s %s\n", + p->name, p->is_set ? " <set_sel>" : "", + p->has_blocks ? " <block_sel>" : "", + write ? p->format : ""); +} + +/* ipmi_cfgp_usage prints format for configuration parameter set + * + * @param set configuration parameter descriptor array + * @param count number of elements in set + * @param write 0 if no value is expected, !=0 otherwise + */ +void +ipmi_cfgp_usage(const struct ipmi_cfgp *set, int count, int write) +{ + const struct ipmi_cfgp *p; + int i; + + if (set == NULL) { + return; + } + + for (i = 0; i < count; i++) { + p = &set[i]; + + if (write && p->access == CFGP_RDONLY) { + continue; + } + + if (!write && p->access == CFGP_WRONLY) { + continue; + } + + cfgp_usage(p, write); + } +} + +/* ipmi_cfgp_parse_data parse parameter data from command line into context + * @param ctx context to add data + * @param sel parameter selector + * @param argc number of elements in argv + * @param argv array of unparsed arguments + * + * @returns 0 on success + * <0 on error + */ +int +ipmi_cfgp_parse_data(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel, int argc, const char **argv) +{ + const struct ipmi_cfgp *p; + struct ipmi_cfgp_data *data; + struct ipmi_cfgp_action action; + + if (ctx == NULL || sel == NULL || argv == NULL) { + return -1; + } + + if (sel->param == -1 || sel->param >= ctx->count) { + lprintf(LOG_ERR, "invalid parameter, must be one of:"); + ipmi_cfgp_usage(ctx->set, ctx->count, 1); + return -1; + } + + if (sel->set == -1) { + lprintf(LOG_ERR, "set selector is not specified"); + return -1; + } + + if (sel->block == -1) { + lprintf(LOG_ERR, "block selector is not specified"); + return -1; + } + + p = &ctx->set[sel->param]; + + if (p->size == 0) { + return -1; + } + + data = malloc(sizeof(struct ipmi_cfgp_data) + p->size); + if (data == NULL) { + return -1; + } + + memset(data, 0, sizeof(struct ipmi_cfgp_data) + p->size); + + action.type = CFGP_PARSE; + action.set = sel->set; + action.block = sel->block; + action.argc = argc; + action.argv = argv; + action.file = NULL; + + if (ctx->handler(ctx->priv, p, &action, data->data) != 0) { + ipmi_cfgp_usage(p, 1, 1); + free(data); + data = NULL; + return -1; + } + + data->sel = *sel; + + cfgp_add_data(ctx, data); + return 0; +} + +/* cfgp_get_param -- get parameter data from MC into data list within context + * + * @param ctx context + * @param p parameter descriptor + * @param set parameter set selector, can be -1 to scan all set selectors + * @param block parameter block selector, can be -1 to get all blocks + * @param quiet set to non-zero to continue on errors + * (required for -1 to work) + * @returns 0 on success, non-zero otherwise + */ +static int +cfgp_get_param(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp *p, + int set, int block, int quiet) +{ + struct ipmi_cfgp_data *data; + struct ipmi_cfgp_action action; + int cset; + int cblock; + int ret; + + if (p->size == 0) { + return -1; + } + + action.type = CFGP_GET; + action.argc = 0; + action.argv = NULL; + action.file = NULL; + + if (set == -1 && !p->is_set) { + set = 0; + } + + if (block == -1 && !p->has_blocks) { + block = 0; + } + + if (set == -1) { + cset = p->first_set; + } else { + cset = set; + } + + action.quiet = quiet; + + do { + if (block == -1) { + cblock = p->first_block; + } else { + cblock = block; + } + + do { + data = malloc(sizeof(struct ipmi_cfgp_data) + p->size); + if (data == NULL) { + return -1; + } + + memset(data, 0, sizeof(struct ipmi_cfgp_data) + p->size); + + action.set = cset; + action.block = cblock; + + ret = ctx->handler(ctx->priv, p, &action, data->data); + if (ret != 0) { + free(data); + data = NULL; + + if (!action.quiet) { + return ret; + } + break; + } + + data->sel.param = p - ctx->set; + data->sel.set = cset; + data->sel.block = cblock; + + cfgp_add_data(ctx, data); + + cblock++; + action.quiet = 1; + } while (block == -1); + + if (ret != 0 && cblock == p->first_block) { + break; + } + + cset++; + } while (set == -1); + + return 0; +} + +/* ipmi_cfgp_get -- get parameters data from MC into data list within context + * + * @param ctx context + * @param sel parameter selector + * @returns 0 on success, non-zero otherwise + */ +int +ipmi_cfgp_get(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp_sel *sel) +{ + int i; + int ret; + + if (ctx == NULL || sel == NULL) { + return -1; + } + + if (sel->param != -1) { + if (sel->param >= ctx->count) { + return -1; + } + + ret = cfgp_get_param(ctx, &ctx->set[sel->param], + sel->set, sel->block, 0); + if (ret) { + return -1; + } + return 0; + } + + for (i = 0; i < ctx->count; i++) { + if (ctx->set[i].access == CFGP_WRONLY) { + continue; + } + + if (cfgp_get_param(ctx, &ctx->set[i], sel->set, sel->block, 1)) { + return -1; + } + } + + return 0; +} + +static int +cfgp_do_action(struct ipmi_cfgp_ctx *ctx, int action_type, + const struct ipmi_cfgp_sel *sel, FILE *file, int filter) +{ + const struct ipmi_cfgp *p; + struct ipmi_cfgp_data *data; + struct ipmi_cfgp_action action; + int ret; + + if (ctx == NULL || sel == NULL) { + return -1; + } + + action.type = action_type; + action.argc = 0; + action.argv = NULL; + action.file = file; + + for (data = ctx->v; data != NULL; data = data->next) { + if (sel->param != -1 && sel->param != data->sel.param) { + continue; + } + if (sel->set != -1 && sel->set != data->sel.set) { + continue; + } + if (sel->block != -1 && sel->block != data->sel.block) { + continue; + } + if (ctx->set[data->sel.param].access == filter) { + continue; + } + + p = &ctx->set[data->sel.param]; + + action.set = data->sel.set; + action.block = data->sel.block; + + if (action_type == CFGP_SAVE) { + fprintf(file, "%s %s ", ctx->cmdname, p->name); + if (p->is_set) { + fprintf(file, "%d ", data->sel.set); + } + if (p->has_blocks) { + fprintf(file, "%d ", data->sel.block); + } + } + + ret = ctx->handler(ctx->priv, p, &action, data->data); + + if (action_type == CFGP_SAVE) { + fputc('\n', file); + } + + if (ret != 0) { + return -1; + } + } + + return 0; +} + +int +ipmi_cfgp_set(struct ipmi_cfgp_ctx *ctx, const struct ipmi_cfgp_sel *sel) +{ + return cfgp_do_action(ctx, CFGP_SET, sel, NULL, CFGP_RDONLY); +} + +int +ipmi_cfgp_save(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel, FILE *file) +{ + if (file == NULL) { + return -1; + } + + return cfgp_do_action(ctx, CFGP_SAVE, sel, file, CFGP_RDONLY); +} + +int +ipmi_cfgp_print(struct ipmi_cfgp_ctx *ctx, + const struct ipmi_cfgp_sel *sel, FILE *file) +{ + if (file == NULL) { + return -1; + } + + return cfgp_do_action(ctx, CFGP_PRINT, sel, file, CFGP_RESERVED); +} diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c index 5171644..fab2e54 100644 --- a/lib/ipmi_channel.c +++ b/lib/ipmi_channel.c @@ -734,7 +734,8 @@ ipmi_get_user_access(struct ipmi_intf *intf, uint8_t channel, uint8_t user_id) (user_access.ipmi_messaging) ? "en" : "dis"); printf("Privilege Level : %s\n", val2str(user_access.privilege_limit, ipmi_privlvl_vals)); - + printf("Enable Status : %s\n", + val2str(user_access.enable_status, ipmi_user_enable_status_vals)); curr_uid ++; } while (!user_id && curr_uid <= max_uid); diff --git a/lib/ipmi_chassis.c b/lib/ipmi_chassis.c index fb7c27d..7b5c2a8 100644 --- a/lib/ipmi_chassis.c +++ b/lib/ipmi_chassis.c @@ -1381,7 +1381,7 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv) } } else { - lprintf(LOG_ERR, "Invalid Chassis command: %s", argv[0]); + lprintf(LOG_ERR, "Invalid chassis command: %s", argv[0]); return -1; } diff --git a/lib/ipmi_delloem.c b/lib/ipmi_delloem.c index 9bb0885..bc78c1d 100644 --- a/lib/ipmi_delloem.c +++ b/lib/ipmi_delloem.c @@ -1652,11 +1652,7 @@ ipmi_macinfo_drac_idrac_virtual_mac(struct ipmi_intf* intf,uint8_t NicNum) printf("\niDRAC6 MAC Address "); } - for (j = 0; j < 5; j++) { - printf("%02x:", VirtualMacAddress[j]); - } - printf("%02x", VirtualMacAddress[j]); - printf("\n"); + printf("%s\n", mac2str(VirtualMacAddress)); return 0; } /* @@ -1724,11 +1720,7 @@ ipmi_macinfo_drac_idrac_mac(struct ipmi_intf* intf,uint8_t NicNum) printf("\niDRAC6 MAC Address "); } - for (j = 0; j < 5; j++) { - printf("%02x:", iDRAC6MacAddressByte[j]); - } - printf("%02x", iDRAC6MacAddressByte[j]); - printf("\n"); + printf("%s\n", mac2str(iDRAC6MacAddressByte)); return 0; } /* @@ -1786,13 +1778,8 @@ ipmi_macinfo_10g(struct ipmi_intf* intf, uint8_t NicNum) for (i = 0; i < Total_No_NICs; i++) { if ((0xff == NicNum) || (i == NicNum)) { printf("\n%d",i); - printf("\t\t"); - for (j = 0 ; j < 5; j++) { - printf("%02x:", - EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte[j]); - } - printf("%02x", - EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte[j]); + printf("\t\t%s", + mac2str(EmbeddedNICMacAddress_10G.MacAddress[i].MacAddressByte)); } } printf("\n"); @@ -1889,13 +1876,7 @@ ipmi_macinfo_11g(struct ipmi_intf* intf, uint8_t NicNum) if ((0xff==NicNum) || (NicNum == EmbeddedNICMacAddress.LOMMacAddress[i].NICNumber)) { printf("\n%d",EmbeddedNICMacAddress.LOMMacAddress[i].NICNumber); - printf("\t\t"); - for (j = 0; j < 5; j++) { - printf("%02x:", - EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte[j]); - } - printf("%02x", - EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte[j]); + printf("\t\t%s", mac2str(EmbeddedNICMacAddress.LOMMacAddress[i].MacAddressByte)); if (LOM_ETHERNET_ENABLED == EmbeddedNICMacAddress.LOMMacAddress[i].EthernetStatus) { @@ -3061,9 +3042,9 @@ ipmi_get_power_headroom_command(struct ipmi_intf * intf,uint8_t unit) if (unit == btuphr) { peakpowerheadroombtuphr = watt_to_btuphr_conversion(powerheadroom.peakheadroom); instantpowerhearoom = watt_to_btuphr_conversion(powerheadroom.instheadroom); - printf("System Instantaneous Headroom : %lld BTU/hr\n", + printf("System Instantaneous Headroom : %" PRId64 " BTU/hr\n", instantpowerhearoom); - printf("System Peak Headroom : %lld BTU/hr\n", + printf("System Peak Headroom : %" PRId64 " BTU/hr\n", peakpowerheadroombtuphr); } else { printf("System Instantaneous Headroom : %d W\n", @@ -3452,63 +3433,63 @@ ipmi_print_power_consmpt_history(struct ipmi_intf * intf, int unit) if (unit == btuphr) { printf("Average Power Consumption "); tempbtuphrconv = watt_to_btuphr_conversion(avgpower.lastminutepower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(avgpower.lasthourpower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(avgpower.lastdaypower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(avgpower.lastweakpower); - printf("%4lld BTU/hr\n", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr\n", tempbtuphrconv); printf("Max Power Consumption "); tempbtuphrconv = watt_to_btuphr_conversion(stPeakpower.lastminutepower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stPeakpower.lasthourpower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stPeakpower.lastdaypower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stPeakpower.lastweakpower); - printf("%4lld BTU/hr\n", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr\n", tempbtuphrconv); printf("Min Power Consumption "); tempbtuphrconv = watt_to_btuphr_conversion(stMinpower.lastminutepower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stMinpower.lasthourpower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stMinpower.lastdaypower); - printf("%4lld BTU/hr ", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr ", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(stMinpower.lastweakpower); - printf("%4lld BTU/hr\n\n", tempbtuphrconv); + printf("%4" PRId64 " BTU/hr\n\n", tempbtuphrconv); } else { printf("Average Power Consumption "); tempbtuphrconv = (avgpower.lastminutepower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (avgpower.lasthourpower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (avgpower.lastdaypower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv=(avgpower.lastweakpower); - printf("%4lld W \n", tempbtuphrconv); + printf("%4" PRId64 " W \n", tempbtuphrconv); printf("Max Power Consumption "); tempbtuphrconv = (stPeakpower.lastminutepower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stPeakpower.lasthourpower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stPeakpower.lastdaypower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stPeakpower.lastweakpower); - printf("%4lld W \n", tempbtuphrconv); + printf("%4" PRId64 " W \n", tempbtuphrconv); printf("Min Power Consumption "); tempbtuphrconv = (stMinpower.lastminutepower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stMinpower.lasthourpower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stMinpower.lastdaypower); - printf("%4lld W ", tempbtuphrconv); + printf("%4" PRId64 " W ", tempbtuphrconv); tempbtuphrconv = (stMinpower.lastweakpower); - printf("%4lld W \n\n", tempbtuphrconv); + printf("%4" PRId64 " W \n\n", tempbtuphrconv); } lastminutepeakpower = stPeakpower.lastminutepowertime; @@ -3612,11 +3593,11 @@ ipmi_print_power_cap(struct ipmi_intf * intf,uint8_t unit) if (rc == 0) { if (unit == btuphr) { tempbtuphrconv = watt_to_btuphr_conversion(ipmipowercap.MaximumPowerConsmp); - printf("Maximum power: %lld BTU/hr\n", tempbtuphrconv); + printf("Maximum power: %" PRId64 " BTU/hr\n", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(ipmipowercap.MinimumPowerConsmp); - printf("Minimum power: %lld BTU/hr\n", tempbtuphrconv); + printf("Minimum power: %" PRId64 " BTU/hr\n", tempbtuphrconv); tempbtuphrconv = watt_to_btuphr_conversion(ipmipowercap.PowerCap); - printf("Power cap : %lld BTU/hr\n", tempbtuphrconv); + printf("Power cap : %" PRId64 " BTU/hr\n", tempbtuphrconv); } else { printf("Maximum power: %d Watt\n", ipmipowercap.MaximumPowerConsmp); printf("Minimum power: %d Watt\n", ipmipowercap.MinimumPowerConsmp); diff --git a/lib/ipmi_ekanalyzer.c b/lib/ipmi_ekanalyzer.c index d6ce4c7..7a6c63d 100644 --- a/lib/ipmi_ekanalyzer.c +++ b/lib/ipmi_ekanalyzer.c @@ -602,10 +602,13 @@ ipmi_ekanalyzer_main(struct ipmi_intf *intf, int argc, char **argv) */ filename_size = strlen(argv[index]) - SIZE_OF_FILE_TYPE + 1; if (filename_size > 0) { - /* TODO - check malloc() retval */ filename[i] = malloc( filename_size ); if (filename[i] != NULL) { strcpy(filename[i], &argv[index][SIZE_OF_FILE_TYPE]); + } else { + lprintf(LOG_ERR, "ipmitool: malloc failure"); + rc = ERROR_STATUS; + break; } } rc = OK_STATUS; @@ -2205,6 +2208,9 @@ ipmi_ek_create_amc_p2p_record(struct ipmi_ek_multi_header *record, int index_oem = 0; amc_record->oem_guid = malloc(amc_record->guid_count * \ sizeof(struct fru_picmgext_guid)); + if (amc_record->oem_guid == NULL) { + return ERROR_STATUS; + } for (index_oem = 0; index_oem < amc_record->guid_count; index_oem++) { memcpy(&amc_record->oem_guid[index_oem].guid, @@ -2232,6 +2238,9 @@ ipmi_ek_create_amc_p2p_record(struct ipmi_ek_multi_header *record, int ch_index = 0; amc_record->ch_desc = malloc((amc_record->ch_count) * \ sizeof(struct fru_picmgext_amc_channel_desc_record)); + if (amc_record->ch_desc == NULL) { + return ERROR_STATUS; + } for (ch_index = 0; ch_index < amc_record->ch_count; ch_index++) { unsigned int data; @@ -2255,6 +2264,9 @@ ipmi_ek_create_amc_p2p_record(struct ipmi_ek_multi_header *record, int i=0; amc_record->link_desc = malloc(amc_record->link_desc_count * \ sizeof(struct fru_picmgext_amc_link_desc_record)); + if (amc_record->link_desc == NULL) { + return ERROR_STATUS; + } for (i = 0; i< amc_record->link_desc_count; i++) { unsigned int data[2]; struct fru_picmgext_amc_link_desc_record *src, *dst; @@ -2767,7 +2779,6 @@ ipmi_ek_display_board_info_area(FILE *input_file, char *board_type, lprintf(LOG_ERR, "ipmitool: malloc failure"); return (size_t)(-1); } - ret = fread(additional_data, size_board, 1, input_file); if ((ret != 1) || ferror(input_file)) { lprintf(LOG_ERR, "Invalid Additional Data!"); @@ -3363,7 +3374,7 @@ ipmi_ek_display_board_p2p_record(struct ipmi_ek_multi_header *record) printf("\n"); offset += sizeof(struct fru_picmgext_guid); } - for (offset; + for (offset = offset; offset < record->header.len; offset += sizeof(struct fru_picmgext_link_desc)) { /* to solve little endian/big endian problem */ @@ -3522,7 +3533,7 @@ ipmi_ek_display_radial_ipmb0_record(struct ipmi_ek_multi_header *record) if (record->data[offset] < 1) { return; } - for (offset; offset < record->header.len;) { + for (offset = offset; offset < record->header.len;) { unsigned char entry_count = 0; printf(" IPMB-0 Hub Descriptor\n"); printf("\tHardware Address: 0x%02x\n", @@ -4046,14 +4057,18 @@ ipmi_ekanalyzer_fru_file2structure(char *filename, fseek(input_file, multi_offset, SEEK_SET); while (!feof(input_file)) { - /* TODO - check malloc() */ *list_record = malloc(sizeof(struct ipmi_ek_multi_header)); + if (*list_record == NULL) { + lprintf(LOG_ERR, "ipmitool: malloc failure"); + return ERROR_STATUS; + } ret = fread(&(*list_record)->header, START_DATA_OFFSET, 1, input_file); if ((ret != 1) || ferror(input_file)) { - /* TODO - no free?! */ - lprintf(LOG_ERR, "Invalid Header!"); + free(*list_record); + *list_record = NULL; fclose(input_file); + lprintf(LOG_ERR, "Invalid Header!"); return ERROR_STATUS; } if ((*list_record)->header.len == 0) { diff --git a/lib/ipmi_event.c b/lib/ipmi_event.c index 16fc80d..bc32ae8 100644 --- a/lib/ipmi_event.c +++ b/lib/ipmi_event.c @@ -207,18 +207,20 @@ ipmi_send_platform_event_num(struct ipmi_intf * intf, int num) } static int -ipmi_event_find_offset(uint8_t code, - struct ipmi_event_sensor_types * evt, - char * desc) +ipmi_event_find_offset(struct ipmi_intf *intf, uint8_t sensor_type, uint8_t event_type, char *desc) { - if (desc == NULL || code == 0) + const struct ipmi_event_sensor_types *evt; + + if (desc == NULL || sensor_type == 0 || event_type == 0) { return 0x00; + } - while (evt->type) { - if (evt->code == code && evt->desc != NULL && - strncasecmp(desc, evt->desc, __maxlen(desc, evt->desc)) == 0) + for (evt = ipmi_get_first_event_sensor_type(intf, sensor_type, event_type); + evt != NULL; evt = ipmi_get_next_event_sensor_type(evt)) { + if (evt->desc != NULL && + strncasecmp(desc, evt->desc, __maxlen(desc, evt->desc)) == 0) { return evt->offset; - evt++; + } } lprintf(LOG_WARN, "Unable to find matching event offset for '%s'", desc); @@ -226,11 +228,11 @@ ipmi_event_find_offset(uint8_t code, } static void -print_sensor_states(uint8_t sensor_type, uint8_t event_type) +print_sensor_states(struct ipmi_intf *intf, uint8_t sensor_type, uint8_t event_type) { - ipmi_sdr_print_discrete_state_mini( + ipmi_sdr_print_discrete_state_mini(intf, "Sensor States: \n ", "\n ", sensor_type, - event_type, 0xff, 0xff); + event_type, 0xff, 0xff); printf("\n"); } @@ -400,7 +402,7 @@ ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * e * print list of available states for this sensor */ if (state == NULL || strncasecmp(state, "list", 4) == 0) { - print_sensor_states(emsg.sensor_type, emsg.event_type); + print_sensor_states(intf, emsg.sensor_type, emsg.event_type); printf("Sensor State Shortcuts:\n"); for (x = 0; x < sizeof(digi_on)/sizeof(*digi_on); x++) { printf(" %-9s %-9s\n", digi_on[x], digi_off[x]); @@ -422,8 +424,8 @@ ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * e } } if (off == 0) { - off = ipmi_event_find_offset( - emsg.event_type, generic_event_types, state); + off = ipmi_event_find_offset(intf, + emsg.sensor_type, emsg.event_type, state); if (off < 0) return -1; emsg.event_data[0] = off; @@ -440,11 +442,11 @@ ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * e * print list of available states for this sensor */ if (state == NULL || strncasecmp(state, "list", 4) == 0) { - print_sensor_states(emsg.sensor_type, emsg.event_type); + print_sensor_states(intf, emsg.sensor_type, emsg.event_type); return 0; } - off = ipmi_event_find_offset( - emsg.event_type, generic_event_types, state); + off = ipmi_event_find_offset(intf, + emsg.sensor_type, emsg.event_type, state); if (off < 0) return -1; emsg.event_data[0] = off; @@ -460,11 +462,11 @@ ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * e * print list of available states for this sensor */ if (state == NULL || strncasecmp(state, "list", 4) == 0) { - print_sensor_states(emsg.sensor_type, emsg.event_type); + print_sensor_states(intf, emsg.sensor_type, emsg.event_type); return 0; } - off = ipmi_event_find_offset( - emsg.sensor_type, sensor_specific_types, state); + off = ipmi_event_find_offset(intf, + emsg.sensor_type, emsg.event_type, state); if (off < 0) return -1; emsg.event_data[0] = off; diff --git a/lib/ipmi_firewall.c b/lib/ipmi_firewall.c index c3f51ad..26bfd30 100644 --- a/lib/ipmi_firewall.c +++ b/lib/ipmi_firewall.c @@ -899,7 +899,7 @@ static int ipmi_firewall_info(struct ipmi_intf * intf, int argc, char ** argv) { int ret = 0; - struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; + struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0}; struct bmc_fn_support * bmc_fn_support; unsigned int l, n, c; @@ -1012,7 +1012,7 @@ ipmi_firewall_info(struct ipmi_intf * intf, int argc, char ** argv) static int ipmi_firewall_enable_disable(struct ipmi_intf * intf, int enable, int argc, char ** argv) { - struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; + struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0}; struct bmc_fn_support * bmc_fn_support; int ret; unsigned int l, n, c; @@ -1103,7 +1103,7 @@ ipmi_firewall_enable_disable(struct ipmi_intf * intf, int enable, int argc, char static int ipmi_firewall_reset(struct ipmi_intf * intf, int argc, char ** argv) { - struct ipmi_function_params p = {0xe, -1, -1, -1, -1}; + struct ipmi_function_params p = {0xe, -1, -1, -1, -1, 0}; struct bmc_fn_support * bmc_fn_support; int ret; unsigned int l, n, c; @@ -1135,8 +1135,8 @@ ipmi_firewall_reset(struct ipmi_intf * intf, int argc, char ** argv) for (l=0; l<MAX_LUN; l++) { p.lun = l; - for (n=0; n<MAX_NETFN; n+=2) { - p.netfn = n; + for (n=0; n<MAX_NETFN_PAIR; n++) { + p.netfn = n*2; for (c=0; c<MAX_COMMAND; c++) { p.command = c; printf("reset lun %d, netfn %d, command %d, subfn\n", l, n, c); diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c index 5c94b08..cf00eff 100644 --- a/lib/ipmi_fru.c +++ b/lib/ipmi_fru.c @@ -50,6 +50,13 @@ #define FRU_MULTIREC_CHUNK_SIZE (255 + sizeof(struct fru_multirec_header)) +static const char *section_id[4] = { + "Internal Use Section", + "Chassis Section", + "Board Section", + "Product Section" +}; + /* From lib/dimm_spd.c: */ int ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id); @@ -677,9 +684,9 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, break; } if (rsp->ccode > 0) { - /* if we get C8h or CAh completion code then we requested too + /* if we get C7h or C8h or CAh return code then we requested too * many bytes at once so try again with smaller size */ - if ((rsp->ccode == 0xc8 || rsp->ccode == 0xca) + if ((rsp->ccode == 0xc7 || rsp->ccode == 0xc8 || rsp->ccode == 0xca) && fru->max_read_size > 8) { if (fru->max_read_size > 32) { /* subtract read length more aggressively */ @@ -2281,8 +2288,7 @@ static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length) printf(" Link Type Extension: 0x%02x - ", d->ext); if (d->type == FRU_PICMGEXT_LINK_TYPE_BASE) { - switch (d->ext) - { + switch (d->ext) { case 0: printf("10/100/1000BASE-T Link (four-pair)\n"); break; @@ -2290,76 +2296,93 @@ static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length) printf("ShMC Cross-connect (two-pair)\n"); break; default: - printf("Unknwon\n"); + printf("Unknown\n"); break; } } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET) { - switch (d->ext) - { + switch (d->ext) { case 0: - printf("Fixed 1000Base-BX\n"); + printf("1000Base-BX\n"); break; case 1: - printf("Fixed 10GBASE-BX4 [XAUI]\n"); + printf("10GBase-BX4 [XAUI]\n"); break; case 2: printf("FC-PI\n"); break; + case 3: + printf("1000Base-KX\n"); + break; + case 4: + printf("10GBase-KX4\n"); + break; + default: + printf("Unknown\n"); + break; + } + } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET_10GBD) { + switch (d->ext) { + case 0: + printf("10GBase-KR\n"); + break; + case 1: + printf("40GBase-KR4\n"); + break; default: - printf("Unknwon\n"); + printf("Unknown\n"); break; } } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND) { - printf("Unknwon\n"); + printf("Unknown\n"); } else if (d->type == FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR) { - printf("Unknwon\n"); + printf("Unknown\n"); } else if (d->type == FRU_PICMGEXT_LINK_TYPE_PCIE) { - printf("Unknwon\n"); + printf("Unknown\n"); } else { - printf("Unknwon\n"); + printf("Unknown\n"); } printf(" Link Type: 0x%02x - ", d->type); - if (d->type == 0 || d->type == 0xff) { - printf("Reserved\n"); - } - else if (d->type >= 0x06 && d->type <= 0xef) { - printf("Reserved\n"); - } - else if (d->type >= 0xf0 && d->type <= 0xfe) { - printf("OEM GUID Definition\n"); - } - else { - switch (d->type) - { - case FRU_PICMGEXT_LINK_TYPE_BASE: - printf("PICMG 3.0 Base Interface 10/100/1000\n"); - break; - case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET: - printf("PICMG 3.1 Ethernet Fabric Interface\n"); - break; - case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND: - printf("PICMG 3.2 Infiniband Fabric Interface\n"); - break; - case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR: - printf("PICMG 3.3 Star Fabric Interface\n"); - break; - case FRU_PICMGEXT_LINK_TYPE_PCIE: - printf("PICMG 3.4 PCI Express Fabric Interface\n"); - break; - default: + switch (d->type) { + case FRU_PICMGEXT_LINK_TYPE_BASE: + printf("PICMG 3.0 Base Interface 10/100/1000\n"); + break; + case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET: + printf("PICMG 3.1 Ethernet Fabric Interface\n"); + printf(" Base signaling Link Class\n"); + break; + case FRU_PICMGEXT_LINK_TYPE_FABRIC_INFINIBAND: + printf("PICMG 3.2 Infiniband Fabric Interface\n"); + break; + case FRU_PICMGEXT_LINK_TYPE_FABRIC_STAR: + printf("PICMG 3.3 Star Fabric Interface\n"); + break; + case FRU_PICMGEXT_LINK_TYPE_PCIE: + printf("PICMG 3.4 PCI Express Fabric Interface\n"); + break; + case FRU_PICMGEXT_LINK_TYPE_FABRIC_ETHERNET_10GBD: + printf("PICMG 3.1 Ethernet Fabric Interface\n"); + printf(" 10.3125Gbd signaling Link Class\n"); + break; + default: + if (d->type == 0 || d->type == 0xff) { + printf("Reserved\n"); + } else if (d->type >= 0x06 && d->type <= 0xef) { + printf("Reserved\n"); + } else if (d->type >= 0xf0 && d->type <= 0xfe) { + printf("OEM GUID Definition\n"); + } else { printf("Invalid\n"); - break; - } + } + break; } printf(" Link Designator: \n"); printf(" Port Flag: 0x%02x\n", d->desig_port); printf(" Interface: 0x%02x - ", d->desig_if); - switch (d->desig_if) - { + switch (d->desig_if) { case FRU_PICMGEXT_DESIGN_IF_BASE: printf("Base Interface\n"); break; diff --git a/lib/ipmi_hpmfwupg.c b/lib/ipmi_hpmfwupg.c index 9cbd4ff..bbcffc0 100644 --- a/lib/ipmi_hpmfwupg.c +++ b/lib/ipmi_hpmfwupg.c @@ -1399,7 +1399,12 @@ HpmfwupgGetBufferFromFile(char *imageFilename, return HPMFWUPG_ERROR; } /* Get the raw data in file */ - fseek(pImageFile, 0, SEEK_END); + ret = fseek(pImageFile, 0, SEEK_END); + if (ret != 0) { + lprintf(LOG_ERR, "Failed to seek in the image file '%s'", + imageFilename); + return HPMFWUPG_ERROR; + } pFwupgCtx->imageSize = ftell(pImageFile); pFwupgCtx->pImageData = malloc(sizeof(unsigned char)*pFwupgCtx->imageSize); if (pFwupgCtx->pImageData == NULL) { diff --git a/lib/ipmi_lanp.c b/lib/ipmi_lanp.c index ecd313a..65d881b 100644 --- a/lib/ipmi_lanp.c +++ b/lib/ipmi_lanp.c @@ -104,7 +104,7 @@ is_lan_channel(struct ipmi_intf * intf, uint8_t chan) * @intf: ipmi interface handle * @start: channel number to start searching from */ -static uint8_t +uint8_t find_lan_channel(struct ipmi_intf * intf, uint8_t start) { uint8_t chan = 0; @@ -704,8 +704,7 @@ ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan) if (p == NULL) return -1; if (p->data != NULL) - printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc, - p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]); + printf("%-24s: %s\n", p->desc, mac2str(p->data)); p = get_lan_param(intf, chan, IPMI_LANP_SNMP_STRING); if (p == NULL) @@ -744,8 +743,7 @@ ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan) if (p == NULL) return -1; if (p->data != NULL) - printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc, - p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]); + printf("%-24s: %s\n", p->desc, mac2str(p->data)); p = get_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_IP); if (p == NULL) @@ -758,8 +756,7 @@ ipmi_lan_print(struct ipmi_intf * intf, uint8_t chan) if (p == NULL) return -1; if (p->data != NULL) - printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", p->desc, - p->data[0], p->data[1], p->data[2], p->data[3], p->data[4], p->data[5]); + printf("%-24s: %s\n", p->desc, mac2str(p->data)); p = get_lan_param(intf, chan, IPMI_LANP_VLAN_ID); if (p != NULL && p->data != NULL) { @@ -1103,42 +1100,6 @@ ipmi_set_user_access(struct ipmi_intf *intf, uint8_t channel, uint8_t user_id) } } -/* get_cmdline_macaddr - parse-out MAC address from given string and store it - * into buffer. - * - * @arg: string to be parsed. - * @buf: buffer of 6 to hold parsed MAC address. - * - * returns zero on success, (-1) on error and error message is printed-out. - */ -static int -get_cmdline_macaddr(char *arg, uint8_t *buf) -{ - uint32_t m1 = 0; - uint32_t m2 = 0; - uint32_t m3 = 0; - uint32_t m4 = 0; - uint32_t m5 = 0; - uint32_t m6 = 0; - if (sscanf(arg, "%02x:%02x:%02x:%02x:%02x:%02x", - &m1, &m2, &m3, &m4, &m5, &m6) != 6) { - lprintf(LOG_ERR, "Invalid MAC address: %s", arg); - return -1; - } - if (m1 > UINT8_MAX || m2 > UINT8_MAX - || m3 > UINT8_MAX || m4 > UINT8_MAX - || m5 > UINT8_MAX || m6 > UINT8_MAX) { - lprintf(LOG_ERR, "Invalid MAC address: %s", arg); - return -1; - } - buf[0] = (uint8_t)m1; - buf[1] = (uint8_t)m2; - buf[2] = (uint8_t)m3; - buf[3] = (uint8_t)m4; - buf[4] = (uint8_t)m5; - buf[5] = (uint8_t)m6; - return 0; -} static int @@ -1243,12 +1204,27 @@ get_cmdline_ipaddr(char * arg, uint8_t * buf) static int ipmi_lan_set_vlan_id(struct ipmi_intf *intf, uint8_t chan, char *string) { + struct lan_param *p; uint8_t data[2]; int rc; if (string == NULL) { - data[0] = 0; - data[1] = 0; + lprintf(LOG_DEBUG, "Get current VLAN ID from BMC."); + p = get_lan_param(intf, chan, IPMI_LANP_VLAN_ID); + if (p != NULL && p->data != NULL && p->data_len > 1) { + int id = ((p->data[1] & 0x0f) << 8) + p->data[0]; + if (id < 1 || id > 4094) { + lprintf(LOG_ERR, + "Retrieved VLAN ID %i is out of range <1..4094>.", + id); + return (-1); + } + data[0] = p->data[0]; + data[1] = p->data[1] & 0x0F; + } else { + data[0] = 0; + data[1] = 0; + } } else { int id = 0; @@ -1540,11 +1516,11 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) print_lan_set_usage(); return -1; } - rc = get_cmdline_macaddr(argv[2], data); + rc = str2mac(argv[2], data); if (rc == 0) { - printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n", - ipmi_lan_params[IPMI_LANP_MAC_ADDR].desc, - data[0], data[1], data[2], data[3], data[4], data[5]); + printf("Setting LAN %s to %s\n", + ipmi_lan_params[IPMI_LANP_MAC_ADDR].desc, + mac2str(data)); rc = set_lan_param(intf, chan, IPMI_LANP_MAC_ADDR, data, 6); } } @@ -1566,10 +1542,10 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_IP, data, 4); } else if ((strncmp(argv[2], "macaddr", 7) == 0) && - (get_cmdline_macaddr(argv[3], data) == 0)) { - printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n", - ipmi_lan_params[IPMI_LANP_DEF_GATEWAY_MAC].desc, - data[0], data[1], data[2], data[3], data[4], data[5]); + (str2mac(argv[3], data) == 0)) { + printf("Setting LAN %s to %s\n", + ipmi_lan_params[IPMI_LANP_DEF_GATEWAY_MAC].desc, + mac2str(data)); rc = set_lan_param(intf, chan, IPMI_LANP_DEF_GATEWAY_MAC, data, 6); } else { @@ -1595,10 +1571,10 @@ ipmi_lan_set(struct ipmi_intf * intf, int argc, char ** argv) rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_IP, data, 4); } else if ((strncmp(argv[2], "macaddr", 7) == 0) && - (get_cmdline_macaddr(argv[3], data) == 0)) { - printf("Setting LAN %s to %02x:%02x:%02x:%02x:%02x:%02x\n", - ipmi_lan_params[IPMI_LANP_BAK_GATEWAY_MAC].desc, - data[0], data[1], data[2], data[3], data[4], data[5]); + (str2mac(argv[3], data) == 0)) { + printf("Setting LAN %s to %s\n", + ipmi_lan_params[IPMI_LANP_BAK_GATEWAY_MAC].desc, + mac2str(data)); rc = set_lan_param(intf, chan, IPMI_LANP_BAK_GATEWAY_MAC, data, 6); } else { @@ -1776,9 +1752,8 @@ ipmi_lan_alert_print(struct ipmi_intf * intf, uint8_t channel, uint8_t alert) printf("%-24s: %d.%d.%d.%d\n", "Alert IP Address", paddr[3], paddr[4], paddr[5], paddr[6]); - printf("%-24s: %02x:%02x:%02x:%02x:%02x:%02x\n", "Alert MAC Address", - paddr[7], paddr[8], paddr[9], - paddr[10], paddr[11], paddr[12]); + printf("%-24s: %s\n", "Alert MAC Address", + mac2str(&paddr[7])); printf("\n"); return 0; @@ -1843,7 +1818,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, } /* alert destination mac address */ else if (strncasecmp(argv[0], "macaddr", 7) == 0 && - (get_cmdline_macaddr(argv[1], temp) == 0)) { + (str2mac(argv[1], temp) == 0)) { /* get current parameter */ p = get_lan_param_select(intf, chan, IPMI_LANP_DEST_ADDR, alert); if (p == NULL) { @@ -1853,8 +1828,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, /* set new macaddr */ memcpy(data+7, temp, 6); printf("Setting LAN Alert %d MAC Address to " - "%02x:%02x:%02x:%02x:%02x:%02x\n", alert, - data[7], data[8], data[9], data[10], data[11], data[12]); + "%s\n", alert, mac2str(&data[7])); rc = set_lan_param_nowait(intf, chan, IPMI_LANP_DEST_ADDR, data, p->data_len); } /* alert destination gateway selector */ diff --git a/lib/ipmi_lanp6.c b/lib/ipmi_lanp6.c new file mode 100644 index 0000000..bbffb89 --- /dev/null +++ b/lib/ipmi_lanp6.c @@ -0,0 +1,1240 @@ +/* + * Copyright (c) 2016 Pentair Technical Products. All right reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Pentair Technical Products 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * PENTAIR TECHNICAL SOLUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <ipmitool/helper.h> +#include <ipmitool/ipmi_cc.h> +#include <ipmitool/ipmi_cfgp.h> +#include <ipmitool/ipmi_lanp.h> +#include <ipmitool/ipmi_lanp6.h> +#include <ipmitool/log.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <arpa/inet.h> + +/* + * LAN6 command values. + */ +enum { + LANP_CMD_SAVE, + LANP_CMD_SET, + LANP_CMD_PRINT, + LANP_CMD_LOCK, + LANP_CMD_COMMIT, + LANP_CMD_DISCARD, + LANP_CMD_HELP, + LANP_CMD_ANY = 0xFF +}; + +/* + * Generic LAN configuration parameters. + */ +const struct ipmi_lanp generic_lanp6[] = { + { 0, "Set In Progress", 1 }, + { 50, "IPv6/IPv4 Support", 1 }, + { 51, "IPv6/IPv4 Addressing Enables", 1 }, + { 52, "IPv6 Header Traffic Class", 1 }, + { 53, "IPv6 Header Static Hop Limit", 1 }, + { 54, "IPv6 Header Flow Label", 3 }, + { 55, "IPv6 Status", 3 }, + { 56, "IPv6 Static Address", 20 }, + { 57, "IPv6 DHCPv6 Static DUID Storage Length", 1 }, + { 58, "IPv6 DHCPv6 Static DUID", 18 }, + { 59, "IPv6 Dynamic Address", 20 }, + { 60, "IPv6 DHCPv6 Dynamic DUID Storage Length", 1 }, + { 61, "IPv6 DHCPv6 Dynamic DUID", 18 }, + { 62, "IPv6 DHCPv6 Timing Configuration Support", 1 }, + { 63, "IPv6 DHCPv6 Timing Configuration", 18 }, + { 64, "IPv6 Router Address Configuration Control", 1 }, + { 65, "IPv6 Static Router 1 IP Address", 16 }, + { 66, "IPv6 Static Router 1 MAC Address", 6 }, + { 67, "IPv6 Static Router 1 Prefix Length", 1 }, + { 68, "IPv6 Static Router 1 Prefix Value", 16 }, + { 69, "IPv6 Static Router 2 IP Address", 16 }, + { 70, "IPv6 Static Router 2 MAC Address", 6 }, + { 71, "IPv6 Static Router 2 Prefix Length", 1 }, + { 72, "IPv6 Static Router 2 Prefix Value", 16 }, + { 73, "IPv6 Number of Dynamic Router Info Sets", 1 }, + { 74, "IPv6 Dynamic Router Info IP Address", 17 }, + { 75, "IPv6 Dynamic Router Info MAC Address", 7 }, + { 76, "IPv6 Dynamic Router Info Prefix Length", 2 }, + { 77, "IPv6 Dynamic Router Info Prefix Value", 17 }, + { 78, "IPv6 Dynamic Router Received Hop Limit", 1 }, + { 79, "IPv6 ND/SLAAC Timing Configuration Support", 1 }, + { 80, "IPv6 ND/SLAAC Timing Configuration", 18 }, + { 0, NULL, 0 } +}; + +/* + * Set/Get LAN Configuration Parameters + * command-specific completion codes. + */ +const struct valstr lanp_cc_vals[] = { + { 0x80, "Parameter not supported" }, + { 0x81, "Set already in progress" }, + { 0x82, "Parameter is read-only" }, + { 0x83, "Write-only parameter" }, + { 0x00, NULL } +}; + +/* + * IPv6/IPv4 Addressing Enables. + */ +const struct valstr ip6_enable_vals[] = { + { 0, "ipv4" }, + { 1, "ipv6" }, + { 2, "both" }, + { 0xFF, NULL } +}; + +/* + * Enable/Disable a static address. + */ +const struct valstr ip6_addr_enable_vals[] = { + { 0x00, "disable" }, + { 0x80, "enable" }, + { 0xFF, NULL } +}; + +/* + * IPv6 address source values. + */ +const struct valstr ip6_addr_sources[] = { + { 0, "static" }, + { 1, "SLAAC" }, + { 2, "DHCPv6" }, + { 0, NULL } +}; + +/* + * IPv6 address status values. + */ +const struct valstr ip6_addr_statuses[] = { + { 0, "active" }, + { 1, "disabled" }, + { 2, "pending" }, + { 3, "failed" }, + { 4, "deprecated" }, + { 5, "invalid" }, + { 0xFF, NULL } +}; + +/* + * DHCPv6 DUID type values. + */ +const struct valstr ip6_duid_types[] = { + { 0, "unknown" }, + { 1, "DUID-LLT" }, + { 2, "DUID-EN" }, + { 3, "DUID-LL" }, + { 0xFF, NULL } +}; + +/* + * Timing Configuration support values. + */ +const struct valstr ip6_cfg_sup_vals[] = { + { 0, "not supported" }, + { 1, "global" }, + { 2, "per interface" }, + { 0xFF, NULL } +}; + +/* + * Router Address Configuration Control values. + */ +const struct valstr ip6_rtr_configs[] = { + { 1, "static" }, + { 2, "dynamic" }, + { 3, "both" }, + { 0xFF, NULL } +}; + + +const struct valstr ip6_command_vals[] = { + { LANP_CMD_SET, "set" }, + { LANP_CMD_SAVE, "save" }, + { LANP_CMD_PRINT, "print" }, + { LANP_CMD_LOCK, "lock" }, + { LANP_CMD_COMMIT, "commit" }, + { LANP_CMD_DISCARD, "discard" }, + { LANP_CMD_HELP, "help" }, + { LANP_CMD_ANY, NULL } +}; + +static const struct ipmi_cfgp lan_cfgp[] = { + { .name = "support", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_SUPPORT + }, + { .name = "enables", .format = "{ipv4|ipv6|both}", .size = 1, + .access = CFGP_RDWR, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_ENABLES + }, + { .name = "traffic_class", .format = "<value>", .size = 1, + .access = CFGP_RDWR, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_TRAFFIC_CLASS + }, + { .name = "static_hops", .format = "<value>", .size = 1, + .access = CFGP_RDWR, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_STATIC_HOPS + }, + { .name = "flow_label", .format = "<value>", .size = 3, + .access = CFGP_RDWR, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_FLOW_LABEL + }, + { .name = "status", .format = NULL, .size = 3, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_STATUS + }, + { .name = "static_addr", + .format = "{enable|disable} <addr> <pfx_len>", .size = 20, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_STATIC_ADDR + }, + { .name = "static_duid_stg", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_STATIC_DUID_STG + }, + { .name = "static_duid", .format = "<data>", .size = 18, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 0, .has_blocks = 1, .first_block = 0, + .specific = IPMI_LANP_IP6_STATIC_DUID + }, + { .name = "dynamic_addr", .format = NULL, .size = 20, + .access = CFGP_RDONLY, + .is_set = 1, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DYNAMIC_ADDR + }, + { .name = "dynamic_duid_stg", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DYNAMIC_DUID_STG + }, + { .name = "dynamic_duid", .format = "<data>", .size = 18, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 0, .has_blocks = 1, .first_block = 0, + .specific = IPMI_LANP_IP6_DYNAMIC_DUID + }, + { .name = "dhcp6_cfg_sup", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DHCP6_CFG_SUP + }, + { .name = "dhcp6_cfg", .format = "<data> <data>", .size = 36, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DHCP6_CFG + }, + { .name = "rtr_cfg", .format = "{static|dynamic|both}", .size = 1, + .access = CFGP_RDWR, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_ROUTER_CFG + }, + { .name = "static_rtr", + .format = "<addr> <macaddr> <prefix> <prefix_len>", .size = 43, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 1, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_STATIC_RTR1_ADDR + }, + { .name = "num_dynamic_rtrs", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_NUM_DYNAMIC_RTRS + }, + { .name = "dynamic_rtr", .format = NULL, .size = 43, + .access = CFGP_RDONLY, + .is_set = 1, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DYNAMIC_RTR_ADDR + }, + { .name = "dynamic_hops", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_DYNAMIC_HOPS + }, + { .name = "ndslaac_cfg_sup", .format = NULL, .size = 1, + .access = CFGP_RDONLY, + .is_set = 0, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_NDSLAAC_CFG_SUP + }, + { .name = "ndslaac_cfg", .format = "<data>", .size = 18, + .access = CFGP_RDWR, + .is_set = 1, .first_set = 0, .has_blocks = 0, .first_block = 0, + .specific = IPMI_LANP_IP6_NDSLAAC_CFG + } +}; + +/* + * Lookup LAN parameter descriptor by parameter selector. + */ +const struct ipmi_lanp * +lookup_lanp(int param) +{ + const struct ipmi_lanp *p = generic_lanp6; + + while (p->name) { + if (p->selector == param) { + return p; + } + + p++; + } + + return NULL; +} + +/* + * Print request error. + */ +static int +ipmi_lanp_err(const struct ipmi_rs *rsp, const struct ipmi_lanp *p, + const char *action, int quiet) +{ + const char *reason; + char cc_msg[10]; + int log_level = LOG_ERR; + int err; + + if (rsp == NULL) { + reason = "No response"; + err = -1; + } else { + err = rsp->ccode; + if (quiet == 1 + && (rsp->ccode == 0x80 + || rsp->ccode == IPMI_CC_PARAM_OUT_OF_RANGE + || rsp->ccode == IPMI_CC_INV_DATA_FIELD_IN_REQ)) { + /* be quiet */ + return err; + } + + if (rsp->ccode >= 0xC0) { + /* browse for generic completion codes */ + reason = val2str(rsp->ccode, completion_code_vals); + } else { + /* browse for command-specific completion codes first */ + reason = val2str(rsp->ccode, lanp_cc_vals); + } + + if (reason == NULL) { + /* print completion code value */ + snprintf(cc_msg, sizeof(cc_msg), "CC=%02x", rsp->ccode); + reason = cc_msg; + } + + if (rsp->ccode == IPMI_CC_OK) { + log_level = LOG_DEBUG; + } + } + + lprintf(log_level, "Failed to %s %s: %s", action, p->name, reason); + return err; +} + +/* + * Get dynamic OEM LAN configuration parameter from BMC. + * Dynamic in this context is when the base for OEM LAN parameters + * is not known apriori. + */ +int +ipmi_get_dynamic_oem_lanp(void *priv, const struct ipmi_lanp *param, + int oem_base, int set_selector, int block_selector, + void *data, int quiet) +{ + struct ipmi_lanp_priv *lp = priv; + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t req_data[4]; + int length; + + if (!priv || !param || !data) { + return -1; + } + req_data[0] = lp->channel; + req_data[1] = param->selector + oem_base; + req_data[2] = set_selector; + req_data[3] = block_selector; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_TRANSPORT; + req.msg.cmd = 2; + req.msg.data = req_data; + req.msg.data_len = 4; + + lprintf(LOG_INFO, "Getting parameter '%s' set %d block %d", + param->name, set_selector, block_selector); + + rsp = lp->intf->sendrecv(lp->intf, &req); + if (rsp == NULL || rsp->ccode) { + return ipmi_lanp_err(rsp, param, "get", quiet); + } + + memset(data, 0, param->size); + + if (rsp->data_len - 1 < param->size) { + length = rsp->data_len - 1; + } else { + length = param->size; + } + + if (length) { + memcpy(data, rsp->data + 1, length); + } + + return 0; +} + +/* + * Get generic LAN configuration parameter. + */ +int +ipmi_get_lanp(void *priv, int param_selector, int set_selector, + int block_selector, void *data, int quiet) +{ + return ipmi_get_dynamic_oem_lanp(priv, lookup_lanp(param_selector), 0, + set_selector, block_selector, data, quiet); +} + +/* + * Set dynamic OEM LAN configuration parameter to BMC. + * Dynamic in this context is when the base for OEM LAN parameters + * is not known apriori. + */ +int +ipmi_set_dynamic_oem_lanp(void *priv, const struct ipmi_lanp *param, + int base, const void *data) +{ + struct ipmi_lanp_priv *lp = priv; + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t req_data[32]; + + if (!priv || !param || !data) { + return -1; + } + /* fill the first two bytes */ + req_data[0] = lp->channel; + req_data[1] = param->selector + base; + + /* fill the rest data */ + memcpy(&req_data[2], data, param->size); + + /* fill request */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_TRANSPORT; + req.msg.cmd = 1; + req.msg.data = req_data; + req.msg.data_len = param->size + 2; + + lprintf(LOG_INFO, "Setting parameter '%s'", param->name); + + rsp = lp->intf->sendrecv(lp->intf, &req); + if (rsp == NULL || rsp->ccode) { + return ipmi_lanp_err(rsp, param, "set", 0); + } + + return 0; +} + +/* + * Set generic LAN configuration parameter. + */ +int +ipmi_set_lanp(void *priv, int param_selector, const void *data) +{ + return ipmi_set_dynamic_oem_lanp(priv, lookup_lanp(param_selector), + 0, data); +} + +static int +lanp_parse_cfgp(const struct ipmi_cfgp *p, int set, int block, + int argc, const char *argv[], unsigned char *data) +{ + unsigned int v; + + if (argc == 0) { + return -1; + } + + switch(p->specific) { + case IPMI_LANP_IP6_ENABLES: + data[0] = str2val(argv[0], ip6_enable_vals); + if (data[0] == 0xFF) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + case IPMI_LANP_IP6_FLOW_LABEL: + if (str2uint(argv[0], &v)) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + + data[0] = (v >> 16) & 0x0F; + data[1] = (v >> 8) & 0xFF; + data[2] = v & 0xFF; + break; + + case IPMI_LANP_IP6_STATUS: + if (argc < 3) { + return -1; + } + + if (str2uchar(argv[0], &data[0]) + || str2uchar(argv[1], &data[1]) + || str2uchar(argv[2], &data[2])) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + case IPMI_LANP_IP6_STATIC_ADDR: + case IPMI_LANP_IP6_DYNAMIC_ADDR: + if (argc < 3) { + return -1; + } + + data[0] = set; + if (p->specific == IPMI_LANP_IP6_STATIC_ADDR) { + data[1] = str2val(argv[0], ip6_addr_enable_vals); + } else { + data[1] = str2val(argv[0], ip6_addr_sources); + } + if (data[1] == 0xFF) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + + if (inet_pton(AF_INET6, argv[1], &data[2]) != 1) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + + if (str2uchar(argv[2], &data[18])) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + + if (argc >= 4) { + data[19] = str2val(argv[3], ip6_addr_statuses); + } + break; + + case IPMI_LANP_IP6_STATIC_DUID: + case IPMI_LANP_IP6_DYNAMIC_DUID: + case IPMI_LANP_IP6_NDSLAAC_CFG: + data[0] = set; + data[1] = block; + if (ipmi_parse_hex(argv[0], &data[2], 16) < 0) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + case IPMI_LANP_IP6_DHCP6_CFG: + data[0] = set; + data[1] = 0; + data[18] = set; + data[19] = 1; + + if (ipmi_parse_hex(argv[0], &data[2], 16) < 0 + || (argc > 1 && + ipmi_parse_hex(argv[1], &data[20], 6) < 0)) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + case IPMI_LANP_IP6_ROUTER_CFG: + data[0] = str2val(argv[0], ip6_rtr_configs); + if (data[0] == 0xFF) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + case IPMI_LANP_IP6_STATIC_RTR1_ADDR: + if (set > 2) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + + case IPMI_LANP_IP6_DYNAMIC_RTR_ADDR: + if (argc < 4) { + return -1; + } + + /* + * Data is stored in the following way: + * 0: <set> <addr1>...<addr16> + * 17: <set> <mac1>...<mac6> + * 24: <set> <pfxlen> + * 26: <set> <pfx1>...<pfx16> + */ + data[0] = data[17] = data[24] = data[26] = set; + + if (inet_pton(AF_INET6, argv[0], &data[1]) != 1 + || str2mac(argv[1], &data[18]) + || inet_pton(AF_INET6, argv[2], &data[27]) != 1 + || str2uchar(argv[3], &data[25])) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + break; + + default: + if (str2uchar(argv[0], &data[0])) { + lprintf(LOG_ERR, "invalid value"); + return -1; + } + } + + return 0; +} + +static int +lanp_set_cfgp(void *priv, const struct ipmi_cfgp *p, const unsigned char *data) +{ + int ret; + int param = p->specific; + int off = 0; + + switch(param) { + case IPMI_LANP_IP6_DHCP6_CFG: + ret = ipmi_set_lanp(priv, param, &data[0]); + if (ret == 0) { + ret = ipmi_set_lanp(priv, param, &data[18]); + } + break; + + case IPMI_LANP_IP6_STATIC_RTR1_ADDR: + if (data[0] == 2) { + param = IPMI_LANP_IP6_STATIC_RTR2_ADDR; + } + off = 1; + + case IPMI_LANP_IP6_DYNAMIC_RTR_ADDR: + ret = ipmi_set_lanp(priv, param, &data[0 + off]); + if (ret == 0) { + ret = ipmi_set_lanp(priv, param + 1, &data[17 + off]); + } + if (ret == 0) { + ret = ipmi_set_lanp(priv, param + 2, &data[24 + off]); + } + if (ret == 0) { + ret = ipmi_set_lanp(priv, param + 3, &data[26 + off]); + } + break; + + + default: + ret = ipmi_set_lanp(priv, param, data); + } + + return ret; +} + +static int +lanp_get_cfgp(void *priv, const struct ipmi_cfgp *p, + int set, int block, unsigned char *data, int quiet) +{ + int ret; + int param = p->specific; + int off = 0; + + switch(param) { + case IPMI_LANP_IP6_DHCP6_CFG: + ret = ipmi_get_lanp(priv, param, set, 0, &data[0], quiet); + if (ret == 0) { + ret = ipmi_get_lanp(priv, param, set, + 1, &data[18], quiet); + } + break; + + case IPMI_LANP_IP6_STATIC_RTR1_ADDR: + if (set > 2) { + return -1; + } + + if (set == 2) { + param = IPMI_LANP_IP6_STATIC_RTR2_ADDR; + } + set = 0; + off = 1; + data[0] = data[17] = data[24] = data[26] = set; + + case IPMI_LANP_IP6_DYNAMIC_RTR_ADDR: + ret = ipmi_get_lanp(priv, param, set, block, + &data[0 + off], quiet); + if (ret == 0) { + ret = ipmi_get_lanp(priv, param + 1, set, block, + &data[17 + off], 0); + } + if (ret == 0) { + ret = ipmi_get_lanp(priv, param + 2, set, block, + &data[24 + off], 0); + } + if (ret == 0) { + ret = ipmi_get_lanp(priv, param + 3, set, block, + &data[26 + off], 0); + } + break; + + default: + ret = ipmi_get_lanp(priv, param, set, block, data, quiet); + } + + return ret; +} + +static int +lanp_save_cfgp(const struct ipmi_cfgp *p, const unsigned char *data, FILE *file) +{ + char addr[INET6_ADDRSTRLEN]; + char pfx[INET6_ADDRSTRLEN]; + const char *src; + + switch(p->specific) { + case IPMI_LANP_IP6_ENABLES: + fputs(val2str(data[0], ip6_enable_vals), file); + break; + + case IPMI_LANP_IP6_FLOW_LABEL: + fprintf(file, "0x%xd", (data[0] << 16 ) | (data[1] << 8) | data[2]); + break; + + case IPMI_LANP_IP6_STATUS: + fprintf(file, "%d %d %d", data[0], data[1], data[2]); + break; + + case IPMI_LANP_IP6_STATIC_ADDR: + case IPMI_LANP_IP6_DYNAMIC_ADDR: + if (p->specific == IPMI_LANP_IP6_STATIC_ADDR) { + src = val2str(data[1], ip6_addr_enable_vals); + } else { + src = val2str(data[1], ip6_addr_sources); + } + + fprintf(file, "%s %s %d %s", src, + inet_ntop(AF_INET6, &data[2], addr, sizeof(addr)), + data[18], val2str(data[19], ip6_addr_statuses)); + break; + + case IPMI_LANP_IP6_STATIC_DUID: + case IPMI_LANP_IP6_DYNAMIC_DUID: + case IPMI_LANP_IP6_NDSLAAC_CFG: + fprintf(file, "%s", buf2str(&data[2], 16)); + break; + + case IPMI_LANP_IP6_DHCP6_CFG: + fprintf(file, "%s", buf2str(&data[2], 16)); + fprintf(file, " %s", buf2str(&data[20], 6)); + break; + + case IPMI_LANP_IP6_ROUTER_CFG: + fputs(val2str(data[0], ip6_rtr_configs), file); + break; + + case IPMI_LANP_IP6_STATIC_RTR1_ADDR: + case IPMI_LANP_IP6_DYNAMIC_RTR_ADDR: + fprintf(file, "%s %s %s %d", + inet_ntop(AF_INET6, &data[1], addr, sizeof(addr)), + mac2str(&data[18]), + inet_ntop(AF_INET6, &data[27], pfx, sizeof(pfx)), data[25]); + break; + + default: + fprintf(file, "%d", data[0]); + } + + return 0; +} + + +static int +lanp_print_cfgp(const struct ipmi_cfgp *p, + int set, int block, const unsigned char *data, FILE *file) +{ + char addr[INET6_ADDRSTRLEN]; + char pfx[INET6_ADDRSTRLEN]; + const char *pname; + const struct ipmi_lanp *lanp = lookup_lanp(p->specific); + + if (!lanp || !p || !file || !data || !lanp->name) { + return -1; + } + pname = lanp->name; + + switch(p->specific) { + case IPMI_LANP_IP6_SUPPORT: + fprintf(file, "%s:\n" + " IPv6 only: %s\n" + " IPv4 and IPv6: %s\n" + " IPv6 Destination Addresses for LAN alerting: %s\n", + pname, + data[0] & 1 ? "yes" : "no", + data[0] & 2 ? "yes" : "no", + data[0] & 4 ? "yes" : "no"); + break; + + case IPMI_LANP_IP6_ENABLES: + fprintf(file, "%s: %s\n", + pname, val2str(data[0], ip6_enable_vals)); + break; + + case IPMI_LANP_IP6_FLOW_LABEL: + fprintf(file, "%s: %d\n", + pname, (data[0] << 16 ) | (data[1] << 8) | data[2]); + break; + + case IPMI_LANP_IP6_STATUS: + fprintf(file, "%s:\n" + " Static address max: %d\n" + " Dynamic address max: %d\n" + " DHCPv6 support: %s\n" + " SLAAC support: %s\n", + pname, + data[0], data[1], + (data[2] & 1) ? "yes" : "no", + (data[2] & 2) ? "yes" : "no"); + break; + + case IPMI_LANP_IP6_STATIC_ADDR: + fprintf(file, "%s %d:\n" + " Enabled: %s\n" + " Address: %s/%d\n" + " Status: %s\n", + pname, set, + (data[1] & 0x80) ? "yes" : "no", + inet_ntop(AF_INET6, &data[2], addr, sizeof(addr)), + data[18], val2str(data[19] & 0xF, ip6_addr_statuses)); + break; + + case IPMI_LANP_IP6_DYNAMIC_ADDR: + fprintf(file, "%s %d:\n" + " Source/Type: %s\n" + " Address: %s/%d\n" + " Status: %s\n", + pname, set, + val2str(data[1] & 0xF, ip6_addr_sources), + inet_ntop(AF_INET6, &data[2], addr, sizeof(addr)), + data[18], val2str(data[19] & 0xF, ip6_addr_statuses)); + break; + + case IPMI_LANP_IP6_STATIC_DUID: + case IPMI_LANP_IP6_DYNAMIC_DUID: + if (block == 0) { + fprintf(file, "%s %d:\n" + " Length: %d\n" + " Type: %s\n", + pname, set, data[2], + val2str((data[3] << 8) + data[4], ip6_duid_types)); + } + fprintf(file, " %s\n", buf2str(&data[2], 16)); + break; + + case IPMI_LANP_IP6_DHCP6_CFG_SUP: + case IPMI_LANP_IP6_NDSLAAC_CFG_SUP: + fprintf(file, "%s: %s\n", + pname, val2str(data[0], ip6_cfg_sup_vals)); + break; + + case IPMI_LANP_IP6_DHCP6_CFG: + fprintf(file, "%s %d:\n", pname, set); + + fprintf(file, + " SOL_MAX_DELAY: %d\n" + " SOL_TIMEOUT: %d\n" + " SOL_MAX_RT: %d\n" + " REQ_TIMEOUT: %d\n" + " REQ_MAX_RT: %d\n" + " REQ_MAX_RC: %d\n" + " CNF_MAX_DELAY: %d\n" + " CNF_TIMEOUT: %d\n" + " CNF_MAX_RT: %d\n" + " CNF_MAX_RD: %d\n" + " REN_TIMEOUT: %d\n" + " REN_MAX_RT: %d\n" + " REB_TIMEOUT: %d\n" + " REB_MAX_RT: %d\n" + " INF_MAX_DELAY: %d\n" + " INF_TIMEOUT: %d\n" + " INF_MAX_RT: %d\n" + " REL_TIMEOUT: %d\n" + " REL_MAX_RC: %d\n" + " DEC_TIMEOUT: %d\n" + " DEC_MAX_RC: %d\n" + " HOP_COUNT_LIMIT: %d\n", + data[2], data[3], data[4], data[5], + data[6], data[7], data[8], data[9], + data[10], data[11], data[12], data[13], + data[14], data[15], data[16], data[17], + data[20], data[21], data[22], data[23], + data[24], data[25]); + break; + + case IPMI_LANP_IP6_ROUTER_CFG: + fprintf(file, "%s:\n" + " Enable static router address: %s\n" + " Enable dynamic router address: %s\n", + pname, + (data[0] & 1) ? "yes" : "no", + (data[0] & 2) ? "yes" : "no"); + break; + + case IPMI_LANP_IP6_STATIC_RTR1_ADDR: + case IPMI_LANP_IP6_DYNAMIC_RTR_ADDR: + if (p->specific == IPMI_LANP_IP6_STATIC_RTR1_ADDR) { + pname = "IPv6 Static Router"; + } else { + pname = "IPv6 Dynamic Router"; + } + + fprintf(file, "%s %d:\n" + " Address: %s\n" + " MAC: %s\n" + " Prefix: %s/%d\n", + pname, set, + inet_ntop(AF_INET6, &data[1], addr, sizeof(addr)), + mac2str(&data[18]), + inet_ntop(AF_INET6, &data[27], pfx, sizeof(pfx)), data[25]); + break; + + case IPMI_LANP_IP6_NDSLAAC_CFG: + fprintf(file, "%s %d:\n" + " MAX_RTR_SOLICITATION_DELAY: %d\n" + " RTR_SOLICITATION_INTERVAL: %d\n" + " MAX_RTR_SOLICITATIONS: %d\n" + " DupAddrDetectTransmits: %d\n" + " MAX_MULTICAST_SOLICIT: %d\n" + " MAX_UNICAST_SOLICIT: %d\n" + " MAX_ANYCAST_DELAY_TIME: %d\n" + " MAX_NEIGHBOR_ADVERTISEMENT: %d\n" + " REACHABLE_TIME: %d\n" + " RETRANS_TIMER: %d\n" + " DELAY_FIRST_PROBE_TIME: %d\n" + " MAX_RANDOM_FACTOR: %d\n" + " MIN_RANDOM_FACTOR: %d\n", + pname, set, + data[2], data[3], data[4], data[5], + data[6], data[7], data[8], data[9], + data[10], data[11], data[12], data[13], + data[14]); + break; + + default: + fprintf(file, "%s: %d\n", pname, data[0]); + } + + return 0; +} + +static int +lanp_ip6_cfgp(void *priv, const struct ipmi_cfgp *p, + const struct ipmi_cfgp_action *action, unsigned char *data) +{ + switch (action->type) { + case CFGP_PARSE: + return lanp_parse_cfgp(p, action->set, action->block, + action->argc, action->argv, data); + + case CFGP_GET: + return lanp_get_cfgp(priv, p, action->set, action->block, + data, action->quiet); + + case CFGP_SET: + return lanp_set_cfgp(priv, p, data); + + case CFGP_SAVE: + return lanp_save_cfgp(p, data, action->file); + + case CFGP_PRINT: + return lanp_print_cfgp(p, action->set, action->block, + data, action->file); + + default: + return -1; + } + + return 0; +} + +static void lanp_print_usage(int cmd) +{ + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_HELP) { + printf(" help [command]\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_SAVE) { + printf(" save <channel> [<parameter> [<set_sel> [<block_sel>]]]\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_SET) { + printf(" set <channel> [nolock] <parameter> [<set_sel> [<block_sel>]] <values...>\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_PRINT) { + printf(" print <channel> [<parameter> [<set_sel> [<block_sel>]]]\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_LOCK) { + printf(" lock <channel>\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_COMMIT) { + printf(" commit <channel>\n"); + } + if (cmd == LANP_CMD_ANY || cmd == LANP_CMD_DISCARD) { + printf(" discard <channel>\n"); + } + if (cmd == LANP_CMD_SAVE + || cmd == LANP_CMD_PRINT + || cmd == LANP_CMD_SET) { + printf("\n available parameters:\n"); + /* 'save' shall use 'write' filter, since it outputs a block + * of 'set's */ + ipmi_cfgp_usage(lan_cfgp, + sizeof(lan_cfgp)/sizeof(lan_cfgp[0]), + cmd != LANP_CMD_PRINT); + } +} + +static int +lanp_lock(struct ipmi_lanp_priv *lp) +{ + unsigned char byte = 1; + + return ipmi_set_lanp(lp, 0, &byte); +} + +static int +lanp_discard(struct ipmi_lanp_priv *lp) +{ + unsigned char byte = 0; + + return ipmi_set_lanp(lp, 0, &byte); +} + +static int +lanp_commit(struct ipmi_lanp_priv *lp) +{ + unsigned char byte = 2; + int ret; + + ret = ipmi_set_lanp(lp, 0, &byte); + if (ret == 0) { + ret = lanp_discard(lp); + } + + return ret; +} + +int +ipmi_lan6_main(struct ipmi_intf *intf, int argc, char **argv) +{ + struct ipmi_cfgp_ctx ctx; + struct ipmi_cfgp_sel sel; + struct ipmi_lanp_priv lp; + int cmd; + int chan; + int nolock = 0; + int ret; + + if (argc == 0) { + lanp_print_usage(LANP_CMD_ANY); + return 0; + } + + cmd = str2val(argv[0], ip6_command_vals); + if (cmd == LANP_CMD_ANY) { + lanp_print_usage(cmd); + return -1; + } + + if (cmd == LANP_CMD_HELP) { + if (argc == 1) { + cmd = LANP_CMD_ANY; + } else { + cmd = str2val(argv[1], ip6_command_vals); + } + + lanp_print_usage(cmd); + return 0; + } + + /* + * the rest commands expect channel number + * with the exception of 'get' and 'print' + */ + if (argc == 1) { + if (cmd == LANP_CMD_SAVE || cmd == LANP_CMD_PRINT) { + chan = find_lan_channel(intf, 1); + if (chan == 0) { + lprintf(LOG_ERR, "No LAN channel found"); + return -1; + } + } else { + lanp_print_usage(cmd); + return -1; + } + + argc -= 1; + argv += 1; + } else { + if (str2int(argv[1], &chan) != 0) { + lprintf(LOG_ERR, "Invalid channel: %s", argv[1]); + return -1; + } + + argc -= 2; + argv += 2; + + if (cmd == LANP_CMD_SET) { + if (argc && !strcasecmp(argv[0], "nolock")) { + nolock = 1; + + argc -= 1; + argv += 1; + } + } + + } + + lp.intf = intf; + lp.channel = chan; + + /* + * lock/commit/discard commands do not require parsing + * of parameter selection + */ + + switch (cmd) { + case LANP_CMD_LOCK: + lprintf(LOG_NOTICE, "Lock parameter(s)..."); + return lanp_lock(&lp); + + case LANP_CMD_COMMIT: + lprintf(LOG_NOTICE, "Commit parameter(s)..."); + return lanp_commit(&lp); + + case LANP_CMD_DISCARD: + lprintf(LOG_NOTICE, "Discard parameter(s)..."); + return lanp_discard(&lp); + } + + /* + * initialize configuration context and parse parameter selection + */ + + ipmi_cfgp_init(&ctx, lan_cfgp, + sizeof(lan_cfgp)/sizeof(lan_cfgp[0]), "lan6 set nolock", + lanp_ip6_cfgp, &lp); + + ret = ipmi_cfgp_parse_sel(&ctx, argc, (const char **)argv, &sel); + if (ret == -1) { + lanp_print_usage(cmd); + ipmi_cfgp_uninit(&ctx); + return -1; + } + + argc -= ret; + argv += ret; + + /* + * handle the rest commands + */ + + switch (cmd) { + case LANP_CMD_SAVE: + case LANP_CMD_PRINT: + lprintf(LOG_NOTICE, "Getting parameter(s)..."); + + ret = ipmi_cfgp_get(&ctx, &sel); + if (ret != 0) { + break; + } + + if (cmd == LANP_CMD_SAVE) { + static char cmd[20]; + FILE *out = stdout; + snprintf(cmd, sizeof(cmd) - 1, "lan6 set %d nolock", + lp.channel); + cmd[sizeof(cmd) - 1] = '\0'; + ctx.cmdname = cmd; + fprintf(out, "lan6 lock %d\n", lp.channel); + ret = ipmi_cfgp_save(&ctx, &sel, out); + fprintf(out, "lan6 commit %d\nlan6 discard %d\nexit\n", + lp.channel, lp.channel); + } else { + ret = ipmi_cfgp_print(&ctx, &sel, stdout); + } + break; + + case LANP_CMD_SET: + ret = ipmi_cfgp_parse_data(&ctx, &sel, argc, + (const char **)argv); + if (ret != 0) { + break; + } + + lprintf(LOG_NOTICE, "Setting parameter(s)..."); + + if (!nolock) { + ret = lanp_lock(&lp); + if (ret != 0) { + break; + } + } + + ret = ipmi_cfgp_set(&ctx, &sel); + if (!nolock) { + if (ret == 0) { + ret = lanp_commit(&lp); + } else { + lanp_discard(&lp); + } + } + break; + } + + /* + * free allocated memory + */ + ipmi_cfgp_uninit(&ctx); + + return ret; +} diff --git a/lib/ipmi_main.c b/lib/ipmi_main.c index e6f96f6..811c80b 100644 --- a/lib/ipmi_main.c +++ b/lib/ipmi_main.c @@ -291,69 +291,6 @@ void ipmi_catch_sigint() exit(-1); } -/* ipmi_parse_hex - convert hexadecimal numbers to ascii string - * Input string must be composed of two-characer hexadecimal numbers. - * There is no separator between the numbers. Each number results in one character - * of the converted string. - * - * Example: ipmi_parse_hex("50415353574F5244") returns 'PASSWORD' - * - * @param str: input string. It must contain only even number of '0'-'9','a'-'f' and 'A-F' characters. - * @returns converted ascii string - * @returns NULL on error - */ -static unsigned char * -ipmi_parse_hex(const char *str) -{ - const char * p; - unsigned char * out, *q; - unsigned char b = 0; - int shift = 4; - - if (strlen(str) == 0) - return NULL; - - if (strlen(str) % 2 != 0) { - lprintf(LOG_ERR, "Number of hex_kg characters is not even"); - return NULL; - } - - if (strlen(str) > (IPMI_KG_BUFFER_SIZE-1)*2) { - lprintf(LOG_ERR, "Kg key is too long"); - return NULL; - } - - out = calloc(IPMI_KG_BUFFER_SIZE, sizeof(unsigned char)); - if (out == NULL) { - lprintf(LOG_ERR, "malloc failure"); - return NULL; - } - - for (p = str, q = out; *p; p++) { - if (!isxdigit(*p)) { - lprintf(LOG_ERR, "Kg_hex is not hexadecimal number"); - free(out); - out = NULL; - return NULL; - } - - if (*p < 'A') /* it must be 0-9 */ - b = *p - '0'; - else /* it's A-F or a-f */ - b = (*p | 0x20) - 'a' + 10; /* convert to lowercase and to 10-15 */ - - *q = *q + (b << shift); - if (shift) - shift = 0; - else { - shift = 4; - q++; - } - } - - return out; -} - static uint8_t ipmi_acquire_ipmb_address(struct ipmi_intf * intf) { @@ -406,7 +343,7 @@ ipmi_main(int argc, char ** argv, char * progname = NULL; char * oemtype = NULL; char * sdrcache = NULL; - unsigned char * kgkey = NULL; + uint8_t kgkey[IPMI_KG_BUFFER_SIZE]; char * seloem = NULL; int port = 0; int devnum = 0; @@ -421,6 +358,7 @@ ipmi_main(int argc, char ** argv, progname = strrchr(argv[0], '/'); progname = ((progname == NULL) ? argv[0] : progname+1); signal(SIGINT, ipmi_catch_sigint); + memset(kgkey, 0, sizeof(kgkey)); while ((argflag = getopt(argc, (char **)argv, OPTION_STRING)) != -1) { @@ -547,38 +485,30 @@ ipmi_main(int argc, char ** argv, } break; case 'k': - if (kgkey) { - free(kgkey); - kgkey = NULL; - } - kgkey = strdup(optarg); - if (kgkey == NULL) { - lprintf(LOG_ERR, "%s: malloc failure", progname); - goto out_free; - } + memset(kgkey, 0, sizeof(kgkey)); + strncpy((char *)kgkey, optarg, sizeof(kgkey) - 1); break; case 'K': if ((tmp_env = getenv("IPMI_KGKEY"))) { - if (kgkey) { - free(kgkey); - kgkey = NULL; - } - kgkey = strdup(tmp_env); - if (kgkey == NULL) { - lprintf(LOG_ERR, "%s: malloc failure", progname); - goto out_free; - } + memset(kgkey, 0, sizeof(kgkey)); + strncpy((char *)kgkey, tmp_env, + sizeof(kgkey) - 1); } else { lprintf(LOG_WARN, "Unable to read kgkey from environment"); } break; case 'y': - if (kgkey) { - free(kgkey); - kgkey = NULL; - } - kgkey = ipmi_parse_hex(optarg); - if (kgkey == NULL) { + memset(kgkey, 0, sizeof(kgkey)); + + rc = ipmi_parse_hex(optarg, kgkey, sizeof(kgkey) - 1); + if (rc == -1) { + lprintf(LOG_ERR, "Number of Kg key characters is not even"); + goto out_free; + } else if (rc == -3) { + lprintf(LOG_ERR, "Kg key is not hexadecimal number"); + goto out_free; + } else if (rc > (IPMI_KG_BUFFER_SIZE-1)) { + lprintf(LOG_ERR, "Kg key is too long"); goto out_free; } break; @@ -589,16 +519,10 @@ ipmi_main(int argc, char ** argv, tmp_pass = getpass("Key: "); #endif if (tmp_pass != NULL) { - if (kgkey) { - free(kgkey); - kgkey = NULL; - } - kgkey = strdup(tmp_pass); + memset(kgkey, 0, sizeof(kgkey)); + strncpy((char *)kgkey, tmp_pass, + sizeof(kgkey) - 1); tmp_pass = NULL; - if (kgkey == NULL) { - lprintf(LOG_ERR, "%s: malloc failure", progname); - goto out_free; - } } break; case 'U': @@ -928,8 +852,7 @@ ipmi_main(int argc, char ** argv, ipmi_intf_session_set_username(ipmi_main_intf, username); if (password != NULL) ipmi_intf_session_set_password(ipmi_main_intf, password); - if (kgkey != NULL) - ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey); + ipmi_intf_session_set_kgkey(ipmi_main_intf, kgkey); if (port > 0) ipmi_intf_session_set_port(ipmi_main_intf, port); if (authtype >= 0) @@ -1123,10 +1046,6 @@ ipmi_main(int argc, char ** argv, free(seloem); seloem = NULL; } - if (kgkey != NULL) { - free(kgkey); - kgkey = NULL; - } if (sdrcache != NULL) { free(sdrcache); sdrcache = NULL; diff --git a/lib/ipmi_mc.c b/lib/ipmi_mc.c index 5b4a080..4580bfb 100644 --- a/lib/ipmi_mc.c +++ b/lib/ipmi_mc.c @@ -462,78 +462,79 @@ ipmi_mc_get_deviceid(struct ipmi_intf * intf) return 0; } -/* Structure follow the IPMI V.2 Rev 1.0 - * See Table 20-10 */ -#ifdef HAVE_PRAGMA_PACK -#pragma pack(1) -#endif - -struct ipmi_guid { - uint32_t time_low; /* timestamp low field */ - uint16_t time_mid; /* timestamp middle field */ - uint16_t time_hi_and_version; /* timestamp high field and version number */ - uint8_t clock_seq_hi_variant;/* clock sequence high field and variant */ - uint8_t clock_seq_low; /* clock sequence low field */ - uint8_t node[6]; /* node */ -} ATTRIBUTE_PACKING; -#ifdef HAVE_PRAGMA_PACK -#pragma pack(0) -#endif - -/* ipmi_mc_get_guid - print this MC GUID +/* _ipmi_mc_get_guid - Gets BMCs GUID according to (22.14) * * @intf: ipmi interface + * @guid: pointer where to store BMC GUID * - * returns 0 on success - * returns -1 on error + * returns - negative number means error, positive is a ccode. */ -static int -ipmi_mc_get_guid(struct ipmi_intf * intf) +int +_ipmi_mc_get_guid(struct ipmi_intf *intf, struct ipmi_guid_t *guid) { - struct ipmi_rs * rsp; + struct ipmi_rs *rsp; struct ipmi_rq req; - struct ipmi_guid guid; + if (guid == NULL) { + return (-3); + } + memset(guid, 0, sizeof(struct ipmi_guid_t)); memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_GUID; rsp = intf->sendrecv(intf, &req); if (rsp == NULL) { - lprintf(LOG_ERR, "Get GUID command failed"); - return -1; - } - if (rsp->ccode > 0) { - lprintf(LOG_ERR, "Get GUID command failed: %s", - val2str(rsp->ccode, completion_code_vals)); - return -1; - } - - if (rsp->data_len == sizeof(struct ipmi_guid)) { - char tbuf[40]; - time_t s; - memset(tbuf, 0, 40); - memset(&guid, 0, sizeof(struct ipmi_guid)); - memcpy(&guid, rsp->data, rsp->data_len); - - /* Kipp - changed order of last field (node) to follow specification */ - printf("System GUID : %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n", - guid.time_low, guid.time_mid, guid.time_hi_and_version, - guid.clock_seq_hi_variant << 8 | guid.clock_seq_low, - guid.node[0], guid.node[1], guid.node[2], - guid.node[3], guid.node[4], guid.node[5]); - - s = (time_t)guid.time_low; /* Kipp - removed the BSWAP_32, it was not needed here */ - strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", localtime(&s)); - printf("Timestamp : %s\n", tbuf); - } - else { - lprintf(LOG_ERR, "Invalid GUID length %d", rsp->data_len); + return (-1); + } else if (rsp->ccode > 0) { + return rsp->ccode; + } else if (rsp->data_len != 16 + || rsp->data_len != sizeof(struct ipmi_guid_t)) { + return (-2); } + memcpy(guid, &rsp->data[0], sizeof(struct ipmi_guid_t)); + return 0; +} +/* ipmi_mc_print_guid - print-out given BMC GUID + * + * @guid - struct with GUID. + * + * returns 0 + */ +static int +ipmi_mc_print_guid(struct ipmi_guid_t guid) +{ + char tbuf[40]; + time_t s; + memset(tbuf, 0, 40); + /* Kipp - changed order of last field (node) to follow specification */ + printf("System GUID : %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\n", + guid.time_low, guid.time_mid, guid.time_hi_and_version, + guid.clock_seq_hi_variant << 8 | guid.clock_seq_low, + guid.node[0], guid.node[1], guid.node[2], + guid.node[3], guid.node[4], guid.node[5]); + + s = (time_t)guid.time_low; /* Kipp - removed the BSWAP_32, it was not needed here */ + strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", localtime(&s)); + printf("Timestamp : %s\n", tbuf); return 0; } +/* ipmi_mc_get_guid - Gets and prints-out System GUID */ +int +ipmi_mc_get_guid(struct ipmi_intf *intf) +{ + struct ipmi_guid_t guid; + int rc; + rc = _ipmi_mc_get_guid(intf, &guid); + if (eval_ccode(rc) != 0) { + return (-1); + } + rc = ipmi_mc_print_guid(guid); + return rc; +} + /* ipmi_mc_get_selftest - returns and print selftest results * * @intf: ipmi interface diff --git a/lib/ipmi_pef.c b/lib/ipmi_pef.c index 22f29e4..bbf25f2 100644 --- a/lib/ipmi_pef.c +++ b/lib/ipmi_pef.c @@ -36,10 +36,13 @@ #include <ipmitool/bswap.h> #include <ipmitool/helper.h> -#include <ipmitool/log.h> #include <ipmitool/ipmi.h> +#include <ipmitool/ipmi_channel.h> #include <ipmitool/ipmi_intf.h> +#include <ipmitool/ipmi_mc.h> #include <ipmitool/ipmi_pef.h> +#include <ipmitool/ipmi_sel.h> +#include <ipmitool/log.h> extern int verbose; /* @@ -75,6 +78,8 @@ static const char * pef_flag_fmts[][3] = { }; static const char * listitem[] = {" | %s", ",%s", "%s"}; +static int ipmi_pef2_list_filters(struct ipmi_intf *); + const char * ipmi_pef_bit_desc(struct bit_desc_map * map, uint32_t value) { /* @@ -184,6 +189,31 @@ ipmi_pef_print_1xd(const char * text, uint32_t val) ipmi_pef_print_field(pef_fld_fmts[F_1XD], text, val); } +/* ipmi_pef_print_guid - print-out GUID. */ +static int +ipmi_pef_print_guid(uint8_t *guid) +{ + if (guid == NULL) { + return (-1); + } + + if (verbose) { + printf("%-*s : %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + KYWD_LENGTH, "System GUID", + guid[0], guid[1], guid[2], guid[3], guid[4], + guid[5], guid[6], guid[7], guid[8], guid[9], + guid[10],guid[11], guid[12], guid[13], guid[14], + guid[15]); + } else { + printf(" | %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + guid[0], guid[1], guid[2], guid[3], guid[4], + guid[5], guid[6], guid[7], guid[8], guid[9], + guid[10], guid[11], guid[12], guid[13], guid[14], + guid[15]); + } + return 0; +} + static struct ipmi_rs * ipmi_pef_msg_exchange(struct ipmi_intf * intf, struct ipmi_rq * req, char * txt) { /* @@ -204,58 +234,423 @@ ipmi_pef_msg_exchange(struct ipmi_intf * intf, struct ipmi_rq * req, char * txt) return(rsp); } -static uint8_t -ipmi_pef_get_policy_table(struct ipmi_intf * intf, - struct pef_cfgparm_policy_table_entry ** table) -{ /* - // get the PEF policy table: allocate space, fillin, and return its size - // NB: the caller must free the returned area (when returned size > 0) - */ - struct ipmi_rs * rsp; +/* _ipmi_get_pef_capabilities - Requests and returns result of (30.1) Get PEF + * Capabilities. + * + * @pcap - pointer where to store results. + * + * returns - negative number means error, positive is a ccode. + */ +int +_ipmi_get_pef_capabilities(struct ipmi_intf *intf, + struct pef_capabilities *pcap) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + if (pcap == NULL) { + return (-3); + } + + memset(pcap, 0, sizeof(struct pef_capabilities)); + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CAPABILITIES; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 3) { + return (-2); + } + pcap->version = rsp->data[0]; + pcap->actions = rsp->data[1]; + pcap->event_filter_count = rsp->data[2]; + return 0; +} + +/* _ipmi_get_pef_filter_entry - Fetches one Entry from Event Filter Table + * identified by Filter ID. + * + * @filter_id - Filter ID of Entry in Event Filter Table. + * @filter_entry - Pointer where to copy Filter Entry data. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_get_pef_filter_entry(struct ipmi_intf *intf, uint8_t filter_id, + struct pef_cfgparm_filter_table_entry *filter_entry) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t data[3]; + uint8_t data_len = 3 * sizeof(uint8_t); + int dest_size; + if (filter_entry == NULL) { + return (-3); + } + + dest_size = (int)sizeof(struct pef_cfgparm_filter_table_entry); + memset(filter_entry, 0, dest_size); + memset(&data, 0, data_len); + data[0] = PEF_CFGPARM_ID_PEF_FILTER_TABLE_ENTRY; + data[1] = filter_id; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&data; + req.msg.data_len = data_len; + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 22 || (rsp->data_len - 1) != dest_size) { + return (-2); + } + memcpy(filter_entry, &rsp->data[1], dest_size); + return 0; +} + +/* _ipmi_get_pef_filter_entry_cfg - Fetches configuration of one Entry from + * Event Filter Table identified by Filter ID. + * + * @filter_id - Filter ID of Entry in Event Filter Table. + * @filter_entry_cfg - Pointer where to copy Filter Entry configuration. + * + * returns - negative number means error, positive is a ccode. + */ +int +_ipmi_get_pef_filter_entry_cfg(struct ipmi_intf *intf, uint8_t filter_id, + struct pef_cfgparm_filter_table_data_1 *filter_cfg) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t data[3]; + uint8_t data_len = 3 * sizeof(uint8_t); + int dest_size; + if (filter_cfg == NULL) { + return (-3); + } + + dest_size = (int)sizeof(struct pef_cfgparm_filter_table_data_1); + memset(filter_cfg, 0, dest_size); + memset(&data, 0, data_len); + data[0] = PEF_CFGPARM_ID_PEF_FILTER_TABLE_DATA_1; + data[1] = filter_id; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&data; + req.msg.data_len = data_len; + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 3 || (rsp->data_len - 1) != dest_size) { + return (-2); + } + memcpy(filter_cfg, &rsp->data[1], dest_size); + return 0; +} + +/* _ipmi_get_pef_policy_entry - Fetches one Entry from Alert Policy Table + * identified by Policy ID. + * + * @policy_id - Policy ID of Entry in Alert Policy Table. + * @policy_entry - Pointer where to copy Policy Entry data. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_get_pef_policy_entry(struct ipmi_intf *intf, uint8_t policy_id, + struct pef_cfgparm_policy_table_entry *policy_entry) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t data[3]; + uint8_t data_len = 3 * sizeof(uint8_t); + int dest_size; + if (policy_entry == NULL) { + return (-3); + } + + dest_size = (int)sizeof(struct pef_cfgparm_policy_table_entry); + memset(policy_entry, 0, dest_size); + memset(&data, 0, data_len); + data[0] = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_ENTRY; + data[1] = policy_id & PEF_POLICY_TABLE_ID_MASK; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&data; + req.msg.data_len = data_len; + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 5 || (rsp->data_len - 1) != dest_size) { + return (-2); + } + memcpy(policy_entry, &rsp->data[1], dest_size); + return 0; +} + +/* _ipmi_get_pef_filter_table_size - Fetch the Number of Event Filter Entries. + * If the number is 0, it means feature is not supported. + * + * @table_size - ptr to where to store number of entries. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_get_pef_filter_table_size(struct ipmi_intf *intf, uint8_t *table_size) +{ + struct ipmi_rs *rsp; struct ipmi_rq req; struct pef_cfgparm_selector psel; - struct pef_cfgparm_policy_table_entry * ptbl, * ptmp; - uint32_t i; - uint8_t tbl_size; + if (table_size == NULL) { + return (-3); + } + + *table_size = 0; + memset(&psel, 0, sizeof(psel)); + psel.id = PEF_CFGPARM_ID_PEF_FILTER_TABLE_SIZE; + memset(&req, 0, sizeof(req)); + + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&psel; + req.msg.data_len = sizeof(psel); + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 2) { + return (-2); + } + *table_size = rsp->data[1] & 0x7F; + return 0; +} + +/* _ipmi_get_pef_policy_table_size - Fetch the Number of Alert Policy Entries. If the + * number is 0, it means feature is not supported. + * + * @table_size - ptr to where to store number of entries. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_get_pef_policy_table_size(struct ipmi_intf *intf, uint8_t *table_size) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct pef_cfgparm_selector psel; + + if (table_size == NULL) { + return (-3); + } + + *table_size = 0; memset(&psel, 0, sizeof(psel)); psel.id = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_SIZE; memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; req.msg.data = (uint8_t *)&psel; req.msg.data_len = sizeof(psel); - rsp = ipmi_pef_msg_exchange(intf, &req, "Alert policy table size"); - if (!rsp) - return(0); - tbl_size = (rsp->data[1] & PEF_POLICY_TABLE_SIZE_MASK); - i = (tbl_size * sizeof(struct pef_cfgparm_policy_table_entry)); - if (!i - || (ptbl = (struct pef_cfgparm_policy_table_entry *)malloc(i)) == NULL) - return(0); + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 2) { + return (-2); + } + *table_size = rsp->data[1] & 0x7F; + return 0; +} + +/* _ipmi_get_pef_system_guid - Fetches System GUID from PEF. This configuration + * parameter is optional. If data1 is 0x0, then this GUID is ignored by BMC. + * + * @system_guid - pointer where to store received data. + * + * returns - negative number means error, positive is a ccode. + */ +int +_ipmi_get_pef_system_guid(struct ipmi_intf *intf, + struct pef_cfgparm_system_guid *system_guid) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct pef_cfgparm_selector psel; + if (system_guid == NULL) { + return (-3); + } + memset(system_guid, 0, sizeof(struct pef_cfgparm_system_guid)); memset(&psel, 0, sizeof(psel)); - psel.id = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_ENTRY; - for (ptmp=ptbl, i=1; i<=tbl_size; i++) { - psel.set = (i & PEF_POLICY_TABLE_ID_MASK); - rsp = ipmi_pef_msg_exchange(intf, &req, "Alert policy table entry"); - if (!rsp - || i != (rsp->data[1] & PEF_POLICY_TABLE_ID_MASK)) { - lprintf(LOG_ERR, " **Error retrieving %s", - "Alert policy table entry"); - free(ptbl); - ptbl = NULL; - tbl_size = 0; - break; - } - memcpy(ptmp, &rsp->data[1], sizeof(*ptmp)); - ptmp++; + psel.id = PEF_CFGPARM_ID_SYSTEM_GUID; + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&psel; + req.msg.data_len = sizeof(psel); + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } else if (rsp->data_len != 18 + || (rsp->data_len - 2) != sizeof(system_guid->guid)) { + return (-2); + } + system_guid->data1 = rsp->data[1] & 0x1; + memcpy(system_guid->guid, &rsp->data[2], sizeof(system_guid->guid)); + return 0; +} + +/* _ipmi_set_pef_filter_entry_cfg - Sets/updates configuration of Entry in Event + * Filter Table identified by Filter ID. + * + * @filter_id - ID of Entry in Event Filter Table to be updated + * @filter_cfg - Pointer to configuration data. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_set_pef_filter_entry_cfg(struct ipmi_intf *intf, uint8_t filter_id, + struct pef_cfgparm_filter_table_data_1 *filter_cfg) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + uint8_t data[3]; + uint8_t data_len = 3 * sizeof(uint8_t); + if (filter_cfg == NULL) { + return (-3); } - *table = ptbl; - return(tbl_size); + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_SET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&data; + req.msg.data_len = data_len; + + memset(&data, 0, data_len); + data[0] = PEF_CFGPARM_ID_PEF_FILTER_TABLE_DATA_1; + data[1] = filter_id; + data[2] = filter_cfg->cfg; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } + return 0; +} + +/* _ipmi_set_pef_policy_entry - Sets/updates Entry in Alert Policy Table identified by + * Policy ID. + * + * @policy_id - Policy ID of Entry in Alert Policy Table to be updated + * @policy_entry - Pointer to data. + * + * returns - negative number means error, positive is a ccode. + */ +static int +_ipmi_set_pef_policy_entry(struct ipmi_intf *intf, uint8_t policy_id, + struct pef_cfgparm_policy_table_entry *policy_entry) +{ + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct pef_cfgparm_set_policy_table_entry payload; + if (policy_entry == NULL) { + return (-3); + } + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = IPMI_CMD_SET_PEF_CONFIG_PARMS; + req.msg.data = (uint8_t *)&payload; + req.msg.data_len = sizeof(payload); + + memset(&payload, 0, sizeof(payload)); + payload.param_selector = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_ENTRY; + payload.policy_id = policy_id & PEF_POLICY_TABLE_ID_MASK; + memcpy(&payload.entry, &policy_entry->entry, + sizeof(policy_entry->entry)); + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + return (-1); + } else if (rsp->ccode != 0) { + return rsp->ccode; + } + return 0; +} + +static void +ipmi_pef_print_oem_lan_dest(struct ipmi_intf *intf, uint8_t ch, uint8_t dest) +{ + char address[128]; + int len; + int rc; + int rlen; + int set; + uint8_t data[32]; + + if (ipmi_get_oem(intf) != IPMI_OEM_DELL) { + return; + } + /* Get # of IPV6 trap destinations */ + rc = ipmi_mc_getsysinfo(intf, IPMI_SYSINFO_DELL_IPV6_COUNT, 0x00, 0x00, 4, data); + if (rc != 0 || dest > data[0]) { + return; + } + ipmi_pef_print_str("Alert destination type", "xxx"); + ipmi_pef_print_str("PET Community", "xxx"); + ipmi_pef_print_dec("ACK timeout/retry (secs)", 0); + ipmi_pef_print_dec("Retries", 0); + + /* Get IPv6 destination string (may be in multiple sets) */ + memset(address, 0, sizeof(address)); + memset(data, 0, sizeof(data)); + rc = ipmi_mc_getsysinfo(intf, IPMI_SYSINFO_DELL_IPV6_DESTADDR, 0x00, dest, 19, data); + if (rc != 0) { + return; + } + /* Total length of IPv6 string */ + len = data[4]; + if ((rlen = len) > (IPMI_SYSINFO_SET0_SIZE-3)) { + /* First set has 11 bytes */ + rlen = IPMI_SYSINFO_SET0_SIZE - 3; + } + memcpy(address, data + 8, rlen); + for (set = 1; len > 11; set++) { + rc = ipmi_mc_getsysinfo(intf, IPMI_SYSINFO_DELL_IPV6_DESTADDR, set, dest, 19, data); + if ((rlen = len - 11) >= (IPMI_SYSINFO_SETN_SIZE - 2)) { + /* Remaining sets have 14 bytes */ + rlen = IPMI_SYSINFO_SETN_SIZE - 2; + } + memcpy(address + (set * 11), data + 3, rlen); + len -= rlen+3; + } + ipmi_pef_print_str("IPv6 Address", address); } +/* TODO - rewrite */ static void ipmi_pef_print_lan_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) { /* @@ -325,16 +720,13 @@ ipmi_pef_print_lan_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) pinfo->ip[0], pinfo->ip[1], pinfo->ip[2], pinfo->ip[3]); ipmi_pef_print_str("IP address", buf); - sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", - pinfo->mac[0], pinfo->mac[1], pinfo->mac[2], - pinfo->mac[3], pinfo->mac[4], pinfo->mac[5]); - ipmi_pef_print_str("MAC address", buf); + ipmi_pef_print_str("MAC address", mac2str(pinfo->mac)); } } static void -ipmi_pef_print_serial_dest_dial(struct ipmi_intf * intf, char * label, - struct pef_serial_cfgparm_selector * ssel) +ipmi_pef_print_serial_dest_dial(struct ipmi_intf *intf, char *label, + struct pef_serial_cfgparm_selector *ssel) { /* // print a dial string */ @@ -381,8 +773,8 @@ ipmi_pef_print_serial_dest_dial(struct ipmi_intf * intf, char * label, } static void -ipmi_pef_print_serial_dest_tap(struct ipmi_intf * intf, - struct pef_serial_cfgparm_selector * ssel) +ipmi_pef_print_serial_dest_tap(struct ipmi_intf *intf, + struct pef_serial_cfgparm_selector *ssel) { /* // print TAP destination info */ @@ -431,28 +823,21 @@ ipmi_pef_print_serial_dest_tap(struct ipmi_intf * intf, /* TODO : additional TAP settings? */ } +/* static void -ipmi_pef_print_serial_dest_ppp(struct ipmi_intf * intf, - struct pef_serial_cfgparm_selector * ssel) -{ /* - // print PPP destination info - */ - - /* TODO */ +ipmi_pef_print_serial_dest_ppp(struct ipmi_intf *intf, + struct pef_serial_cfgparm_selector *ssel) +{ } static void -ipmi_pef_print_serial_dest_callback(struct ipmi_intf * intf, - struct pef_serial_cfgparm_selector * ssel) -{ /* - // print callback destination info - */ - - /* TODO */ +ipmi_pef_print_serial_dest_callback(struct ipmi_intf *intf, + struct pef_serial_cfgparm_selector *ssel) } +*/ static void -ipmi_pef_print_serial_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) +ipmi_pef_print_serial_dest(struct ipmi_intf *intf, uint8_t ch, uint8_t dest) { /* // print Serial/PPP alert destination info */ @@ -479,6 +864,10 @@ ipmi_pef_print_serial_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) tbl_size = (rsp->data[1] & PEF_SERIAL_DEST_TABLE_SIZE_MASK); if (!dest || tbl_size == 0) /* Page alerting not supported */ return; + if (dest > tbl_size) { + ipmi_pef_print_oem_lan_dest(intf, ch, dest - tbl_size); + return; + } ssel.id = PEF_SERIAL_CFGPARM_ID_DESTINFO; ssel.set = dest; @@ -503,11 +892,11 @@ ipmi_pef_print_serial_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest) ipmi_pef_print_serial_dest_tap(intf, &ssel); break; case PEF_SERIAL_DEST_TYPE_PPP: - ipmi_pef_print_serial_dest_ppp(intf, &ssel); + /* ipmi_pef_print_serial_dest_ppp(intf, &ssel); */ break; case PEF_SERIAL_DEST_TYPE_BASIC_CALLBACK: case PEF_SERIAL_DEST_TYPE_PPP_CALLBACK: - ipmi_pef_print_serial_dest_callback(intf, &ssel); + /* ipmi_pef_print_serial_dest_callback(intf, &ssel); */ break; } } @@ -529,7 +918,7 @@ ipmi_pef_print_event_info(struct pef_cfgparm_filter_table_entry * pef, char * bu static char * classes[] = {"Discrete", "Threshold", "OEM"}; uint16_t offmask; char * p; - int i; + unsigned int i; uint8_t t; ipmi_pef_print_str("Event severity", @@ -574,170 +963,234 @@ ipmi_pef_print_event_info(struct pef_cfgparm_filter_table_entry * pef, char * bu ipmi_pef_print_str("Event trigger(s)", buf); } +/* ipmi_pef_print_filter_entry - Print-out Entry of Event Filter Table. */ static void -ipmi_pef_print_entry(struct ipmi_rs * rsp, uint8_t id, - struct pef_cfgparm_filter_table_entry * pef) -{ /* - // print a PEF table entry - */ - uint8_t wrk, set; +ipmi_pef_print_filter_entry(struct pef_cfgparm_filter_table_entry *filter_entry) +{ char buf[128]; + uint8_t filter_enabled; + uint8_t set; - ipmi_pef_print_dec("PEF table entry", id); + ipmi_pef_print_dec("PEF Filter Table entry", filter_entry->data1); - wrk = !!(pef->entry.config & PEF_CONFIG_ENABLED); - sprintf(buf, "%sactive", (wrk ? "" : "in")); - if (pef->entry.config & PEF_CONFIG_PRECONFIGURED) - strcat(buf, ", pre-configured"); + filter_enabled = filter_entry->entry.config & PEF_CONFIG_ENABLED; + sprintf(buf, "%sabled", (filter_enabled ? "en" : "dis")); + switch (filter_entry->entry.config & 0x60) { + case 0x40: + strcat(buf, ", pre-configured"); + break; + case 0x00: + strcat(buf, ", configurable"); + break; + default: + /* Covers 0x60 and 0x20 which are reserved */ + strcat(buf, ", reserved"); + break; + } ipmi_pef_print_str("Status", buf); - if (wrk != 0) { - ipmi_pef_print_1xd("Version", rsp->data[0]); - ipmi_pef_print_str("Sensor type", - ipmi_pef_bit_desc(&pef_b2s_sensortypes, pef->entry.sensor_type)); + if (!filter_enabled) { + return; + } - if (pef->entry.sensor_number == PEF_SENSOR_NUMBER_MATCH_ANY) - ipmi_pef_print_str("Sensor number", "Any"); - else - ipmi_pef_print_dec("Sensor number", pef->entry.sensor_number); + ipmi_pef_print_str("Sensor type", + ipmi_pef_bit_desc(&pef_b2s_sensortypes, + filter_entry->entry.sensor_type)); - ipmi_pef_print_event_info(pef, buf); - ipmi_pef_print_str("Action", - ipmi_pef_bit_desc(&pef_b2s_actions, pef->entry.action)); + if (filter_entry->entry.sensor_number == PEF_SENSOR_NUMBER_MATCH_ANY) { + ipmi_pef_print_str("Sensor number", "Any"); + } else { + ipmi_pef_print_dec("Sensor number", + filter_entry->entry.sensor_number); + } - if (pef->entry.action & PEF_ACTION_ALERT) { - set = (pef->entry.policy_number & PEF_POLICY_NUMBER_MASK); - ipmi_pef_print_int("Policy set", set); - } + ipmi_pef_print_event_info(filter_entry, buf); + ipmi_pef_print_str("Action", + ipmi_pef_bit_desc(&pef_b2s_actions, + filter_entry->entry.action)); + + if (filter_entry->entry.action & PEF_ACTION_ALERT) { + set = (filter_entry->entry.policy_number & PEF_POLICY_NUMBER_MASK); + ipmi_pef_print_int("Policy set", set); } } -static void -ipmi_pef_list_entries(struct ipmi_intf * intf) -{ /* - // list all PEF table entries - */ - struct ipmi_rs * rsp; - struct ipmi_rq req; - struct pef_cfgparm_selector psel; - struct pef_cfgparm_filter_table_entry * pcfg; - uint32_t i; - uint8_t max_filters; +/* ipmi_pef2_filter_enable - Enable/Disable specific PEF Event Filter. + * + * @enable - enable(1) or disable(0) PEF Event Filter. + * @filter_id - Filter ID of Entry in Event Filter Table. + * + * returns - 0 on success, any other value means error. + */ +static int +ipmi_pef2_filter_enable(struct ipmi_intf *intf, uint8_t enable, uint8_t filter_id) +{ + struct pef_cfgparm_filter_table_data_1 filter_cfg; + int rc; + uint8_t filter_table_size; + + rc = _ipmi_get_pef_filter_table_size(intf, &filter_table_size); + if (eval_ccode(rc) != 0) { + return (-1); + } else if (filter_table_size == 0) { + lprintf(LOG_ERR, "PEF Filter isn't supported."); + return (-1); + } else if (filter_id > filter_table_size) { + lprintf(LOG_ERR, + "PEF Filter ID out of range. Valid range is (1..%d).", + filter_table_size); + return (-1); + } - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_SE; - req.msg.cmd = IPMI_CMD_GET_PEF_CAPABILITIES; - rsp = ipmi_pef_msg_exchange(intf, &req, "PEF capabilities"); - if (!rsp - || (max_filters = ((struct pef_capabilities *)rsp->data)->tblsize) == 0) - return; /* sssh, not supported */ + memset(&filter_cfg, 0, sizeof(filter_cfg)); + rc = _ipmi_set_pef_filter_entry_cfg(intf, filter_id, &filter_cfg); + if (eval_ccode(rc) != 0) { + return (-1); + } - memset(&psel, 0, sizeof(psel)); - psel.id = PEF_CFGPARM_ID_PEF_FILTER_TABLE_ENTRY; - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_SE; - req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; - req.msg.data = (uint8_t *)&psel; - req.msg.data_len = sizeof(psel); - for (i=1; i<=max_filters; i++) { - if (i > 1) - printf("\n"); - psel.set = (i & PEF_FILTER_TABLE_ID_MASK); - rsp = ipmi_pef_msg_exchange(intf, &req, "PEF table entry"); - if (!rsp - || (psel.set != (rsp->data[1] & PEF_FILTER_TABLE_ID_MASK))) { - lprintf(LOG_ERR, " **Error retrieving %s", - "PEF table entry"); - continue; - } - pcfg = (struct pef_cfgparm_filter_table_entry *)&rsp->data[1]; - first_field = 1; - ipmi_pef_print_entry(rsp, psel.set, pcfg); + if (enable != 0) { + /* Enable */ + filter_cfg.cfg |= PEF_FILTER_ENABLED; + } else { + /* Disable */ + filter_cfg.cfg &= PEF_FILTER_DISABLED; } + rc = _ipmi_set_pef_filter_entry_cfg(intf, filter_id, &filter_cfg); + if (eval_ccode(rc) != 0) { + lprintf(LOG_ERR, "Failed to %s PEF Filter ID %d.", + enable ? "enable" : "disable", + filter_id); + return (-1); + } + printf("PEF Filter ID %" PRIu8 " is %s now.\n", filter_id, + enable ? "enabled" : "disabled"); + return rc; } -static void -ipmi_pef_list_policies(struct ipmi_intf * intf) -{ /* - // list PEF alert policies - */ - struct ipmi_rs * rsp; - struct ipmi_rq req; - struct pef_cfgparm_policy_table_entry * ptbl = NULL; - struct pef_cfgparm_policy_table_entry * ptmp = NULL; - uint32_t i; - uint8_t wrk, ch, medium, tbl_size; - - tbl_size = ipmi_pef_get_policy_table(intf, &ptbl); - if (!tbl_size) { - if (ptbl != NULL) { - free(ptbl); - ptbl = NULL; +void +ipmi_pef2_filter_help(void) +{ + lprintf(LOG_NOTICE, +"usage: pef filter help"); + lprintf(LOG_NOTICE, +" pef filter list"); + lprintf(LOG_NOTICE, +" pef filter enable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef filter disable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef filter create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, +" pef filter delete <id = 1..n>"); +} + +/* ipmi_pef2_filter - Handle processing of "filter" CLI args. */ +int +ipmi_pef2_filter(struct ipmi_intf *intf, int argc, char **argv) +{ + int rc = 0; + + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + ipmi_pef2_filter_help(); + rc = (-1); + } else if (!strncmp(argv[0], "help\0", 5)) { + ipmi_pef2_filter_help(); + rc = 0; + } else if (!strncmp(argv[0], "list\0", 5)) { + rc = ipmi_pef2_list_filters(intf); + } else if (!strncmp(argv[0], "enable\0", 7) + ||(!strncmp(argv[0], "disable\0", 8))) { + uint8_t enable; + uint8_t filter_id; + if (argc != 2) { + lprintf(LOG_ERR, "Not enough arguments given."); + ipmi_pef2_filter_help(); + return (-1); } - return; + if (str2uchar(argv[1], &filter_id) != 0) { + lprintf(LOG_ERR, "Invalid PEF Event Filter ID given: %s", argv[1]); + return (-1); + } else if (filter_id < 1) { + lprintf(LOG_ERR, "PEF Event Filter ID out of range. " + "Valid range is <1..255>."); + return (-1); + } + if (!strncmp(argv[0], "enable\0", 7)) { + enable = 1; + } else { + enable = 0; + } + rc = ipmi_pef2_filter_enable(intf, enable, filter_id); + } else if (!strncmp(argv[0], "create\0", 7)) { + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else if (!strncmp(argv[0], "delete\0", 7)) { + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else { + lprintf(LOG_ERR, "Invalid PEF Filter command: %s", argv[0]); + ipmi_pef2_filter_help(); + rc = 1; } - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_APP; - req.msg.cmd = IPMI_CMD_GET_CHANNEL_INFO; - req.msg.data = &ch; - req.msg.data_len = sizeof(ch); - for (ptmp=ptbl, i=1; i<=tbl_size; i++, ptmp++) { - if ((ptmp->entry.policy & PEF_POLICY_ENABLED) == PEF_POLICY_ENABLED) { - if (i > 1) - printf("\n"); - first_field = 1; - ipmi_pef_print_dec("Alert policy table entry", - (ptmp->data1 & PEF_POLICY_TABLE_ID_MASK)); - ipmi_pef_print_dec("Policy set", - (ptmp->entry.policy & PEF_POLICY_ID_MASK) >> PEF_POLICY_ID_SHIFT); - ipmi_pef_print_str("Policy entry rule", - ipmi_pef_bit_desc(&pef_b2s_policies, (ptmp->entry.policy & PEF_POLICY_FLAGS_MASK))); - - if (ptmp->entry.alert_string_key & PEF_POLICY_EVENT_SPECIFIC) { - ipmi_pef_print_str("Event-specific", "true"); -// continue; - } - wrk = ptmp->entry.chan_dest; - - /* channel/description */ - ch = (wrk & PEF_POLICY_CHANNEL_MASK) >> PEF_POLICY_CHANNEL_SHIFT; - rsp = ipmi_pef_msg_exchange(intf, &req, "Channel info"); - if (!rsp || rsp->data[0] != ch) { - lprintf(LOG_ERR, " **Error retrieving %s", - "Channel info"); - continue; - } - medium = rsp->data[1]; - ipmi_pef_print_dec("Channel number", ch); - ipmi_pef_print_str("Channel medium", - ipmi_pef_bit_desc(&pef_b2s_ch_medium, medium)); - - /* destination/description */ - wrk &= PEF_POLICY_DESTINATION_MASK; - switch (medium) { - case PEF_CH_MEDIUM_TYPE_LAN: - ipmi_pef_print_lan_dest(intf, ch, wrk); - break; - case PEF_CH_MEDIUM_TYPE_SERIAL: - ipmi_pef_print_serial_dest(intf, ch, wrk); - break; - default: - ipmi_pef_print_dest(intf, ch, wrk); - break; - } + return rc; +} + +/* ipmi_pef2_get_info - Reports PEF capabilities + System GUID */ +static int +ipmi_pef2_get_info(struct ipmi_intf *intf) +{ + struct pef_capabilities pcap; + struct pef_cfgparm_system_guid psys_guid; + struct ipmi_guid_t guid; + int rc; + uint8_t *guid_ptr = NULL; + uint8_t policy_table_size; + + rc = _ipmi_get_pef_policy_table_size(intf, &policy_table_size); + if (eval_ccode(rc) != 0) { + lprintf(LOG_WARN, "Failed to get size of PEF Policy Table."); + policy_table_size = 0; + } + rc = _ipmi_get_pef_capabilities(intf, &pcap); + if (eval_ccode(rc) != 0) { + lprintf(LOG_ERR, "Failed to get PEF Capabilities."); + return (-1); + } + + ipmi_pef_print_1xd("Version", pcap.version); + ipmi_pef_print_dec("PEF Event Filter count", + pcap.event_filter_count); + ipmi_pef_print_dec("PEF Alert Policy Table size", + policy_table_size); + + rc = _ipmi_get_pef_system_guid(intf, &psys_guid); + if (rc != 0x80 && eval_ccode(rc) != 0) { + lprintf(LOG_ERR, "Failed to get PEF System GUID. %i", rc); + return (-1); + } else if (psys_guid.data1 == 0x1) { + /* IPMI_CMD_GET_SYSTEM_GUID */ + guid_ptr = &psys_guid.guid[0]; + } else { + rc = _ipmi_mc_get_guid(intf, &guid); + if (rc == 0) { + guid_ptr = (uint8_t *)&guid; } } - free(ptbl); - ptbl = NULL; + /* Got GUID? */ + if (guid_ptr) { + ipmi_pef_print_guid(guid_ptr); + } + ipmi_pef_print_flags(&pef_b2s_actions, P_SUPP, pcap.actions); + return 0; } -static void -ipmi_pef_get_status(struct ipmi_intf * intf) -{ /* - // report the PEF status - */ - struct ipmi_rs * rsp; +/* ipmi_pef2_get_status - TODO rewrite - report the PEF status */ +static int +ipmi_pef2_get_status(struct ipmi_intf *intf) +{ + struct ipmi_rs *rsp; struct ipmi_rq req; struct pef_cfgparm_selector psel; char tbuf[40]; @@ -751,7 +1204,7 @@ ipmi_pef_get_status(struct ipmi_intf * intf) if (!rsp) { lprintf(LOG_ERR, " **Error retrieving %s", "Last S/W processed ID"); - return; + return (-1); } memcpy(&timei, rsp->data, sizeof(timei)); #if WORDS_BIGENDIAN @@ -777,7 +1230,7 @@ ipmi_pef_get_status(struct ipmi_intf * intf) if (!rsp) { lprintf(LOG_ERR, " **Error retrieving %s", "PEF control"); - return; + return (-1); } ipmi_pef_print_flags(&pef_b2s_control, P_ABLE, rsp->data[1]); @@ -786,102 +1239,312 @@ ipmi_pef_get_status(struct ipmi_intf * intf) if (!rsp) { lprintf(LOG_ERR, " **Error retrieving %s", "PEF action"); - return; + return (-1); } ipmi_pef_print_flags(&pef_b2s_actions, P_ACTV, rsp->data[1]); + return 0; } -static void -ipmi_pef_get_info(struct ipmi_intf * intf) -{ /* - // report PEF capabilities + System GUID - */ - struct ipmi_rs * rsp; - struct ipmi_rq req; - struct pef_capabilities * pcap; - struct pef_cfgparm_selector psel; - struct pef_cfgparm_policy_table_entry * ptbl = NULL; - uint8_t * uid; - uint8_t actions, tbl_size; +/* ipmi_pef2_list_filters - List all entries in PEF Event Filter Table. */ +static int +ipmi_pef2_list_filters(struct ipmi_intf *intf) +{ + struct pef_capabilities pcap; + struct pef_cfgparm_filter_table_entry filter_entry; + int rc; + uint8_t i; + + rc = _ipmi_get_pef_capabilities(intf, &pcap); + if (eval_ccode(rc) != 0) { + return (-1); + } else if (pcap.event_filter_count == 0) { + lprintf(LOG_ERR, "PEF Event Filtering isn't supported."); + return (-1); + } - tbl_size = ipmi_pef_get_policy_table(intf, &ptbl); - if (ptbl != NULL) { - free(ptbl); - ptbl = NULL; + for (i = 1; i <= pcap.event_filter_count; i++) { + first_field = 1; + rc = _ipmi_get_pef_filter_entry(intf, i, &filter_entry); + if (eval_ccode(rc) != 0) { + lprintf(LOG_ERR, "Failed to get PEF Event Filter Entry %i.", + i); + continue; + } + ipmi_pef_print_filter_entry(&filter_entry); + printf("\n"); } + return 0; +} - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_SE; - req.msg.cmd = IPMI_CMD_GET_PEF_CAPABILITIES; - rsp = ipmi_pef_msg_exchange(intf, &req, "PEF capabilities"); - if (!rsp) - return; - pcap = (struct pef_capabilities *)rsp->data; +/* ipmi_pef2_list_policies - List Entries in PEF Alert Policy Table. */ +static int +ipmi_pef2_list_policies(struct ipmi_intf *intf) +{ + struct channel_info_t channel_info; + struct pef_cfgparm_policy_table_entry entry; + int rc; + uint8_t dest; + uint8_t i; + uint8_t policy_table_size; + + rc = _ipmi_get_pef_policy_table_size(intf, &policy_table_size); + if (eval_ccode(rc) != 0) { + return (-1); + } else if (policy_table_size == 0) { + lprintf(LOG_ERR, "PEF Alert Policy isn't supported."); + return (-1); + } - ipmi_pef_print_1xd("Version", pcap->version); - ipmi_pef_print_dec("PEF table size", pcap->tblsize); - ipmi_pef_print_dec("Alert policy table size", tbl_size); - actions = pcap->actions; + for (i = 1; i <= policy_table_size; i++) { + first_field = 1; + rc = _ipmi_get_pef_policy_entry(intf, i, &entry); + if (eval_ccode(rc) != 0) { + continue; + } - memset(&psel, 0, sizeof(psel)); - psel.id = PEF_CFGPARM_ID_SYSTEM_GUID; - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_SE; - req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS; - req.msg.data = (uint8_t *)&psel; - req.msg.data_len = sizeof(psel); - rsp = ipmi_pef_msg_exchange(intf, &req, "System GUID"); - uid = NULL; - if (rsp && (rsp->data[1] & PEF_SYSTEM_GUID_USED_IN_PET)) - uid = &rsp->data[2]; - else { - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_APP; - req.msg.cmd = IPMI_CMD_GET_SYSTEM_GUID; - rsp = ipmi_pef_msg_exchange(intf, &req, "System GUID"); - if (rsp) - uid = &rsp->data[0]; - } - if (uid) { /* got GUID? */ - if (verbose) - printf(pef_fld_fmts[F_UID][0], KYWD_LENGTH, "System GUID", - uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7], - uid[8], uid[9], uid[10],uid[11],uid[12],uid[13],uid[14],uid[15]); - else - printf(pef_fld_fmts[F_UID][1], - uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7], - uid[8], uid[9], uid[10],uid[11],uid[12],uid[13],uid[14],uid[15]); + ipmi_pef_print_dec("Alert policy table entry", + (entry.data1 & PEF_POLICY_TABLE_ID_MASK)); + ipmi_pef_print_dec("Policy set", + (entry.entry.policy & PEF_POLICY_ID_MASK) >> PEF_POLICY_ID_SHIFT); + ipmi_pef_print_str("State", + entry.entry.policy & PEF_POLICY_ENABLED ? "enabled" : "disabled"); + ipmi_pef_print_str("Policy entry rule", + ipmi_pef_bit_desc(&pef_b2s_policies, + (entry.entry.policy & PEF_POLICY_FLAGS_MASK))); + + if (entry.entry.alert_string_key & PEF_POLICY_EVENT_SPECIFIC) { + ipmi_pef_print_str("Event-specific", "true"); + } + channel_info.channel = ((entry.entry.chan_dest & + PEF_POLICY_CHANNEL_MASK) >> + PEF_POLICY_CHANNEL_SHIFT); + rc = _ipmi_get_channel_info(intf, &channel_info); + if (eval_ccode(rc) != 0) { + continue; + } + ipmi_pef_print_dec("Channel number", channel_info.channel); + ipmi_pef_print_str("Channel medium", + ipmi_pef_bit_desc(&pef_b2s_ch_medium, + channel_info.medium)); + dest = entry.entry.chan_dest & PEF_POLICY_DESTINATION_MASK; + switch (channel_info.medium) { + case PEF_CH_MEDIUM_TYPE_LAN: + ipmi_pef_print_lan_dest(intf, channel_info.channel, + dest); + break; + case PEF_CH_MEDIUM_TYPE_SERIAL: + ipmi_pef_print_serial_dest(intf, channel_info.channel, + dest); + break; + default: + ipmi_pef_print_dest(intf, channel_info.channel, dest); + break; + } + printf("\n"); } - ipmi_pef_print_flags(&pef_b2s_actions, P_SUPP, actions); + return 0; } -int ipmi_pef_main(struct ipmi_intf * intf, int argc, char ** argv) -{ /* - // PEF subcommand handling - */ - int help = 0; - int rc = 0; - - if (!argc || !strncmp(argv[0], "info", 4)) - ipmi_pef_get_info(intf); - else if (!strncmp(argv[0], "help", 4)) - help = 1; - else if (!strncmp(argv[0], "status", 6)) - ipmi_pef_get_status(intf); - else if (!strncmp(argv[0], "policy", 6)) - ipmi_pef_list_policies(intf); - else if (!strncmp(argv[0], "list", 4)) - ipmi_pef_list_entries(intf); - else { - help = 1; - rc = -1; - lprintf(LOG_ERR, "Invalid PEF command: '%s'\n", argv[0]); +void +ipmi_pef2_policy_help(void) +{ + lprintf(LOG_NOTICE, +"usage: pef policy help"); + lprintf(LOG_NOTICE, +" pef policy list"); + lprintf(LOG_NOTICE, +" pef policy enable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef policy disable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef policy create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, +" pef policy delete <id = 1..n>"); +} + +/* ipmi_pef2_policy_enable - Enable/Disable specific PEF policy + * + * @enable - enable(1) or disable(0) PEF Alert Policy + * @policy_id - Policy ID of Entry in Alert Policy Table. + * + * returns - 0 on success, any other value means error. + */ +static int +ipmi_pef2_policy_enable(struct ipmi_intf *intf, int enable, uint8_t policy_id) +{ + struct pef_cfgparm_policy_table_entry policy_entry; + int rc; + uint8_t policy_table_size; + + rc = _ipmi_get_pef_policy_table_size(intf, &policy_table_size); + if (eval_ccode(rc) != 0) { + return (-1); + } else if (policy_table_size == 0) { + lprintf(LOG_ERR, "PEF Policy isn't supported."); + return (-1); + } else if (policy_id > policy_table_size) { + lprintf(LOG_ERR, + "PEF Policy ID out of range. Valid range is (1..%d).", + policy_table_size); + return (-1); } - if (help) - lprintf(LOG_NOTICE, "PEF commands: info status policy list"); - else if (!verbose) - printf("\n"); + memset(&policy_entry, 0, sizeof(policy_entry)); + rc = _ipmi_get_pef_policy_entry(intf, policy_id, &policy_entry); + if (eval_ccode(rc) != 0) { + return (-1); + } + + if (enable != 0) { + /* Enable */ + policy_entry.entry.policy |= PEF_POLICY_ENABLED; + } else { + /* Disable */ + policy_entry.entry.policy &= PEF_POLICY_DISABLED; + } + rc = _ipmi_set_pef_policy_entry(intf, policy_id, &policy_entry); + if (eval_ccode(rc) != 0) { + lprintf(LOG_ERR, "Failed to %s PEF Policy ID %d.", + enable ? "enable" : "disable", + policy_id); + return (-1); + } + printf("PEF Policy ID %" PRIu8 " is %s now.\n", policy_id, + enable ? "enabled" : "disabled"); + return rc; +} + +/* ipmi_pef2_policy - Handle processing of "policy" CLI args. */ +int +ipmi_pef2_policy(struct ipmi_intf *intf, int argc, char **argv) +{ + int rc = 0; + + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + ipmi_pef2_policy_help(); + rc = (-1); + } else if (!strncmp(argv[0], "help\0", 5)) { + ipmi_pef2_policy_help(); + rc = 0; + } else if (!strncmp(argv[0], "list\0", 5)) { + rc = ipmi_pef2_list_policies(intf); + } else if (!strncmp(argv[0], "enable\0", 7) + || !strncmp(argv[0], "disable\0", 8)) { + uint8_t enable; + uint8_t policy_id; + if (argc != 2) { + lprintf(LOG_ERR, "Not enough arguments given."); + ipmi_pef2_policy_help(); + return (-1); + } + if (str2uchar(argv[1], &policy_id) != 0) { + lprintf(LOG_ERR, "Invalid PEF Policy ID given: %s", argv[1]); + return (-1); + } else if (policy_id < 1 || policy_id > 127) { + lprintf(LOG_ERR, "PEF Policy ID out of range. Valid range is <1..127>."); + return (-1); + } + if (!strncmp(argv[0], "enable\0", 7)) { + enable = 1; + } else { + enable = 0; + } + rc = ipmi_pef2_policy_enable(intf, enable, policy_id); + } else if (!strncmp(argv[0], "create\0", 7)) { + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else if (!strncmp(argv[0], "delete\0", 7)) { + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else { + lprintf(LOG_ERR, "Invalid PEF Policy command: %s", argv[0]); + ipmi_pef2_policy_help(); + rc = 1; + } + return rc; +} + +/* ipmi_pef2_help - print-out help text. */ +void +ipmi_pef2_help(void) +{ + lprintf(LOG_NOTICE, +"usage: pef help"); + lprintf(LOG_NOTICE, +" pef capabilities"); + lprintf(LOG_NOTICE, +" pef event <params>"); + lprintf(LOG_NOTICE, +" pef filter list"); + lprintf(LOG_NOTICE, +" pef filter enable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef filter disable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef filter create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, +" pef filter delete <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef info"); + lprintf(LOG_NOTICE, +" pef policy list"); + lprintf(LOG_NOTICE, +" pef policy enable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef policy disable <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef policy create <id = 1..n> <params>"); + lprintf(LOG_NOTICE, +" pef policy delete <id = 1..n>"); + lprintf(LOG_NOTICE, +" pef pet ack <params>"); + lprintf(LOG_NOTICE, +" pef status"); + lprintf(LOG_NOTICE, +" pef timer get"); + lprintf(LOG_NOTICE, +" pef timer set <0x00-0xFF>"); +} +int ipmi_pef_main(struct ipmi_intf *intf, int argc, char **argv) +{ + int rc = 0; + + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + ipmi_pef2_help(); + rc = (-1); + } else if (!strncmp(argv[0], "help\0", 5)) { + ipmi_pef2_help(); + rc = 0; + } else if (!strncmp(argv[0], "capabilities\0", 13)) { + /* rc = ipmi_pef2_get_capabilities(intf); */ + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else if (!strncmp(argv[0], "event\0", 6)) { + /* rc = ipmi_pef2_event(intf, (argc - 1), ++argv); */ + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else if (!strncmp(argv[0], "filter\0", 7)) { + rc = ipmi_pef2_filter(intf, (argc - 1), ++argv); + } else if (!strncmp(argv[0], "info\0", 5)) { + rc = ipmi_pef2_get_info(intf); + } else if (!strncmp(argv[0], "pet\0", 4)) { + /* rc = ipmi_pef2_pet(intf, (argc - 1), ++argv); */ + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else if (!strncmp(argv[0], "policy\0", 7)) { + rc = ipmi_pef2_policy(intf, (argc - 1), ++argv); + } else if (!strncmp(argv[0], "status\0", 7)) { + rc = ipmi_pef2_get_status(intf); + } else if (!strncmp(argv[0], "timer\0", 6)) { + /* rc = ipmi_pef2_timer(intf, (argc - 1), ++argv); */ + lprintf(LOG_ERR, "Not implemented."); + rc = 1; + } else { + lprintf(LOG_ERR, "Invalid PEF command: '%s'\n", argv[0]); + rc = (-1); + } return rc; } diff --git a/lib/ipmi_picmg.c b/lib/ipmi_picmg.c index 70f845d..c7d9c8e 100644 --- a/lib/ipmi_picmg.c +++ b/lib/ipmi_picmg.c @@ -2301,7 +2301,7 @@ uint8_t ipmi_picmg_ipmb_address(struct ipmi_intf *intf) { struct ipmi_rq req; struct ipmi_rs *rsp; - char msg_data; + uint8_t msg_data; if (!intf->picmg_avail) { return 0; @@ -2336,12 +2336,13 @@ picmg_discover(struct ipmi_intf *intf) { * PICMG Extension Version 2.0 (PICMG 3.0 Revision 1.0 ATCA) to * PICMG Extension Version 2.3 (PICMG 3.0 Revision 3.0 ATCA) * PICMG Extension Version 4.1 (PICMG 3.0 Revision 3.0 AMC) + * PICMG Extension Version 5.0 (MTCA.0 R1.0) */ /* First, check if PICMG extension is available and supported */ struct ipmi_rq req; struct ipmi_rs *rsp; - char msg_data; + uint8_t msg_data; uint8_t picmg_avail = 0; memset(&req, 0, sizeof(req)); @@ -2366,8 +2367,9 @@ picmg_discover(struct ipmi_intf *intf) { } else if (rsp->data[0] != 0) { lprintf(LOG_INFO,"Invalid Get PICMG Properties group extension %#x", rsp->data[0]); - } else if ((rsp->data[1] & 0x0F) != PICMG_ATCA_MAJOR_VERSION - && (rsp->data[1] & 0x0F) != PICMG_AMC_MAJOR_VERSION) { + } else if ((rsp->data[1] & 0x0F) != PICMG_EXTENSION_ATCA_MAJOR_VERSION + && (rsp->data[1] & 0x0F) != PICMG_EXTENSION_AMC0_MAJOR_VERSION + && (rsp->data[1] & 0x0F) != PICMG_EXTENSION_UTCA_MAJOR_VERSION) { lprintf(LOG_INFO,"Unknown PICMG Extension Version %d.%d", (rsp->data[1] & 0x0F), (rsp->data[1] >> 4)); } else { diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c index e3122dc..2a9cbe3 100644 --- a/lib/ipmi_sdr.c +++ b/lib/ipmi_sdr.c @@ -689,32 +689,6 @@ ipmi_sdr_get_sensor_event_enable(struct ipmi_intf *intf, uint8_t sensor, return rsp; } -/* ipmi_sdr_get_sensor_type_desc - Get sensor type descriptor - * - * @type: ipmi sensor type - * - * returns - * string from sensor_type_desc - * or "reserved" - * or "OEM reserved" - */ -const char * -ipmi_sdr_get_sensor_type_desc(const uint8_t type) -{ - static char desc[32]; - memset(desc, 0, 32); - if (type <= SENSOR_TYPE_MAX) - return sensor_type_desc[type]; - if (type < 0xc0) - snprintf(desc, 32, "reserved #%02x", type); - else - { - snprintf(desc, 32, oemval2str(sdriana,type,ipmi_oem_sdr_type_vals), - type); - } - return desc; -} - /* ipmi_sdr_get_thresh_status - threshold status indicator * * @rsp: response from Get Sensor Reading comand @@ -1014,21 +988,21 @@ ipmi_sdr_print_sensor_event_status(struct ipmi_intf *intf, switch (numeric_fmt) { case DISCRETE_SENSOR: if (rsp->data_len == 2) { - ipmi_sdr_print_discrete_state("Assertion Events", + ipmi_sdr_print_discrete_state(intf, "Assertion Events", sensor_type, event_type, rsp->data[1], 0); } else if (rsp->data_len > 2) { - ipmi_sdr_print_discrete_state("Assertion Events", + ipmi_sdr_print_discrete_state(intf, "Assertion Events", sensor_type, event_type, rsp->data[1], rsp->data[2]); } if (rsp->data_len == 4) { - ipmi_sdr_print_discrete_state("Deassertion Events", + ipmi_sdr_print_discrete_state(intf, "Deassertion Events", sensor_type, event_type, rsp->data[3], 0); } else if (rsp->data_len > 4) { - ipmi_sdr_print_discrete_state("Deassertion Events", + ipmi_sdr_print_discrete_state(intf, "Deassertion Events", sensor_type, event_type, rsp->data[3], rsp->data[4]); @@ -1081,22 +1055,23 @@ ipmi_sdr_print_sensor_event_status(struct ipmi_intf *intf, } static int -ipmi_sdr_print_sensor_mask(struct sdr_record_mask *mask, - uint8_t sensor_type, - uint8_t event_type, int numeric_fmt) +ipmi_sdr_print_sensor_mask(struct ipmi_intf *intf, + struct sdr_record_mask *mask, + uint8_t sensor_type, + uint8_t event_type, int numeric_fmt) { /* iceblink - don't print some event status fields - CVS rev1.53 */ return 0; switch (numeric_fmt) { case DISCRETE_SENSOR: - ipmi_sdr_print_discrete_state("Assert Event Mask", sensor_type, + ipmi_sdr_print_discrete_state(intf, "Assert Event Mask", sensor_type, event_type, mask->type.discrete. assert_event & 0xff, (mask->type.discrete. assert_event & 0xff00) >> 8); - ipmi_sdr_print_discrete_state("Deassert Event Mask", + ipmi_sdr_print_discrete_state(intf, "Deassert Event Mask", sensor_type, event_type, mask->type.discrete. deassert_event & 0xff, @@ -1224,21 +1199,21 @@ ipmi_sdr_print_sensor_event_enable(struct ipmi_intf *intf, case DISCRETE_SENSOR: /* discrete */ if (rsp->data_len == 2) { - ipmi_sdr_print_discrete_state("Assertions Enabled", + ipmi_sdr_print_discrete_state(intf, "Assertions Enabled", sensor_type, event_type, rsp->data[1], 0); } else if (rsp->data_len > 2) { - ipmi_sdr_print_discrete_state("Assertions Enabled", + ipmi_sdr_print_discrete_state(intf, "Assertions Enabled", sensor_type, event_type, rsp->data[1], rsp->data[2]); } if (rsp->data_len == 4) { - ipmi_sdr_print_discrete_state("Deassertions Enabled", + ipmi_sdr_print_discrete_state(intf, "Deassertions Enabled", sensor_type, event_type, rsp->data[3], 0); } else if (rsp->data_len > 4) { - ipmi_sdr_print_discrete_state("Deassertions Enabled", + ipmi_sdr_print_discrete_state(intf, "Deassertions Enabled", sensor_type, event_type, rsp->data[3], rsp->data[4]); @@ -1381,8 +1356,9 @@ print_sensor_min_max(struct sdr_record_full_sensor *full) * returns void */ static void -print_csv_discrete(struct sdr_record_common_sensor *sensor, - const struct sensor_reading *sr) +print_csv_discrete(struct ipmi_intf *intf, + struct sdr_record_common_sensor *sensor, + const struct sensor_reading *sr) { if (!sr->s_reading_valid || sr->s_reading_unavailable) { printf("%02Xh,ns,%d.%d,No Reading", @@ -1400,7 +1376,7 @@ print_csv_discrete(struct sdr_record_common_sensor *sensor, printf("ok,%d.%d,", sensor->entity.id, sensor->entity.instance); - ipmi_sdr_print_discrete_state_mini(NULL, ", ", + ipmi_sdr_print_discrete_state_mini(intf, NULL, ", ", sensor->sensor.type, sensor->event_type, sr->s_data2, @@ -1430,7 +1406,7 @@ ipmi_sdr_read_sensor_value(struct ipmi_intf *intf, memset(&sr, 0, sizeof(sr)); switch (sdr_record_type) { - int idlen; + unsigned int idlen; case (SDR_RECORD_TYPE_FULL_SENSOR): sr.full = (struct sdr_record_full_sensor *)sensor; idlen = sr.full->id_code & 0x1f; @@ -1542,7 +1518,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, uint8_t sdr_record_type) { char sval[16]; - int i = 0; + unsigned int i = 0; uint8_t target, lun, channel; struct sensor_reading *sr; @@ -1567,7 +1543,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, printf("%s,", sr->s_id); if (!IS_THRESHOLD_SENSOR(sensor)) { /* Discrete/Non-Threshold */ - print_csv_discrete(sensor, sr); + print_csv_discrete(intf, sensor, sr); printf("\n"); } else { @@ -1581,7 +1557,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, printf("%s,%s", sr->s_a_units, ipmi_sdr_get_thresh_status(sr, "ns")); } else { /* Discrete/Threshold */ - print_csv_discrete(sensor, sr); + print_csv_discrete(intf, sensor, sr); } } else { printf(",,ns"); @@ -1589,10 +1565,9 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, if (verbose) { printf(",%d.%d,%s,%s,", - sensor->entity.id, sensor->entity.instance, - val2str(sensor->entity.id, entity_id_vals), - ipmi_sdr_get_sensor_type_desc(sensor->sensor. - type)); + sensor->entity.id, sensor->entity.instance, + val2str(sensor->entity.id, entity_id_vals), + ipmi_get_sensor_type(intf, sensor->sensor.type)); if (sr->full) { SENSOR_PRINT_CSV(sr->full, sr->full->analog_flag.nominal_read, @@ -1712,7 +1687,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, printf("%s %s", sr->s_a_str, sr->s_a_units); header = ", "; } - ipmi_sdr_print_discrete_state_mini(header, ", ", + ipmi_sdr_print_discrete_state_mini(intf, header, ", ", sensor->sensor.type, sensor->event_type, sr->s_data2, @@ -1740,7 +1715,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, if (!IS_THRESHOLD_SENSOR(sensor)) { /* Discrete */ printf(" Sensor Type (Discrete): %s (0x%02x)\n", - ipmi_sdr_get_sensor_type_desc(sensor->sensor.type), + ipmi_get_sensor_type(intf, sensor->sensor.type), sensor->sensor.type); lprintf(LOG_DEBUG, " Event Type Code : 0x%02x", sensor->event_type); @@ -1776,12 +1751,12 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, break; } - ipmi_sdr_print_discrete_state("States Asserted", + ipmi_sdr_print_discrete_state(intf, "States Asserted", sensor->sensor.type, sensor->event_type, sr->s_data2, sr->s_data3); - ipmi_sdr_print_sensor_mask(&sensor->mask, sensor->sensor.type, + ipmi_sdr_print_sensor_mask(intf, &sensor->mask, sensor->sensor.type, sensor->event_type, DISCRETE_SENSOR); ipmi_sdr_print_sensor_event_status(intf, sensor->keys.sensor_num, @@ -1804,7 +1779,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, return 0; /* done */ } printf(" Sensor Type (Threshold) : %s (0x%02x)\n", - ipmi_sdr_get_sensor_type_desc(sensor->sensor.type), + ipmi_get_sensor_type(intf, sensor->sensor.type), sensor->sensor.type); printf(" Sensor Reading : "); @@ -1945,7 +1920,7 @@ ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, printf("\n"); } - ipmi_sdr_print_sensor_mask(&sensor->mask, + ipmi_sdr_print_sensor_mask(intf, &sensor->mask, sensor->sensor.type, sensor->event_type, ANALOG_SENSOR); ipmi_sdr_print_sensor_event_status(intf, @@ -1988,46 +1963,43 @@ get_offset(uint8_t x) * no meaningful return value */ void -ipmi_sdr_print_discrete_state_mini(const char *header, const char *separator, +ipmi_sdr_print_discrete_state_mini(struct ipmi_intf *intf, + const char *header, const char *separator, uint8_t sensor_type, uint8_t event_type, uint8_t state1, uint8_t state2) { - uint8_t typ; - struct ipmi_event_sensor_types *evt; + const struct ipmi_event_sensor_types *evt; int pre = 0, c = 0; if (state1 == 0 && (state2 & 0x7f) == 0) return; - if (event_type == 0x6f) { - evt = sensor_specific_types; - typ = sensor_type; - } else { - evt = generic_event_types; - typ = event_type; - } - if (header) printf("%s", header); - for (; evt->type != NULL; evt++) { - if ((evt->code != typ) || - (evt->data != 0xFF)) + for (evt = ipmi_get_first_event_sensor_type(intf, sensor_type, event_type); + evt != NULL; evt = ipmi_get_next_event_sensor_type(evt)) { + if (evt->data != 0xFF) { continue; + } if (evt->offset > 7) { if ((1 << (evt->offset - 8)) & (state2 & 0x7f)) { - if (pre++ != 0) + if (pre++ != 0) { printf("%s", separator); - if (evt->desc) + } + if (evt->desc) { printf("%s", evt->desc); + } } } else { if ((1 << evt->offset) & state1) { - if (pre++ != 0) + if (pre++ != 0) { printf("%s", separator); - if (evt->desc) + } + if (evt->desc) { printf("%s", evt->desc); + } } } c++; @@ -2045,32 +2017,24 @@ ipmi_sdr_print_discrete_state_mini(const char *header, const char *separator, * no meaningful return value */ void -ipmi_sdr_print_discrete_state(const char *desc, +ipmi_sdr_print_discrete_state(struct ipmi_intf *intf, const char *desc, uint8_t sensor_type, uint8_t event_type, uint8_t state1, uint8_t state2) { - uint8_t typ; - struct ipmi_event_sensor_types *evt; + const struct ipmi_event_sensor_types *evt; int pre = 0, c = 0; if (state1 == 0 && (state2 & 0x7f) == 0) return; - if (event_type == 0x6f) { - evt = sensor_specific_types; - typ = sensor_type; - } else { - evt = generic_event_types; - typ = event_type; - } - - for (; evt->type != NULL; evt++) { - if ((evt->code != typ) || - (evt->data != 0xFF)) + for (evt = ipmi_get_first_event_sensor_type(intf, sensor_type, event_type); + evt != NULL; evt = ipmi_get_next_event_sensor_type(evt)) { + if (evt->data != 0xFF) { continue; + } if (pre == 0) { - printf(" %-21s : %s\n", desc, evt->type); + printf(" %-21s : %s\n", desc, ipmi_get_sensor_type(intf, sensor_type)); pre = 1; } @@ -2129,7 +2093,7 @@ ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf, sensor->entity.id, sensor->entity.instance, val2str(sensor->entity.id, entity_id_vals)); printf("Sensor Type : %s (0x%02x)\n", - ipmi_sdr_get_sensor_type_desc(sensor->sensor_type), + ipmi_get_sensor_type(intf, sensor->sensor_type), sensor->sensor_type); lprintf(LOG_DEBUG, "Event Type Code : 0x%02x", sensor->event_type); @@ -2509,8 +2473,8 @@ ipmi_sdr_print_sensor_oem(struct ipmi_intf *intf, struct sdr_record_oem *oem) * returns -1 on error */ int -ipmi_sdr_print_name_from_rawentry(struct ipmi_intf *intf,uint16_t id, - uint8_t type,uint8_t * raw) +ipmi_sdr_print_name_from_rawentry(struct ipmi_intf *intf, uint16_t id, + uint8_t type, uint8_t *raw) { union { struct sdr_record_full_sensor *full; diff --git a/lib/ipmi_sel.c b/lib/ipmi_sel.c index b6629a2..8b0395e 100644 --- a/lib/ipmi_sel.c +++ b/lib/ipmi_sel.c @@ -49,6 +49,7 @@ #include <ipmitool/ipmi_sdr.h> #include <ipmitool/ipmi_fru.h> #include <ipmitool/ipmi_sensor.h> +#include <ipmitool/ipmi_strings.h> extern int verbose; static int sel_extended = 0; @@ -446,13 +447,14 @@ ipmi_sel_add_entries_fromfile(struct ipmi_intf * intf, const char * filename) return rc; } -static struct ipmi_event_sensor_types oem_kontron_event_reading_types[] __attribute__((unused)) = { - { 0x70 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "OEM Firmware Info 1", "Code Assert" }, - { 0x71 , 0x00 , 0xff, IPMI_EVENT_CLASS_DISCRETE , "OEM Firmware Info 2", "Code Assert" }, +static struct ipmi_event_sensor_types oem_kontron_event_reading_types[] __attribute__((unused)) = { + { 0x70 , 0x00 , 0xff, "Code Assert" }, + { 0x71 , 0x00 , 0xff, "Code Assert" }, + { 0, 0, 0xFF, NULL } }; char * -get_kontron_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec) +get_kontron_evt_desc(struct ipmi_intf *intf, struct sel_event_record * rec) { char * description = NULL; /* @@ -462,8 +464,8 @@ get_kontron_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec) /* Only standard records are defined so far */ if( rec->record_type < 0xC0 ){ - struct ipmi_event_sensor_types *st=NULL; - for ( st=oem_kontron_event_reading_types ; st->type != NULL; st++){ + const struct ipmi_event_sensor_types *st=NULL; + for ( st=oem_kontron_event_types ; st->desc != NULL; st++){ if (st->code == rec->sel_type.standard_type.event_type ){ size_t len =strlen(st->desc); description = (char*)malloc( len + 1 ); @@ -546,7 +548,7 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) struct ipmi_rs *rsp; struct ipmi_rq req; char *desc = NULL; - int chipset_type = 1; + int chipset_type = 4; int data1; int data2; int data3; @@ -612,12 +614,48 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) break; } } + for (i = 0; supermicro_older[i] != 0xFFFF; i++) { + if (oem_id == supermicro_older[i]) { + chipset_type = 0; + break; + } + } + for (i = 0; supermicro_romely[i] != 0xFFFF; i++) { + if (oem_id == supermicro_romely[i]) { + chipset_type = 1; + break; + } + } for (i = 0; supermicro_x9[i] != 0xFFFF; i++) { if (oem_id == supermicro_x9[i]) { chipset_type = 2; break; } } + for (i = 0; supermicro_brickland[i] != 0xFFFF; i++) { + if (oem_id == supermicro_brickland[i]) { + chipset_type = 3; + break; + } + } + for (i = 0; supermicro_x10QRH[i] != 0xFFFF; i++) { + if (oem_id == supermicro_x10QRH[i]) { + chipset_type = 4; + break; + } + } + for (i = 0; supermicro_x10QBL[i] != 0xFFFF; i++) { + if (oem_id == supermicro_x10QBL[i]) { + chipset_type = 4; + break; + } + } + for (i = 0; supermicro_x10OBi[i] != 0xFFFF; i++) { + if (oem_id == supermicro_x10OBi[i]) { + chipset_type = 5; + break; + } + } if (chipset_type == 0) { snprintf(desc, SIZE_OF_DESC, "@DIMM%2X(CPU%x)", data2, @@ -630,6 +668,21 @@ get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec) snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)", (data2 >> 4) + 0x40 + (data3 & 0x3) * 3, (data2 & 0xf) + 0x27, (data3 & 0x03) + 1); + } else if (chipset_type == 3) { + snprintf(desc, SIZE_OF_DESC, "@DIMM%c%d(P%dM%d)", + ((data2 & 0xf) >> 4) > 4 + ? '@' - 4 + ((data2 & 0xff) >> 4) + : '@' + ((data2 & 0xff) >> 4), + (data2 & 0xf) - 0x09, (data3 & 0x0f) + 1, + (data2 & 0xff) >> 4 > 4 ? 2 : 1); + } else if (chipset_type == 4) { + snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)", + (data2 >> 4) + 0x40, + (data2 & 0xf) + 0x27, (data3 & 0x03) + 1); + } else if (chipset_type == 5) { + snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)", + (data2 >> 4) + 0x40, + (data2 & 0xf) + 0x27, (data3 & 0x07) + 1); } else { /* No description. */ desc[0] = '\0'; @@ -1200,11 +1253,71 @@ ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec) } +const struct ipmi_event_sensor_types * +ipmi_get_first_event_sensor_type(struct ipmi_intf *intf, + uint8_t sensor_type, uint8_t event_type) +{ + const struct ipmi_event_sensor_types *evt, *start, *next = NULL; + uint8_t code; + + if (event_type == 0x6f) { + if (sensor_type >= 0xC0 + && sensor_type < 0xF0 + && ipmi_get_oem(intf) == IPMI_OEM_KONTRON) { + /* check Kontron OEM sensor event types */ + start = oem_kontron_event_types; + } else if (intf->vita_avail) { + /* check VITA sensor event types first */ + start = vita_sensor_event_types; + + /* then check generic sensor types */ + next = sensor_specific_event_types; + } else { + /* check generic sensor types */ + start = sensor_specific_event_types; + } + code = sensor_type; + } else { + start = generic_event_types; + code = event_type; + } + + for (evt = start; evt->desc != NULL || next != NULL; evt++) { + /* check if VITA sensor event types has finished */ + if (evt->desc == NULL) { + /* proceed with next table */ + evt = next; + next = NULL; + } + + if (code == evt->code) + return evt; + } + + return NULL; +} + + +const struct ipmi_event_sensor_types * +ipmi_get_next_event_sensor_type(const struct ipmi_event_sensor_types *evt) +{ + const struct ipmi_event_sensor_types *start = evt; + + for (evt = start + 1; evt->desc != NULL; evt++) { + if (evt->code == start->code) { + return evt; + } + } + + return NULL; +} + + void ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char ** desc) { - uint8_t code, offset; - struct ipmi_event_sensor_types *evt = NULL; + uint8_t offset; + const struct ipmi_event_sensor_types *evt = NULL; char *sfx = NULL; /* This will be assigned if the Platform is DELL, additional info is appended to the current Description */ @@ -1223,86 +1336,61 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char case IPMI_OEM_KONTRON: lprintf(LOG_DEBUG, "oem sensor type %x %d using oem type supplied description", rec->sel_type.standard_type.sensor_type , iana); - - evt = oem_kontron_event_types; - code = rec->sel_type.standard_type.sensor_type; break; case IPMI_OEM_DELL: /* OEM Bytes Decoding for DELLi */ - evt = sensor_specific_types; - code = rec->sel_type.standard_type.sensor_type; if ( (OEM_CODE_IN_BYTE2 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK)) || (OEM_CODE_IN_BYTE3 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE3_SPECIFIED_MASK)) ) { - if(rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK) - evt->data = rec->sel_type.standard_type.event_data[1]; - sfx = ipmi_get_oem_desc(intf, rec); } break; case IPMI_OEM_SUPERMICRO: case IPMI_OEM_SUPERMICRO_47488: - evt = sensor_specific_types; - code = rec->sel_type.standard_type.sensor_type; sfx = ipmi_get_oem_desc(intf, rec); break; /* add your oem sensor assignation here */ default: + lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description", + rec->sel_type.standard_type.sensor_type ); break; - } - if( evt == NULL ){ - lprintf(LOG_DEBUG, "oem sensor type %x using standard type supplied description", - rec->sel_type.standard_type.sensor_type ); } } else { switch (ipmi_get_oem(intf)) { case IPMI_OEM_SUPERMICRO: case IPMI_OEM_SUPERMICRO_47488: - evt = sensor_specific_types; - code = rec->sel_type.standard_type.sensor_type; sfx = ipmi_get_oem_desc(intf, rec); break; default: break; } } - if( evt == NULL ){ - evt = sensor_specific_types; - code = rec->sel_type.standard_type.sensor_type; - } /* * Check for the OEM DELL Interface based on the Dell Specific Vendor Code. * If its Dell Platform, do the OEM Byte decode from the SEL Records. * Additional information should be written by the ipmi_get_oem_desc() */ if(ipmi_get_oem(intf) == IPMI_OEM_DELL) { - code = rec->sel_type.standard_type.sensor_type; if ( (OEM_CODE_IN_BYTE2 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK)) || (OEM_CODE_IN_BYTE3 == (rec->sel_type.standard_type.event_data[0] & DATA_BYTE3_SPECIFIED_MASK)) ) { - if(rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK) - evt->data = rec->sel_type.standard_type.event_data[1]; - sfx = ipmi_get_oem_desc(intf, rec); - + sfx = ipmi_get_oem_desc(intf, rec); } else if(SENSOR_TYPE_OEM_SEC_EVENT == rec->sel_type.standard_type.event_data[0]) { /* 0x23 : Sensor Number.*/ if(0x23 == rec->sel_type.standard_type.sensor_num) - { - evt->data = rec->sel_type.standard_type.event_data[1]; sfx = ipmi_get_oem_desc(intf, rec); - } } } - } else { - evt = generic_event_types; - code = rec->sel_type.standard_type.event_type; } offset = rec->sel_type.standard_type.event_data[0] & 0xf; - while (evt->type) { - if ((evt->code == code && evt->offset == offset && evt->desc != NULL) && + for (evt = ipmi_get_first_event_sensor_type(intf, + rec->sel_type.standard_type.sensor_type, + rec->sel_type.standard_type.event_type); + evt != NULL; evt = ipmi_get_next_event_sensor_type(evt)) { + if ((evt->offset == offset && evt->desc != NULL) && ((evt->data == ALL_OFFSETS_SPECIFIED) || ((rec->sel_type.standard_type.event_data[0] & DATA_BYTE2_SPECIFIED_MASK) && (evt->data == rec->sel_type.standard_type.event_data[1])))) @@ -1326,15 +1414,14 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char sprintf(*desc, "%s", evt->desc); } return; - } - evt++; + } } /* The Above while Condition was not met beacouse the below sensor type were Newly defined OEM Secondary Events. 0xC1, 0xC2, 0xC3. */ if((sfx) && (0x6F == rec->sel_type.standard_type.event_type)) { uint8_t flag = 0x00; - switch(code) + switch(rec->sel_type.standard_type.sensor_type) { case SENSOR_TYPE_FRM_PROG: if(0x0F == offset) @@ -1379,74 +1466,58 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char } -const char * -ipmi_sel_get_oem_sensor_type(IPMI_OEM iana, uint8_t code) +const char* +ipmi_get_generic_sensor_type(uint8_t code) { - struct ipmi_event_sensor_types *st = NULL; - - switch(iana){ - case IPMI_OEM_KONTRON: - st = oem_kontron_event_types; - break; - /* add you oem sensor type lookup assignement here */ - default: - lprintf(LOG_DEBUG, "ipmitool: missing OEM sensor type for %ul",iana); - break; + if (code <= SENSOR_TYPE_MAX) { + return ipmi_generic_sensor_type_vals[code]; } - if( st != NULL ) - for (; st->type != NULL; st++) - if (st->code == code) - return st->type; - - return ipmi_sel_get_sensor_type(code); + return NULL; } + const char * -ipmi_sel_get_oem_sensor_type_offset(IPMI_OEM iana, uint8_t code, uint8_t offset) +ipmi_get_oem_sensor_type(struct ipmi_intf *intf, uint8_t code) { - struct ipmi_event_sensor_types *st = NULL; + const struct oemvalstr *v, *found = NULL; + uint32_t iana = ipmi_get_oem(intf); - switch(iana){ - case IPMI_OEM_KONTRON: - st = oem_kontron_event_types; - break; - /* add you oem sensor type lookup assignement here */ - default: - lprintf(LOG_DEBUG, - "ipmitool: missing OEM sensor type offset for %ul",iana); - break; - } + for (v = ipmi_oem_sensor_type_vals; v->str; v++) { + if (v->oem == iana && v->val == code) { + return v->str; + } - if( st != NULL ) - for (; st->type != NULL; st++) - { - if (st->code == code && st->offset == (offset&0xf)) - return st->type; + if ((intf->picmg_avail + && v->oem == IPMI_OEM_PICMG + && v->val == code) + || (intf->vita_avail + && v->oem == IPMI_OEM_VITA + && v->val == code)) { + found = v; } + } - return ipmi_sel_get_oem_sensor_type(iana,code); + return found ? found->str : NULL; } -const char * -ipmi_sel_get_sensor_type(uint8_t code) -{ - struct ipmi_event_sensor_types *st; - for (st = sensor_specific_types; st->type != NULL; st++) - if (st->code == code) - return st->type; - return "Unknown"; -} const char * -ipmi_sel_get_sensor_type_offset(uint8_t code, uint8_t offset) +ipmi_get_sensor_type(struct ipmi_intf *intf, uint8_t code) { - struct ipmi_event_sensor_types *st; - for (st = sensor_specific_types; st->type != NULL; st++) - if (st->code == code && st->offset == (offset&0xf)) - return st->type; + const char *type; + + if (code >= 0xC0) { + type = ipmi_get_oem_sensor_type(intf, code); + } else { + type = ipmi_get_generic_sensor_type(code); + } + + if (type == NULL) { + type = "Unknown"; + } - return ipmi_sel_get_sensor_type(code); + return type; } static int @@ -1693,13 +1764,7 @@ ipmi_sel_print_event_file(struct ipmi_intf * intf, struct sel_event_record * evt evt->sel_type.standard_type.event_data[0], evt->sel_type.standard_type.event_data[1], evt->sel_type.standard_type.event_data[2], - ( - (evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0) - ? - ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - : - ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - ), + ipmi_get_sensor_type(intf, evt->sel_type.standard_type.sensor_type), evt->sel_type.standard_type.sensor_num, (description != NULL) ? description : "Unknown"); @@ -1819,15 +1884,8 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt) /* lookup SDR entry based on sensor number and type */ if (sdr != NULL) { - printf("%s ", - ( - (evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0) - ? - ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - : - ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - ) - ); + printf("%s ", ipmi_get_sensor_type(intf, + evt->sel_type.standard_type.sensor_type)); switch (sdr->type) { case SDR_RECORD_TYPE_FULL_SENSOR: printf("%s", sdr->record.full->id_string); @@ -1852,13 +1910,8 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt) break; } } else { - printf("%s",( - (evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0) - ? - ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - : - ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - )); + printf("%s", ipmi_get_sensor_type(intf, + evt->sel_type.standard_type.sensor_type)); if (evt->sel_type.standard_type.sensor_num != 0) printf(" #0x%02x", evt->sel_type.standard_type.sensor_num); } @@ -2025,14 +2078,8 @@ ipmi_sel_print_std_entry_verbose(struct ipmi_intf * intf, struct sel_event_recor printf(" EvM Revision : %02x\n", evt->sel_type.standard_type.evm_rev); printf(" Sensor Type : %s\n", - ( - (evt->sel_type.standard_type.sensor_type >=0xC0 && evt->sel_type.standard_type.sensor_type < 0xF0) - ? - ipmi_sel_get_oem_sensor_type_offset(ipmi_get_oem(intf),evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - : - ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0]) - ) - ); + ipmi_get_sensor_type(intf, + evt->sel_type.standard_type.sensor_type)); printf(" Sensor Number : %02x\n", evt->sel_type.standard_type.sensor_num); printf(" Event Type : %s\n", @@ -2096,7 +2143,7 @@ ipmi_sel_print_extended_entry_verbose(struct ipmi_intf * intf, struct sel_event_ printf(" EvM Revision : %02x\n", evt->sel_type.standard_type.evm_rev); printf(" Sensor Type : %s\n", - ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, evt->sel_type.standard_type.event_data[0])); + ipmi_get_sensor_type(intf, evt->sel_type.standard_type.sensor_type)); printf(" Sensor Number : %02x\n", evt->sel_type.standard_type.sensor_num); printf(" Event Type : %s\n", @@ -2255,7 +2302,7 @@ __ipmi_sel_savelist_entries(struct ipmi_intf * intf, int count, const char * sav if (count < 0) { /** Show only the most recent 'count' records. */ - int delta; + int i; uint16_t entries; req.msg.cmd = IPMI_CMD_GET_SEL_INFO; @@ -2273,15 +2320,20 @@ __ipmi_sel_savelist_entries(struct ipmi_intf * intf, int count, const char * sav if (-count > entries) count = -entries; - /* Get first record. */ - next_id = ipmi_sel_get_std_entry(intf, 0, &evt); - - delta = next_id - evt.record_id; - - /* Get last record. */ - next_id = ipmi_sel_get_std_entry(intf, 0xffff, &evt); - - next_id = evt.record_id + count * delta + delta; + for(i = 0; i < entries + count; i++) { + next_id = ipmi_sel_get_std_entry(intf, next_id, &evt); + if (next_id == 0) { + /* + * usually next_id of zero means end but + * retry because some hardware has quirks + * and will return 0 randomly. + */ + next_id = ipmi_sel_get_std_entry(intf, next_id, &evt); + if (next_id == 0) { + break; + } + } + } } if (savefile != NULL) { @@ -2402,7 +2454,7 @@ ipmi_sel_interpret(struct ipmi_intf *intf, unsigned long iana, evt.sel_type.standard_type.evm_rev = 4; /* FIXME: convert*/ - evt.sel_type.standard_type.timestamp; + /* evt.sel_type.standard_type.timestamp; */ /* skip timestamp */ cursor = index((const char *)cursor, ';'); diff --git a/lib/ipmi_sensor.c b/lib/ipmi_sensor.c index 063dfb0..a0b7eb8 100644 --- a/lib/ipmi_sensor.c +++ b/lib/ipmi_sensor.c @@ -200,14 +200,14 @@ ipmi_sensor_print_fc_discrete(struct ipmi_intf *intf, printf(" Entity ID : %d.%d\n", sensor->entity.id, sensor->entity.instance); printf(" Sensor Type (Discrete): %s\n", - ipmi_sdr_get_sensor_type_desc(sensor->sensor. + ipmi_get_sensor_type(intf, sensor->sensor. type)); if( sr->s_reading_valid ) { if (sr->s_has_analog_value) { printf(" Sensor Reading : %s %s\n", sr->s_a_str, sr->s_a_units); } - ipmi_sdr_print_discrete_state("States Asserted", + ipmi_sdr_print_discrete_state(intf, "States Asserted", sensor->sensor.type, sensor->event_type, sr->s_data2, @@ -315,7 +315,7 @@ ipmi_sensor_print_fc_threshold(struct ipmi_intf *intf, sensor->entity.id, sensor->entity.instance); printf(" Sensor Type (Threshold) : %s\n", - ipmi_sdr_get_sensor_type_desc(sensor->sensor. + ipmi_get_sensor_type(intf, sensor->sensor. type)); printf(" Sensor Reading : "); diff --git a/lib/ipmi_session.c b/lib/ipmi_session.c index 4855bc4..141f0f4 100644 --- a/lib/ipmi_session.c +++ b/lib/ipmi_session.c @@ -99,13 +99,8 @@ print_session_info_csv(const struct get_session_info_rsp * session_info, buffer, 16)); - printf(",%02x:%02x:%02x:%02x:%02x:%02x", - session_info->channel_data.lan_data.console_mac[0], - session_info->channel_data.lan_data.console_mac[1], - session_info->channel_data.lan_data.console_mac[2], - session_info->channel_data.lan_data.console_mac[3], - session_info->channel_data.lan_data.console_mac[4], - session_info->channel_data.lan_data.console_mac[5]); + printf(",%s", mac2str( + session_info->channel_data.lan_data.console_mac)); console_port_tmp = session_info->channel_data.lan_data.console_port; #if WORDS_BIGENDIAN @@ -187,13 +182,8 @@ print_session_info_verbose(const struct get_session_info_rsp * session_info, buffer, 16)); - printf("console mac : %02x:%02x:%02x:%02x:%02x:%02x\n", - session_info->channel_data.lan_data.console_mac[0], - session_info->channel_data.lan_data.console_mac[1], - session_info->channel_data.lan_data.console_mac[2], - session_info->channel_data.lan_data.console_mac[3], - session_info->channel_data.lan_data.console_mac[4], - session_info->channel_data.lan_data.console_mac[5]); + printf("console mac : %s\n", mac2str( + session_info->channel_data.lan_data.console_mac)); console_port_tmp = session_info->channel_data.lan_data.console_port; #if WORDS_BIGENDIAN diff --git a/lib/ipmi_sol.c b/lib/ipmi_sol.c index 333ce90..3acd5bb 100644 --- a/lib/ipmi_sol.c +++ b/lib/ipmi_sol.c @@ -1648,15 +1648,11 @@ ipmi_sol_red_pill(struct ipmi_intf * intf, int instance) else if (FD_ISSET(intf->fd, &read_fds)) { struct ipmi_rs * rs =intf->recv_sol(intf); - if ( rs) - { + if (rs) { output(rs); + } else { + bShouldExit = bBmcClosedSession = 1; } - /* - * Should recv_sol come back null, the incoming packet was not ours. - * Just fall through, the keepalive logic will determine if - * the BMC has dropped the session. - */ } diff --git a/lib/ipmi_strings.c b/lib/ipmi_strings.c index 7fefee9..94b2abd 100644 --- a/lib/ipmi_strings.c +++ b/lib/ipmi_strings.c @@ -64,12 +64,13 @@ const struct valstr ipmi_oem_info[] = { { IPMI_OEM_TOSHIBA, "Toshiba" }, { IPMI_OEM_HITACHI_116, "Hitachi" }, { IPMI_OEM_HITACHI_399, "Hitachi" }, - { IPMI_OEM_NOKIA_SOLUTIONS_AND_NETWORKS, "Nokia Solutions and Networks (formerly 'Nokia Siemens Networks')" }, + { IPMI_OEM_NOKIA_SOLUTIONS_AND_NETWORKS, "Nokia Solutions and Networks" }, { IPMI_OEM_BULL, "Bull Company" }, { IPMI_OEM_PPS, "Pigeon Point Systems" }, { IPMI_OEM_BROADCOM, "Broadcom Corporation" }, { IPMI_OEM_ERICSSON, "Ericsson AB"}, { IPMI_OEM_QUANTA, "Quanta" }, + { IPMI_OEM_VITA, "VITA" }, { IPMI_OEM_ADVANTECH, "Advantech" }, /************************************************************************ * Add ID String for IANA Enterprise Number of IBM & ADLINK @@ -286,34 +287,63 @@ const struct oemvalstr ipmi_oem_product_info[] = { { 0xffffff , 0xffff , NULL }, }; -const struct oemvalstr ipmi_oem_sdr_type_vals[] = { +const char *ipmi_generic_sensor_type_vals[] = { + "reserved", + "Temperature", "Voltage", "Current", "Fan", + "Physical Security", "Platform Security", "Processor", + "Power Supply", "Power Unit", "Cooling Device", "Other", + "Memory", "Drive Slot / Bay", "POST Memory Resize", + "System Firmwares", "Event Logging Disabled", "Watchdog1", + "System Event", "Critical Interrupt", "Button", + "Module / Board", "Microcontroller", "Add-in Card", + "Chassis", "Chip Set", "Other FRU", "Cable / Interconnect", + "Terminator", "System Boot Initiated", "Boot Error", + "OS Boot", "OS Critical Stop", "Slot / Connector", + "System ACPI Power State", "Watchdog2", "Platform Alert", + "Entity Presence", "Monitor ASIC", "LAN", + "Management Subsys Health", "Battery", "Session Audit", + "Version Change", "FRU State", + NULL +}; + +const struct oemvalstr ipmi_oem_sensor_type_vals[] = { /* Keep OEM grouped together */ - { IPMI_OEM_KONTRON , 0xC0 , "OEM Firmware Info" }, - { IPMI_OEM_KONTRON , 0xC2 , "OEM Init Agent" }, - { IPMI_OEM_KONTRON , 0xC3 , "OEM IPMBL Link State" }, - { IPMI_OEM_KONTRON , 0xC4 , "OEM Board Reset" }, - { IPMI_OEM_KONTRON , 0xC5 , "OEM FRU Information Agent" }, - { IPMI_OEM_KONTRON , 0xC6 , "OEM POST Value Sensor" }, - { IPMI_OEM_KONTRON , 0xC7 , "OEM FWUM Status" }, - { IPMI_OEM_KONTRON , 0xC8 , "OEM Switch Mngt Software Status" }, - { IPMI_OEM_KONTRON , 0xC9 , "OEM OEM Diagnostic Status" }, - { IPMI_OEM_KONTRON , 0xCA , "OEM Component Firmware Upgrade" }, - { IPMI_OEM_KONTRON , 0xCB , "OEM FRU Over Current" }, - { IPMI_OEM_KONTRON , 0xCC , "OEM FRU Sensor Error" }, - { IPMI_OEM_KONTRON , 0xCD , "OEM FRU Power Denied" }, - { IPMI_OEM_KONTRON , 0xCE , "OEM Reserved" }, - { IPMI_OEM_KONTRON , 0xCF , "OEM Board Reset" }, - { IPMI_OEM_KONTRON , 0xD0 , "OEM Clock Resource Control" }, - { IPMI_OEM_KONTRON , 0xD1 , "OEM Power State" }, - { IPMI_OEM_KONTRON , 0xD2 , "OEM FRU Mngt Power Failure" }, - { IPMI_OEM_KONTRON , 0xD3 , "OEM Jumper Status" }, - { IPMI_OEM_KONTRON , 0xF2 , "OEM RTM Module Hotswap" }, - - { IPMI_OEM_PICMG , 0xF0 , "PICMG FRU Hotswap" }, - { IPMI_OEM_PICMG , 0xF1 , "PICMG IPMB0 Link State" }, - { IPMI_OEM_PICMG , 0xF2 , "PICMG Module Hotswap" }, - - { 0xffffff, 0x00, NULL } + { IPMI_OEM_KONTRON, 0xC0, "Firmware Info" }, + { IPMI_OEM_KONTRON, 0xC2, "Init Agent" }, + { IPMI_OEM_KONTRON, 0xC2, "Board Reset(cPCI)" }, + { IPMI_OEM_KONTRON, 0xC3, "IPMBL Link State" }, + { IPMI_OEM_KONTRON, 0xC4, "Board Reset" }, + { IPMI_OEM_KONTRON, 0xC5, "FRU Information Agent" }, + { IPMI_OEM_KONTRON, 0xC6, "POST Value Sensor" }, + { IPMI_OEM_KONTRON, 0xC7, "FWUM Status" }, + { IPMI_OEM_KONTRON, 0xC8, "Switch Mngt Software Status" }, + { IPMI_OEM_KONTRON, 0xC9, "OEM Diagnostic Status" }, + { IPMI_OEM_KONTRON, 0xCA, "Component Firmware Upgrade" }, + { IPMI_OEM_KONTRON, 0xCB, "FRU Over Current" }, + { IPMI_OEM_KONTRON, 0xCC, "FRU Sensor Error" }, + { IPMI_OEM_KONTRON, 0xCD, "FRU Power Denied" }, + { IPMI_OEM_KONTRON, 0xCE, "Reserved" }, + { IPMI_OEM_KONTRON, 0xCF, "Board Reset" }, + { IPMI_OEM_KONTRON, 0xD0, "Clock Resource Control" }, + { IPMI_OEM_KONTRON, 0xD1, "Power State" }, + { IPMI_OEM_KONTRON, 0xD2, "FRU Mngt Power Failure" }, + { IPMI_OEM_KONTRON, 0xD3, "Jumper Status" }, + { IPMI_OEM_KONTRON, 0xF2, "RTM Module Hotswap" }, + /* PICMG Sensor Types */ + { IPMI_OEM_PICMG, 0xF0, "FRU Hot Swap" }, + { IPMI_OEM_PICMG, 0xF1,"IPMB Physical Link" }, + { IPMI_OEM_PICMG, 0xF2, "Module Hot Swap" }, + { IPMI_OEM_PICMG, 0xF3, "Power Channel Notification" }, + { IPMI_OEM_PICMG, 0xF4, "Telco Alarm Input" }, + /* VITA 46.11 Sensor Types */ + { IPMI_OEM_VITA, 0xF0, "FRU State" }, + { IPMI_OEM_VITA, 0xF1, "System IPMB Link" }, + { IPMI_OEM_VITA, 0xF2, "FRU Health" }, + { IPMI_OEM_VITA, 0xF3, "FRU Temperature" }, + { IPMI_OEM_VITA, 0xF4, "Payload Test Results" }, + { IPMI_OEM_VITA, 0xF5, "Payload Test Status" }, + + { 0xffffff, 0x00, NULL } }; const struct valstr ipmi_netfn_vals[] = { @@ -591,6 +621,9 @@ const struct valstr ipmi_auth_algorithms[] = { { IPMI_AUTH_RAKP_NONE, "none" }, { IPMI_AUTH_RAKP_HMAC_SHA1, "hmac_sha1" }, { IPMI_AUTH_RAKP_HMAC_MD5, "hmac_md5" }, +#ifdef HAVE_CRYPTO_SHA256 + { IPMI_AUTH_RAKP_HMAC_SHA256, "hmac_sha256" }, +#endif /* HAVE_CRYPTO_SHA256 */ { 0x00, NULL } }; @@ -599,6 +632,9 @@ const struct valstr ipmi_integrity_algorithms[] = { { IPMI_INTEGRITY_HMAC_SHA1_96, "hmac_sha1_96" }, { IPMI_INTEGRITY_HMAC_MD5_128, "hmac_md5_128" }, { IPMI_INTEGRITY_MD5_128 , "md5_128" }, +#ifdef HAVE_CRYPTO_SHA256 + { IPMI_INTEGRITY_HMAC_SHA256_128, "sha256_128" }, +#endif /* HAVE_CRYPTO_SHA256 */ { 0x00, NULL } }; @@ -610,6 +646,14 @@ const struct valstr ipmi_encryption_algorithms[] = { { 0x00, NULL } }; +const struct valstr ipmi_user_enable_status_vals[] = { + { 0x00, "unknown" }, + { 0x40, "enabled" }, + { 0x80, "disabled" }, + { 0xC0, "reserved" }, + { 0xFF, NULL }, +}; + const struct valstr picmg_frucontrol_vals[] = { { 0, "Cold Reset" }, { 1, "Warm Reset" }, diff --git a/lib/ipmi_sunoem.c b/lib/ipmi_sunoem.c index e4fae65..ecbcbd9 100644 --- a/lib/ipmi_sunoem.c +++ b/lib/ipmi_sunoem.c @@ -1436,7 +1436,7 @@ ipmi_sunoem_echo(struct ipmi_intf * intf, int argc, char *argv[]) received++; if (!quiet_mode) { - printf("Receive %u Bytes - Seq. # %d time=%d ms\n", + printf("Receive %lu Bytes - Seq. # %d time=%d ms\n", sizeof(sunoem_echo_msg_t), echo_rsp->seq_num, resp_time); } } /* for (i = 0; i < num; i++) */ diff --git a/src/ipmievd.c b/src/ipmievd.c index caefd95..67788e5 100644 --- a/src/ipmievd.c +++ b/src/ipmievd.c @@ -239,8 +239,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) return; } - type = ipmi_sel_get_sensor_type_offset(evt->sel_type.standard_type.sensor_type, - evt->sel_type.standard_type.event_data[0]); + type = ipmi_get_sensor_type(intf, evt->sel_type.standard_type.sensor_type); ipmi_get_event_desc(intf, evt, &desc); @@ -333,7 +332,7 @@ log_event(struct ipmi_event_intf * eintf, struct sel_event_record * evt) break; default: - lprintf(LOG_NOTICE, "%s%s sensor - %s", + lprintf(LOG_NOTICE, "%s%s sensor (0x%02x) - %s", eintf->prefix, type, evt->sel_type.standard_type.sensor_num, desc ? desc : ""); break; diff --git a/src/ipmitool.c b/src/ipmitool.c index 164fd44..5e19c6e 100644 --- a/src/ipmitool.c +++ b/src/ipmitool.c @@ -77,6 +77,7 @@ extern int ipmi_shell_main(struct ipmi_intf * intf, int argc, char ** argv); extern int ipmi_echo_main(struct ipmi_intf * intf, int argc, char ** argv); extern int ipmi_set_main(struct ipmi_intf * intf, int argc, char ** argv); extern int ipmi_exec_main(struct ipmi_intf * intf, int argc, char ** argv); +extern int ipmi_lan6_main(struct ipmi_intf *intf, int argc, char **argv); int csv_output = 0; @@ -122,6 +123,7 @@ struct ipmi_cmd ipmitool_cmd_list[] = { { ipmi_ekanalyzer_main,"ekanalyzer", "run FRU-Ekeying analyzer using FRU files"}, { ipmi_ime_main, "ime", "Update Intel Manageability Engine Firmware"}, { ipmi_vita_main, "vita", "Run a VITA 46.11 extended cmd"}, + { ipmi_lan6_main, "lan6", "Configure IPv6 LAN Channels"}, { NULL }, }; diff --git a/src/plugins/imb/imbapi.c b/src/plugins/imb/imbapi.c index 84eec2e..34c9c82 100644 --- a/src/plugins/imb/imbapi.c +++ b/src/plugins/imb/imbapi.c @@ -1,1889 +1,1307 @@ -/*M* -// PVCS: -// $Workfile: imbapi.c $ -// $Revision: 1.5 $ -// $Modtime: 06 Aug 2001 13:16:56 $ -// $Author: stybla $ -// -// Purpose: This file contains the entry point that opens the IMB device in -// order to issue the IMB driver API related IOCTLs. -// This file implements the IMB driver API for the Server -// Management Agents -// -// -*M*/ -/*----------------------------------------------------------------------* -The BSD License -Copyright (c) 2002, Intel Corporation -All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - a.. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - b.. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - c.. Neither the name of Intel Corporation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *----------------------------------------------------------------------*/ /* - * $Log: imbapi.c,v $ - * Revision 1.5 2013/07/22 08:35:23 stybla - * ID: 65 - Fixes for configure.in for cross compilation + * Copyright (c) 2002, Intel Corporation * - * 'src/plugins/imb/imbapi.c' - don't cast NULL to int, ever!!! + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * Revision 1.4 2013/07/21 11:33:57 stybla - * ID: 65 - Fixes for configure.in for cross compilation + * Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * - * NULL should never be cast to an int. + * 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. * - * Commit for Dan Gora + * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * - * Revision 1.3 2013/01/18 12:46:52 ledva - * 3600962 descriptor leaks - * - * Revision 1.2 2004/08/31 23:52:58 iceblink - * fix lots of little errors that show up with -Werror -Wall - * - * Revision 1.1 2004/08/27 16:33:25 iceblink - * add support for Intel IMB kernel driver (for legacy kernel support) - * imbapi.[ch] code is BSD licensed and taken from panicsel.sf.net - * - * - * Rev 1.12ac 04 Apr 2002 13:17:58 arcress - * Mods for open-source & various compile cleanup mods - * - * Rev 1.12 06 Aug 2001 13:17:58 spoola - * Fixed tracker items #15667, #15666, #15664 - * - * Rev 1.0 05 Sep 1999 17:20:30 mramacha - * Linux checkin - * - * Note: This file is derived from the NTWORK version of the imbapi.c - * It was decided to create OS specific ones for Linux and Solaris. - * It has all the fixes that went into the imbapi.c up to Rev 1.12 - * in the 2.2 NTWORK branch. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Purpose: This file contains the entry point that opens the IMB device in + * order to issue the IMB driver API related IOCTLs. This file implements the + * IMB driver API for the Server Management Agents + */ + + +/* Use -DLINUX_DEBUG_MAX in the Makefile, resp. CFLAGS if you want a dump of the + * memory to debug mmap system call in MapPhysicalMemory() below. */ #define IMB_API #ifdef WIN32 -#define NO_MACRO_ARGS 1 -#include <windows.h> -#include <stdio.h> - -#else /* LINUX, SCO_UW, UNIX */ -#include <unistd.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <sys/ioctl.h> -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <string.h> +# define NO_MACRO_ARGS 1 +# include <stdio.h> +# include <windows.h> +#else /* LINUX, SCO_UW, UNIX */ +# include <fcntl.h> +# include <stdio.h> +# include <stdlib.h> +# include <string.h> +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/param.h> +# include <sys/stat.h> +# include <sys/types.h> +# include <unistd.h> #endif + #include "imbapi.h" #include <sys/socket.h> +#include <ipmitool/log.h> #ifdef SCO_UW -#define NO_MACRO_ARGS 1 -#define __FUNCTION__ "func" -#define IMB_DEVICE "/dev/instru/mismic" +# define NO_MACRO_ARGS 1 +# define __FUNCTION__ "func" +# define IMB_DEVICE "/dev/instru/mismic" #else -#define IMB_DEVICE "/dev/imb" +# define IMB_DEVICE "/dev/imb" #endif #if !defined(PAGESIZE) && defined(PAGE_SIZE) -# define PAGESIZE PAGE_SIZE +# define PAGESIZE PAGE_SIZE #endif #if !defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE) -# define _SC_PAGESIZE _SC_PAGE_SIZE -#endif - -/*Just to make the DEBUG code cleaner.*/ -#ifndef NO_MACRO_ARGS -#ifdef LINUX_DEBUG -#define DEBUG(format, args...) printf(format, ##args) -#else -#define DEBUG(format, args...) +# define _SC_PAGESIZE _SC_PAGE_SIZE #endif -#endif - -/* uncomment out the #define below or use -DLINUX_DEBUG_MAX in the makefile -// if you want a dump of the memory to debug mmap system call in -// MapPhysicalMemory() below. -// -//#define LINUX_DEBUG_MAX */ - -/*keep it simple. use global varibles for event objects and handles -//pai 10/8 */ - -/* UnixWare should eventually have its own source code file. Right now -// new code has been added based on the exsisting policy of using -// pre-processor directives to separate os-specific code (pai 11/21) */ - -HANDLE AsyncEventHandle = 0; -//static void * AsyncEventObject = 0; +HANDLE AsyncEventHandle = 0; static int IpmiVersion; -/*//////////////////////////////////////////////////////////////////////////// -// GLOBAL VARIABLES -///////////////////////////////////////////////////////////////////////////// */ - -IO_STATUS_BLOCK NTstatus; /*dummy place holder. See deviceiocontrol. */ +/* GLOBAL VARIABLES */ +/* dummy place holder. See deviceiocontrol. */ +IO_STATUS_BLOCK NTstatus; static HANDLE hDevice1; static HANDLE hDevice; -/*mutex_t deviceMutex; */ -static int fDriverTyp; /*from ipmicmd.c*/ +static int fDriverTyp; /* from ipmicmd.c */ -/*//////////////////////////////////////////////////////////////////// -// open_imb -////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: open_imb -// Purpose: To open imb device -// Context: Called from each routine to make sure that open is done. -// Returns: returns 0 for Fail and 1 for Success, sets hDevice to open -// handle. -// Parameters: none -// Notes: none -*F*/ +/* open_imb - Open IMB device. Called from each routine to make sure that open + * is done. + * + * Returns: returns 0 for Fail and 1 for Success, sets hDevice to open handle. + */ #ifdef WIN32 -int open_imb(void) +int +open_imb(void) { -/* This routine will be called from all other routines before doing any - interfacing with imb driver. It will open only once. */ - IMBPREQUESTDATA requestData; - BYTE respBuffer[16]; - DWORD respLength; - BYTE completionCode; - - if (hDevice1 == 0) /*INVALID_HANDLE_VALUE*/ - { - // - // Open IMB driver device - // - hDevice = CreateFile( "\\\\.\\Imb", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - if (hDevice == NULL || hDevice == INVALID_HANDLE_VALUE) - return (0); /*FALSE*/ - - // Detect the IPMI version for processing requests later. - // This is a crude but most reliable method to differentiate - // between old IPMI versions and the 1.0 version. If we had used the - // version field instead then we would have had to revalidate all the - // older platforms (pai 4/27/99) - requestData.cmdType = GET_DEVICE_ID; - requestData.rsSa = BMC_SA; - requestData.rsLun = BMC_LUN; - requestData.netFn = APP_NETFN ; - requestData.busType = PUBLIC_BUS; - requestData.data = NULL; - requestData.dataLength = 0; - respLength = 16; - if ( (SendTimedImbpRequest ( &requestData, (DWORD)400, - respBuffer, &respLength, &completionCode - ) != ACCESN_OK ) || ( completionCode != 0) ) - { - CloseHandle(hDevice); - return (0); /*FALSE*/ - } - hDevice1 = hDevice; + /* This routine will be called from all other routines before doing any + * interfacing with imb driver. It will open only once. + */ + IMBPREQUESTDATA requestData; + BYTE respBuffer[16]; + DWORD respLength; + BYTE completionCode; - if (respLength < (IPMI10_GET_DEVICE_ID_RESP_LENGTH-1)) - IpmiVersion = IPMI_09_VERSION; - else { - if ( respBuffer[4] == 0x51 ) - IpmiVersion = IPMI_15_VERSION; - else - IpmiVersion = IPMI_10_VERSION; - } - } - return (1); /*TRUE*/ + if (hDevice1 != 0) { + return 1; + } -} /*end open_imb for Win32 */ + /* Open IMB driver device */ + hDevice = CreateFile("\\\\.\\Imb", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hDevice == NULL || hDevice == INVALID_HANDLE_VALUE) { + return 0; + } + /* Detect the IPMI version for processing requests later. This + * is a crude but most reliable method to differentiate between + * old IPMI versions and the 1.0 version. If we had used the + * version field instead then we would have had to revalidate + * all the older platforms (pai 4/27/99) + */ + requestData.cmdType = GET_DEVICE_ID; + requestData.rsSa = BMC_SA; + requestData.rsLun = BMC_LUN; + requestData.netFn = APP_NETFN ; + requestData.busType = PUBLIC_BUS; + requestData.data = NULL; + requestData.dataLength = 0; + respLength = 16; + if ((SendTimedImbpRequest(&requestData, (DWORD)400, respBuffer, + &respLength, &completionCode) != ACCESN_OK) + || (completionCode != 0)) { + CloseHandle(hDevice); + return 0; + } + hDevice1 = hDevice; + if (respLength < (IPMI10_GET_DEVICE_ID_RESP_LENGTH - 1)) { + IpmiVersion = IPMI_09_VERSION; + } else { + if (respBuffer[4] == 0x51) { + IpmiVersion = IPMI_15_VERSION; + } else { + IpmiVersion = IPMI_10_VERSION; + } + } + return 1; +} /* end open_imb for Win32 */ #else /* LINUX, SCO_UW, etc. */ -int open_imb(void) +int +open_imb(void) { -/* This routine will be called from all other routines before doing any - interfacing with imb driver. It will open only once. */ - IMBPREQUESTDATA requestData; - BYTE respBuffer[16]; - DWORD respLength; - BYTE completionCode; - + /* This routine will be called from all other routines before doing any + * interfacing with imb driver. It will open only once. + */ + IMBPREQUESTDATA requestData; + BYTE respBuffer[16]; + DWORD respLength; + BYTE completionCode; int my_ret_code; - if (hDevice1 == 0) - { -#ifndef NO_MACRO_ARGS - DEBUG("%s: opening the driver\n", __FUNCTION__); -#endif - /* - printf("open_imb: " + if (hDevice1 != 0) { + return 1; + } + lprintf(LOG_DEBUG, "%s: opening the driver", __FUNCTION__); + /* printf("open_imb: " "IOCTL_IMB_SEND_MESSAGE =%x \n" "IOCTL_IMB_GET_ASYNC_MSG=%x \n" "IOCTL_IMB_MAP_MEMORY = %x \n" "IOCTL_IMB_UNMAP_MEMORY= %x \n" "IOCTL_IMB_SHUTDOWN_CODE=%x \n" "IOCTL_IMB_REGISTER_ASYNC_OBJ =%x \n" "IOCTL_IMB_DEREGISTER_ASYNC_OBJ=%x \n" "IOCTL_IMB_CHECK_EVENT =%x \n" "IOCTL_IMB_POLL_ASYNC =%x \n", - IOCTL_IMB_SEND_MESSAGE, IOCTL_IMB_GET_ASYNC_MSG, + IOCTL_IMB_SEND_MESSAGE, IOCTL_IMB_GET_ASYNC_MSG, IOCTL_IMB_MAP_MEMORY, IOCTL_IMB_UNMAP_MEMORY, IOCTL_IMB_SHUTDOWN_CODE, IOCTL_IMB_REGISTER_ASYNC_OBJ, IOCTL_IMB_DEREGISTER_ASYNC_OBJ, - IOCTL_IMB_CHECK_EVENT , IOCTL_IMB_POLL_ASYNC); *%%%%*/ - - /*O_NDELAY flag will cause problems later when driver makes - //you wait. Hence removing it. */ - /*if ((hDevice1 = open(IMB_DEVICE,O_RDWR|O_NDELAY)) <0) */ - if ((hDevice1 = open(IMB_DEVICE,O_RDWR)) <0) - { - char buf[128]; - - hDevice1 = 0; - if (fDriverTyp != 0) { /*not 1st time*/ - sprintf(buf,"%s %s: open(%s) failed", - __FILE__,__FUNCTION__,IMB_DEVICE); - perror(buf); - } - return (0); - } - - /* Detect the IPMI version for processing requests later. - // This is a crude but most reliable method to differentiate - // between old IPMI versions and the 1.0 version. If we had used the - // version field instead then we would have had to revalidate all - // the older platforms (pai 4/27/99) */ - requestData.cmdType = GET_DEVICE_ID; - requestData.rsSa = BMC_SA; - requestData.rsLun = BMC_LUN; - requestData.netFn = APP_NETFN ; - requestData.busType = PUBLIC_BUS; - requestData.data = NULL; - requestData.dataLength = 0; - respLength = 16; -#ifndef NO_MACRO_ARGS - DEBUG("%s: opened driver, getting IPMI version\n", __FUNCTION__); -#endif - if ( ((my_ret_code = SendTimedImbpRequest(&requestData, (DWORD)400, - respBuffer, (int *)&respLength, &completionCode) - ) != ACCESN_OK ) || ( completionCode != 0) ) - { - printf("%s: SendTimedImbpRequest error. Ret = %d CC = 0x%X\n", - __FUNCTION__, my_ret_code, completionCode); - close(hDevice1); - hDevice1 = 0; - return (0); - } + IOCTL_IMB_CHECK_EVENT , IOCTL_IMB_POLL_ASYNC); + */ - if (respLength < (IPMI10_GET_DEVICE_ID_RESP_LENGTH-1)) - IpmiVersion = IPMI_09_VERSION; - else { - if ( respBuffer[4] == 0x51 ) - IpmiVersion = IPMI_15_VERSION; - else - IpmiVersion = IPMI_10_VERSION; - } -#ifndef NO_MACRO_ARGS - DEBUG("%s: IPMI version 0x%x\n", __FUNCTION__, IpmiVersion); -#endif - -/* -//initialise a mutex - if(mutex_init(&deviceMutex , USYNC_THREAD, NULL) != 0) - { - return(0); + /* O_NDELAY flag will cause problems later when driver makes + * you wait. Hence removing it. + */ + if ((hDevice1 = open(IMB_DEVICE, O_RDWR)) < 0) { + char buf[128]; + hDevice1 = 0; + if (fDriverTyp != 0) { + /* not 1st time */ + sprintf(buf,"%s %s: open(%s) failed", + __FILE__, __FUNCTION__, IMB_DEVICE); + perror(buf); } -*/ + return 0; + } + /* Detect the IPMI version for processing requests later. + * This is a crude but most reliable method to differentiate + * between old IPMI versions and the 1.0 version. If we had used the + * version field instead then we would have had to revalidate all + * the older platforms (pai 4/27/99) + */ + requestData.cmdType = GET_DEVICE_ID; + requestData.rsSa = BMC_SA; + requestData.rsLun = BMC_LUN; + requestData.netFn = APP_NETFN ; + requestData.busType = PUBLIC_BUS; + requestData.data = NULL; + requestData.dataLength = 0; + respLength = 16; + lprintf(LOG_DEBUG, "%s: opened driver, getting IPMI version", __FUNCTION__); + if (((my_ret_code = SendTimedImbpRequest(&requestData, (DWORD)400, + respBuffer, + (int *)&respLength, + &completionCode)) != ACCESN_OK) + || (completionCode != 0)) { + printf("%s: SendTimedImbpRequest error. Ret = %d CC = 0x%X\n", + __FUNCTION__, my_ret_code, completionCode); + close(hDevice1); + hDevice1 = 0; + return 0; + } + if (respLength < (IPMI10_GET_DEVICE_ID_RESP_LENGTH - 1)) { + IpmiVersion = IPMI_09_VERSION; + } else { + if (respBuffer[4] == 0x51) { + IpmiVersion = IPMI_15_VERSION; + } else { + IpmiVersion = IPMI_10_VERSION; + } } - - return (1); -} /*end open_imb()*/ + lprintf(LOG_DEBUG, "%s: IPMI version 0x%x", __FUNCTION__, + IpmiVersion); + return 1; +} /* end open_imb() */ #endif -/*---------------------------------------------------------------------* - * ipmi_open_ia & ipmi_close_ia - *---------------------------------------------------------------------*/ -int ipmi_open_ia(void) +/* ipmi_open_ia */ +int +ipmi_open_ia(void) { - int rc = 0; - rc = open_imb(); /*sets hDevice1*/ - if (rc == 1) rc = 0; - else rc = -1; - return(rc); + int rc = 0; + /* sets hDevice1 */ + rc = open_imb(); + if (rc == 1) { + rc = 0; + } else { + rc = -1; + } + return rc; } -int ipmi_close_ia(void) +/* ipmi_close_ia */ +int +ipmi_close_ia(void) { - int rc = 0; - if (hDevice1 != 0) { + int rc = 0; + if (hDevice1 != 0) { #ifdef WIN32 - CloseHandle(hDevice1); + CloseHandle(hDevice1); #else - rc = close(hDevice1); + rc = close(hDevice1); #endif - } - return(rc); + } + return rc; } #ifndef WIN32 -/*/////////////////////////////////////////////////////////////////////////// -// DeviceIoControl -///////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: DeviceIoControl -// Purpose: Simulate NT DeviceIoControl using unix calls and structures. -// Context: called for every NT DeviceIoControl -// Returns: FALSE for fail and TRUE for success. Same as standarad NTOS call -// as it also sets Ntstatus.status. -// Parameters: Standard NT call parameters, see below. -// Notes: none -*F*/ +/* DeviceIoControl - Simulate NT DeviceIoControl using unix calls and structures. + * + * @dummy_hDevice - handle of device + * @dwIoControlCode - control code of operation to perform + * @lpvInBuffer, address of buffer for input data + * @cbInBuffer, size of input buffer + * @lpvOutBuffer, address of output buffer + * @cbOutBuffer, size of output buffer + * @lpcbBytesReturned, address of actual bytes of output + * @lpoOverlapped address of overlapped struct + * + * returns - FALSE for fail and TRUE for success. Same as standarad NTOS call as + * it also sets Ntstatus.status. + */ static BOOL -DeviceIoControl( - HANDLE dummey_hDevice, /* handle of device */ - DWORD dwIoControlCode, /* control code of operation to perform*/ - LPVOID lpvInBuffer, /* address of buffer for input data */ - DWORD cbInBuffer, /* size of input buffer */ - LPVOID lpvOutBuffer, /* address of output buffer */ - DWORD cbOutBuffer, /* size of output buffer */ - LPDWORD lpcbBytesReturned, /* address of actual bytes of output */ - LPOVERLAPPED lpoOverlapped /* address of overlapped struct */ - ) +DeviceIoControl(HANDLE dummey_hDevice, DWORD dwIoControlCode, LPVOID + lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, + DWORD cbOutBuffer, LPDWORD lpcbBytesReturned, + LPOVERLAPPED lpoOverlapped) { struct smi s; int rc; int ioctl_status; - rc = open_imb(); - if (rc == 0) { - return FALSE; - } + rc = open_imb(); + if (rc == 0) { + return FALSE; + } + lprintf(LOG_DEBUG, "%s: ioctl cmd = 0x%lx", __FUNCTION__, + dwIoControlCode); + lprintf(LOG_DEBUG, "cbInBuffer %d cbOutBuffer %d", cbInBuffer, + cbOutBuffer); + if (cbInBuffer > 41) { + cbInBuffer = 41; /* Intel driver max buf */ + } - /* - //lock the mutex, before making the request.... - if(mutex_lock(&deviceMutex) != 0) - { - return(FALSE); - } - */ -#ifndef NO_MACRO_ARGS - DEBUG("%s: ioctl cmd = 0x%lx ", __FUNCTION__,dwIoControlCode); - DEBUG("cbInBuffer %d cbOutBuffer %d\n", cbInBuffer, cbOutBuffer); -#endif - if (cbInBuffer > 41) cbInBuffer = 41; /* Intel driver max buf */ - - s.lpvInBuffer = lpvInBuffer; - s.cbInBuffer = cbInBuffer; - s.lpvOutBuffer = lpvOutBuffer; - s.cbOutBuffer = cbOutBuffer; - s.lpcbBytesReturned = lpcbBytesReturned; - s.lpoOverlapped = lpoOverlapped; - s.ntstatus = (LPVOID)&NTstatus; /*dummy place holder. Linux IMB driver - //doesnt return status or info via it.*/ - - if ( (ioctl_status = ioctl(hDevice1, dwIoControlCode,&s) ) <0) { -#ifndef NO_MACRO_ARGS - DEBUG("%s %s: ioctl cmd = 0x%x failed", - __FILE__,__FUNCTION__,dwIoControlCode); -#endif - /* mutex_unlock(&deviceMutex); */ - return FALSE; - } - /* mutex_unlock(&deviceMutex); */ - -#ifndef NO_MACRO_ARGS - DEBUG("%s: ioctl_status %d bytes returned = %d \n", - __FUNCTION__, ioctl_status, *lpcbBytesReturned); -#endif + s.lpvInBuffer = lpvInBuffer; + s.cbInBuffer = cbInBuffer; + s.lpvOutBuffer = lpvOutBuffer; + s.cbOutBuffer = cbOutBuffer; + s.lpcbBytesReturned = lpcbBytesReturned; + s.lpoOverlapped = lpoOverlapped; + /* dummy place holder. Linux IMB driver doesnt return status or info + * via it + */ + s.ntstatus = (LPVOID)&NTstatus; -/*MR commented this just as in Sol1.10. lpcbBytesReturned has the right data -// *lpcbBytesReturned = NTstatus.Information; */ - + if ((ioctl_status = ioctl(hDevice1, dwIoControlCode,&s)) < 0) { + lprintf(LOG_DEBUG, "%s %s: ioctl cmd = 0x%x failed", + __FILE__, __FUNCTION__, dwIoControlCode); + return FALSE; + } + lprintf(LOG_DEBUG, "%s: ioctl_status %d bytes returned = %d", + __FUNCTION__, ioctl_status, *lpcbBytesReturned); if (ioctl_status == STATUS_SUCCESS) { -#ifndef NO_MACRO_ARGS - DEBUG("%s returning true\n", __FUNCTION__); -#endif - return (TRUE); + lprintf(LOG_DEBUG, "%s returning true", __FUNCTION__); + return (TRUE); + } else { + lprintf(LOG_DEBUG, "%s returning false", __FUNCTION__); + return (FALSE); } - else { -#ifndef NO_MACRO_ARGS - DEBUG("%s returning false\n", __FUNCTION__); -#endif - return (FALSE); - } } #endif -/*Used only by UW. Left here for now. IMB driver will not accept this -//ioctl. */ +/* Used only by UW. Left here for now. IMB driver will not accept this ioctl. */ ACCESN_STATUS StartAsyncMesgPoll() { + DWORD retLength; + BOOL status; + lprintf(LOG_DEBUG, "%s: DeviceIoControl cmd = %x", + __FUNCTION__, IOCTL_IMB_POLL_ASYNC); - DWORD retLength; - BOOL status; - -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl cmd = %x\n",__FUNCTION__,IOCTL_IMB_POLL_ASYNC); -#endif - status = DeviceIoControl ( hDevice, - IOCTL_IMB_POLL_ASYNC, - NULL, - 0, - NULL, - 0, - & retLength, - 0 - ); - -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif + status = DeviceIoControl(hDevice, IOCTL_IMB_POLL_ASYNC, NULL, 0, NULL, + 0, &retLength, 0); - if( status == TRUE ) { + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if (status == TRUE) { return ACCESN_OK; } else { return ACCESN_ERROR; } - } -/*///////////////////////////////////////////////////////////////////////////// -// SendTimedI2cRequest -///////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: SendTimedI2cRequest -// Purpose: This function sends a request to a I2C device -// Context: Used by Upper level agents (sis modules) to access dumb I2c devices -// Returns: ACCESN_OK else error status code -// Parameters: -// reqPtr -// timeOut -// respDataPtr -// respLen -// Notes: none -*F*/ - +/* SendTimedI2cRequest - This function sends a request to a I2C device. Used by + * Upper level agents (sis modules) to access dumb I2c devices. + * + * @reqPtr - pointer to I2C request + * timeOut - how long to wait, mSec units + * @respDataPtr - where to put response data + * @respDataLen - size of response buffer and size of returned data + * @completionCode - request status from BMC + * + * returns - ACCESN_OK else error status code + */ ACCESN_STATUS -SendTimedI2cRequest ( - I2CREQUESTDATA *reqPtr, /* I2C request */ - int timeOut, /* how long to wait, mSec units */ - BYTE *respDataPtr, /* where to put response data */ - int *respDataLen, /* size of response buffer and */ - /* size of returned data */ - BYTE *completionCode /* request status from BMC */ - ) +SendTimedI2cRequest(I2CREQUESTDATA *reqPtr, int timeOut, BYTE *respDataPtr, + int *respDataLen, BYTE *completionCode) { - BOOL status; - BYTE responseData[MAX_IMB_RESP_SIZE]; - ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; - DWORD respLength = sizeof( responseData ); - BYTE requestData[MAX_IMB_RESP_SIZE]; - ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; - - struct WriteReadI2C { /* format of a write/read I2C request */ +/* size of write/read request minus any data */ +# define MIN_WRI2C_SIZE 3 + BOOL status; + BYTE responseData[MAX_IMB_RESP_SIZE]; + ImbResponseBuffer *resp = (ImbResponseBuffer *)responseData; + DWORD respLength = sizeof(responseData); + BYTE requestData[MAX_IMB_RESP_SIZE]; + ImbRequestBuffer *req = (ImbRequestBuffer *)requestData; + + /* format of a write/read I2C request */ + struct WriteReadI2C { BYTE busType; BYTE rsSa; BYTE count; BYTE data[1]; - } * wrReq = (struct WriteReadI2C *) req->req.data; - -#define MIN_WRI2C_SIZE 3 /* size of write/read request minus any data */ - - - /* - // If the Imb driver is not present return AccessFailed - */ - - req->req.rsSa = BMC_SA; - req->req.cmd = WRITE_READ_I2C; - req->req.netFn = APP_NETFN; - req->req.rsLun = BMC_LUN; - req->req.dataLength = reqPtr->dataLength + MIN_WRI2C_SIZE; - - wrReq->busType = reqPtr->busType; - wrReq->rsSa = reqPtr->rsSa; - wrReq->count = reqPtr->numberOfBytesToRead; - - memcpy( wrReq->data, reqPtr->data, reqPtr->dataLength ); - - req->flags = 0; - req->timeOut = timeOut * 1000; /* convert to uSec units */ - - status = DeviceIoControl( hDevice, - IOCTL_IMB_SEND_MESSAGE, - requestData, - sizeof( requestData ), - & responseData, - sizeof( responseData ), - & respLength, - NULL - ); -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif - - if( status != TRUE ) { + } *wrReq = (struct WriteReadI2C *)req->req.data; + + /* If the IMB driver is not present return AccessFailed */ + req->req.rsSa = BMC_SA; + req->req.cmd = WRITE_READ_I2C; + req->req.netFn = APP_NETFN; + req->req.rsLun = BMC_LUN; + req->req.dataLength = reqPtr->dataLength + MIN_WRI2C_SIZE; + + wrReq->busType = reqPtr->busType; + wrReq->rsSa = reqPtr->rsSa; + wrReq->count = reqPtr->numberOfBytesToRead; + + memcpy(wrReq->data, reqPtr->data, reqPtr->dataLength); + + req->flags = 0; + /* convert to uSec units */ + req->timeOut = timeOut * 1000; + + status = DeviceIoControl(hDevice, IOCTL_IMB_SEND_MESSAGE, requestData, + sizeof(requestData), &responseData, + sizeof(responseData), &respLength, NULL); + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if (status != TRUE) { DWORD error; error = GetLastError(); return error; } - if( respLength == 0 ) { + if (respLength == 0) { return ACCESN_ERROR; } - - /* - // give the caller his response - */ + /* give the caller his response */ *completionCode = resp->cCode; - *respDataLen = respLength - 1; - - if(( *respDataLen ) && (respDataPtr)) - memcpy( respDataPtr, resp->data, *respDataLen); - + *respDataLen = respLength - 1; + if ((*respDataLen) && (respDataPtr)) { + memcpy(respDataPtr, resp->data, *respDataLen); + } return ACCESN_OK; - } -/*This is not a API exported by the driver in stricter sense. It is -//added to support EMP functionality. Upper level software could have -//implemented this function.(pai 5/4/99) */ -/*///////////////////////////////////////////////////////////////////////////// -// SendTimedEmpMessageResponse -///////////////////////////////////////////////////////////////////////////// */ - -/*F* -// Name: SendTimedEmpMessageResponse -// Purpose: This function sends a response message to the EMP port -// Context: -// Returns: OK else error status code -// Parameters: -// -// Notes: none -*F*/ - +/* SendTimedEmpMessageResponse - This function sends a response message to the + * EMP port. + * + * @ptr - pointer to the original request from EMP + * @responseDataBuf + * @responseDataLen + * @timeOut - how long to wait, in mSec units + * + * retruns - OK else error status code + */ ACCESN_STATUS -SendTimedEmpMessageResponse ( - ImbPacket *ptr, /* pointer to the original request from EMP */ - char *responseDataBuf, - int responseDataLen, - int timeOut /* how long to wait, in mSec units */ - ) +SendTimedEmpMessageResponse (ImbPacket *ptr, char *responseDataBuf, + int responseDataLen, int timeOut) { - BOOL status; - BYTE responseData[MAX_IMB_RESP_SIZE]; - /*ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */ - DWORD respLength = sizeof( responseData ); - BYTE requestData[MAX_IMB_RESP_SIZE]; - ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; - int i,j; - - /*form the response packet first */ - req->req.rsSa = BMC_SA; - if (IpmiVersion == IPMI_09_VERSION) - req->req.cmd = WRITE_EMP_BUFFER; - else - req->req.cmd = SEND_MESSAGE; - req->req.netFn = APP_NETFN; - req->req.rsLun = 0; + BOOL status; + BYTE responseData[MAX_IMB_RESP_SIZE]; + DWORD respLength = sizeof(responseData); + BYTE requestData[MAX_IMB_RESP_SIZE]; + ImbRequestBuffer *req = (ImbRequestBuffer *)requestData; + int i; + int j; + /* form the response packet first */ + req->req.rsSa = BMC_SA; + if (IpmiVersion == IPMI_09_VERSION) { + req->req.cmd = WRITE_EMP_BUFFER; + } else { + req->req.cmd = SEND_MESSAGE; + } + req->req.netFn = APP_NETFN; + req->req.rsLun = 0; i = 0; - if (IpmiVersion != IPMI_09_VERSION) - req->req.data[i++] = EMP_CHANNEL; - - req->req.data[i++] = ptr->rqSa; - req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); - if (IpmiVersion == IPMI_09_VERSION) - req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1); - else - req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1); - - req->req.data[i++] = BMC_SA; /*though software is responding, we have to - //provide BMCs slave address as responder - //address. */ - - req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) ); - - req->req.data[i++] = ptr->cmd; - for ( j = 0 ; j < responseDataLen ; ++j,++i) - req->req.data[i] = responseDataBuf[j]; - - req->req.data[i] = 0; - if (IpmiVersion == IPMI_09_VERSION) - j = 0; - else - j = 1; - for ( ; j < ( i -3); ++j) - req->req.data[i] += req->req.data[j+3]; - req->req.data[i] = ~(req->req.data[i]) +1; - ++i; - req->req.dataLength = i; - - req->flags = 0; - req->timeOut = timeOut * 1000; /* convert to uSec units */ - - - status = DeviceIoControl( hDevice, - IOCTL_IMB_SEND_MESSAGE, - requestData, - sizeof(requestData), - responseData, - sizeof( responseData ), - & respLength, - NULL - ); - -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif + if (IpmiVersion != IPMI_09_VERSION) { + req->req.data[i++] = EMP_CHANNEL; + } + req->req.data[i++] = ptr->rqSa; + req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); + if (IpmiVersion == IPMI_09_VERSION) { + req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) + 1); + } else { + req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) + 1); + } + /* though software is responding, we have to provide BMCs slave address + * as responder address. + */ + req->req.data[i++] = BMC_SA; + req->req.data[i++] = ((ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3)); + req->req.data[i++] = ptr->cmd; + for (j = 0; j < responseDataLen; ++j, ++i) { + req->req.data[i] = responseDataBuf[j]; + } - if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) ) - { + req->req.data[i] = 0; + if (IpmiVersion == IPMI_09_VERSION) { + j = 0; + } else { + j = 1; + } + for (; j < (i - 3); ++j) { + req->req.data[i] += req->req.data[j + 3]; + } + req->req.data[i] = ~(req->req.data[i]) + 1; + ++i; + req->req.dataLength = i; + + req->flags = 0; + /* convert to uSec units */ + req->timeOut = timeOut * 1000; + status = DeviceIoControl(hDevice, IOCTL_IMB_SEND_MESSAGE, requestData, + sizeof(requestData), responseData, sizeof(responseData), + &respLength, NULL); + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if ((status != TRUE) || (respLength != 1) || (responseData[0] != 0)) { return ACCESN_ERROR; } return ACCESN_OK; } - -/*This is not a API exported by the driver in stricter sense. It is added to support -// EMP functionality. Upper level software could have implemented this function.(pai 5/4/99) */ -/*/////////////////////////////////////////////////////////////////////////// -// SendTimedEmpMessageResponse_Ex -//////////////////////////////////////////////////////////////////////////// */ - -/*F* -// Name: SendTimedEmpMessageResponse_Ex -// Purpose: This function sends a response message to the EMP port -// Context: -// Returns: OK else error status code -// Parameters: -// -// Notes: none -*F*/ - - - +/* SendTimedEmpMessageResponse_Ex - sends response message to the EMP port. + * + * @ptr - pointer to the original request from EMP + * @responseDataBuf + * @responseDataLen + * @timeOut - how long to wait, in mSec units + * @sessionHandle - This is introduced in IPMI1.5,this is required to be sent in + * sendd message command as a parameter, which is then used by BMC + * to identify the correct DPC session to send the mesage to. + * @channelNumber - There are 3 different channels on which DPC communication + * goes on: + * * Emp - 1 + * * Lan channel one - 6, + * * Lan channel two(primary channel) - 7 + * + * returns - OK else error status code + */ ACCESN_STATUS -SendTimedEmpMessageResponse_Ex ( - - ImbPacket * ptr, /* pointer to the original request from EMP */ - char *responseDataBuf, - int responseDataLen, - int timeOut, /* how long to wait, in mSec units*/ - BYTE sessionHandle, /*This is introduced in IPMI1.5,this is required to be sent in - //send message command as a parameter,which is then used by BMC - //to identify the correct DPC session to send the mesage to. */ - BYTE channelNumber /*There are 3 different channels on which DPC communication goes on - //Emp - 1,Lan channel one - 6,Lan channel two(primary channel) - 7. */ - ) +SendTimedEmpMessageResponse_Ex (ImbPacket *ptr, char *responseDataBuf, int + responseDataLen, int timeOut, BYTE sessionHandle, BYTE + channelNumber) { - BOOL status; - BYTE responseData[MAX_IMB_RESP_SIZE]; - /* ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */ - DWORD respLength = sizeof( responseData ); - BYTE requestData[MAX_IMB_RESP_SIZE]; - ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; - int i,j; - + BOOL status; + BYTE responseData[MAX_IMB_RESP_SIZE]; + DWORD respLength = sizeof(responseData); + BYTE requestData[MAX_IMB_RESP_SIZE]; + ImbRequestBuffer *req = (ImbRequestBuffer *)requestData; + int i; + int j; /*form the response packet first */ - req->req.rsSa = BMC_SA; - if (IpmiVersion == IPMI_09_VERSION) - req->req.cmd = WRITE_EMP_BUFFER; - else - req->req.cmd = SEND_MESSAGE; - req->req.netFn = APP_NETFN; - req->req.rsLun = 0; + req->req.rsSa = BMC_SA; + if (IpmiVersion == IPMI_09_VERSION) { + req->req.cmd = WRITE_EMP_BUFFER; + } else { + req->req.cmd = SEND_MESSAGE; + } + req->req.netFn = APP_NETFN; + req->req.rsLun = 0; i = 0; + /* checking for the IPMI version & then assigning the channel number for + * EMP. Actually the channel number is same in both the versions.This is + * just to maintain the consistancy with the same method for LAN. This + * is the 1st byte of the SEND MESSAGE command. + */ + if (IpmiVersion == IPMI_10_VERSION) { + req->req.data[i++] = EMP_CHANNEL; + } else if (IpmiVersion == IPMI_15_VERSION) { + req->req.data[i++] = channelNumber; + } - /*checking for the IPMI version & then assigning the channel number for EMP - //Actually the channel number is same in both the versions.This is just to - //maintain the consistancy with the same method for LAN. - //This is the 1st byte of the SEND MESSAGE command. */ - if (IpmiVersion == IPMI_10_VERSION) - req->req.data[i++] = EMP_CHANNEL; - else if (IpmiVersion == IPMI_15_VERSION) - req->req.data[i++] = channelNumber; - - /*The second byte of data for SEND MESSAGE starts with session handle */ + /* The second byte of data for SEND MESSAGE starts with session + * handle + */ req->req.data[i++] = sessionHandle; - - /*Then it is the response slave address for SEND MESSAGE. */ - req->req.data[i++] = ptr->rqSa; - - /*Then the net function + lun for SEND MESSAGE command. */ - req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); - - /*Here the checksum is calculated.The checksum calculation starts after the channel number. - //so for the IPMI 1.5 version its a checksum of 3 bytes that is session handle,response slave - //address & netfun+lun. */ - if (IpmiVersion == IPMI_09_VERSION) - req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1); - else - { - if (IpmiVersion == IPMI_10_VERSION) - req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1); - else - req->req.data[i++] = ((~(req->req.data[2]+ req->req.data[3])) +1); - } - - /*This is the next byte of the message data for SEND MESSAGE command.It is the request - //slave address. */ - req->req.data[i++] = BMC_SA; /*though software is responding, we have to - //provide BMCs slave address as responder - //address. */ - - /*This is just the sequence number,which is the next byte of data for SEND MESSAGE */ - req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) ); - - /*The next byte is the command like get software ID(00).*/ - req->req.data[i++] = ptr->cmd; - - /*after the cmd the data ,which is sent by DPC & is retrived using the get message earlier - // is sent back to DPC. */ - for ( j = 0 ; j < responseDataLen ; ++j,++i) - req->req.data[i] = responseDataBuf[j]; - - req->req.data[i] = 0; - - /*The last byte of data for SEND MESSAGE command is the check sum ,which is calculated - //from the next byte of the previous checksum that is the request slave address. */ - if (IpmiVersion == IPMI_09_VERSION) - j = 0; - else - { - if (IpmiVersion == IPMI_10_VERSION) + /* Then it is the response slave address for SEND MESSAGE. */ + req->req.data[i++] = ptr->rqSa; + /* Then the net function + lun for SEND MESSAGE command. */ + req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); + /* Here the checksum is calculated.The checksum calculation starts after + * the channel number. So for the IPMI 1.5 version its a checksum of 3 + * bytes that is session handle,response slave address & netfun+lun. + */ + if (IpmiVersion == IPMI_09_VERSION) { + req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1); + } else { + if (IpmiVersion == IPMI_10_VERSION) { + req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) + 1); + } else { + req->req.data[i++] = ((~(req->req.data[2] + req->req.data[3])) + 1); + } + } + /* This is the next byte of the message data for SEND MESSAGE command.It + * is the request slave address. + */ + /* though software is responding, we have to provide BMCs slave address + * as responder address. + */ + req->req.data[i++] = BMC_SA; + /* This is just the sequence number,which is the next byte of data for + * SEND MESSAGE + */ + req->req.data[i++] = ((ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3)); + /* The next byte is the command like get software ID(00). */ + req->req.data[i++] = ptr->cmd; + /* after the cmd the data, which is sent by DPC & is retrived using the + * get message earlier is sent back to DPC. + */ + for (j = 0; j < responseDataLen; ++j, ++i) { + req->req.data[i] = responseDataBuf[j]; + } + + req->req.data[i] = 0; + /* The last byte of data for SEND MESSAGE command is the check sum, which + * is calculated from the next byte of the previous checksum that is the + * request slave address. + */ + if (IpmiVersion == IPMI_09_VERSION) { + j = 0; + } else { + if (IpmiVersion == IPMI_10_VERSION) { j = 1; - else + } else { j = 2; - } - for ( ; j < ( i -3); ++j) - req->req.data[i] += req->req.data[j+3]; - req->req.data[i] = ~(req->req.data[i]) +1; + } + } + for (; j < (i - 3); ++j) { + req->req.data[i] += req->req.data[j + 3]; + } + req->req.data[i] = ~(req->req.data[i]) + 1; ++i; - req->req.dataLength = i; - - /*The flags & timeouts are used by the driver internally. */ - req->flags = 0; - req->timeOut = timeOut * 1000; /* convert to uSec units */ - - status = DeviceIoControl( hDevice, - IOCTL_IMB_SEND_MESSAGE, - requestData, - sizeof(requestData), - responseData, - sizeof( responseData ), - & respLength, - NULL - ); - - -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif - - - if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) ) - { + req->req.dataLength = i; + /* The flags & timeouts are used by the driver internally. */ + req->flags = 0; + /* convert to uSec units */ + req->timeOut = timeOut * 1000; + status = DeviceIoControl(hDevice, IOCTL_IMB_SEND_MESSAGE, requestData, + sizeof(requestData), responseData, sizeof(responseData), + &respLength, NULL); + + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if ((status != TRUE) || (respLength != 1) || (responseData[0] != 0)) { return ACCESN_ERROR; } return ACCESN_OK; - - - } -/*This is not a API exported by the driver in stricter sense. It is -//added to support EMP functionality. Upper level software could have -//implemented this function.(pai 5/4/99) */ -/*/////////////////////////////////////////////////////////////////////////// -// SendTimedLanMessageResponse -///////////////////////////////////////////////////////////////////////////// */ - -/*F* -// Name: SendTimedLanMessageResponse -// Purpose: This function sends a response message to the DPC Over Lan -// Context: -// Returns: OK else error status code -// Parameters: -// -// Notes: none -*F*/ - +/* SendTimedLanMessageResponse - sends a response message to the DPC Over Lan + * + * @ptr - pointer to the original request from EMP + * @responseDataBuf + * @responseDataLen, + * @timeOut - how long to wait, in mSec units + * + * returns: OK else error status code + */ ACCESN_STATUS -SendTimedLanMessageResponse( - ImbPacket *ptr, /* pointer to the original request from EMP */ - char *responseDataBuf, - int responseDataLen, - int timeOut /* how long to wait, in mSec units */ - ) +SendTimedLanMessageResponse(ImbPacket *ptr, char *responseDataBuf, + int responseDataLen, int timeOut) { - BOOL status; - BYTE responseData[MAX_IMB_RESP_SIZE]; - /* ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */ - DWORD respLength = sizeof( responseData ); - BYTE requestData[MAX_IMB_RESP_SIZE]; - ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; - int i,j; - - /*form the response packet first */ - req->req.rsSa = BMC_SA; - if (IpmiVersion == IPMI_09_VERSION) - req->req.cmd = WRITE_EMP_BUFFER; - else - req->req.cmd = SEND_MESSAGE; - req->req.netFn = APP_NETFN; - - /* After discussion with firmware team (Shailendra), the lun number needs to stay at 0 - // even though the DPC over Lan firmware EPS states that the lun should be 1 for DPC - // Over Lan. - Simont (5/17/00) */ - req->req.rsLun = 0; + BOOL status; + BYTE responseData[MAX_IMB_RESP_SIZE]; + DWORD respLength = sizeof(responseData); + BYTE requestData[MAX_IMB_RESP_SIZE]; + ImbRequestBuffer *req = (ImbRequestBuffer *)requestData; + int i; + int j; + /* Form the response packet first */ + req->req.rsSa = BMC_SA; + if (IpmiVersion == IPMI_09_VERSION) { + req->req.cmd = WRITE_EMP_BUFFER; + } else { + req->req.cmd = SEND_MESSAGE; + } + req->req.netFn = APP_NETFN; + /* After discussion with firmware team (Shailendra), the lun number + * needs to stay at 0 even though the DPC over Lan firmware EPS states + * that the lun should be 1 for DPC Over Lan. - Simont (5/17/00) + */ + req->req.rsLun = 0; i = 0; - if (IpmiVersion != IPMI_09_VERSION) - req->req.data[i++] = LAN_CHANNEL; - - req->req.data[i++] = ptr->rqSa; - req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); - if (IpmiVersion == IPMI_09_VERSION) - req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1); - else - req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1); - - req->req.data[i++] = BMC_SA; /*though software is responding, we have to - //provide BMCs slave address as responder - //address. */ - - req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) ); - - req->req.data[i++] = ptr->cmd; - for ( j = 0 ; j < responseDataLen ; ++j,++i) - req->req.data[i] = responseDataBuf[j]; - - req->req.data[i] = 0; - if (IpmiVersion == IPMI_09_VERSION) - j = 0; - else - j = 1; - for ( ; j < ( i -3); ++j) - req->req.data[i] += req->req.data[j+3]; - req->req.data[i] = ~(req->req.data[i]) +1; - ++i; - req->req.dataLength = i; - - req->flags = 0; - req->timeOut = timeOut * 1000; /* convert to uSec units */ - + if (IpmiVersion != IPMI_09_VERSION) { + req->req.data[i++] = LAN_CHANNEL; + } - status = DeviceIoControl( hDevice, - IOCTL_IMB_SEND_MESSAGE, - requestData, - sizeof(requestData), - responseData, - sizeof( responseData ), - & respLength, - NULL - ); + req->req.data[i++] = ptr->rqSa; + req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); + if (IpmiVersion == IPMI_09_VERSION) { + req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) + 1); + } else { + req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) + 1); + } + /* Though software is responding, we have to provide BMCs slave address + * as responder address. + */ + req->req.data[i++] = BMC_SA; + req->req.data[i++] = ((ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3)); + req->req.data[i++] = ptr->cmd; + for (j = 0; j < responseDataLen; ++j, ++i) { + req->req.data[i] = responseDataBuf[j]; + } -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif + req->req.data[i] = 0; + if (IpmiVersion == IPMI_09_VERSION) { + j = 0; + } else { + j = 1; + } - if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) ) - { + for (; j < (i - 3); ++j) { + req->req.data[i] += req->req.data[j + 3]; + } + req->req.data[i] = ~(req->req.data[i]) + 1; + ++i; + req->req.dataLength = i; + + req->flags = 0; + /* convert to uSec units */ + req->timeOut = timeOut * 1000; + status = DeviceIoControl(hDevice, IOCTL_IMB_SEND_MESSAGE, requestData, + sizeof(requestData), responseData, sizeof(responseData), + &respLength, NULL); + + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if ((status != TRUE) || (respLength != 1) || (responseData[0] != 0)) { return ACCESN_ERROR; } return ACCESN_OK; } -/*This is not a API exported by the driver in stricter sense. It is -//added to support EMP functionality. Upper level software could have -//implemented this function.(pai 5/4/99) */ -/*/////////////////////////////////////////////////////////////////////////// -// SendTimedLanMessageResponse_Ex -///////////////////////////////////////////////////////////////////////////// */ - -/*F* -// Name: SendTimedLanMessageResponse_Ex -// Purpose: This function sends a response message to the DPC Over Lan -// Context: -// Returns: OK else error status code -// Parameters: -// -// Notes: none -*F*/ - +/* SendTimedLanMessageResponse_Ex - sends a response message to the DPC Over + * LAN. + * + * @ptr - pointer to the original request from EMP + * @responseDataBuf + * @responseDataLen + * @timeOut - how long to wait, in mSec units + * @sessionHandle - This is introduced in IPMI1.5,this is required to be sent in + * send message command as a parameter,which is then used by BMC to identify the + * correct DPC session to send the mesage to. + * @channelNumber - There are 3 different channels on which DPC communication + * goes on: + * * Emp - 1 + * * Lan channel one - 6 + * * Lan channel two(primary channel) - 7 + * + * returns: OK else error status code + */ ACCESN_STATUS -SendTimedLanMessageResponse_Ex( - ImbPacket *ptr, /* pointer to the original request from EMP */ - char *responseDataBuf, - int responseDataLen, - int timeOut , /* how long to wait, in mSec units */ - BYTE sessionHandle, /*This is introduced in IPMI1.5,this is required to be sent in - //send message command as a parameter,which is then used by BMC - //to identify the correct DPC session to send the mesage to. */ - BYTE channelNumber /*There are 3 different channels on which DPC communication goes on - //Emp - 1,Lan channel one - 6,Lan channel two(primary channel) - 7. */ - ) +SendTimedLanMessageResponse_Ex(ImbPacket *ptr, char *responseDataBuf, int + responseDataLen, int timeOut, BYTE sessionHandle, BYTE + channelNumber) { - BOOL status; - BYTE responseData[MAX_IMB_RESP_SIZE]; - /* ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; */ - DWORD respLength = sizeof( responseData ); - BYTE requestData[MAX_IMB_RESP_SIZE]; - ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; - int i,j; - - /*form the response packet first */ - req->req.rsSa = BMC_SA; - if (IpmiVersion == IPMI_09_VERSION) - req->req.cmd = WRITE_EMP_BUFFER; - else - req->req.cmd = SEND_MESSAGE; - req->req.netFn = APP_NETFN; - - /* After discussion with firmware team (Shailendra), the lun number needs to stay at 0 - // even though the DPC over Lan firmware EPS states that the lun should be 1 for DPC - // Over Lan. - Simont (5/17/00) */ - req->req.rsLun = 0; + BOOL status; + BYTE responseData[MAX_IMB_RESP_SIZE]; + DWORD respLength = sizeof(responseData); + BYTE requestData[MAX_IMB_RESP_SIZE]; + ImbRequestBuffer *req = (ImbRequestBuffer *)requestData; + int i; + int j; + /* form the response packet first */ + req->req.rsSa = BMC_SA; + if (IpmiVersion == IPMI_09_VERSION) { + req->req.cmd = WRITE_EMP_BUFFER; + } else { + req->req.cmd = SEND_MESSAGE; + } + req->req.netFn = APP_NETFN; + /* After discussion with firmware team (Shailendra), the lun number + * needs to stay at 0 even though the DPC over Lan firmware EPS states + * that the lun should be 1 for DPC Over Lan. - Simont (5/17/00) + */ + req->req.rsLun = 0; i = 0; - - /*checking for the IPMI version & then assigning the channel number for Lan accordingly. - //This is the 1st byte of the SEND MESSAGE command. */ - if (IpmiVersion == IPMI_10_VERSION) - req->req.data[i++] = LAN_CHANNEL; - else if (IpmiVersion == IPMI_15_VERSION) - req->req.data[i++] = channelNumber; - - /*The second byte of data for SEND MESSAGE starts with session handle */ + /* checking for the IPMI version & then assigning the channel number for + * LAN accordingly. + * This is the 1st byte of the SEND MESSAGE command. + */ + if (IpmiVersion == IPMI_10_VERSION) { + req->req.data[i++] = LAN_CHANNEL; + } else if (IpmiVersion == IPMI_15_VERSION) { + req->req.data[i++] = channelNumber; + } + /* The second byte of data for SEND MESSAGE starts with session handle + */ req->req.data[i++] = sessionHandle; - - /*Then it is the response slave address for SEND MESSAGE. */ - req->req.data[i++] = ptr->rqSa; - - /*Then the net function + lun for SEND MESSAGE command. */ - req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); - - /*Here the checksum is calculated.The checksum calculation starts after the channel number. - //so for the IPMI 1.5 version its a checksum of 3 bytes that is session handle,response slave - //address & netfun+lun. */ - if (IpmiVersion == IPMI_09_VERSION) - req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) +1); - else - { - if (IpmiVersion == IPMI_10_VERSION) - req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) +1); - else - req->req.data[i++] = ((~(req->req.data[2]+ req->req.data[3])) +1); - } - - /*This is the next byte of the message data for SEND MESSAGE command.It is the request - //slave address. */ - req->req.data[i++] = BMC_SA; /*though software is responding, we have to - //provide BMC's slave address as responder - //address. */ - - /*This is just the sequence number,which is the next byte of data for SEND MESSAGE */ - req->req.data[i++] = ( (ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3) ); - - /*The next byte is the command like get software ID(00). */ - req->req.data[i++] = ptr->cmd; - - /*after the cmd the data ,which is sent by DPC & is retrived using the get message earlier - // is sent back to DPC. */ - for ( j = 0 ; j < responseDataLen ; ++j,++i) - req->req.data[i] = responseDataBuf[j]; - - req->req.data[i] = 0; - - /*The last byte of data for SEND MESSAGE command is the check sum ,which is calculated - //from the next byte of the previous checksum that is the request slave address. */ - if (IpmiVersion == IPMI_09_VERSION) - j = 0; - else - { - if (IpmiVersion == IPMI_10_VERSION) + /* Then it is the response slave address for SEND MESSAGE. */ + req->req.data[i++] = ptr->rqSa; + /* Then the net function + lun for SEND MESSAGE command. */ + req->req.data[i++] = (((ptr->nfLn & 0xfc) | 0x4) | ((ptr->seqLn) & 0x3)); + /* Here the checksum is calculated.The checksum calculation starts after + * the channel number. So for the IPMI 1.5 version its a checksum of 3 + * bytes that is session handle,response slave address & netfun+lun. + */ + if (IpmiVersion == IPMI_09_VERSION) { + req->req.data[i++] = ((~(req->req.data[0] + req->req.data[1])) + 1); + } else { + if (IpmiVersion == IPMI_10_VERSION) { + req->req.data[i++] = ((~(req->req.data[1] + req->req.data[2])) + 1); + } else { + req->req.data[i++] = ((~(req->req.data[2] + req->req.data[3])) + 1); + } + } + /* This is the next byte of the message data for SEND MESSAGE command.It + * is the request slave address. + */ + /* Though software is responding, we have to provide BMC's slave address + * as responder address. + */ + req->req.data[i++] = BMC_SA; + /* This is just the sequence number,which is the next byte of data for + * SEND MESSAGE + */ + req->req.data[i++] = ((ptr->seqLn & 0xfc) | (ptr->nfLn & 0x3)); + /* The next byte is the command like get software ID(00). */ + req->req.data[i++] = ptr->cmd; + /* After the cmd the data ,which is sent by DPC & is retrived using the + * get message earlier is sent back to DPC. + */ + for (j = 0; j < responseDataLen; ++j, ++i) { + req->req.data[i] = responseDataBuf[j]; + } + req->req.data[i] = 0; + /* The last byte of data for SEND MESSAGE command is the check sum which + * is calculated from the next byte of the previous checksum that is the + * request slave address. + */ + if (IpmiVersion == IPMI_09_VERSION) { + j = 0; + } else { + if (IpmiVersion == IPMI_10_VERSION) { j = 1; - else + } else { j = 2; - } - for ( ; j < ( i -3); ++j) - req->req.data[i] += req->req.data[j+3]; - req->req.data[i] = ~(req->req.data[i]) +1; + } + } + for (; j < (i - 3); ++j) { + req->req.data[i] += req->req.data[j + 3]; + } + req->req.data[i] = ~(req->req.data[i]) + 1; ++i; - req->req.dataLength = i; - - /*The flags & timeouts are used by the driver internally */ - req->flags = 0; - req->timeOut = timeOut * 1000; /* convert to uSec units */ - - - status = DeviceIoControl( hDevice, - IOCTL_IMB_SEND_MESSAGE, - requestData, - sizeof(requestData), - responseData, - sizeof( responseData ), - & respLength, - NULL - ); - -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif - - if ( (status != TRUE) || (respLength != 1) || (responseData[0] != 0) ) - { + req->req.dataLength = i; + /* The flags & timeouts are used by the driver internally */ + req->flags = 0; + /* convert to uSec units */ + req->timeOut = timeOut * 1000; + status = DeviceIoControl(hDevice, IOCTL_IMB_SEND_MESSAGE, requestData, + sizeof(requestData), responseData, sizeof(responseData), + &respLength, NULL); + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if ((status != TRUE) || (respLength != 1) || (responseData[0] != 0)) { return ACCESN_ERROR; } return ACCESN_OK; } -/*/////////////////////////////////////////////////////////////////////////// -// SendTimedImbpRequest -///////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: SendTimedImbpRequest -// Purpose: This function sends a request for BMC implemented function -// Context: Used by Upper level agents (sis modules) to access BMC implemented functionality. -// Returns: OK else error status code -// Parameters: -// reqPtr -// timeOut -// respDataPtr -// respLen -// Notes: none -*F*/ +/* SendTimedImbpRequest - This function sends a request for BMC implemented function + * + * @reqPtr - request info and data + * @timeOut - how long to wait, in mSec units + * @respDataPtr - where to put response data + * @respDataLen - how much response data there is + * @completionCode - request status from dest controller + * + * returns: OK else error status code + */ ACCESN_STATUS -SendTimedImbpRequest ( - IMBPREQUESTDATA *reqPtr, /* request info and data */ - int timeOut, /* how long to wait, in mSec units */ - BYTE *respDataPtr, /* where to put response data */ - int *respDataLen, /* how much response data there is */ - BYTE *completionCode /* request status from dest controller */ - ) +SendTimedImbpRequest(IMBPREQUESTDATA *reqPtr, int timeOut, BYTE *respDataPtr, + int *respDataLen, BYTE *completionCode) { - BYTE responseData[MAX_BUFFER_SIZE]; - ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; - DWORD respLength = sizeof( responseData ); - BYTE requestData[MAX_BUFFER_SIZE]; - ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; - BOOL status; - - - req->req.rsSa = reqPtr->rsSa; - req->req.cmd = reqPtr->cmdType; - req->req.netFn = reqPtr->netFn; - req->req.rsLun = reqPtr->rsLun; - req->req.dataLength = reqPtr->dataLength; - -#ifndef NO_MACRO_ARGS - DEBUG("cmd=%02x, pdata=%p, datalen=%x\n", req->req.cmd, - reqPtr->data, reqPtr->dataLength ); -#endif - memcpy( req->req.data, reqPtr->data, reqPtr->dataLength ); - - req->flags = 0; - req->timeOut = timeOut * 1000; /* convert to uSec units */ - -#ifndef NO_MACRO_ARGS - DEBUG("%s: rsSa 0x%x cmd 0x%x netFn 0x%x rsLun 0x%x\n", __FUNCTION__, - req->req.rsSa, req->req.cmd, req->req.netFn, req->req.rsLun); -#endif - - - status = DeviceIoControl( hDevice, - IOCTL_IMB_SEND_MESSAGE, - requestData, - sizeof( requestData ), - & responseData, - sizeof( responseData ), - & respLength, - NULL - ); -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl returned status = %d\n",__FUNCTION__, status); -#endif + BYTE responseData[MAX_BUFFER_SIZE]; + ImbResponseBuffer *resp = (ImbResponseBuffer *)responseData; + DWORD respLength = sizeof(responseData); + BYTE requestData[MAX_BUFFER_SIZE]; + ImbRequestBuffer *req = (ImbRequestBuffer *)requestData; + BOOL status; + + req->req.rsSa = reqPtr->rsSa; + req->req.cmd = reqPtr->cmdType; + req->req.netFn = reqPtr->netFn; + req->req.rsLun = reqPtr->rsLun; + req->req.dataLength = reqPtr->dataLength; + + lprintf(LOG_DEBUG, "cmd=%02x, pdata=%p, datalen=%x", req->req.cmd, + reqPtr->data, reqPtr->dataLength); + memcpy(req->req.data, reqPtr->data, reqPtr->dataLength); + + req->flags = 0; + /* convert to uSec units */ + req->timeOut = timeOut * 1000; + lprintf(LOG_DEBUG, "%s: rsSa 0x%x cmd 0x%x netFn 0x%x rsLun 0x%x", + __FUNCTION__, req->req.rsSa, req->req.cmd, + req->req.netFn, req->req.rsLun); + + status = DeviceIoControl(hDevice, IOCTL_IMB_SEND_MESSAGE, requestData, + sizeof(requestData), &responseData, + sizeof(responseData), &respLength, NULL); + + lprintf(LOG_DEBUG, "%s: DeviceIoControl returned status = %d", + __FUNCTION__, status); #ifdef DBG_IPMI - printf("%s: rsSa %x cmd %x netFn %x lun %x, status=%d, cc=%x, rlen=%d\n", - __FUNCTION__, req->req.rsSa, req->req.cmd, req->req.netFn, - req->req.rsLun, status, resp->cCode, respLength ); + /* TODO */ + printf("%s: rsSa %x cmd %x netFn %x lun %x, status=%d, cc=%x, rlen=%d\n", + __FUNCTION__, req->req.rsSa, req->req.cmd, + req->req.netFn, req->req.rsLun, status, resp->cCode, + respLength); #endif - if( status != TRUE ) { + if (status != TRUE) { DWORD error; error = GetLastError(); return error; - } - if( respLength == 0 ) { + } else if (respLength == 0) { return ACCESN_ERROR; } - - /* - * give the caller his response - */ + /* give the caller his response */ *completionCode = resp->cCode; - *respDataLen = 0; + *respDataLen = 0; - if(( respLength > 1 ) && ( respDataPtr)) - { - *respDataLen = respLength - 1; - memcpy( respDataPtr, resp->data, *respDataLen); + if ((respLength > 1) && (respDataPtr)) { + *respDataLen = respLength - 1; + memcpy(respDataPtr,resp->data, *respDataLen); } - - return ACCESN_OK; } - -/*///////////////////////////////////////////////////////////////////////// -//SendAsyncImbpRequest -/////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: SendAsyncImbpRequest -// Purpose: This function sends a request for Asynchronous IMB implemented function -// Context: Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality. -// Returns: OK else error status code -// Parameters: -// reqPtr Pointer to Async IMB request -// seqNo Sequence Munber -// Notes: none -*F*/ +/* SendAsyncImbpRequest - sends a request for Asynchronous IMB implemented function. + * + * @reqPtr - Pointer to Async IMB request + * @seqNo -Sequence Munber + * + * returns: OK else error status code + */ ACCESN_STATUS -SendAsyncImbpRequest ( - IMBPREQUESTDATA *reqPtr, /* request info and data */ - BYTE * seqNo /* sequence number used in creating IMB msg */ - ) +SendAsyncImbpRequest(IMBPREQUESTDATA *reqPtr, BYTE *seqNo) { - - BOOL status; - BYTE responseData[MAX_IMB_RESP_SIZE]; - ImbResponseBuffer * resp = (ImbResponseBuffer *) responseData; - DWORD respLength = sizeof( responseData ); - BYTE requestData[MAX_IMB_RESP_SIZE]; - ImbRequestBuffer * req = (ImbRequestBuffer *) requestData; - - req->req.rsSa = reqPtr->rsSa; - req->req.cmd = reqPtr->cmdType; - req->req.netFn = reqPtr->netFn; - req->req.rsLun = reqPtr->rsLun; - req->req.dataLength = reqPtr->dataLength; - - memcpy( req->req.data, reqPtr->data, reqPtr->dataLength ); - - req->flags = NO_RESPONSE_EXPECTED; - req->timeOut = 0; /* no timeouts for async sends */ - - status = DeviceIoControl( hDevice, - IOCTL_IMB_SEND_MESSAGE, - requestData, - sizeof( requestData ), - & responseData, - sizeof( responseData ), - & respLength, - NULL - ); -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif - - if( status != TRUE ) { + BOOL status; + BYTE responseData[MAX_IMB_RESP_SIZE]; + ImbResponseBuffer *resp = (ImbResponseBuffer *)responseData; + DWORD respLength = sizeof(responseData); + BYTE requestData[MAX_IMB_RESP_SIZE]; + ImbRequestBuffer *req = (ImbRequestBuffer *)requestData; + + req->req.rsSa = reqPtr->rsSa; + req->req.cmd = reqPtr->cmdType; + req->req.netFn = reqPtr->netFn; + req->req.rsLun = reqPtr->rsLun; + req->req.dataLength = reqPtr->dataLength; + memcpy(req->req.data, reqPtr->data, reqPtr->dataLength); + + req->flags = NO_RESPONSE_EXPECTED; + /* no timeouts for async sends */ + req->timeOut = 0; + + status = DeviceIoControl(hDevice, IOCTL_IMB_SEND_MESSAGE, requestData, + sizeof(requestData), &responseData, + sizeof(responseData), &respLength, NULL); + + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if (status != TRUE) { DWORD error; error = GetLastError(); return error; - } - if( respLength != 2 ) { + } else if (respLength != 2) { return ACCESN_ERROR; } - /* - // give the caller his sequence number - */ + /* give the caller his sequence number */ *seqNo = resp->data[0]; - return ACCESN_OK; - } -/*/////////////////////////////////////////////////////////////////////////// -//GetAsyncImbpMessage -///////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: GetAsyncImbpMessage -// Purpose: This function gets the next available async message with a message id -// greater than SeqNo. The message looks like an IMB packet -// and the length and Sequence number is returned -// Context: Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality. -// Returns: OK else error status code -// Parameters: -// msgPtr Pointer to Async IMB request -// msgLen Length -// timeOut Time to wait -// seqNo Sequence Munber -// Notes: none -*F*/ - +/* GetAsyncImbpMessage - This function gets the next available async message + * with a message ID greater than SeqNo. The message looks like an IMB packet + * and the length and Sequence number is returned. + * + * @msgPtr - request info and data + * @msgLen - IN - length of buffer, OUT - msg len + * @timeOut - how long to wait for the message + * @seqNo - previously returned seq number(or ASYNC_SEQ_START) + * @channelNumber + * + * returns: OK else error status code + */ ACCESN_STATUS -GetAsyncImbpMessage ( - ImbPacket * msgPtr, /* request info and data */ - DWORD *msgLen, /* IN - length of buffer, OUT - msg len */ - DWORD timeOut, /* how long to wait for the message */ - ImbAsyncSeq *seqNo, /* previously returned seq number */ - /* (or ASYNC_SEQ_START) */ - DWORD channelNumber - ) +GetAsyncImbpMessage (ImbPacket *msgPtr, DWORD *msgLen, DWORD timeOut, + ImbAsyncSeq *seqNo, DWORD channelNumber) { - - BOOL status; - BYTE responseData[MAX_ASYNC_RESP_SIZE], lun; - ImbAsyncResponse * resp = (ImbAsyncResponse *) responseData; - DWORD respLength = sizeof( responseData ); - ImbAsyncRequest req; - - while(1) - { - - - if( (msgPtr == NULL) || (msgLen == NULL) || ( seqNo == NULL) ) + BOOL status; + BYTE responseData[MAX_ASYNC_RESP_SIZE]; + BYTE lun; + ImbAsyncResponse *resp = (ImbAsyncResponse *)responseData; + DWORD respLength = sizeof(responseData); + ImbAsyncRequest req; + + while (1) { + if ((msgPtr == NULL) || (msgLen == NULL) || ( seqNo == NULL)) { + return ACCESN_ERROR; + } + /* convert to uSec units */ + req.timeOut = timeOut * 1000; + req.lastSeq = *seqNo; + + status = DeviceIoControl(hDevice, IOCTL_IMB_GET_ASYNC_MSG, &req, + sizeof(req), &responseData, + sizeof(responseData), &respLength, NULL); + + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", + __FUNCTION__, status); + if (status != TRUE) { + DWORD error = GetLastError(); + /* handle "msg not available" specially. it is different + * from a random old error. + */ + switch (error) { + case IMB_MSG_NOT_AVAILABLE: + return ACCESN_END_OF_DATA; + break; + default: return ACCESN_ERROR; + break; + } + } else if (respLength < MIN_ASYNC_RESP_SIZE) { + return ACCESN_ERROR; + } + respLength -= MIN_ASYNC_RESP_SIZE; - req.timeOut = timeOut * 1000; /* convert to uSec units */ - req.lastSeq = *seqNo; - - - status = DeviceIoControl( hDevice, - IOCTL_IMB_GET_ASYNC_MSG, - & req, - sizeof( req ), - & responseData, - sizeof( responseData ), - & respLength, - NULL - ); - -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif + if (*msgLen < respLength) { + return ACCESN_ERROR; + } - if( status != TRUE ) { - DWORD error = GetLastError(); - /* - // handle "msg not available" specially. it is - // different from a random old error. - */ - switch( error ) { - case IMB_MSG_NOT_AVAILABLE: - return ACCESN_END_OF_DATA; - default: - return ACCESN_ERROR; - } - return ACCESN_ERROR; + /* same code as in NT section */ + if (IpmiVersion == IPMI_09_VERSION) { + switch (channelNumber) { + case IPMB_CHANNEL: + lun = IPMB_LUN; + break; + case EMP_CHANNEL: + lun = EMP_LUN; + break; + default: + lun = RESERVED_LUN; + break; } - if( respLength < MIN_ASYNC_RESP_SIZE ) { - return ACCESN_ERROR; + if ((lun == RESERVED_LUN) + || (lun != ((((ImbPacket *)(resp->data))->nfLn) & 0x3 ))) { + *seqNo = resp->thisSeq; + continue; } - respLength -= MIN_ASYNC_RESP_SIZE; - - if( *msgLen < respLength ) { - return ACCESN_ERROR; - } - - - /*same code as in NT section */ - if ( IpmiVersion == IPMI_09_VERSION) - { - - switch( channelNumber) { - case IPMB_CHANNEL: - lun = IPMB_LUN; - break; - - case EMP_CHANNEL: - lun = EMP_LUN; - break; - - default: - lun = RESERVED_LUN; - break; - } - - if ( (lun == RESERVED_LUN) || - (lun != ((((ImbPacket *)(resp->data))->nfLn) & 0x3 )) - ) - { - *seqNo = resp->thisSeq; - continue; - } - - - memcpy( msgPtr, resp->data, respLength ); - *msgLen = respLength; - - } - else - { - /* it is a 1.0 or above version */ - - if (resp->data[0] != (BYTE)channelNumber) - { - *seqNo = resp->thisSeq; - continue; - } - - memcpy( msgPtr, &(resp->data[1]), respLength-1 ); - *msgLen = respLength-1; - - + memcpy(msgPtr, resp->data, respLength); + *msgLen = respLength; + } else { + /* it is version 1.0 or better */ + if (resp->data[0] != (BYTE)channelNumber) { + *seqNo = resp->thisSeq; + continue; } - - /* - // give the caller his sequence number - */ + memcpy(msgPtr, &(resp->data[1]), (respLength - 1)); + *msgLen = respLength - 1; + } + /* give the caller his sequence number */ *seqNo = resp->thisSeq; - return ACCESN_OK; - - } /*while (1) */ + } } - -/*/////////////////////////////////////////////////////////////////////////// -//GetAsyncImbpMessage_Ex -///////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: GetAsyncImbpMessage_Ex -// Purpose: This function gets the next available async message with a message id -// greater than SeqNo. The message looks like an IMB packet -// and the length and Sequence number is returned -// Context: Used by Upper level agents (sis modules) to access Asynchronous IMB implemented functionality. -// Returns: OK else error status code -// Parameters: -// msgPtr Pointer to Async IMB request -// msgLen Length -// timeOut Time to wait -// seqNo Sequence Munber -// Notes: none -*F*/ - +/* GetAsyncImbpMessage_Ex - gets the next available async message with a message + * ID greater than SeqNo. The message looks like an IMB packet and the length + * and Sequence number is returned. + * + * @msgPtr - request info and data + * @msgLen - IN - length of buffer, OUT - msg len + * @timeOut - how long to wait for the message + * @seqNo - previously returned seq number(or ASYNC_SEQ_START) + * @channelNumber + * @sessionHandle + * @privilege + * + * returns: OK else error status code + */ ACCESN_STATUS -GetAsyncImbpMessage_Ex ( - ImbPacket * msgPtr, /* request info and data */ - DWORD *msgLen, /* IN - length of buffer, OUT - msg len */ - DWORD timeOut, /* how long to wait for the message */ - ImbAsyncSeq *seqNo, /* previously returned seq number */ - /* (or ASYNC_SEQ_START) */ - DWORD channelNumber, - BYTE * sessionHandle, - BYTE * privilege - ) +GetAsyncImbpMessage_Ex(ImbPacket *msgPtr, DWORD *msgLen, DWORD timeOut, + ImbAsyncSeq *seqNo, DWORD channelNumber, BYTE *sessionHandle, + BYTE *privilege) { + BOOL status; + BYTE responseData[MAX_ASYNC_RESP_SIZE]; + BYTE lun; + ImbAsyncResponse *resp = (ImbAsyncResponse *)responseData; + DWORD respLength = sizeof(responseData); + ImbAsyncRequest req; + + while (1) { + if ((msgPtr == NULL) || (msgLen == NULL) || ( seqNo == NULL)) { + return ACCESN_ERROR; + } - BOOL status; - BYTE responseData[MAX_ASYNC_RESP_SIZE], lun; - ImbAsyncResponse * resp = (ImbAsyncResponse *) responseData; - DWORD respLength = sizeof( responseData ); - ImbAsyncRequest req; - - while(1) - { - - - if( (msgPtr == NULL) || (msgLen == NULL) || ( seqNo == NULL) ) + /* convert to uSec units */ + req.timeOut = timeOut * 1000; + req.lastSeq = *seqNo; + status = DeviceIoControl(hDevice, IOCTL_IMB_GET_ASYNC_MSG, &req, + sizeof(req), &responseData, + sizeof(responseData), &respLength, NULL); + + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", + __FUNCTION__, status); + if (status != TRUE) { + DWORD error = GetLastError(); + /* handle "msg not available" specially. it is + * different from a random old error. + */ + switch (error) { + case IMB_MSG_NOT_AVAILABLE: + return ACCESN_END_OF_DATA; + break; + default: return ACCESN_ERROR; + break; + } + } + if (respLength < MIN_ASYNC_RESP_SIZE) { + return ACCESN_ERROR; + } - req.timeOut = timeOut * 1000; /* convert to uSec units */ - req.lastSeq = *seqNo; - - - status = DeviceIoControl( hDevice, - IOCTL_IMB_GET_ASYNC_MSG, - & req, - sizeof( req ), - & responseData, - sizeof( responseData ), - & respLength, - NULL - ); - -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif + respLength -= MIN_ASYNC_RESP_SIZE; + if (*msgLen < respLength) { + return ACCESN_ERROR; + } - if( status != TRUE ) { - DWORD error = GetLastError(); - /* - // handle "msg not available" specially. it is - // different from a random old error. - */ - switch( error ) { - case IMB_MSG_NOT_AVAILABLE: - return ACCESN_END_OF_DATA; - default: - return ACCESN_ERROR; - } - return ACCESN_ERROR; - } - if( respLength < MIN_ASYNC_RESP_SIZE ) { - return ACCESN_ERROR; + /* same code as in NT section */ + if (IpmiVersion == IPMI_09_VERSION) { + switch (channelNumber) { + case IPMB_CHANNEL: + lun = IPMB_LUN; + break; + case EMP_CHANNEL: + lun = EMP_LUN; + break; + default: + lun = RESERVED_LUN; + break; } - respLength -= MIN_ASYNC_RESP_SIZE; - if( *msgLen < respLength ) { - return ACCESN_ERROR; + if ((lun == RESERVED_LUN) + || (lun != ((((ImbPacket *)(resp->data))->nfLn) & 0x3))) { + *seqNo = resp->thisSeq; + continue; } - - /*same code as in NT section */ - if ( IpmiVersion == IPMI_09_VERSION) - { - - switch( channelNumber) { - case IPMB_CHANNEL: - lun = IPMB_LUN; - break; - - case EMP_CHANNEL: - lun = EMP_LUN; - break; - - default: - lun = RESERVED_LUN; - break; - } - - if ( (lun == RESERVED_LUN) || - (lun != ((((ImbPacket *)(resp->data))->nfLn) & 0x3 )) - ) - { - *seqNo = resp->thisSeq; - continue; - } - - - memcpy( msgPtr, resp->data, respLength ); - *msgLen = respLength; - - } - else - { - if((sessionHandle ==NULL) || (privilege ==NULL)) - return ACCESN_ERROR; - - /*With the new IPMI version the get message command returns the - //channel number along with the privileges.The 1st 4 bits of the - //second byte of the response data for get message command represent - //the channel number & the last 4 bits are the privileges. */ - *privilege = (resp->data[0] & 0xf0)>> 4; - - if ((resp->data[0] & 0x0f) != (BYTE)channelNumber) - { - *seqNo = resp->thisSeq; - continue; - } - - - /*The get message command according to IPMI 1.5 spec now even - //returns the session handle.This is required to be captured - //as it is required as request data for send message command. */ - *sessionHandle = resp->data[1]; - memcpy( msgPtr, &(resp->data[2]), respLength-1 ); - *msgLen = respLength-1; - - + memcpy(msgPtr, resp->data, respLength); + *msgLen = respLength; + } else { + if ((sessionHandle ==NULL) || (privilege ==NULL)) { + return ACCESN_ERROR; + } + /* With the new IPMI version the get message command + * returns the channel number along with the + * privileges.The 1st 4 bits of the second byte of the + * response data for get message command represent the + * channel number & the last 4 bits are the privileges. + */ + *privilege = (resp->data[0] & 0xf0)>> 4; + if ((resp->data[0] & 0x0f) != (BYTE)channelNumber) { + *seqNo = resp->thisSeq; + continue; } - - /* - // give the caller his sequence number - */ + /* The get message command according to IPMI 1.5 spec + * now even returns the session handle.This is required + * to be captured as it is required as request data for + * send message command. + */ + *sessionHandle = resp->data[1]; + memcpy(msgPtr, &(resp->data[2]), (respLength - 1)); + *msgLen = respLength - 1; + } + /* give the caller his sequence number */ *seqNo = resp->thisSeq; - return ACCESN_OK; - - } /*while (1) */ -} - - - -/*////////////////////////////////////////////////////////////////////////////// -//IsAsyncMessageAvailable -///////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: IsMessageAvailable -// Purpose: This function waits for an Async Message -// -// Context: Used by Upper level agents access Asynchronous IMB based -// messages -// Returns: OK else error status code -// Parameters: -// eventId -// -// Notes: This call will block the calling thread if no Async events are -// are available in the queue. -// -*F*/ -ACCESN_STATUS -IsAsyncMessageAvailable (unsigned int eventId ) -{ - int dummy; - int respLength = 0; - BOOL status; - - /* confirm that app is not using a bad Id */ - - - if ( AsyncEventHandle != (HANDLE) eventId) - return ACCESN_ERROR; - - status = DeviceIoControl(hDevice, - IOCTL_IMB_CHECK_EVENT, - &AsyncEventHandle, - sizeof(HANDLE ), - &dummy, - sizeof(int), - (LPDWORD) & respLength, - NULL - ); -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif - - if( status != TRUE ) - return ACCESN_ERROR; - - - return ACCESN_OK; + } } - -/*I have retained this commented code because later we may want to use -//DPC message specific Processing (pai 11/21) */ - -#ifdef NOT_COMPILED_BUT_LEFT_HERE_FOR_NOW - -/*////////////////////////////////////////////////////////////////////////////// -//GetAsyncDpcMessage -///////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: GetAsyncDpcMessage -// Purpose: This function gets the next available async message from -// the DPC client. -// -// Context: Used by Upper level agents access Asynchronous IMB based -// messages sent by the DPC client. -// Returns: OK else error status code -// Parameters: -// msgPtr Pointer to Async IMB request -// msgLen Length -// timeOut Time to wait -// seqNo Sequence Munber -// Notes: This call will block the calling thread if no Async events are -// are available in the queue. -// -*F*/ - +/* IsAsyncMessageAvailable - Waits for an Async Message. This call will block + * the calling thread if no Async events are are available in the queue. + * + * @dummy + * @respLength + * @status + * + * returns: OK else error status code + */ ACCESN_STATUS -GetAsyncDpcMessage ( - ImbPacket * msgPtr, /* request info and data */ - DWORD * msgLen, /* IN - length of buffer, OUT - msg len */ - DWORD timeOut, /* how long to wait for the message */ - ImbAsyncSeq * seqNo, /* previously returned seq number (or ASYNC_SEQ_START) */ - ) +IsAsyncMessageAvailable(unsigned int eventId) { - BOOL status; - BYTE responseData[MAX_ASYNC_RESP_SIZE]; - ImbAsyncResponse * resp = (ImbAsyncResponse *) responseData; - DWORD respLength = sizeof( responseData ); - ImbAsyncRequest req; - - if( msgPtr == NULL || msgLen == NULL || seqNo == NULL ) - return ACCESN_ERROR; - - req.lastSeq = *seqNo; - - - hEvt = CreateEvent (NULL, TRUE, FALSE, NULL) ; - if (!hEvt) { + int dummy; + int respLength = 0; + BOOL status; + /* confirm that app is not using a bad Id */ + if (AsyncEventHandle != (HANDLE)eventId) { return ACCESN_ERROR; } - - status = DeviceIoControl( hDevice, - IOCTL_IMB_GET_DPC_MSG, - & req, - sizeof( req ), - & responseData, - sizeof( responseData ), - & respLength, - &ovl - ); - - if( status != TRUE ) { - DWORD error = GetLastError(); - /* - // handle "msg not available" specially. it is different from - // a random old error. - // - */ - if (!status) - { - switch (error ) - { - case ERROR_IO_PENDING: - - WaitForSingleObject (hEvt, INFINITE) ; - ResetEvent (hEvt) ; - break; - - case IMB_MSG_NOT_AVAILABLE: - - CloseHandle(hEvt); - return ACCESN_END_OF_DATA; - - default: - CloseHandle(hEvt); - return ACCESN_ERROR; - - } - } - - - - if ( - ( GetOverlappedResult(hDevice, - &ovl, - (LPDWORD)&respLength, - TRUE - ) == 0 ) || (respLength <= 0) - ) - - { - - CloseHandle(hEvt); - return ACCESN_ERROR; - - } - - - } - - if( respLength < MIN_ASYNC_RESP_SIZE ) { - CloseHandle(hEvt); - return ACCESN_ERROR; - } - - respLength -= MIN_ASYNC_RESP_SIZE; - - if( *msgLen < respLength ) { - - /* The following code should have been just return ACCESN_out_of_range */ - CloseHandle(hEvt); + status = DeviceIoControl(hDevice, IOCTL_IMB_CHECK_EVENT, + &AsyncEventHandle, sizeof(HANDLE), &dummy, sizeof(int), + (LPDWORD)&respLength, NULL); + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if (status != TRUE) { return ACCESN_ERROR; } - - memcpy( msgPtr, resp->data, respLength ); - - *msgLen = respLength; - /* - // give the caller his sequence number - */ - *seqNo = resp->thisSeq; - - CloseHandle(hEvt); - - return ACCESN_OK; - } -#endif /*NOT_COMPILED_BUT_LEFT_HERE_FOR_NOW*/ - - -/*///////////////////////////////////////////////////////////////////////////// -//RegisterForImbAsyncMessageNotification -///////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: RegisterForImbAsyncMessageNotification -// Purpose: This function Registers the calling application -// for Asynchronous notification when a sms message -// is available with the IMB driver. -// -// Context: Used by Upper level agents to know that an async -// SMS message is available with the driver. -// Returns: OK else error status code -// Parameters: -// handleId pointer to the registration handle -// -// Notes: The calling application should use the returned handle to -// get the Async messages.. -*F*/ +/* RegisterForImbAsyncMessageNotification - This function Registers the calling + * application for Asynchronous notification when a sms message is available + * with the IMB driver. + * + * Notes: The calling application should use the returned handle to + * get the Async messages.. + * + * @handleId - pointer to the registration handle + * + * returns: OK else error status code + */ ACCESN_STATUS -RegisterForImbAsyncMessageNotification (unsigned int *handleId) - +RegisterForImbAsyncMessageNotification(unsigned int *handleId) { - BOOL status; - DWORD respLength ; - int dummy; - + BOOL status; + DWORD respLength ; + int dummy; /*allow only one app to register */ - - if( (handleId == NULL ) || (AsyncEventHandle) ) + if ((handleId == NULL ) || (AsyncEventHandle)) { return ACCESN_ERROR; - - - status = DeviceIoControl(hDevice, - IOCTL_IMB_REGISTER_ASYNC_OBJ, - &dummy, - sizeof( int ), - &AsyncEventHandle, - (DWORD)sizeof(HANDLE ), - (LPDWORD) & respLength, - NULL - ); -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif - - if( (respLength != sizeof(int)) || (status != TRUE )) - return ACCESN_ERROR; - + } + status = DeviceIoControl(hDevice, IOCTL_IMB_REGISTER_ASYNC_OBJ, &dummy, + sizeof(int), &AsyncEventHandle, (DWORD)sizeof(HANDLE), + (LPDWORD)&respLength, NULL); + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if ((respLength != sizeof(int)) || (status != TRUE)) { + return ACCESN_ERROR; + } /* printf("imbapi: Register handle = %x\n",AsyncEventHandle); *//*++++*/ - *handleId = (unsigned int) AsyncEventHandle; - -#ifndef NO_MACRO_ARGS - DEBUG("handleId = %x AsyncEventHandle %x\n", *handleId, AsyncEventHandle); -#endif + *handleId = (unsigned int)AsyncEventHandle; + lprintf(LOG_DEBUG, "handleId = %x AsyncEventHandle %x", *handleId, + AsyncEventHandle); return ACCESN_OK; } - - - - -/*///////////////////////////////////////////////////////////////////////////// -//UnRegisterForImbAsyncMessageNotification -///////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: UnRegisterForImbAsyncMessageNotification -// Purpose: This function un-registers the calling application -// for Asynchronous notification when a sms message -// is available with the IMB driver. -// -// Context: Used by Upper level agents to un-register -// for async. notification of sms messages -// Returns: OK else error status code -// Parameters: -// handleId pointer to the registration handle -// iFlag value used to determine where this function was called from -// _it is used currently on in NetWare environment_ -// -// Notes: -*F*/ +/* UnRegisterForImbAsyncMessageNotification - This function un-registers the + * calling application for Asynchronous notification when a sms message is + * available with the IMB driver. It is used by Upper level agents to + * un-register for async. notification of sms messages. + * + * @handleId - pointer to the registration handle + * @iFlag - value used to determine where this function was called from. It is + * used currently on in NetWare environment. + * + * returns - status + */ ACCESN_STATUS -UnRegisterForImbAsyncMessageNotification (unsigned int handleId, int iFlag) - +UnRegisterForImbAsyncMessageNotification(unsigned int handleId, int iFlag) { - BOOL status; - DWORD respLength ; - int dummy; - - iFlag = iFlag; /* to keep compiler happy We are not using this flag*/ - - if ( AsyncEventHandle != (HANDLE) handleId) - return ACCESN_ERROR; - - status = DeviceIoControl(hDevice, - IOCTL_IMB_DEREGISTER_ASYNC_OBJ, - &AsyncEventHandle, - (DWORD)sizeof(HANDLE ), - &dummy, - (DWORD)sizeof(int ), - (LPDWORD) & respLength, - NULL - ); -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif + BOOL status; + DWORD respLength ; + int dummy; + /* to keep compiler happy. We are not using this flag*/ + iFlag = iFlag; - if( status != TRUE ) - return ACCESN_ERROR; + if (AsyncEventHandle != (HANDLE)handleId) { + return ACCESN_ERROR; + } + status = DeviceIoControl(hDevice, IOCTL_IMB_DEREGISTER_ASYNC_OBJ, + &AsyncEventHandle, (DWORD)sizeof(HANDLE ), &dummy, + (DWORD)sizeof(int), (LPDWORD)&respLength, NULL ); + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if (status != TRUE) { + return ACCESN_ERROR; + } return ACCESN_OK; } - -/*/////////////////////////////////////////////////////////////////////////// -// SetShutDownCode -///////////////////////////////////////////////////////////////////////////// */ -/*F* -// Name: SetShutDownCode -// Purpose: To set the shutdown action code -// Context: Called by the System Control Subsystem -// Returns: none -// Parameters: -// code shutdown action code which can be either -// SD_NO_ACTION, SD_RESET, SD_POWER_OFF as defined in imb_if.h -*F*/ - -ACCESN_STATUS -SetShutDownCode ( - int delayTime, /* time to delay in 100ms units */ - int code /* what to do when time expires */ - ) -{ - DWORD retLength; - BOOL status; - ShutdownCmdBuffer cmd; - - /* - // If Imb driver is not present return AccessFailed - */ - if(hDevice == INVALID_HANDLE_VALUE) +/* SetShutDownCode - To set the shutdown action code. + * + * @code - shutdown action code which can be either SD_NO_ACTION, SD_RESET, + * SD_POWER_OFF as defined in imb_if.h + * @delayTime - time to delay in 100ms units + * + * returns - status + */ +ACCESN_STATUS +SetShutDownCode(int delayTime, int code) +{ + DWORD retLength; + BOOL status; + ShutdownCmdBuffer cmd; + /* If IMB interface isn't open, return AccessFailed */ + if (hDevice == INVALID_HANDLE_VALUE) { return ACCESN_ERROR; - - cmd.code = code; - cmd.delayTime = delayTime; - - status = DeviceIoControl( hDevice, - IOCTL_IMB_SHUTDOWN_CODE, - & cmd, - sizeof( cmd ), - NULL, - 0, - & retLength, - NULL - ); -#ifndef NO_MACRO_ARGS - DEBUG("%s: DeviceIoControl status = %d\n",__FUNCTION__, status); -#endif - - if(status == TRUE) + } + cmd.code = code; + cmd.delayTime = delayTime; + status = DeviceIoControl(hDevice, IOCTL_IMB_SHUTDOWN_CODE, &cmd, + sizeof(cmd), NULL, 0, &retLength, NULL); + lprintf(LOG_DEBUG, "%s: DeviceIoControl status = %d", __FUNCTION__, + status); + if (status == TRUE) { return ACCESN_OK; - else + } else { return ACCESN_ERROR; + } } /*///////////////////////////////////////////////////////////////////////// @@ -1919,36 +1337,27 @@ SetShutDownCode ( *F*/ #ifdef WIN32 ACCESN_STATUS -MapPhysicalMemory ( - int startAddress, // physical address to map in - int addressLength, // how much to map - int *virtualAddress // where it got mapped to - ) +MapPhysicalMemory(int startAddress, int addressLength, int *virtualAddress) { - DWORD retLength; - BOOL status; + DWORD retLength; + BOOL status; PHYSICAL_MEMORY_INFO pmi; - if (startAddress == 0 || addressLength <= 0) + if (startAddress == 0 || addressLength <= 0) { return ACCESN_OUT_OF_RANGE; + } - pmi.InterfaceType = Internal; - pmi.BusNumber = 0; + pmi.InterfaceType = Internal; + pmi.BusNumber = 0; pmi.BusAddress.HighPart = (LONG)0x0; - pmi.BusAddress.LowPart = (LONG)startAddress; - pmi.AddressSpace = (LONG) 0; - pmi.Length = addressLength; - - status = DeviceIoControl ( hDevice, - IOCTL_IMB_MAP_MEMORY, - & pmi, - sizeof(PHYSICAL_MEMORY_INFO), - virtualAddress, - sizeof(PVOID), - & retLength, - 0 - ); - if( status == TRUE ) { + pmi.BusAddress.LowPart = (LONG)startAddress; + pmi.AddressSpace = (LONG)0; + pmi.Length = addressLength; + + status = DeviceIoControl(hDevice, IOCTL_IMB_MAP_MEMORY, &pmi, + sizeof(PHYSICAL_MEMORY_INFO), virtualAddress, + sizeof(PVOID), &retLength, 0); + if (status == TRUE) { return ACCESN_OK; } else { return ACCESN_ERROR; @@ -1956,40 +1365,27 @@ MapPhysicalMemory ( } ACCESN_STATUS -UnmapPhysicalMemory ( - int virtualAddress, // what memory to unmap - int Length ) +UnmapPhysicalMemory(int virtualAddress, int Length) { - DWORD retLength; - BOOL status; - - status = DeviceIoControl ( hDevice, - IOCTL_IMB_UNMAP_MEMORY, - & virtualAddress, - sizeof(PVOID), - NULL, - 0, - & retLength, - 0 - ); - - if( status == TRUE ) { + DWORD retLength; + BOOL status; + status = DeviceIoControl(hDevice, IOCTL_IMB_UNMAP_MEMORY, + &virtualAddress, sizeof(PVOID), NULL, 0, &retLength, 0); + if (status == TRUE) { return ACCESN_OK; } else { return ACCESN_ERROR; } } - -#else /*Linux, SCO, UNIX, etc.*/ - +#else /* Linux, SCO, UNIX, etc. */ ACCESN_STATUS -MapPhysicalMemory(int startAddress,int addressLength, int *virtualAddress ) +MapPhysicalMemory(int startAddress, int addressLength, int *virtualAddress) { - int fd; - unsigned int length = addressLength; - off_t startpAddress = (off_t)startAddress; - unsigned int diff; - char *startvAddress; + int fd; + unsigned int length = addressLength; + off_t startpAddress = (off_t)startAddress; + unsigned int diff; + char *startvAddress; #if defined(PAGESIZE) long int pagesize = PAGESIZE; #elif defined(_SC_PAGESIZE) @@ -1998,64 +1394,47 @@ MapPhysicalMemory(int startAddress,int addressLength, int *virtualAddress ) perror("Invalid pagesize"); } #else -# error PAGESIZE unsupported +# error PAGESIZE unsupported #endif - - if ((startAddress == 0) || (addressLength <= 0)) + if ((startAddress == 0) || (addressLength <= 0)) { return ACCESN_ERROR; - - if ( (fd = open("/dev/mem", O_RDONLY)) < 0) { + } + if ((fd = open("/dev/mem", O_RDONLY)) < 0) { char buf[128]; - sprintf(buf,"%s %s: open(%s) failed", - __FILE__,__FUNCTION__,IMB_DEVICE); + __FILE__, __FUNCTION__, IMB_DEVICE); perror(buf); - return ACCESN_ERROR ; + return ACCESN_ERROR; } - /* aliging the offset to a page boundary and adjusting the length */ diff = (int)startpAddress % pagesize; startpAddress -= diff; length += diff; - - if ( (startvAddress = mmap(0, - length, - PROT_READ, - MAP_SHARED, - fd, - startpAddress - ) ) == MAP_FAILED) - { + if ((startvAddress = mmap(0, length, PROT_READ, MAP_SHARED, fd, + startpAddress)) == MAP_FAILED) { char buf[128]; - - sprintf(buf,"%s %s: mmap failed", __FILE__,__FUNCTION__); + sprintf(buf, "%s %s: mmap failed", __FILE__, __FUNCTION__); perror(buf); close(fd); return ACCESN_ERROR; } -#ifndef NO_MACRO_ARGS - DEBUG("%s: mmap of 0x%x success\n",__FUNCTION__,startpAddress); -#endif + lprintf(LOG_DEBUG, "%s: mmap of 0x%x success", __FUNCTION__, + startpAddress); #ifdef LINUX_DEBUG_MAX -/* dont want this memory dump for normal level of debugging. -// So, I have put it under a stronger debug symbol. mahendra */ - - for(i=0; i < length; i++) - { + for (int i = 0; i < length; i++) { printf("0x%x ", (startvAddress[i])); if(isascii(startvAddress[i])) { printf("%c ", (startvAddress[i])); } - } -#endif /*LINUX_DEBUG_MAX */ - + } +#endif /* LINUX_DEBUG_MAX */ *virtualAddress = (long)(startvAddress + diff); close(fd); return ACCESN_OK; } ACCESN_STATUS -UnmapPhysicalMemory( int virtualAddress, int Length ) +UnmapPhysicalMemory(int virtualAddress, int Length) { unsigned int diff = 0; #if defined(PAGESIZE) @@ -2066,53 +1445,29 @@ UnmapPhysicalMemory( int virtualAddress, int Length ) perror("Invalid pagesize"); } #else -# error PAGESIZE unsupported +# error PAGESIZE unsupported #endif - /* page align the virtual address and adjust length accordingly */ - diff = ((unsigned int) virtualAddress) % pagesize; + diff = ((unsigned int)virtualAddress) % pagesize; virtualAddress -= diff; Length += diff; -#ifndef NO_MACRO_ARGS - DEBUG("%s: calling munmap(0x%x,%d)\n",__FUNCTION__,virtualAddress,Length); -#endif - - if(munmap(&virtualAddress, Length) != 0) - { + lprintf(LOG_DEBUG, "%s: calling munmap(0x%x,%d)", __FUNCTION__, + virtualAddress,Length); + if (munmap(&virtualAddress, Length) != 0) { char buf[128]; - - sprintf(buf,"%s %s: munmap failed", __FILE__,__FUNCTION__); + sprintf(buf, "%s %s: munmap failed", __FILE__, __FUNCTION__); perror(buf); return ACCESN_ERROR; - } -#ifndef NO_MACRO_ARGS - DEBUG("%s: munmap(0x%x,%d) success\n",__FUNCTION__,virtualAddress,Length); -#endif - + lprintf(LOG_DEBUG, "%s: munmap(0x%x,%d) success", __FUNCTION__, + virtualAddress, Length); return ACCESN_OK; } -#endif /*unix*/ +#endif /* unix */ - -/*///////////////////////////////////////////////////////////////////////////// -// GetIpmiVersion -//////////////////////////////////////////////////////////////////////////// */ - -/*F* -// Name: GetIpmiVersion -// Purpose: This function returns current IPMI version -// Context: -// Returns: IPMI version -// Parameters: -// reqPtr -// timeOut -// respDataPtr -// respLen -// Notes: svuppula -*F*/ -BYTE GetIpmiVersion() +/* GetIpmiVersion - returns current IPMI version. */ +BYTE +GetIpmiVersion() { - return IpmiVersion; + return IpmiVersion; } - diff --git a/src/plugins/ipmi_intf.c b/src/plugins/ipmi_intf.c index 6cf0553..9225a34 100644 --- a/src/plugins/ipmi_intf.c +++ b/src/plugins/ipmi_intf.c @@ -264,15 +264,9 @@ ipmi_intf_session_set_sol_escape_char(struct ipmi_intf * intf, char sol_escape_c } void -ipmi_intf_session_set_kgkey(struct ipmi_intf * intf, char * kgkey) +ipmi_intf_session_set_kgkey(struct ipmi_intf *intf, const uint8_t *kgkey) { - memset(intf->ssn_params.kg, 0, IPMI_KG_BUFFER_SIZE); - - if (kgkey == NULL) - return; - - memcpy(intf->ssn_params.kg, kgkey, - __min(strlen(kgkey), IPMI_KG_BUFFER_SIZE)); + memcpy(intf->ssn_params.kg, kgkey, IPMI_KG_BUFFER_SIZE); } void diff --git a/src/plugins/lanplus/lanplus.c b/src/plugins/lanplus/lanplus.c index 2a89a14..a0e388c 100644 --- a/src/plugins/lanplus/lanplus.c +++ b/src/plugins/lanplus/lanplus.c @@ -169,9 +169,14 @@ int lanplus_get_requested_ciphers(int cipher_suite_id, uint8_t * integrity_alg, uint8_t * crypt_alg) { +#ifdef HAVE_CRYPTO_SHA256 + if ((cipher_suite_id < 0) || (cipher_suite_id > 17)) { + return 1; + } +#else if ((cipher_suite_id < 0) || (cipher_suite_id > 14)) return 1; - +#endif /* HAVE_CRYPTO_SHA256 */ /* See table 22-19 for the source of the statement */ switch (cipher_suite_id) { @@ -250,6 +255,23 @@ int lanplus_get_requested_ciphers(int cipher_suite_id, *integrity_alg = IPMI_INTEGRITY_MD5_128; *crypt_alg = IPMI_CRYPT_XRC4_40; break; +#ifdef HAVE_CRYPTO_SHA256 + case 15: + *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256; + *integrity_alg = IPMI_INTEGRITY_NONE; + *crypt_alg = IPMI_CRYPT_NONE; + break; + case 16: + *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256; + *integrity_alg = IPMI_INTEGRITY_HMAC_SHA256_128; + *crypt_alg = IPMI_CRYPT_NONE; + break; + case 17: + *auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256; + *integrity_alg = IPMI_INTEGRITY_HMAC_SHA256_128; + *crypt_alg = IPMI_CRYPT_AES_CBC_128; + break; +#endif /* HAVE_CRYPTO_SHA256 */ } return 0; @@ -1022,15 +1044,34 @@ read_rakp2_message( break; case IPMI_AUTH_RAKP_HMAC_SHA1: - /* We need to copy 20 bytes */ - for (i = 0; i < 20; ++i) - rsp->payload.rakp2_message.key_exchange_auth_code[i] = - rsp->data[offset + 40 + i]; - break; + /* We need to copy 20 bytes */ + for (i = 0; i < IPMI_SHA_DIGEST_LENGTH; ++i) { + rsp->payload.rakp2_message.key_exchange_auth_code[i] = + rsp->data[offset + 40 + i]; + } + break; case IPMI_AUTH_RAKP_HMAC_MD5: - lprintf(LOG_ERR, "read_rakp2_message: no support for " - "IPMI_AUTH_RAKP_HMAC_MD5"); + /* We need to copy 16 bytes */ + for (i = 0; i < IPMI_MD5_DIGEST_LENGTH; ++i) { + rsp->payload.rakp2_message.key_exchange_auth_code[i] = + rsp->data[offset + 40 + i]; + } + break; + +#ifdef HAVE_CRYPTO_SHA256 + case IPMI_AUTH_RAKP_HMAC_SHA256: + /* We need to copy 32 bytes */ + for (i = 0; i < IPMI_SHA256_DIGEST_LENGTH; ++i) { + rsp->payload.rakp2_message.key_exchange_auth_code[i] = + rsp->data[offset + 40 + i]; + } + break; +#endif /* HAVE_CRYPTO_SHA256 */ + + default: + lprintf(LOG_ERR, "read_rakp2_message: no support " + "for authentication algorithm 0x%x", auth_alg); assert(0); break; } @@ -1088,13 +1129,32 @@ read_rakp4_message( break; case IPMI_AUTH_RAKP_HMAC_SHA1: - /* We need to copy 12 bytes */ - for (i = 0; i < 12; ++i) - rsp->payload.rakp4_message.integrity_check_value[i] = - rsp->data[offset + 8 + i]; - break; + /* We need to copy 12 bytes */ + for (i = 0; i < IPMI_SHA1_AUTHCODE_SIZE; ++i) { + rsp->payload.rakp4_message.integrity_check_value[i] = + rsp->data[offset + 8 + i]; + } + break; case IPMI_AUTH_RAKP_HMAC_MD5: + /* We need to copy 16 bytes */ + for (i = 0; i < IPMI_HMAC_MD5_AUTHCODE_SIZE; ++i) { + rsp->payload.rakp4_message.integrity_check_value[i] = + rsp->data[offset + 8 + i]; + } + break; + +#ifdef HAVE_CRYPTO_SHA256 + case IPMI_AUTH_RAKP_HMAC_SHA256: + /* We need to copy 16 bytes */ + for (i = 0; i < IPMI_HMAC_SHA256_AUTHCODE_SIZE; ++i) { + rsp->payload.rakp4_message.integrity_check_value[i] = + rsp->data[offset + 8 + i]; + } + break; +#endif /* HAVE_CRYPTO_SHA256 */ + + default: lprintf(LOG_ERR, "read_rakp4_message: no support " "for authentication algorithm 0x%x", auth_alg); assert(0); @@ -1760,7 +1820,11 @@ ipmi_lanplus_build_v2x_msg( if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) && (session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE)) { - uint32_t i, hmac_length, integrity_pad_size = 0, hmac_input_size; + uint32_t i; + uint32_t hmac_length; + uint32_t auth_length = 0; + uint32_t integrity_pad_size = 0; + uint32_t hmac_input_size; uint8_t * hmac_output; uint32_t start_of_session_trailer = IPMI_LANPLUS_OFFSET_PAYLOAD + @@ -1818,22 +1882,43 @@ ipmi_lanplus_build_v2x_msg( /* Auth Code */ lanplus_HMAC(session->v2_data.integrity_alg, session->v2_data.k1, /* key */ - 20, /* key length */ + session->v2_data.k1_len, /* key length */ msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, /* hmac input */ hmac_input_size, hmac_output, &hmac_length); - assert(hmac_length == 20); + switch(session->v2_data.integrity_alg) { + case IPMI_INTEGRITY_HMAC_SHA1_96: + assert(hmac_length == IPMI_SHA_DIGEST_LENGTH); + auth_length = IPMI_SHA1_AUTHCODE_SIZE; + break; + case IPMI_INTEGRITY_HMAC_MD5_128 : + assert(hmac_length == IPMI_MD5_DIGEST_LENGTH); + auth_length = IPMI_HMAC_MD5_AUTHCODE_SIZE; + break; +#ifdef HAVE_CRYPTO_SHA256 + case IPMI_INTEGRITY_HMAC_SHA256_128: + assert(hmac_length == IPMI_SHA256_DIGEST_LENGTH); + auth_length = IPMI_HMAC_SHA256_AUTHCODE_SIZE; + break; +#endif /* HAVE_CRYPTO_SHA256 */ + default: + assert(0); + break; + } if (verbose > 2) - printbuf(hmac_output, 12, "authcode output"); + printbuf(hmac_output, auth_length, "authcode output"); /* Set session_trailer_length appropriately */ session_trailer_length = integrity_pad_size + 2 + /* pad length + next header */ - 12; /* Size of the authcode (we only use the first 12 bytes) */ + auth_length; /* Size of the authcode. We only + * use the first 12(SHA1) or + * 16(MD5/SHA256) bytes. + */ } @@ -2284,6 +2369,10 @@ ipmi_lanplus_send_payload( rsp = ipmi_lanplus_recv_sol(intf); /* Grab the next packet */ + if (!is_sol_packet(rsp)) { + break; + } + if (sol_response_acks_packet(rsp, payload)) break; @@ -2296,6 +2385,7 @@ ipmi_lanplus_send_payload( intf->session->sol_data.sol_input_handler(rsp); /* In order to avoid duplicate output, just set data_len to 0 */ rsp->data_len = 0; + break; } } diff --git a/src/plugins/lanplus/lanplus.h b/src/plugins/lanplus/lanplus.h index 4b6ae1e..d967462 100644 --- a/src/plugins/lanplus/lanplus.h +++ b/src/plugins/lanplus/lanplus.h @@ -96,12 +96,20 @@ #define IPMI_MAX_CONF_HEADER_SIZE 0x20 #define IPMI_MAX_PAYLOAD_SIZE 0xFFFF /* Includes confidentiality header/trailer */ #define IPMI_MAX_CONF_TRAILER_SIZE 0x20 -#define IPMI_MAX_INTEGRITY_PAD_SIZE 0x20 -#define IPMI_MAX_AUTH_CODE_SIZE 0x20 +#define IPMI_MAX_INTEGRITY_PAD_SIZE IPMI_MAX_MD_SIZE +#define IPMI_MAX_AUTH_CODE_SIZE IPMI_MAX_MD_SIZE #define IPMI_REQUEST_MESSAGE_SIZE 0x07 -#define IPMI_MAX_MAC_SIZE 0x14 /* The largest mac we ever expect to generate */ -#define IPMI_SHA1_AUTHCODE_SIZE 0x0C +#define IPMI_MAX_MAC_SIZE IPMI_MAX_MD_SIZE /* The largest mac we ever expect to generate */ + +#define IPMI_SHA1_AUTHCODE_SIZE 12 +#define IPMI_HMAC_MD5_AUTHCODE_SIZE 16 +#define IPMI_MD5_AUTHCODE_SIZE 16 +#define IPMI_HMAC_SHA256_AUTHCODE_SIZE 16 + +#define IPMI_SHA_DIGEST_LENGTH 20 +#define IPMI_MD5_DIGEST_LENGTH 16 +#define IPMI_SHA256_DIGEST_LENGTH 32 /* *This is accurate, as long as we're only passing 1 auth algorithm, @@ -109,7 +117,7 @@ */ #define IPMI_OPEN_SESSION_REQUEST_SIZE 32 #define IPMI_RAKP1_MESSAGE_SIZE 44 -#define IPMI_RAKP3_MESSAGE_MAX_SIZE 28 +#define IPMI_RAKP3_MESSAGE_MAX_SIZE (8 + IPMI_MAX_MD_SIZE) #define IPMI_MAX_USER_NAME_LENGTH 16 diff --git a/src/plugins/lanplus/lanplus_crypt.c b/src/plugins/lanplus/lanplus_crypt.c index 1cdd050..cb963f4 100644 --- a/src/plugins/lanplus/lanplus_crypt.c +++ b/src/plugins/lanplus/lanplus_crypt.c @@ -74,7 +74,7 @@ lanplus_rakp2_hmac_matches(const struct ipmi_session * session, { uint8_t * buffer; int bufferLength, i; - uint8_t mac[20]; + uint8_t mac[IPMI_MAX_MD_SIZE]; uint32_t macLength; uint32_t SIDm_lsbf, SIDc_lsbf; @@ -84,7 +84,12 @@ lanplus_rakp2_hmac_matches(const struct ipmi_session * session, return 1; /* We don't yet support other algorithms */ - assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1); + assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1) + || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5) +#ifdef HAVE_CRYPTO_SHA256 + || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256) +#endif /* HAVE_CRYPTO_SHA256 */ + ); bufferLength = @@ -228,8 +233,9 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session, { uint8_t * buffer; int bufferLength, i; - uint8_t mac[20]; + uint8_t mac[IPMI_MAX_MD_SIZE]; uint32_t macLength; + uint32_t cmpLength; uint32_t SIDc_lsbf; if (ipmi_oem_active(intf, "intelplus")){ @@ -238,13 +244,19 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session, return 1; /* We don't yet support other algorithms */ - assert(session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96); + assert((session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96) + || (session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_MD5_128)); } else { if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE) return 1; /* We don't yet support other algorithms */ - assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1); + assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1) + || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5) +#ifdef HAVE_CRYPTO_SHA256 + || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256) +#endif /* HAVE_CRYPTO_SHA256 */ + ); } bufferLength = @@ -294,7 +306,8 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session, if (verbose > 2) { printbuf((const uint8_t *)buffer, bufferLength, ">> rakp4 mac input buffer"); - printbuf(session->v2_data.sik, 20l, ">> rakp4 mac key (sik)"); + printbuf(session->v2_data.sik, session->v2_data.sik_len, + ">> rakp4 mac key (sik)"); } @@ -305,7 +318,7 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session, ? session->v2_data.integrity_alg : session->v2_data.auth_alg , session->v2_data.sik, - IPMI_SIK_BUFFER_SIZE, + session->v2_data.sik_len, buffer, bufferLength, mac, @@ -317,12 +330,48 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session, printbuf(mac, macLength, ">> rakp4 mac as computed by the remote console"); } - + if (ipmi_oem_active(intf, "intelplus")) { + /* Intel BMC responds with the integrity Algorithm in RAKP4 */ + switch(session->v2_data.integrity_alg) { + case IPMI_INTEGRITY_HMAC_SHA1_96: + assert(macLength == IPMI_SHA_DIGEST_LENGTH); + cmpLength = IPMI_SHA1_AUTHCODE_SIZE; + break; + case IPMI_INTEGRITY_HMAC_MD5_128: + assert(macLength == IPMI_MD5_DIGEST_LENGTH); + cmpLength = IPMI_HMAC_MD5_AUTHCODE_SIZE; + break; + default: + assert(0); + break; + } + } else { + /* We don't yet support other algorithms */ + switch(session->v2_data.auth_alg) { + case IPMI_AUTH_RAKP_HMAC_SHA1: + assert(macLength == IPMI_SHA_DIGEST_LENGTH); + cmpLength = IPMI_SHA1_AUTHCODE_SIZE; + break; + case IPMI_AUTH_RAKP_HMAC_MD5: + assert(macLength == IPMI_MD5_DIGEST_LENGTH); + cmpLength = IPMI_HMAC_MD5_AUTHCODE_SIZE; + break; +#ifdef HAVE_CRYPTO_SHA256 + case IPMI_AUTH_RAKP_HMAC_SHA256: + assert(macLength == IPMI_SHA256_DIGEST_LENGTH); + cmpLength = IPMI_HMAC_SHA256_AUTHCODE_SIZE; + break; +#endif /* HAVE_CRYPTO_SHA256 */ + default: + assert(0); + break; + } + } free(buffer); buffer = NULL; - assert(macLength == 20); - return (memcmp(bmc_mac, mac, 12) == 0); + assert(macLength >= cmpLength); + return (memcmp(bmc_mac, mac, cmpLength) == 0); } @@ -368,7 +417,12 @@ lanplus_generate_rakp3_authcode(uint8_t * output_buffer, } /* We don't yet support other algorithms */ - assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1); + assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1) + || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5) +#ifdef HAVE_CRYPTO_SHA256 + || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256) +#endif /* HAVE_CRYPTO_SHA256 */ + ); input_buffer_length = 16 + /* Rc */ @@ -478,13 +532,19 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf) uint32_t mac_length; - memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE); + memset(session->v2_data.sik, 0, sizeof(session->v2_data.sik)); + session->v2_data.sik_len = 0; if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE) return 0; /* We don't yet support other algorithms */ - assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1); + assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1) + || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5) +#ifdef HAVE_CRYPTO_SHA256 + || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256) +#endif /* HAVE_CRYPTO_SHA256 */ + ); input_buffer_length = 16 + /* Rm */ @@ -572,15 +632,33 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf) free(input_buffer); input_buffer = NULL; - assert(mac_length == 20); + switch (session->v2_data.auth_alg) { + case IPMI_AUTH_RAKP_HMAC_SHA1: + assert(mac_length == IPMI_SHA_DIGEST_LENGTH); + break; + case IPMI_AUTH_RAKP_HMAC_MD5: + assert(mac_length == IPMI_MD5_DIGEST_LENGTH); + break; +#ifdef HAVE_CRYPTO_SHA256 + case IPMI_AUTH_RAKP_HMAC_SHA256: + assert(mac_length == IPMI_SHA256_DIGEST_LENGTH); + break; +#endif /* HAVE_CRYPTO_SHA256 */ + default: + assert(0); + break; + } + + session->v2_data.sik_len = mac_length; /* * The key MAC generated is 20 bytes, but we will only be using the first * 12 for SHA1 96 */ - if (verbose >= 2) - printbuf(session->v2_data.sik, 20, "Generated session integrity key"); - + if (verbose >= 2) { + printbuf(session->v2_data.sik, session->v2_data.sik_len, + "Generated session integrity key"); + } return 0; } @@ -614,16 +692,32 @@ lanplus_generate_k1(struct ipmi_session * session) { lanplus_HMAC(session->v2_data.auth_alg, session->v2_data.sik, - IPMI_SIK_BUFFER_SIZE, /* SIK length */ + session->v2_data.sik_len, /* SIK length */ CONST_1, 20, session->v2_data.k1, &mac_length); - assert(mac_length == 20); + switch (session->v2_data.auth_alg) { + case IPMI_AUTH_RAKP_HMAC_SHA1: + assert(mac_length == IPMI_SHA_DIGEST_LENGTH); + break; + case IPMI_AUTH_RAKP_HMAC_MD5: + assert(mac_length == IPMI_MD5_DIGEST_LENGTH); + break; +#ifdef HAVE_CRYPTO_SHA256 + case IPMI_AUTH_RAKP_HMAC_SHA256: + assert(mac_length == IPMI_SHA256_DIGEST_LENGTH); + break; +#endif /* HAVE_CRYPTO_SHA256 */ + default: + assert(0); + break; + } + session->v2_data.k1_len = mac_length; } if (verbose >= 2) - printbuf(session->v2_data.k1, 20, "Generated K1"); + printbuf(session->v2_data.k1, session->v2_data.k1_len, "Generated K1"); return 0; } @@ -658,16 +752,32 @@ lanplus_generate_k2(struct ipmi_session * session) { lanplus_HMAC(session->v2_data.auth_alg, session->v2_data.sik, - IPMI_SIK_BUFFER_SIZE, /* SIK length */ + session->v2_data.sik_len, /* SIK length */ CONST_2, 20, session->v2_data.k2, &mac_length); - assert(mac_length == 20); + switch (session->v2_data.auth_alg) { + case IPMI_AUTH_RAKP_HMAC_SHA1: + assert(mac_length == IPMI_SHA_DIGEST_LENGTH); + break; + case IPMI_AUTH_RAKP_HMAC_MD5: + assert(mac_length == IPMI_MD5_DIGEST_LENGTH); + break; +#ifdef HAVE_CRYPTO_SHA256 + case IPMI_AUTH_RAKP_HMAC_SHA256: + assert(mac_length == IPMI_SHA256_DIGEST_LENGTH); + break; +#endif /* HAVE_CRYPTO_SHA256 */ + default: + assert(0); + break; + } + session->v2_data.k2_len = mac_length; } if (verbose >= 2) - printbuf(session->v2_data.k2, 20, "Generated K2"); + printbuf(session->v2_data.k2, session->v2_data.k2_len, "Generated K2"); return 0; } @@ -803,6 +913,7 @@ lanplus_has_valid_auth_code(struct ipmi_rs * rs, struct ipmi_session * session) uint8_t * bmc_authcode; uint8_t generated_authcode[IPMI_MAX_MAC_SIZE]; uint32_t generated_authcode_length; + uint32_t authcode_length; if ((rs->session.authtype != IPMI_SESSION_AUTHTYPE_RMCP_PLUS) || @@ -811,36 +922,51 @@ lanplus_has_valid_auth_code(struct ipmi_rs * rs, struct ipmi_session * session) (session->v2_data.integrity_alg == IPMI_INTEGRITY_NONE)) return 1; - /* We only support SHA1-96 now */ - assert(session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96); + switch (session->v2_data.integrity_alg) { + case IPMI_INTEGRITY_HMAC_SHA1_96: + authcode_length = IPMI_SHA1_AUTHCODE_SIZE; + break; + case IPMI_INTEGRITY_HMAC_MD5_128: + authcode_length = IPMI_HMAC_MD5_AUTHCODE_SIZE; + break; +#ifdef HAVE_CRYPTO_SHA256 + case IPMI_INTEGRITY_HMAC_SHA256_128: + authcode_length = IPMI_HMAC_SHA256_AUTHCODE_SIZE; + break; +#endif /* HAVE_CRYPTO_SHA256 */ + /* Unsupported */ + default: + assert(0); + break; + } /* * For SHA1-96, the authcode will be the last 12 bytes in the packet + * For SHA256-128 or MD5-128, the authcode will be the last 16 bytes in the packet */ - bmc_authcode = rs->data + (rs->data_len - IPMI_SHA1_AUTHCODE_SIZE); + bmc_authcode = rs->data + (rs->data_len - authcode_length); lanplus_HMAC(session->v2_data.integrity_alg, session->v2_data.k1, - IPMI_AUTHCODE_BUFFER_SIZE, + session->v2_data.k1_len, rs->data + IPMI_LANPLUS_OFFSET_AUTHTYPE, - rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE, + rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - authcode_length, generated_authcode, &generated_authcode_length); if (verbose > 3) { lprintf(LOG_DEBUG+2, "Validating authcode"); - printbuf(session->v2_data.k1, 20, "K1"); + printbuf(session->v2_data.k1, session->v2_data.k1_len, "K1"); printbuf(rs->data + IPMI_LANPLUS_OFFSET_AUTHTYPE, - rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE, + rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - authcode_length, "Authcode Input Data"); - printbuf(generated_authcode, 12, "Generated authcode"); - printbuf(bmc_authcode, 12, "Expected authcode"); + printbuf(generated_authcode, generated_authcode_length, "Generated authcode"); + printbuf(bmc_authcode, authcode_length, "Expected authcode"); } - - assert(generated_authcode_length == 20); - return (memcmp(bmc_authcode, generated_authcode, 12) == 0); + assert(generated_authcode_length >= authcode_length); + return (memcmp(bmc_authcode, generated_authcode, authcode_length) == 0); } diff --git a/src/plugins/lanplus/lanplus_crypt_impl.c b/src/plugins/lanplus/lanplus_crypt_impl.c index cde6c54..d5fac37 100644 --- a/src/plugins/lanplus/lanplus_crypt_impl.c +++ b/src/plugins/lanplus/lanplus_crypt_impl.c @@ -99,7 +99,8 @@ lanplus_rand(uint8_t * buffer, uint32_t num_bytes) /* * lanplus_HMAC * - * param mac specifies the algorithm to be used, currently only SHA1 is supported + * param mac specifies the algorithm to be used, currently SHA1, SHA256 and MD5 + * are supported * param key is the key used for HMAC generation * param key_len is the lenght of key * param d is the data to be MAC'd @@ -123,6 +124,14 @@ lanplus_HMAC(uint8_t mac, if ((mac == IPMI_AUTH_RAKP_HMAC_SHA1) || (mac == IPMI_INTEGRITY_HMAC_SHA1_96)) evp_md = EVP_sha1(); + else if ((mac == IPMI_AUTH_RAKP_HMAC_MD5) || + (mac == IPMI_INTEGRITY_HMAC_MD5_128)) + evp_md = EVP_md5(); +#ifdef HAVE_CRYPTO_SHA256 + else if ((mac == IPMI_AUTH_RAKP_HMAC_SHA256) || + (mac == IPMI_INTEGRITY_HMAC_SHA256_128)) + evp_md = EVP_sha256(); +#endif /* HAVE_CRYPTO_SHA256 */ else { lprintf(LOG_DEBUG, "Invalid mac type 0x%x in lanplus_HMAC\n", mac); diff --git a/src/plugins/lanplus/lanplus_dump.c b/src/plugins/lanplus/lanplus_dump.c index 8d52fab..bbfc1b0 100644 --- a/src/plugins/lanplus/lanplus_dump.c +++ b/src/plugins/lanplus/lanplus_dump.c @@ -31,6 +31,7 @@ */ #include "lanplus.h" +#include "lanplus_crypt.h" #include "lanplus_dump.h" extern const struct valstr ipmi_rakp_return_codes[]; @@ -127,16 +128,27 @@ void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, uint8_t auth_alg) break; case IPMI_AUTH_RAKP_HMAC_SHA1: printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING); - for (i = 0; i < 20; ++i) + for (i = 0; i < IPMI_SHA_DIGEST_LENGTH; ++i) { printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]); - printf("\n"); + } + printf("\n"); break; case IPMI_AUTH_RAKP_HMAC_MD5: printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING); - for (i = 0; i < 16; ++i) + for (i = 0; i < IPMI_MD5_DIGEST_LENGTH; ++i) { printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]); - printf("\n"); + } + printf("\n"); break; +#ifdef HAVE_CRYPTO_SHA256 + case IPMI_AUTH_RAKP_HMAC_SHA256: + printf("%s Key exchange auth code [sha256]: 0x", DUMP_PREFIX_INCOMING); + for (i = 0; i < IPMI_SHA256_DIGEST_LENGTH; ++i) { + printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]); + } + printf("\n"); + break; +#endif /* HAVE_CRYPTO_SHA256 */ default: printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING); } @@ -174,16 +186,27 @@ void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, uint8_t auth_alg) break; case IPMI_AUTH_RAKP_HMAC_SHA1: printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING); - for (i = 0; i < 12; ++i) + for (i = 0; i < IPMI_SHA1_AUTHCODE_SIZE; ++i) { printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]); - printf("\n"); + } + printf("\n"); break; case IPMI_AUTH_RAKP_HMAC_MD5: printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING); - for (i = 0; i < 12; ++i) + for (i = 0; i < IPMI_HMAC_MD5_AUTHCODE_SIZE; ++i) { + printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]); + } + printf("\n"); + break; +#ifdef HAVE_CRYPTO_SHA256 + case IPMI_AUTH_RAKP_HMAC_SHA256: + printf("%s Key exchange auth code [sha256]: 0x", DUMP_PREFIX_INCOMING); + for (i = 0; i < IPMI_HMAC_SHA256_AUTHCODE_SIZE; ++i) { printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]); - printf("\n"); + } + printf("\n"); break; +#endif /* HAVE_CRYPTO_SHA256 */ default: printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING); } diff --git a/src/plugins/open/open.c b/src/plugins/open/open.c index df56172..5beeac7 100644 --- a/src/plugins/open/open.c +++ b/src/plugins/open/open.c @@ -29,7 +29,7 @@ * 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 _POSIX_C_SOURCE 1 #include <stdio.h> #include <fcntl.h> diff --git a/src/plugins/serial/serial_basic.c b/src/plugins/serial/serial_basic.c index e3322c1..21a239a 100644 --- a/src/plugins/serial/serial_basic.c +++ b/src/plugins/serial/serial_basic.c @@ -33,7 +33,9 @@ /* Serial Interface, Basic Mode plugin. */ +#if defined HAVE_ALLOCA_H #include <alloca.h> +#endif #include <stdio.h> #include <fcntl.h> #include <time.h> @@ -79,7 +81,7 @@ struct ipmb_msg_hdr { unsigned char rqSA; unsigned char rqSeq; /* RQ SEQ | RQ LUN */ unsigned char cmd; - unsigned char data[0]; + unsigned char data[]; }; /* @@ -101,7 +103,7 @@ struct ipmi_get_message_rp { unsigned char rsSA; unsigned char rqSeq; unsigned char cmd; - unsigned char data[0]; + unsigned char data[]; }; /* @@ -128,7 +130,7 @@ struct serial_bm_parse_ctx{ * Receiving context */ struct serial_bm_recv_ctx { - char buffer[SERIAL_BM_MAX_BUFFER_SIZE]; + uint8_t buffer[SERIAL_BM_MAX_BUFFER_SIZE]; size_t buffer_size; size_t max_buffer_size; }; diff --git a/src/plugins/serial/serial_terminal.c b/src/plugins/serial/serial_terminal.c index cd33422..4459f64 100644 --- a/src/plugins/serial/serial_terminal.c +++ b/src/plugins/serial/serial_terminal.c @@ -33,7 +33,9 @@ /* Serial Interface, Terminal Mode plugin. */ +#if defined HAVE_ALLOCA_H #include <alloca.h> +#endif #include <stdio.h> #include <fcntl.h> #include <unistd.h> @@ -77,7 +79,7 @@ struct ipmb_msg_hdr { unsigned char rqSA; unsigned char rqSeq; /* RQ SEQ | RQ LUN */ unsigned char cmd; - unsigned char data[0]; + unsigned char data[]; }; /* @@ -99,7 +101,7 @@ struct ipmi_get_message_rp { unsigned char rsSA; unsigned char rqSeq; unsigned char cmd; - unsigned char data[0]; + unsigned char data[]; }; /* @@ -371,8 +373,9 @@ recv_response(struct ipmi_intf * intf, unsigned char *data, int len) } p += rv; resp_len += rv; - if (*(p - 2) == ']' && (*(p - 1) == '\n' || *(p - 1) == '\r')) { - *p = 0; + if (resp_len >= 2 && *(p - 2) == ']' + && (*(p - 1) == '\n' || *(p - 1) == '\r')) { + *(p - 1) = 0; /* overwrite EOL */ break; } } |