Thomas Renninger
3e87539103
OBS-URL: https://build.opensuse.org/package/show/systemsmanagement/ipmitool?expand=0&rev=22
13829 lines
433 KiB
Diff
13829 lines
433 KiB
Diff
diff --git a/ipmitool/AUTHORS b/ipmitool/AUTHORS
|
|
index 80ec56b..9589d87 100644
|
|
--- a/ipmitool/AUTHORS
|
|
+++ b/ipmitool/AUTHORS
|
|
@@ -2,3 +2,4 @@ Duncan Laurie <duncan@iceblink.org>
|
|
Fredrik Öhrn <ohrn@chl.chalmers.se>
|
|
Jon Cassorla <jon.cassorla@newisys.com>
|
|
Jeremy Ellington <jeremy@jeremye.net>
|
|
+Petter Reinholdtsen <pere@hungry.com>
|
|
diff --git a/ipmitool/README b/ipmitool/README
|
|
index ebcb188..cc5915c 100644
|
|
--- a/ipmitool/README
|
|
+++ b/ipmitool/README
|
|
@@ -410,3 +410,5 @@ http://www.intel.com/design/servers/ipmi/spec.htm
|
|
OpenIPMI project: Linux IPMI kernel driver and userland library
|
|
http://openipmi.sourceforge.net
|
|
|
|
+IPMItool commit archive
|
|
+https://lists.sourceforge.net/lists/listinfo/ipmitool-cvs
|
|
diff --git a/ipmitool/configure.in b/ipmitool/configure.in
|
|
index d98d754..a42e158 100644
|
|
--- a/ipmitool/configure.in
|
|
+++ b/ipmitool/configure.in
|
|
@@ -29,7 +29,7 @@ AC_C_BIGENDIAN
|
|
AC_FUNC_MALLOC
|
|
AC_FUNC_SELECT_ARGTYPES
|
|
AC_FUNC_STRTOD
|
|
-AC_CHECK_FUNCS([alarm gethostbyname socket select])
|
|
+AC_CHECK_FUNCS([alarm gethostbyname getaddrinfo getifaddrs socket select])
|
|
AC_CHECK_FUNCS([memmove memset strchr strdup strerror])
|
|
AC_CHECK_FUNCS([getpassphrase])
|
|
|
|
@@ -39,6 +39,8 @@ AM_PROG_LIBTOOL
|
|
LIBTOOL="$LIBTOOL --silent"
|
|
|
|
AC_SEARCH_LIBS([gethostbyname], [nsl])
|
|
+AC_SEARCH_LIBS([getaddrinfo], [nsl])
|
|
+AC_SEARCH_LIBS([getifaddrs], [nsl])
|
|
AC_SEARCH_LIBS([socket], [socket], [],
|
|
[AC_CHECK_LIB([nsl], [socket],
|
|
[LIBS="$LIBS -lsocket -lnsl"], [], [-lsocket])])
|
|
@@ -60,6 +62,7 @@ xenable_intf_imb=yes
|
|
xenable_intf_open=yes
|
|
xenable_intf_lipmi=yes
|
|
#xenable_intf_serial=yes
|
|
+xenable_intf_dummy=no
|
|
xenable_all_options=yes
|
|
xenable_ipmishell=yes
|
|
|
|
@@ -106,6 +109,11 @@ solaris*)
|
|
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
|
|
+ ;;
|
|
esac
|
|
|
|
AC_SUBST(ARCH, $host_cpu)
|
|
@@ -503,6 +511,18 @@ if test "x$xenable_intf_bmc" = "xyes"; then
|
|
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB bmc/libintf_bmc.la"
|
|
fi
|
|
|
|
+dnl enable Dummy interface for testing
|
|
+AC_ARG_ENABLE([intf-dummy],
|
|
+ [AC_HELP_STRING([--enable-intf-dummy],
|
|
+ [enable Dummy(test) interface [default=no]])],
|
|
+ [xenable_intf_dummy=$enableval], [xenable_intf_dummy=no])
|
|
+if test "x$xenable_intf_dummy" = "xyes"; then
|
|
+ AC_DEFINE(IPMI_INTF_DUMMY, [1], [Define to 1 to enable Dummy interface.])
|
|
+ AC_SUBST(INTF_DUMMY, [dummy])
|
|
+ AC_SUBST(INTF_DUMMY_LIB, [libintf_dummy.la])
|
|
+ IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB dummy/libintf_dummy.la"
|
|
+fi
|
|
+
|
|
AC_SUBST(IPMITOOL_INTF_LIB)
|
|
|
|
if test "x$xenable_ipmishell" = "xyes"; then
|
|
@@ -602,7 +622,8 @@ AC_CONFIG_FILES([Makefile
|
|
src/plugins/imb/Makefile
|
|
src/plugins/bmc/Makefile
|
|
src/plugins/lipmi/Makefile
|
|
- src/plugins/serial/Makefile])
|
|
+ src/plugins/serial/Makefile
|
|
+ src/plugins/dummy/Makefile])
|
|
|
|
AC_OUTPUT
|
|
|
|
@@ -618,6 +639,7 @@ AC_MSG_RESULT([ imb : $xenable_intf_imb])
|
|
AC_MSG_RESULT([ bmc : $xenable_intf_bmc])
|
|
AC_MSG_RESULT([ lipmi : $xenable_intf_lipmi])
|
|
AC_MSG_RESULT([ serial : $xenable_intf_serial])
|
|
+AC_MSG_RESULT([ dummy : $xenable_intf_dummy])
|
|
AC_MSG_RESULT([])
|
|
AC_MSG_RESULT([Extra tools])
|
|
AC_MSG_RESULT([ ipmievd : yes])
|
|
diff --git a/ipmitool/contrib/Makefile.am b/ipmitool/contrib/Makefile.am
|
|
index a04f92f..c067dcb 100644
|
|
--- a/ipmitool/contrib/Makefile.am
|
|
+++ b/ipmitool/contrib/Makefile.am
|
|
@@ -34,6 +34,8 @@ dist_pkgdata_DATA = oem_ibm_sel_map
|
|
|
|
EXTRA_DIST = README \
|
|
bmclanconf ipmi.init.basic ipmi.init.redhat \
|
|
+ exchange-bmc-os-info.init.redhat exchange-bmc-os-info.service.redhat \
|
|
+ exchange-bmc-os-info.sysconf \
|
|
ipmievd.init.redhat ipmievd.init.suse ipmievd.init.debian \
|
|
collect_data.sh create_rrds.sh create_webpage_compact.sh create_webpage.sh \
|
|
bmc-snmp-proxy bmc-snmp-proxy.service bmc-snmp-proxy.sysconf
|
|
diff --git a/ipmitool/contrib/exchange-bmc-os-info.init.redhat b/ipmitool/contrib/exchange-bmc-os-info.init.redhat
|
|
new file mode 100644
|
|
index 0000000..b7ec43f
|
|
--- /dev/null
|
|
+++ b/ipmitool/contrib/exchange-bmc-os-info.init.redhat
|
|
@@ -0,0 +1,326 @@
|
|
+#!/bin/sh
|
|
+#############################################################################
|
|
+#
|
|
+# exchange-bmc-os-info: Set OS and BMC (Baseboard Management Controller)
|
|
+# parameters during system startup.
|
|
+#
|
|
+# version: 0.72
|
|
+#
|
|
+# Authors: Charles Rose <charles_rose@dell.com>
|
|
+# Jordan Hargrave <jordan_hargrave@dell.com>
|
|
+#
|
|
+# Description: Script to set OS information in the BMC; fetch BMC IP/URL
|
|
+# and set in the OS for use by other scripts/user.
|
|
+#
|
|
+# BMC IP and URL are made available in /var/run/bmc-info
|
|
+#
|
|
+# Example to launch BMC web-interface:
|
|
+# # . /var/run/bmc-info
|
|
+# # xdg-open $BMC_URL
|
|
+#
|
|
+# See here for details:
|
|
+# https://fedoraproject.org/wiki/Features/AgentFreeManagement
|
|
+#
|
|
+# OEM Specific: OEM specific ipmi commands go in:
|
|
+# 'oem_set_os_version' and 'oem_get_bmc_url'
|
|
+#############################################################################
|
|
+#
|
|
+# chkconfig: 345 99 00
|
|
+# description: Set OS name, hostname in BMC; make BMC IP/URL available in OS
|
|
+# processname: exchange-bmc-os-info
|
|
+# config: /etc/sysconfig/exchange-bmc-os-info
|
|
+#
|
|
+### BEGIN INIT INFO
|
|
+# Provides: exchange-bmc-os-info
|
|
+# Required-Start: ipmi
|
|
+# Default-Start: 3 4 5
|
|
+# Default-Stop: 0 1 2 6
|
|
+
|
|
+
|
|
+#############################################################################
|
|
+# GLOBALS
|
|
+#############################################################################
|
|
+CONFIGFILE=/etc/sysconfig/exchange-bmc-os-info
|
|
+IPMI_TOOL=/usr/bin/ipmitool
|
|
+BMC_INFO=/var/run/bmc-info
|
|
+
|
|
+# BMC Manufacturer ID used in 'oem_set_os_version' and 'oem_get_bmc_url'
|
|
+DELL="674"
|
|
+#OTHER_OEM="123"
|
|
+
|
|
+# Defaults for ${CONFIGFILE}
|
|
+SET_OS_INFO="yes"
|
|
+RESET_OS_INFO="no"
|
|
+SET_BMC_INFO="yes"
|
|
+
|
|
+# getsysinfo and setsysinfo commands
|
|
+IPMI_SET_SYSINFO="${IPMI_TOOL} mc setsysinfo"
|
|
+IPMI_GET_SYSINFO="${IPMI_TOOL} mc getsysinfo"
|
|
+#############################################################################
|
|
+SCRIPT_NAME=$(basename $0)
|
|
+
|
|
+# source config
|
|
+[ -r ${CONFIGFILE} ] && . ${CONFIGFILE}
|
|
+
|
|
+RETVAL=0
|
|
+
|
|
+if [ -f /bin/gettext.sh ]; then
|
|
+ GETTEXT=1
|
|
+ . /bin/gettext.sh
|
|
+ OUTPUT="eval_gettext"
|
|
+else
|
|
+ GETTEXT=0
|
|
+ OUTPUT="echo"
|
|
+fi
|
|
+
|
|
+#############################################################################
|
|
+# Get Vendor ID of BMC for use in 'oem_set_os_version' and 'oem_get_bmc_url'
|
|
+#
|
|
+get_bmc_vendor_id()
|
|
+{
|
|
+ BMC_VENDOR=$(${IPMI_TOOL} mc info 2>/dev/null | \
|
|
+ sed -n "s#^Manufacturer ID.*: ##p")
|
|
+ [ -z "${BMC_VENDOR}" ] && RETVAL=4
|
|
+}
|
|
+
|
|
+check_ipmitool()
|
|
+{
|
|
+ if [ -x ${IPMI_TOOL} ]; then
|
|
+ # v1.8.12 plus patches are required for set/getsysinfo support
|
|
+ # http://sourceforge.net/mailarchive/message.php?msg_id=29647222
|
|
+ [ ! ${IPMI_GET_SYSINFO} >/dev/null 2>&1 ] && \
|
|
+ RETVAL=3
|
|
+ else
|
|
+ RETVAL=2
|
|
+ fi
|
|
+}
|
|
+
|
|
+bmc_exists()
|
|
+{
|
|
+ check_ipmitool
|
|
+ [ $RETVAL -eq 0 ] && get_bmc_vendor_id
|
|
+ return $RETVAL
|
|
+}
|
|
+#############################################################################
|
|
+
|
|
+get_os_info()
|
|
+{
|
|
+ OS_HOSTNAME=$(hostname)
|
|
+ KERNEL_VERSION=$(uname -r -m)
|
|
+
|
|
+ if [ -e /etc/lsb-release ] ; then
|
|
+ . /etc/lsb-release
|
|
+ NAME=${DISTRIB_ID}
|
|
+ VERSION="${DISTRIB_RELEASE} ${DISTRIB_CODENAME}"
|
|
+ fi
|
|
+
|
|
+ # we prefer systemd's /etc/os-release over other sources
|
|
+ [ -e /etc/os-release ] && . /etc/os-release
|
|
+
|
|
+ OS_NAME=${NAME}
|
|
+ OS_VERSION="${VERSION} kernel ${KERNEL_VERSION}"
|
|
+}
|
|
+
|
|
+oem_set_os_version()
|
|
+{
|
|
+ # OS Version setting is not standard yet
|
|
+ # we need per vendor oem commands
|
|
+ case "${BMC_VENDOR}" in
|
|
+ $DELL) ${IPMI_SET_SYSINFO} delloem_os_version \
|
|
+ "${OS_VERSION}" > /dev/null 2>&1
|
|
+ return $?
|
|
+ ;;
|
|
+# Add OEM specific commands.
|
|
+# Example:
|
|
+# $OTHER_OEM) ${IPMI_SET_SYSINFO} otheroem_os_version \
|
|
+# "${OS_VERSION}" > /dev/null 2>&1
|
|
+# return $?
|
|
+# ;;
|
|
+ *) return 0
|
|
+ ;;
|
|
+ esac
|
|
+}
|
|
+
|
|
+set_os_info()
|
|
+{
|
|
+ # Set and reset OS info in the BMC
|
|
+ if [ "$1" = "reset" ]; then
|
|
+ OS_NAME=""
|
|
+ OS_HOSTNAME=""
|
|
+ OS_VERSION=""
|
|
+ fi
|
|
+
|
|
+ ${IPMI_SET_SYSINFO} os_name "${OS_NAME}" >/dev/null 2>&1 \
|
|
+ || RETVAL=6
|
|
+ ${IPMI_SET_SYSINFO} primary_os_name "${OS_NAME}" >/dev/null 2>&1 \
|
|
+ || RETVAL=6
|
|
+ ${IPMI_SET_SYSINFO} system_name "${OS_HOSTNAME}" >/dev/null 2>&1 \
|
|
+ || RETVAL=6
|
|
+ oem_set_os_version || RETVAL=6
|
|
+}
|
|
+
|
|
+#############################################################################
|
|
+valid_url()
|
|
+{
|
|
+ url="(https?|http)://[a-z0-9-]+(\.[a-z0-9-]+)+([/?].*)?"
|
|
+ printf -- "%s" "${TMP_URL}"| grep -Eq "^${url}"
|
|
+ return $?
|
|
+}
|
|
+
|
|
+oem_get_bmc_url()
|
|
+{
|
|
+ # BMC URL is not standard yet
|
|
+ # we need per vendor oem commands
|
|
+ case "$BMC_VENDOR" in
|
|
+ $DELL) TMP_URL=$(${IPMI_GET_SYSINFO} delloem_url 2> /dev/null)
|
|
+ ;;
|
|
+# Add OEM specific commands
|
|
+# Example:
|
|
+# $OTHER_OEM)
|
|
+# TMP_URL=$(${IPMI_GET_SYSINFO} otheroem_url 2> /dev/null)
|
|
+# ;;
|
|
+ *) TMP_URL="" ;;
|
|
+ esac
|
|
+
|
|
+ valid_url && BMC_URL=${TMP_URL} || BMC_URL=""
|
|
+}
|
|
+
|
|
+valid_ip()
|
|
+{
|
|
+ #Thanks to mkyong.com
|
|
+ octet="([01]?[[:digit:]][[:digit:]]?|2[0-4][[:digit:]]|25[0-5])"
|
|
+
|
|
+ printf -- "%s" "${TMP_IPv4}"| grep -Eq "^${octet}\\.${octet}\\.${octet}\\.${octet}$"
|
|
+ return $?
|
|
+}
|
|
+
|
|
+get_bmc_ip()
|
|
+{
|
|
+ #Thanks to http://ingvar.blog.redpill-linpro.com
|
|
+ for CHANNEL in `seq 1 14`
|
|
+ do
|
|
+ [ $(${IPMI_TOOL} lan print ${CHANNEL} 2>/dev/null \
|
|
+ | grep -q "^Set") ] || break
|
|
+ done
|
|
+
|
|
+ # Get BMC_IPv4 and BMC_URL from BMC
|
|
+ TMP_IPv4=$(${IPMI_TOOL} lan print ${CHANNEL} 2>/dev/null \
|
|
+ | sed -n "s#^IP Address .*: ##p")
|
|
+
|
|
+ valid_ip && BMC_IPv4=${TMP_IPv4} || BMC_IPv4=""
|
|
+}
|
|
+
|
|
+get_bmc_info()
|
|
+{
|
|
+ get_bmc_ip
|
|
+ if [ -z "${BMC_IPv4}" ] || [ "${BMC_IPv4}" = "0.0.0.0" ]; then
|
|
+ BMC_IPv4=""
|
|
+ RETVAL=5
|
|
+ else
|
|
+ # URL makes sense only if there is an IP
|
|
+ oem_get_bmc_url
|
|
+ fi
|
|
+}
|
|
+
|
|
+set_bmc_info()
|
|
+{
|
|
+ if [ ! $(touch "${BMC_INFO}" && chmod 600 "${BMC_INFO}") ]; then
|
|
+ printf "BMC_IPv4=%s\n" "${BMC_IPv4}" > "${BMC_INFO}"
|
|
+ [ -n "${BMC_URL}" ] && \
|
|
+ printf "BMC_URL=%s\n" "${BMC_URL}" >> "${BMC_INFO}"
|
|
+ else
|
|
+ RETVAL=5
|
|
+ fi
|
|
+}
|
|
+
|
|
+unset_bmc_info()
|
|
+{
|
|
+ [ -f ${BMC_INFO} ] && rm -f ${BMC_INFO} > /dev/null 2>&1
|
|
+}
|
|
+
|
|
+#############################################################################
|
|
+start()
|
|
+{
|
|
+ if bmc_exists; then
|
|
+ [ "${SET_OS_INFO}" = "yes" ] && \
|
|
+ get_os_info && set_os_info
|
|
+
|
|
+ if [ "${SET_BMC_INFO}" = "yes" ]; then
|
|
+ get_bmc_info
|
|
+ if [ ${RETVAL} -eq 0 ]; then
|
|
+ set_bmc_info
|
|
+ fi
|
|
+ fi
|
|
+ fi
|
|
+}
|
|
+
|
|
+#############################################################################
|
|
+stop()
|
|
+{
|
|
+ if bmc_exists; then
|
|
+ # reset OS info while system reboots
|
|
+ # aids with debugging OS boot-up issues
|
|
+ if [ "${RESET_OS_INFO}" = "yes" ]; then
|
|
+ set_os_info reset
|
|
+ fi
|
|
+ unset_bmc_info
|
|
+ fi
|
|
+}
|
|
+
|
|
+#############################################################################
|
|
+restart()
|
|
+{
|
|
+ stop
|
|
+ [ $RETVAL -eq 0 ] && start
|
|
+}
|
|
+
|
|
+#############################################################################
|
|
+status()
|
|
+{
|
|
+ [ -r ${BMC_INFO} ] && \
|
|
+ grep -q "BMC_IPv4" "${BMC_INFO}" >/dev/null 1>&2 && \
|
|
+ BMC_STATUS="ok" || BMC_STATUS="inactive"
|
|
+ ${OUTPUT} "${SCRIPT_NAME}: ${BMC_STATUS}" 1>&2
|
|
+ [ ${GETTEXT} -eq 1 ] && echo
|
|
+}
|
|
+
|
|
+#############################################################################
|
|
+usage()
|
|
+{
|
|
+ ${OUTPUT} "Usage: ${SCRIPT_NAME} {start|stop|restart|status}" 1>&2
|
|
+ [ ${GETTEXT} -eq 1 ] && echo
|
|
+ RETVAL=1
|
|
+}
|
|
+
|
|
+#############################################################################
|
|
+# MAIN
|
|
+#############################################################################
|
|
+case "$1" in
|
|
+ start) start ;;
|
|
+ stop) stop ;;
|
|
+ restart) restart ;;
|
|
+ status) status ;;
|
|
+ *) usage ;;
|
|
+esac
|
|
+
|
|
+case "$RETVAL" in
|
|
+ 0|1) ;;
|
|
+ 2) ${OUTPUT} "${SCRIPT_NAME}: ipmitool(1) not found." 1>&2 ;;
|
|
+ 3) ${OUTPUT} "${SCRIPT_NAME}: this version of ipmitool does not support getsysinfo." 1>&2 ;;
|
|
+ 4) ${OUTPUT} "${SCRIPT_NAME}: failed to communicate with BMC." 1>&2 ;;
|
|
+ 5) ${OUTPUT} "${SCRIPT_NAME}: failed to set OS information in BMC." 1>&2 ;;
|
|
+ 6) ${OUTPUT} "${SCRIPT_NAME}: failed to get BMC information." 1>&2 ;;
|
|
+ *) ${OUTPUT} "${SCRIPT_NAME}: unexpected error." 1>&2 ;;
|
|
+esac
|
|
+
|
|
+if [ ${RETVAL} -gt 1 ]; then
|
|
+ ${OUTPUT} " Return code: ${RETVAL}" 1>&2
|
|
+ [ ${GETTEXT} -eq 1 ] && echo
|
|
+fi
|
|
+
|
|
+
|
|
+exit ${RETVAL}
|
|
+
|
|
+#############################################################################
|
|
+# end of file
|
|
+#############################################################################
|
|
diff --git a/ipmitool/contrib/exchange-bmc-os-info.service.redhat b/ipmitool/contrib/exchange-bmc-os-info.service.redhat
|
|
new file mode 100644
|
|
index 0000000..100493b
|
|
--- /dev/null
|
|
+++ b/ipmitool/contrib/exchange-bmc-os-info.service.redhat
|
|
@@ -0,0 +1,13 @@
|
|
+[Unit]
|
|
+Description=Exchange Information between BMC and OS
|
|
+After=ipmi.service network.target
|
|
+Requires=ipmi.service
|
|
+
|
|
+[Service]
|
|
+Type=oneshot
|
|
+RemainAfterExit=yes
|
|
+ExecStart=/usr/libexec/exchange-bmc-os-info start
|
|
+ExecStop=/usr/libexec/exchange-bmc-os-info stop
|
|
+
|
|
+[Install]
|
|
+WantedBy=multi-user.target
|
|
diff --git a/ipmitool/contrib/exchange-bmc-os-info.sysconf b/ipmitool/contrib/exchange-bmc-os-info.sysconf
|
|
new file mode 100644
|
|
index 0000000..2f0e675
|
|
--- /dev/null
|
|
+++ b/ipmitool/contrib/exchange-bmc-os-info.sysconf
|
|
@@ -0,0 +1,26 @@
|
|
+# exchange-bmc-os-info
|
|
+#
|
|
+# Config file to control Exchange of information between
|
|
+# the OS and Service Processor/Baseboard Management Controller (BMC)
|
|
+#
|
|
+# See here for details
|
|
+# https://fedoraproject.org/wiki/Features/AgentFreeManagement
|
|
+
|
|
+### Set OS Info in BMC/Service Processor ###
|
|
+# Name: SET_OS_INFO
|
|
+# Description: Set OS Name, Version and Hostname in the Service Processor (BMC)
|
|
+# Default: yes
|
|
+SET_OS_INFO="yes"
|
|
+
|
|
+### Reset OS Info in BMC/Service Processor ###
|
|
+# Name: RESET_OS_INFO
|
|
+# Description: Reset OS Name, Version and Hostname in the Service Processor (BMC).
|
|
+# Useful when the OS Name/Hostname should be empty on reboot
|
|
+# Default: no
|
|
+RESET_OS_INFO="no"
|
|
+
|
|
+### Set BMC/Service Processor Info in OS ###
|
|
+# Name; SET_BMC_INFO
|
|
+# Description: Set IP Address and URL of Service Processor/BMC in /run/bmc-info
|
|
+# Default: yes
|
|
+SET_BMC_INFO="yes"
|
|
diff --git a/ipmitool/include/ipmitool/helper.h b/ipmitool/include/ipmitool/helper.h
|
|
index 4b80058..b6ee7fa 100644
|
|
--- a/ipmitool/include/ipmitool/helper.h
|
|
+++ b/ipmitool/include/ipmitool/helper.h
|
|
@@ -99,6 +99,7 @@ void printbuf(const uint8_t * buf, int len, const char * desc);
|
|
uint8_t ipmi_csum(uint8_t * d, int s);
|
|
FILE * ipmi_open_file(const char * file, int rw);
|
|
void ipmi_start_daemon(struct ipmi_intf *intf);
|
|
+uint16_t ipmi_get_oem_id(struct ipmi_intf *intf);
|
|
|
|
#define ipmi_open_file_read(file) ipmi_open_file(file, 0)
|
|
#define ipmi_open_file_write(file) ipmi_open_file(file, 1)
|
|
diff --git a/ipmitool/include/ipmitool/ipmi.h b/ipmitool/include/ipmitool/ipmi.h
|
|
index e74c252..1fd3e2a 100644
|
|
--- a/ipmitool/include/ipmitool/ipmi.h
|
|
+++ b/ipmitool/include/ipmitool/ipmi.h
|
|
@@ -281,7 +281,8 @@ typedef enum IPMI_OEM {
|
|
IPMI_OEM_KONTRON = 15000,
|
|
IPMI_OEM_PPS = 16394,
|
|
IPMI_OEM_AMI = 20974,
|
|
- IPMI_OEM_NOKIA_SIEMENS_NETWORKS = 28458
|
|
+ IPMI_OEM_NOKIA_SIEMENS_NETWORKS = 28458,
|
|
+ IPMI_OEM_SUPERMICRO_47488 = 47488
|
|
} IPMI_OEM;
|
|
|
|
extern const struct valstr completion_code_vals[];
|
|
diff --git a/ipmitool/include/ipmitool/ipmi_fru.h b/ipmitool/include/ipmitool/ipmi_fru.h
|
|
index 6833dd4..4d255a8 100644
|
|
--- a/ipmitool/include/ipmitool/ipmi_fru.h
|
|
+++ b/ipmitool/include/ipmitool/ipmi_fru.h
|
|
@@ -63,6 +63,8 @@ enum {
|
|
struct fru_info {
|
|
uint16_t size;
|
|
uint8_t access:1;
|
|
+ uint8_t max_read_size;
|
|
+ uint8_t max_write_size;
|
|
};
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
@@ -70,13 +72,16 @@ struct fru_info {
|
|
#endif
|
|
struct fru_header {
|
|
uint8_t version;
|
|
- struct {
|
|
- uint8_t internal;
|
|
- uint8_t chassis;
|
|
- uint8_t board;
|
|
- uint8_t product;
|
|
- uint8_t multi;
|
|
- } offset;
|
|
+ union {
|
|
+ struct {
|
|
+ uint8_t internal;
|
|
+ uint8_t chassis;
|
|
+ uint8_t board;
|
|
+ uint8_t product;
|
|
+ uint8_t multi;
|
|
+ } offset;
|
|
+ uint8_t offsets[5];
|
|
+ };
|
|
uint8_t pad;
|
|
uint8_t checksum;
|
|
}ATTRIBUTE_PACKING;
|
|
@@ -598,6 +603,20 @@ static const char * chassis_type_desc[] __attribute__((unused)) = {
|
|
"AdvancedTCA", "Blade", "Blade Enclosure"
|
|
};
|
|
|
|
+typedef struct ipmi_fru_bloc {
|
|
+ struct ipmi_fru_bloc * next;
|
|
+ uint16_t start;
|
|
+ uint16_t size;
|
|
+ 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/ipmitool/include/ipmitool/ipmi_fwum.h b/ipmitool/include/ipmitool/ipmi_fwum.h
|
|
index 712428f..c19a582 100644
|
|
--- a/ipmitool/include/ipmitool/ipmi_fwum.h
|
|
+++ b/ipmitool/include/ipmitool/ipmi_fwum.h
|
|
@@ -31,12 +31,213 @@
|
|
*/
|
|
|
|
#ifndef IPMI_KFWUM_H
|
|
-#define IPMI_KFWUM_H
|
|
+# define IPMI_KFWUM_H
|
|
|
|
#include <inttypes.h>
|
|
#include <ipmitool/ipmi.h>
|
|
|
|
+/* KFWUM Version */
|
|
+# define VER_MAJOR 1
|
|
+# define VER_MINOR 3
|
|
+/* Minimum size (IPMB/IOL/old protocol) */
|
|
+# define KFWUM_SMALL_BUFFER 32
|
|
+/* Maximum size on KCS interface */
|
|
+# define KFWUM_BIG_BUFFER 32
|
|
+# define MAX_BUFFER_SIZE 1024*16
|
|
+
|
|
+/* 3 address + 1 size + 1 checksum + 1 command */
|
|
+# define KFWUM_OLD_CMD_OVERHEAD 6
|
|
+/* 1 sequence + 1 size + 1 checksum + 1 command */
|
|
+# define KFWUM_NEW_CMD_OVERHEAD 4
|
|
+# define KFWUM_PAGE_SIZE 256
|
|
+
|
|
+# define FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT 6
|
|
+# define FWUM_MAX_UPLOAD_RETRY 6
|
|
+
|
|
+# define TRACE_LOG_CHUNK_COUNT 7
|
|
+# define TRACE_LOG_CHUNK_SIZE 7
|
|
+# define TRACE_LOG_ATT_COUNT 3
|
|
+
|
|
+# define IN_FIRMWARE_INFO_OFFSET_LOCATION 0x5a0
|
|
+# define IN_FIRMWARE_INFO_SIZE 20
|
|
+# define IN_FIRMWARE_INFO_OFFSET_FILE_SIZE 0
|
|
+# define IN_FIRMWARE_INFO_OFFSET_CHECKSUM 4
|
|
+# define IN_FIRMWARE_INFO_OFFSET_BOARD_ID 6
|
|
+# define IN_FIRMWARE_INFO_OFFSET_DEVICE_ID 8
|
|
+# define IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION 9
|
|
+# define IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV 10
|
|
+# define IN_FIRMWARE_INFO_OFFSET_VER_MAJOROR 11
|
|
+# define IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB 12
|
|
+# define IN_FIRMWARE_INFO_OFFSET_SDR_REV 13
|
|
+# define IN_FIRMWARE_INFO_OFFSET_IANA0 14
|
|
+# define IN_FIRMWARE_INFO_OFFSET_IANA1 15
|
|
+# define IN_FIRMWARE_INFO_OFFSET_IANA2 16
|
|
+
|
|
+# define KWUM_GET_BYTE_AT_OFFSET(pBuffer,os) pBuffer[os]
|
|
|
|
int ipmi_fwum_main(struct ipmi_intf *, int, char **);
|
|
|
|
+typedef enum eKFWUM_BoardList
|
|
+{
|
|
+ KFWUM_BOARD_KONTRON_UNKNOWN = 0,
|
|
+ KFWUM_BOARD_KONTRON_5002 = 5002,
|
|
+} tKFWUM_BoardList;
|
|
+
|
|
+typedef struct sKFWUM_BoardInfo
|
|
+{
|
|
+ tKFWUM_BoardList boardId;
|
|
+ IPMI_OEM iana;
|
|
+} tKFWUM_BoardInfo;
|
|
+
|
|
+typedef enum eKFWUM_DownloadType
|
|
+{
|
|
+ KFWUM_DOWNLOAD_TYPE_ADDRESS = 0,
|
|
+ KFWUM_DOWNLOAD_TYPE_SEQUENCE,
|
|
+} tKFWUM_DownloadType;
|
|
+
|
|
+typedef enum eKFWUM_DownloadBuffferType
|
|
+{
|
|
+ KFWUM_SMALL_BUFFER_TYPE = 0,
|
|
+ KFUMW_BIG_BUFFER_TYPE
|
|
+} tKFWUM_DownloadBuffferType;
|
|
+
|
|
+typedef struct sKFWUM_InFirmwareInfo
|
|
+{
|
|
+ unsigned long fileSize;
|
|
+ unsigned short checksum;
|
|
+ unsigned short sumToRemoveFromChecksum;
|
|
+ /* Since the checksum is added in the bin
|
|
+ * after the checksum is calculated, we
|
|
+ * need to remove the each byte value. This
|
|
+ * byte will contain the addition of both bytes
|
|
+ */
|
|
+ tKFWUM_BoardList boardId;
|
|
+ unsigned char deviceId;
|
|
+ unsigned char tableVers;
|
|
+ unsigned char implRev;
|
|
+ unsigned char versMajor;
|
|
+ unsigned char versMinor;
|
|
+ unsigned char versSubMinor;
|
|
+ unsigned char sdrRev;
|
|
+ IPMI_OEM iana;
|
|
+} tKFWUM_InFirmwareInfo;
|
|
+
|
|
+typedef struct sKFWUM_SaveFirmwareInfo
|
|
+{
|
|
+ tKFWUM_DownloadType downloadType;
|
|
+ unsigned char bufferSize;
|
|
+ unsigned char overheadSize;
|
|
+} tKFWUM_SaveFirmwareInfo;
|
|
+
|
|
+/* COMMANDS */
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+# endif
|
|
+struct KfwumGetInfoResp {
|
|
+ unsigned char protocolRevision;
|
|
+ unsigned char controllerDeviceId;
|
|
+ struct {
|
|
+ unsigned char mode:1;
|
|
+ unsigned char seqAdd:1;
|
|
+ unsigned char res : 6;
|
|
+ } byte;
|
|
+ unsigned char firmRev1;
|
|
+ unsigned char firmRev2;
|
|
+ unsigned char numBank;
|
|
+} ATTRIBUTE_PACKING;
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+# endif
|
|
+
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+# endif
|
|
+struct KfwumGetStatusResp {
|
|
+ unsigned char bankState;
|
|
+ unsigned char firmLengthLSB;
|
|
+ unsigned char firmLengthMid;
|
|
+ unsigned char firmLengthMSB;
|
|
+ unsigned char firmRev1;
|
|
+ unsigned char firmRev2;
|
|
+ unsigned char firmRev3;
|
|
+} ATTRIBUTE_PACKING;
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+# endif
|
|
+
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+# endif
|
|
+struct KfwumManualRollbackReq {
|
|
+ unsigned char type;
|
|
+} ATTRIBUTE_PACKING;
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+# endif
|
|
+
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+# endif
|
|
+struct KfwumStartFirmwareDownloadReq {
|
|
+ unsigned char lengthLSB;
|
|
+ unsigned char lengthMid;
|
|
+ unsigned char lengthMSB;
|
|
+ unsigned char paddingLSB;
|
|
+ unsigned char paddingMSB;
|
|
+ unsigned char useSequence;
|
|
+} ATTRIBUTE_PACKING;
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+# endif
|
|
+
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+# endif
|
|
+struct KfwumStartFirmwareDownloadResp {
|
|
+ unsigned char bank;
|
|
+} ATTRIBUTE_PACKING;
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+# endif
|
|
+
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+# endif
|
|
+struct KfwumSaveFirmwareAddressReq
|
|
+{
|
|
+ unsigned char addressLSB;
|
|
+ unsigned char addressMid;
|
|
+ unsigned char addressMSB;
|
|
+ unsigned char numBytes;
|
|
+ unsigned char txBuf[KFWUM_SMALL_BUFFER-KFWUM_OLD_CMD_OVERHEAD];
|
|
+} ATTRIBUTE_PACKING;
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+# endif
|
|
+
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+# endif
|
|
+struct KfwumSaveFirmwareSequenceReq
|
|
+{
|
|
+ unsigned char sequenceNumber;
|
|
+ unsigned char txBuf[KFWUM_BIG_BUFFER];
|
|
+} ATTRIBUTE_PACKING;
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+# endif
|
|
+
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+# endif
|
|
+struct KfwumFinishFirmwareDownloadReq {
|
|
+ unsigned char versionMaj;
|
|
+ unsigned char versionMinSub;
|
|
+ unsigned char versionSdr;
|
|
+ unsigned char reserved;
|
|
+} ATTRIBUTE_PACKING;
|
|
+# ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+# endif
|
|
+
|
|
#endif /* IPMI_KFWUM_H */
|
|
diff --git a/ipmitool/include/ipmitool/ipmi_hpmfwupg.h b/ipmitool/include/ipmitool/ipmi_hpmfwupg.h
|
|
index c464ad4..305091e 100644
|
|
--- a/ipmitool/include/ipmitool/ipmi_hpmfwupg.h
|
|
+++ b/ipmitool/include/ipmitool/ipmi_hpmfwupg.h
|
|
@@ -38,4 +38,771 @@
|
|
|
|
int ipmi_hpmfwupg_main(struct ipmi_intf *, int, char **);
|
|
|
|
+/* Agent version */
|
|
+#define HPMFWUPG_VERSION_MAJOR 1
|
|
+#define HPMFWUPG_VERSION_MINOR 0
|
|
+#define HPMFWUPG_VERSION_SUBMINOR 9
|
|
+
|
|
+/* HPM.1 FIRMWARE UPGRADE COMMANDS (part of PICMG) */
|
|
+#define HPMFWUPG_GET_TARGET_UPG_CAPABILITIES 0x2E
|
|
+#define HPMFWUPG_GET_COMPONENT_PROPERTIES 0x2F
|
|
+#define HPMFWUPG_ABORT_UPGRADE 0x30
|
|
+#define HPMFWUPG_INITIATE_UPGRADE_ACTION 0x31
|
|
+#define HPMFWUPG_UPLOAD_FIRMWARE_BLOCK 0x32
|
|
+#define HPMFWUPG_FINISH_FIRMWARE_UPLOAD 0x33
|
|
+#define HPMFWUPG_GET_UPGRADE_STATUS 0x34
|
|
+#define HPMFWUPG_ACTIVATE_FIRMWARE 0x35
|
|
+#define HPMFWUPG_QUERY_SELFTEST_RESULT 0x36
|
|
+#define HPMFWUPG_QUERY_ROLLBACK_STATUS 0x37
|
|
+#define HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK 0x38
|
|
+
|
|
+/* HPM.1 SPECIFIC COMPLETION CODES */
|
|
+#define HPMFWUPG_ROLLBACK_COMPLETED 0x00
|
|
+#define HPMFWUPG_COMMAND_IN_PROGRESS 0x80
|
|
+#define HPMFWUPG_NOT_SUPPORTED 0x81
|
|
+#define HPMFWUPG_SIZE_MISMATCH 0x81
|
|
+#define HPMFWUPG_ROLLBACK_FAILURE 0x81
|
|
+#define HPMFWUPG_INV_COMP_MASK 0x81
|
|
+#define HPMFWUPG__ABORT_FAILURE 0x81
|
|
+#define HPMFWUPG_INV_COMP_ID 0x82
|
|
+#define HPMFWUPG_INT_CHECKSUM_ERROR 0x82
|
|
+#define HPMFWUPG_INV_UPLOAD_MODE 0x82
|
|
+#define HPMFWUPG_ROLLBACK_OVERRIDE 0x82
|
|
+#define HPMFWUPG_INV_COMP_PROP 0x83
|
|
+#define HPMFWUPG_FW_MISMATCH 0x83
|
|
+#define HPMFWUPG_ROLLBACK_DENIED 0x83
|
|
+
|
|
+/*
|
|
+ * This error code is used as a temporary PATCH to
|
|
+ * the latest Open ipmi driver. This PATCH
|
|
+ * will be removed once a new Open IPMI driver is released.
|
|
+ * (Buggy version = 39)
|
|
+ */
|
|
+#define ENABLE_OPENIPMI_V39_PATCH
|
|
+
|
|
+#ifdef ENABLE_OPENIPMI_V39_PATCH
|
|
+# define RETRY_COUNT_MAX 3
|
|
+static int errorCount;
|
|
+# define HPMFWUPG_IS_RETRYABLE(error) \
|
|
+ ((((error==0x83)||(error==0x82)||(error==0x80)) && (errorCount++<RETRY_COUNT_MAX))?TRUE:FALSE)
|
|
+#else
|
|
+# define HPMFWUPG_IS_RETRYABLE(error) FALSE
|
|
+#endif
|
|
+
|
|
+/* HPM FIRMWARE UPGRADE GENERAL DEFINITIONS */
|
|
+#define HPMFWUPG_PICMG_IDENTIFIER 0
|
|
+#define HPMFWUPG_VERSION_SIZE 6
|
|
+#define HPMFWUPG_DESC_STRING_LENGTH 12
|
|
+#define HPMFWUPG_DEFAULT_INACCESS_TIMEOUT 60 /* sec */
|
|
+#define HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT 60 /* sec */
|
|
+#define HPMFWUPG_MD5_SIGNATURE_LENGTH 16
|
|
+
|
|
+/* Component IDs */
|
|
+typedef enum eHpmfwupgComponentId {
|
|
+ HPMFWUPG_COMPONENT_ID_0 = 0,
|
|
+ HPMFWUPG_COMPONENT_ID_1,
|
|
+ HPMFWUPG_COMPONENT_ID_2,
|
|
+ HPMFWUPG_COMPONENT_ID_3,
|
|
+ HPMFWUPG_COMPONENT_ID_4,
|
|
+ HPMFWUPG_COMPONENT_ID_5,
|
|
+ HPMFWUPG_COMPONENT_ID_6,
|
|
+ HPMFWUPG_COMPONENT_ID_7,
|
|
+ HPMFWUPG_COMPONENT_ID_MAX
|
|
+} tHpmfwupgComponentId;
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgComponentBitMask {
|
|
+ union {
|
|
+ unsigned char byte;
|
|
+ struct {
|
|
+#ifdef WORDS_BIGENDIAN
|
|
+ unsigned char component7 : 1;
|
|
+ unsigned char component6 : 1;
|
|
+ unsigned char component5 : 1;
|
|
+ unsigned char component4 : 1;
|
|
+ unsigned char component3 : 1;
|
|
+ unsigned char component2 : 1;
|
|
+ unsigned char component1 : 1;
|
|
+ unsigned char component0 : 1;
|
|
+#else
|
|
+ unsigned char component0 : 1;
|
|
+ unsigned char component1 : 1;
|
|
+ unsigned char component2 : 1;
|
|
+ unsigned char component3 : 1;
|
|
+ unsigned char component4 : 1;
|
|
+ unsigned char component5 : 1;
|
|
+ unsigned char component6 : 1;
|
|
+ unsigned char component7 : 1;
|
|
+#endif
|
|
+ } ATTRIBUTE_PACKING bitField;
|
|
+ } ATTRIBUTE_PACKING ComponentBits;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+
|
|
+static const int HPMFWUPG_SUCCESS = 0;
|
|
+static const int HPMFWUPG_ERROR = -1;
|
|
+/* Upload firmware specific error codes */
|
|
+static const int HPMFWUPG_UPLOAD_BLOCK_LENGTH = 1;
|
|
+static const int HPMFWUPG_UPLOAD_RETRY = 2;
|
|
+
|
|
+
|
|
+/* TARGET UPGRADE CAPABILITIES DEFINITIONS */
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetTargetUpgCapabilitiesReq {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetTargetUpgCapabilitiesResp {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char hpmVersion;
|
|
+ union {
|
|
+ unsigned char byte;
|
|
+ struct {
|
|
+#if WORDS_BIGENDIAN
|
|
+ unsigned char fwUpgUndesirable : 1;
|
|
+ unsigned char autRollbackOverride : 1;
|
|
+ unsigned char ipmcDegradedDurinUpg: 1;
|
|
+ unsigned char deferActivation : 1;
|
|
+ unsigned char servAffectDuringUpg : 1;
|
|
+ unsigned char manualRollback : 1;
|
|
+ unsigned char autRollback : 1;
|
|
+ unsigned char ipmcSelftestCap : 1;
|
|
+#else
|
|
+ unsigned char ipmcSelftestCap : 1;
|
|
+ unsigned char autRollback : 1;
|
|
+ unsigned char manualRollback : 1;
|
|
+ unsigned char servAffectDuringUpg : 1;
|
|
+ unsigned char deferActivation : 1;
|
|
+ unsigned char ipmcDegradedDurinUpg: 1;
|
|
+ unsigned char autRollbackOverride : 1;
|
|
+ unsigned char fwUpgUndesirable : 1;
|
|
+#endif
|
|
+ } ATTRIBUTE_PACKING bitField;
|
|
+ } ATTRIBUTE_PACKING GlobalCapabilities;
|
|
+ unsigned char upgradeTimeout;
|
|
+ unsigned char selftestTimeout;
|
|
+ unsigned char rollbackTimeout;
|
|
+ unsigned char inaccessTimeout;
|
|
+ struct HpmfwupgComponentBitMask componentsPresent;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetTargetUpgCapabilitiesCtx {
|
|
+ struct HpmfwupgGetTargetUpgCapabilitiesReq req;
|
|
+ struct HpmfwupgGetTargetUpgCapabilitiesResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* COMPONENT PROPERTIES DEFINITIONS */
|
|
+typedef enum eHpmfwupgCompPropertiesSelect {
|
|
+ HPMFWUPG_COMP_GEN_PROPERTIES = 0,
|
|
+ HPMFWUPG_COMP_CURRENT_VERSION,
|
|
+ HPMFWUPG_COMP_DESCRIPTION_STRING,
|
|
+ HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION,
|
|
+ HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION,
|
|
+ HPMFWUPG_COMP_RESERVED,
|
|
+ HPMFWUPG_COMP_OEM_PROPERTIES = 192
|
|
+} tHpmfwupgCompPropertiesSelect;
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetComponentPropertiesReq {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char componentId;
|
|
+ unsigned char selector;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetGeneralPropResp {
|
|
+ unsigned char picmgId;
|
|
+ union {
|
|
+ unsigned char byte;
|
|
+ struct {
|
|
+#if WORDS_BIGENDIAN
|
|
+ unsigned char reserved : 2;
|
|
+ unsigned char payloadColdReset : 1;
|
|
+ unsigned char deferredActivation : 1;
|
|
+ unsigned char comparisonSupport : 1;
|
|
+ unsigned char preparationSupport : 1;
|
|
+ unsigned char rollbackBackup : 2;
|
|
+#else
|
|
+ unsigned char rollbackBackup : 2;
|
|
+ unsigned char preparationSupport : 1;
|
|
+ unsigned char comparisonSupport : 1;
|
|
+ unsigned char deferredActivation : 1;
|
|
+ unsigned char payloadColdReset : 1;
|
|
+ unsigned char reserved : 2;
|
|
+#endif
|
|
+ } ATTRIBUTE_PACKING bitfield;
|
|
+ } ATTRIBUTE_PACKING GeneralCompProperties;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetCurrentVersionResp {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char currentVersion[HPMFWUPG_VERSION_SIZE];
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetDescStringResp {
|
|
+ unsigned char picmgId;
|
|
+ char descString[HPMFWUPG_DESC_STRING_LENGTH];
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetRollbackFwVersionResp {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char rollbackFwVersion[HPMFWUPG_VERSION_SIZE];
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetDeferredFwVersionResp {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char deferredFwVersion[HPMFWUPG_VERSION_SIZE];
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* GetComponentProperties - OEM properties (192) */
|
|
+#define HPMFWUPG_OEM_LENGTH 4
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetOemProperties {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char oemRspData[HPMFWUPG_OEM_LENGTH];
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetComponentPropertiesResp {
|
|
+ union {
|
|
+ struct HpmfwupgGetGeneralPropResp generalPropResp;
|
|
+ struct HpmfwupgGetCurrentVersionResp currentVersionResp;
|
|
+ struct HpmfwupgGetDescStringResp descStringResp;
|
|
+ struct HpmfwupgGetRollbackFwVersionResp rollbackFwVersionResp;
|
|
+ struct HpmfwupgGetDeferredFwVersionResp deferredFwVersionResp;
|
|
+ struct HpmfwupgGetOemProperties oemProperties;
|
|
+ } ATTRIBUTE_PACKING Response;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetComponentPropertiesCtx {
|
|
+ struct HpmfwupgGetComponentPropertiesReq req;
|
|
+ struct HpmfwupgGetComponentPropertiesResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* ABORT UPGRADE DEFINITIONS */
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgAbortUpgradeReq {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgAbortUpgradeResp {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgAbortUpgradeCtx {
|
|
+ struct HpmfwupgAbortUpgradeReq req;
|
|
+ struct HpmfwupgAbortUpgradeResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* UPGRADE ACTIONS DEFINITIONS */
|
|
+typedef enum eHpmfwupgUpgradeAction {
|
|
+ HPMFWUPG_UPGRADE_ACTION_BACKUP = 0,
|
|
+ HPMFWUPG_UPGRADE_ACTION_PREPARE,
|
|
+ HPMFWUPG_UPGRADE_ACTION_UPGRADE,
|
|
+ HPMFWUPG_UPGRADE_ACTION_COMPARE,
|
|
+ HPMFWUPG_UPGRADE_ACTION_INVALID = 0xff
|
|
+} tHpmfwupgUpgradeAction;
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgInitiateUpgradeActionReq {
|
|
+ unsigned char picmgId;
|
|
+ struct HpmfwupgComponentBitMask componentsMask;
|
|
+ unsigned char upgradeAction;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgInitiateUpgradeActionResp {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgInitiateUpgradeActionCtx {
|
|
+ struct HpmfwupgInitiateUpgradeActionReq req;
|
|
+ struct HpmfwupgInitiateUpgradeActionResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* UPLOAD FIRMWARE BLOCK DEFINITIONS */
|
|
+#define HPMFWUPG_SEND_DATA_COUNT_KCS 30
|
|
+#define HPMFWUPG_SEND_DATA_COUNT_LAN 25
|
|
+#define HPMFWUPG_SEND_DATA_COUNT_IPMB 26
|
|
+#define HPMFWUPG_SEND_DATA_COUNT_IPMBL 26
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgUploadFirmwareBlockReq {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char blockNumber;
|
|
+ unsigned char data[0];
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgUploadFirmwareBlockResp {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgUploadFirmwareBlockCtx {
|
|
+ struct HpmfwupgUploadFirmwareBlockReq * req;
|
|
+ struct HpmfwupgUploadFirmwareBlockResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* FINISH FIRMWARE UPLOAD DEFINITIONS */
|
|
+#define HPMFWUPG_IMAGE_SIZE_BYTE_COUNT 4
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgFinishFirmwareUploadReq {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char componentId;
|
|
+ unsigned char imageLength[HPMFWUPG_IMAGE_SIZE_BYTE_COUNT];
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgFinishFirmwareUploadResp {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgFinishFirmwareUploadCtx {
|
|
+ struct HpmfwupgFinishFirmwareUploadReq req;
|
|
+ struct HpmfwupgFinishFirmwareUploadResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* ACTIVATE FW DEFINITIONS */
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgActivateFirmwareReq {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char rollback_override;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgActivateFirmwareResp {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgActivateFirmwareCtx {
|
|
+ struct HpmfwupgActivateFirmwareReq req;
|
|
+ struct HpmfwupgActivateFirmwareResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* GET UPGRADE STATUS DEFINITIONS */
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetUpgradeStatusReq {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetUpgradeStatusResp {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char cmdInProcess;
|
|
+ unsigned char lastCmdCompCode;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgGetUpgradeStatusCtx {
|
|
+ struct HpmfwupgGetUpgradeStatusReq req;
|
|
+ struct HpmfwupgGetUpgradeStatusResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* MANUAL FW ROLLBACK DEFINITIONS */
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgManualFirmwareRollbackReq {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgManualFirmwareRollbackResp {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+struct HpmfwupgManualFirmwareRollbackCtx {
|
|
+ struct HpmfwupgManualFirmwareRollbackReq req;
|
|
+ struct HpmfwupgManualFirmwareRollbackResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* QUERY ROLLBACK STATUS DEFINITIONS */
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgQueryRollbackStatusReq {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgQueryRollbackStatusResp {
|
|
+ unsigned char picmgId;
|
|
+ struct HpmfwupgComponentBitMask rollbackComp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgQueryRollbackStatusCtx {
|
|
+ struct HpmfwupgQueryRollbackStatusReq req;
|
|
+ struct HpmfwupgQueryRollbackStatusResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* QUERY SELF TEST RESULT DEFINITIONS */
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgQuerySelftestResultReq {
|
|
+ unsigned char picmgId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgQuerySelftestResultResp {
|
|
+ unsigned char picmgId;
|
|
+ unsigned char result1;
|
|
+ unsigned char result2;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgQuerySelftestResultCtx {
|
|
+ struct HpmfwupgQuerySelftestResultReq req;
|
|
+ struct HpmfwupgQuerySelftestResultResp resp;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+/* HPM.1 IMAGE DEFINITIONS */
|
|
+#define HPMFWUPG_HEADER_SIGNATURE_LENGTH 8
|
|
+#define HPMFWUPG_MANUFATURER_ID_LENGTH 3
|
|
+#define HPMFWUPG_PRODUCT_ID_LENGTH 2
|
|
+#define HPMFWUPG_TIME_LENGTH 4
|
|
+#define HPMFWUPG_TIMEOUT_LENGTH 1
|
|
+#define HPMFWUPG_COMP_REVISION_LENGTH 2
|
|
+#define HPMFWUPG_FIRM_REVISION_LENGTH 6
|
|
+#define HPMFWUPG_IMAGE_HEADER_VERSION 0
|
|
+#define HPMFWUPG_IMAGE_SIGNATURE "PICMGFWU"
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+#pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgImageHeader {
|
|
+ char signature[HPMFWUPG_HEADER_SIGNATURE_LENGTH];
|
|
+ unsigned char formatVersion;
|
|
+ unsigned char deviceId;
|
|
+ unsigned char manId[HPMFWUPG_MANUFATURER_ID_LENGTH];
|
|
+ unsigned char prodId[HPMFWUPG_PRODUCT_ID_LENGTH];
|
|
+ unsigned char time[HPMFWUPG_TIME_LENGTH];
|
|
+ union {
|
|
+ struct {
|
|
+#if WORDS_BIGENDIAN
|
|
+ unsigned char imageSelfTest : 1;
|
|
+ unsigned char autRollback : 1;
|
|
+ unsigned char manRollback : 1;
|
|
+ unsigned char servAffected : 1;
|
|
+ unsigned char reserved : 4;
|
|
+#else
|
|
+ unsigned char reserved : 4;
|
|
+ unsigned char servAffected : 1;
|
|
+ unsigned char manRollback : 1;
|
|
+ unsigned char autRollback : 1;
|
|
+ unsigned char imageSelfTest : 1;
|
|
+#endif
|
|
+ } ATTRIBUTE_PACKING bitField;
|
|
+ unsigned char byte;
|
|
+ }ATTRIBUTE_PACKING imageCapabilities;
|
|
+ struct HpmfwupgComponentBitMask components;
|
|
+ unsigned char selfTestTimeout;
|
|
+ unsigned char rollbackTimeout;
|
|
+ unsigned char inaccessTimeout;
|
|
+ unsigned char compRevision[HPMFWUPG_COMP_REVISION_LENGTH];
|
|
+ unsigned char firmRevision[HPMFWUPG_FIRM_REVISION_LENGTH];
|
|
+ unsigned short oemDataLength;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#define HPMFWUPG_DESCRIPTION_LENGTH 21
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgActionRecord {
|
|
+ unsigned char actionType;
|
|
+ struct HpmfwupgComponentBitMask components;
|
|
+ unsigned char checksum;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#define HPMFWUPG_FIRMWARE_SIZE_LENGTH 4
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgFirmwareImage {
|
|
+ unsigned char version[HPMFWUPG_FIRM_REVISION_LENGTH];
|
|
+ char desc[HPMFWUPG_DESCRIPTION_LENGTH];
|
|
+ unsigned char length[HPMFWUPG_FIRMWARE_SIZE_LENGTH];
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(1)
|
|
+#endif
|
|
+struct HpmfwupgUpgradeCtx {
|
|
+ struct HpmfwupgComponentBitMask compUpdateMask;
|
|
+ unsigned int imageSize;
|
|
+ unsigned char* pImageData;
|
|
+ unsigned char componentId;
|
|
+ struct HpmfwupgGetTargetUpgCapabilitiesResp targetCap;
|
|
+ struct HpmfwupgGetGeneralPropResp genCompProp[HPMFWUPG_COMPONENT_ID_MAX];
|
|
+ struct ipm_devid_rsp devId;
|
|
+} ATTRIBUTE_PACKING;
|
|
+#ifdef HAVE_PRAGMA_PACK
|
|
+# pragma pack(0)
|
|
+#endif
|
|
+
|
|
+typedef enum eHpmfwupgActionType {
|
|
+ HPMFWUPG_ACTION_BACKUP_COMPONENTS = 0,
|
|
+ HPMFWUPG_ACTION_PREPARE_COMPONENTS,
|
|
+ HPMFWUPG_ACTION_UPLOAD_FIRMWARE,
|
|
+ HPMFWUPG_ACTION_RESERVED = 0xFF
|
|
+} tHpmfwupgActionType;
|
|
+
|
|
+/* FUNCTIONS PROTOTYPES */
|
|
+#define HPMFWUPG_MAJORMINOR_VERSION_SIZE 2
|
|
+
|
|
+/* Options added for user to check the version and to view both the FILE and
|
|
+ * TARGET Version
|
|
+ */
|
|
+#define VIEW_MODE 0x01
|
|
+#define DEBUG_MODE 0x02
|
|
+#define FORCE_MODE 0x04
|
|
+#define COMPARE_MODE 0x08
|
|
+
|
|
+typedef struct _VERSIONINFO {
|
|
+ unsigned char componentId;
|
|
+ unsigned char targetMajor;
|
|
+ unsigned char targetMinor;
|
|
+ unsigned char targetAux[4];
|
|
+ unsigned char rollbackMajor;
|
|
+ unsigned char rollbackMinor;
|
|
+ unsigned char rollbackAux[4];
|
|
+ unsigned char deferredMajor;
|
|
+ unsigned char deferredMinor;
|
|
+ unsigned char deferredAux[4];
|
|
+ unsigned char imageMajor;
|
|
+ unsigned char imageMinor;
|
|
+ unsigned char imageAux[4];
|
|
+ unsigned char coldResetRequired;
|
|
+ unsigned char rollbackSupported;
|
|
+ char descString[HPMFWUPG_DESC_STRING_LENGTH + 1];
|
|
+}VERSIONINFO, *PVERSIONINFO;
|
|
+
|
|
+VERSIONINFO gVersionInfo[HPMFWUPG_COMPONENT_ID_MAX];
|
|
+
|
|
+#define TARGET_VER (0x01)
|
|
+#define ROLLBACK_VER (0x02)
|
|
+#define IMAGE_VER (0x04)
|
|
+
|
|
#endif /* IPMI_KFWUM_H */
|
|
diff --git a/ipmitool/include/ipmitool/ipmi_intf.h b/ipmitool/include/ipmitool/ipmi_intf.h
|
|
index 7ab2b13..774c6b2 100644
|
|
--- a/ipmitool/include/ipmitool/ipmi_intf.h
|
|
+++ b/ipmitool/include/ipmitool/ipmi_intf.h
|
|
@@ -89,8 +89,9 @@ struct ipmi_session {
|
|
uint32_t out_seq;
|
|
uint32_t timeout;
|
|
|
|
- struct sockaddr_in addr;
|
|
+ struct sockaddr_storage addr;
|
|
socklen_t addrlen;
|
|
+ int ai_family; /* Protocol family for socket. */
|
|
|
|
/*
|
|
* This struct holds state data specific to IPMI v2 / RMCP+ sessions
|
|
@@ -211,4 +212,7 @@ void ipmi_intf_session_set_timeout(struct ipmi_intf * intf, uint32_t timeout);
|
|
void ipmi_intf_session_set_retry(struct ipmi_intf * intf, int retry);
|
|
void ipmi_cleanup(struct ipmi_intf * intf);
|
|
|
|
+#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
|
|
+int ipmi_intf_socket_connect(struct ipmi_intf * intf);
|
|
+#endif
|
|
#endif /* IPMI_INTF_H */
|
|
diff --git a/ipmitool/include/ipmitool/ipmi_sel.h b/ipmitool/include/ipmitool/ipmi_sel.h
|
|
index 3077eb9..a125f85 100644
|
|
--- a/ipmitool/include/ipmitool/ipmi_sel.h
|
|
+++ b/ipmitool/include/ipmitool/ipmi_sel.h
|
|
@@ -107,6 +107,7 @@ struct standard_spec_sel_rec{
|
|
#define SENSOR_TYPE_OEM_NFATAL_ERROR 0xC2
|
|
#define SENSOR_TYPE_OEM_FATAL_ERROR 0xC3
|
|
#define SENSOR_TYPE_TXT_CMD_ERROR 0x20
|
|
+#define SENSOR_TYPE_SUPERMICRO_OEM 0xD0
|
|
/* End of Macro for DELL Specific */
|
|
#define SEL_OEM_TS_DATA_LEN 6
|
|
#define SEL_OEM_NOTS_DATA_LEN 13
|
|
@@ -676,6 +677,56 @@ static struct ipmi_event_sensor_types sensor_specific_types[] __attribute__((unu
|
|
{ 0x00, 0x00, 0x00, 0x00, NULL, NULL },
|
|
};
|
|
|
|
+static uint16_t supermicro_x9dal[] = {
|
|
+ 0x0635
|
|
+};
|
|
+
|
|
+static uint16_t supermicro_x9db[] = {
|
|
+ 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637
|
|
+};
|
|
+
|
|
+static uint16_t supermicro_x9sb[] = {
|
|
+ 0x0651
|
|
+};
|
|
+
|
|
+static uint16_t supermicro_x9[] = {
|
|
+ 0x0635, 0x0733, 0x0722, 0x0703, 0x0721, 0x0716, 0x0637, 0x0651
|
|
+};
|
|
+
|
|
+static uint16_t supermicro_b8[] = {
|
|
+ 0x000A, 0x061c, 0x0620, 0x0101, 0x061f, 0x0612, 0x061e
|
|
+};
|
|
+
|
|
+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
|
|
+};
|
|
+
|
|
+static uint16_t supermicro_p8[] = {
|
|
+ 0x6480, 0x7380, 0x6280, 0x7480, 0x5980
|
|
+};
|
|
+
|
|
+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
|
|
+};
|
|
+
|
|
+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,
|
|
+ 0x0009
|
|
+};
|
|
+
|
|
int ipmi_sel_main(struct ipmi_intf *, int, char **);
|
|
void ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt);
|
|
void ipmi_sel_print_std_entry_verbose(struct ipmi_intf * intf, struct sel_event_record * evt);
|
|
diff --git a/ipmitool/lib/helper.c b/ipmitool/lib/helper.c
|
|
index f795a34..4b903b0 100644
|
|
--- a/ipmitool/lib/helper.c
|
|
+++ b/ipmitool/lib/helper.c
|
|
@@ -44,6 +44,7 @@
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
+#include <assert.h>
|
|
|
|
#if HAVE_CONFIG_H
|
|
# include <config.h>
|
|
@@ -663,9 +664,10 @@ ipmi_start_daemon(struct ipmi_intf *intf)
|
|
close(fd);
|
|
}
|
|
|
|
- open("/dev/null", O_RDWR);
|
|
- dup(0);
|
|
- dup(0);
|
|
+ fd = open("/dev/null", O_RDWR);
|
|
+ assert(0 == fd);
|
|
+ dup(fd);
|
|
+ dup(fd);
|
|
}
|
|
|
|
/* is_fru_id - wrapper for str-2-int FRU ID conversion. Message is printed
|
|
@@ -756,3 +758,32 @@ is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr)
|
|
IPMI_UID_MIN, IPMI_UID_MAX);
|
|
return (-1);
|
|
}
|
|
+
|
|
+uint16_t
|
|
+ipmi_get_oem_id(struct ipmi_intf *intf)
|
|
+{
|
|
+ /* Execute a Get Board ID command to determine the board */
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ uint16_t oem_id;
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_TSOL;
|
|
+ req.msg.cmd = 0x21;
|
|
+ req.msg.data_len = 0;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Get Board ID command failed");
|
|
+ return 0;
|
|
+ }
|
|
+ if (rsp->ccode > 0) {
|
|
+ lprintf(LOG_ERR, "Get Board ID command failed: %#x %s",
|
|
+ rsp->ccode, val2str(rsp->ccode, completion_code_vals));
|
|
+ return 0;
|
|
+ }
|
|
+ oem_id = rsp->data[0] | (rsp->data[1] << 8);
|
|
+ lprintf(LOG_DEBUG,"Board ID: %x", oem_id);
|
|
+
|
|
+ return oem_id;
|
|
+}
|
|
diff --git a/ipmitool/lib/ipmi_dcmi.c b/ipmitool/lib/ipmi_dcmi.c
|
|
index ff9646c..0cce769 100755
|
|
--- a/ipmitool/lib/ipmi_dcmi.c
|
|
+++ b/ipmitool/lib/ipmi_dcmi.c
|
|
@@ -481,44 +481,14 @@ ipmi_dcmi_prnt_oobDiscover(struct ipmi_intf * intf)
|
|
intf->abort = 1;
|
|
intf->session->sol_data.sequence_number = 1;
|
|
|
|
- /* open port to BMC */
|
|
- memset(&s->addr, 0, sizeof(struct sockaddr_in));
|
|
- s->addr.sin_family = AF_INET;
|
|
- s->addr.sin_port = htons(s->port);
|
|
-
|
|
- rc = inet_pton(AF_INET, (const char *)s->hostname, &s->addr.sin_addr);
|
|
- if (rc <= 0) {
|
|
- struct hostent *host = gethostbyname((const char *)s->hostname);
|
|
- if (host == NULL) {
|
|
- lprintf(LOG_ERR, "Address lookup for %s failed",
|
|
- s->hostname);
|
|
- return -1;
|
|
- }
|
|
- if (host->h_addrtype != AF_INET) {
|
|
- lprintf(LOG_ERR,
|
|
- "Address lookup for %s failed. Got %s, expected IPv4 address.",
|
|
- s->hostname,
|
|
- (host->h_addrtype == AF_INET6) ? "IPv6" : "Unknown");
|
|
- return (-1);
|
|
- }
|
|
- s->addr.sin_family = host->h_addrtype;
|
|
- memcpy(&s->addr.sin_addr, host->h_addr, host->h_length);
|
|
- }
|
|
-
|
|
- lprintf(LOG_DEBUG, "IPMI LAN host %s port %d",
|
|
- s->hostname, ntohs(s->addr.sin_port));
|
|
-
|
|
- intf->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
- if (intf->fd < 0) {
|
|
- lperror(LOG_ERR, "Socket failed");
|
|
+ if (ipmi_intf_socket_connect(intf) == -1) {
|
|
+ lprintf(LOG_ERR, "Could not open socket!");
|
|
return -1;
|
|
}
|
|
|
|
- /* connect to UDP socket so we get async errors */
|
|
- rc = connect(intf->fd, (struct sockaddr *)&s->addr,
|
|
- sizeof(struct sockaddr_in));
|
|
- if (rc < 0) {
|
|
- lperror(LOG_ERR, "Connect failed");
|
|
+ if (intf->fd < 0) {
|
|
+ lperror(LOG_ERR, "Connect to %s failed",
|
|
+ s->hostname);
|
|
intf->close(intf);
|
|
return -1;
|
|
}
|
|
diff --git a/ipmitool/lib/ipmi_delloem.c b/ipmitool/lib/ipmi_delloem.c
|
|
index b4e541a..e190cd4 100644
|
|
--- a/ipmitool/lib/ipmi_delloem.c
|
|
+++ b/ipmitool/lib/ipmi_delloem.c
|
|
@@ -3232,7 +3232,7 @@ ipmi_get_avgpower_consmpt_history(struct ipmi_intf * intf,
|
|
if (verbose > 1) {
|
|
rdata = (void *)pavgpower;
|
|
printf("Average power consumption history data"
|
|
- " :%x %x %x %x %x %x %x\n\n",
|
|
+ " :%x %x %x %x %x %x %x %x\n\n",
|
|
rdata[0], rdata[1], rdata[2], rdata[3],
|
|
rdata[4], rdata[5], rdata[6], rdata[7]);
|
|
}
|
|
@@ -3281,7 +3281,7 @@ ipmi_get_peakpower_consmpt_history(struct ipmi_intf * intf,
|
|
rdata = (void *)pstPeakpower;
|
|
printf("Peak power consmhistory Data : "
|
|
"%x %x %x %x %x %x %x %x %x %x\n "
|
|
- "%x %x %x %x %x %x %x %x %x %x %x %x %x\n\n",
|
|
+ "%x %x %x %x %x %x %x %x %x %x %x %x %x %x\n\n",
|
|
rdata[0], rdata[1], rdata[2], rdata[3],
|
|
rdata[4], rdata[5], rdata[6], rdata[7],
|
|
rdata[8], rdata[9], rdata[10], rdata[11],
|
|
@@ -3633,7 +3633,7 @@ ipmi_set_power_cap(struct ipmi_intf * intf, int unit, int val)
|
|
}
|
|
if (verbose > 1) {
|
|
rdata = (void *)&ipmipowercap;
|
|
- printf("power cap Data :%x %x %x %x %x %x %x %x %x %x ",
|
|
+ printf("power cap Data :%x %x %x %x %x %x %x %x %x %x %x ",
|
|
rdata[1], rdata[2], rdata[3],
|
|
rdata[4], rdata[5], rdata[6], rdata[7],
|
|
rdata[8], rdata[9], rdata[10],rdata[11]);
|
|
diff --git a/ipmitool/lib/ipmi_ekanalyzer.c b/ipmitool/lib/ipmi_ekanalyzer.c
|
|
index f2c9c82..2ac1012 100644
|
|
--- a/ipmitool/lib/ipmi_ekanalyzer.c
|
|
+++ b/ipmitool/lib/ipmi_ekanalyzer.c
|
|
@@ -2745,6 +2745,8 @@ ipmi_ek_display_board_info_area(FILE * input_file, char * board_type,
|
|
ret = fread(data, size_board, 1, input_file);
|
|
if ((ret != 1) || ferror(input_file)) {
|
|
lprintf(LOG_ERR, "Invalid board type size!");
|
|
+ free(data);
|
|
+ data = NULL;
|
|
goto out;
|
|
}
|
|
printf("%s type: 0x%02x\n", board_type, len);
|
|
@@ -2761,6 +2763,7 @@ ipmi_ek_display_board_info_area(FILE * input_file, char * board_type,
|
|
}
|
|
printf("\n");
|
|
free(data);
|
|
+ data = NULL;
|
|
(*board_length) -= size_board;
|
|
goto out;
|
|
}
|
|
@@ -2807,6 +2810,7 @@ ipmi_ek_display_board_info_area(FILE * input_file, char * board_type,
|
|
}
|
|
printf("\n");
|
|
free(additional_data);
|
|
+ additional_data = NULL;
|
|
(*board_length) -= size_board;
|
|
}
|
|
else {
|
|
@@ -2843,7 +2847,7 @@ out:
|
|
static int
|
|
ipmi_ek_display_product_info_area(FILE * input_file, long offset)
|
|
{
|
|
- size_t file_offset = ftell(input_file);
|
|
+ size_t file_offset;
|
|
int ret = 0;
|
|
unsigned char ch_len = 0;
|
|
unsigned char data = 0;
|
|
@@ -2853,6 +2857,7 @@ ipmi_ek_display_product_info_area(FILE * input_file, long offset)
|
|
lprintf(LOG_ERR, "No file stream to read.");
|
|
return (-1);
|
|
}
|
|
+ file_offset = ftell(input_file);
|
|
printf("%s\n", EQUAL_LINE_LIMITER);
|
|
printf("Product Info Area\n");
|
|
printf("%s\n", EQUAL_LINE_LIMITER);
|
|
diff --git a/ipmitool/lib/ipmi_fru.c b/ipmitool/lib/ipmi_fru.c
|
|
index 6ba2ada..09d5abe 100644
|
|
--- a/ipmitool/lib/ipmi_fru.c
|
|
+++ b/ipmitool/lib/ipmi_fru.c
|
|
@@ -48,16 +48,6 @@
|
|
# include <config.h>
|
|
#endif
|
|
|
|
-/*
|
|
-* Apparently some systems have problems with FRU access greater than 16 bytes
|
|
-* at a time, even when using byte (not word) access. In order to ensure we
|
|
-* work with the widest variety of hardware request size is capped at 16 bytes.
|
|
-* Since this may result in slowdowns on some systems with lots of FRU data you
|
|
-* can undefine this to enable larger (up to 32 bytes at a time) access.
|
|
-*
|
|
-* TODO: make this a command line option
|
|
-*/
|
|
-#define LIMIT_ALL_REQUEST_SIZE 1
|
|
#define FRU_MULTIREC_CHUNK_SIZE (255 + sizeof(struct fru_multirec_header))
|
|
|
|
extern int verbose;
|
|
@@ -71,7 +61,7 @@ static int ipmi_fru_get_multirec_location_from_fru(struct ipmi_intf * intf, uint
|
|
static int ipmi_fru_get_multirec_from_file(char * pFileName, uint8_t * pBufArea,
|
|
uint32_t size, uint32_t offset);
|
|
static int ipmi_fru_get_multirec_size_from_file(char * pFileName, uint32_t * pSize, uint32_t * pOffset);
|
|
-int ipmi_fru_get_adjust_size_from_buffer(uint8_t * pBufArea, uint32_t *pSize);
|
|
+int ipmi_fru_get_adjust_size_from_buffer(uint8_t *pBufArea, uint32_t *pSize);
|
|
static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length);
|
|
|
|
static int ipmi_fru_set_field_string(struct ipmi_intf * intf, unsigned
|
|
@@ -87,6 +77,7 @@ fru_area_print_multirec_bloc(struct ipmi_intf * intf, struct fru_info * fru,
|
|
int
|
|
read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
|
|
uint32_t offset, uint32_t length, uint8_t *frubuf);
|
|
+void free_fru_bloc(t_ipmi_fru_bloc *bloc);
|
|
|
|
/* get_fru_area_str - Parse FRU area string from raw data
|
|
*
|
|
@@ -235,30 +226,17 @@ is_valid_filename(const char *input_filename)
|
|
* returns -1 on error
|
|
*/
|
|
#define FRU_NUM_BLOC_COMMON_HEADER 6
|
|
-typedef struct ipmi_fru_bloc
|
|
-{
|
|
- uint16_t start;
|
|
- uint16_t size;
|
|
- uint8_t blocId[32];
|
|
-}t_ipmi_fru_bloc;
|
|
-
|
|
t_ipmi_fru_bloc *
|
|
-build_fru_bloc(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
|
|
- /* OUT */uint16_t * ptr_number_bloc)
|
|
+build_fru_bloc(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id)
|
|
{
|
|
- t_ipmi_fru_bloc * p_bloc;
|
|
+ t_ipmi_fru_bloc * p_first, * p_bloc, * p_new;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
struct fru_header header;
|
|
- uint8_t * fru_data = NULL;
|
|
+ struct fru_multirec_header rec_hdr;
|
|
uint8_t msg_data[4];
|
|
- uint16_t num_bloc;
|
|
- uint16_t bloc_count;
|
|
-
|
|
- (* ptr_number_bloc) = 0;
|
|
-
|
|
- /*memset(&fru, 0, sizeof(struct fru_info));*/
|
|
- memset(&header, 0, sizeof(struct fru_header));
|
|
+ uint32_t off;
|
|
+ uint16_t i;
|
|
|
|
/*
|
|
* get COMMON Header format
|
|
@@ -274,464 +252,322 @@ build_fru_bloc(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
|
|
req.msg.data = msg_data;
|
|
req.msg.data_len = 4;
|
|
|
|
-
|
|
rsp = intf->sendrecv(intf, &req);
|
|
+
|
|
if (rsp == NULL) {
|
|
- lprintf(LOG_ERR, " Device not present (No Response)\n");
|
|
+ lprintf(LOG_ERR, " Device not present (No Response)");
|
|
return NULL;
|
|
}
|
|
+
|
|
if (rsp->ccode > 0) {
|
|
- lprintf(LOG_ERR," Device not present (%s)\n",
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
+ lprintf(LOG_ERR," Device not present (%s)",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
return NULL;
|
|
}
|
|
|
|
- if (verbose > 1)
|
|
+ if (verbose > 1) {
|
|
printbuf(rsp->data, rsp->data_len, "FRU DATA");
|
|
+ }
|
|
|
|
memcpy(&header, rsp->data + 1, 8);
|
|
|
|
+ /* verify header checksum */
|
|
+ if (ipmi_csum((uint8_t *)&header, 8)) {
|
|
+ lprintf(LOG_ERR, " Bad header checksum");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
if (header.version != 1) {
|
|
- lprintf(LOG_ERR, " Unknown FRU header version 0x%02x",
|
|
- header.version);
|
|
+ lprintf(LOG_ERR, " Unknown FRU header version 0x%02x", header.version);
|
|
return NULL;
|
|
}
|
|
|
|
/******************************************
|
|
- Count the number of bloc
|
|
+ Malloc and fill up the bloc contents
|
|
*******************************************/
|
|
|
|
// Common header
|
|
- num_bloc = 1;
|
|
- // Internal
|
|
- if( header.offset.internal )
|
|
- num_bloc ++;
|
|
- // Chassis
|
|
- if( header.offset.chassis )
|
|
- num_bloc ++;
|
|
- // Board
|
|
- if( header.offset.board )
|
|
- num_bloc ++;
|
|
- // Product
|
|
- if( header.offset.product )
|
|
- num_bloc ++;
|
|
-
|
|
- // Multi
|
|
- if( header.offset.multi )
|
|
- {
|
|
-
|
|
- uint32_t i;
|
|
- struct fru_multirec_header * h;
|
|
- uint32_t last_off, len;
|
|
-
|
|
- i = last_off = (header.offset.multi*8);
|
|
- //fru_len = 0;
|
|
-
|
|
- fru_data = malloc(fru->size + 1);
|
|
- if (fru_data == NULL) {
|
|
- lprintf(LOG_ERR, " Out of memory!");
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- memset(fru_data, 0, fru->size + 1);
|
|
-
|
|
- do {
|
|
- h = (struct fru_multirec_header *) (fru_data + i);
|
|
-
|
|
- // read area in (at most) FRU_MULTIREC_CHUNK_SIZE bytes at a time
|
|
- if ((last_off < (i + sizeof(*h))) || (last_off < (i + h->len)))
|
|
- {
|
|
- len = fru->size - last_off;
|
|
- if (len > FRU_MULTIREC_CHUNK_SIZE)
|
|
- len = FRU_MULTIREC_CHUNK_SIZE;
|
|
+ p_first = malloc(sizeof(struct ipmi_fru_bloc));
|
|
+ if (!p_first) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ return NULL;
|
|
+ }
|
|
|
|
- if (read_fru_area(intf, fru, id, last_off, len, fru_data) < 0)
|
|
- break;
|
|
+ p_bloc = p_first;
|
|
+ p_bloc->next = NULL;
|
|
+ p_bloc->start= 0;
|
|
+ p_bloc->size = fru->size;
|
|
+ strcpy((char *)p_bloc->blocId, "Common Header Section");
|
|
|
|
- last_off += len;
|
|
+ for (i = 0; i < 4; i++) {
|
|
+ if (header.offsets[i]) {
|
|
+ p_new = malloc(sizeof(struct ipmi_fru_bloc));
|
|
+ if (!p_new) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ free_fru_bloc(p_first);
|
|
+ return NULL;
|
|
}
|
|
|
|
- num_bloc++;
|
|
- //printf("Bloc Numb : %i\n", counter);
|
|
- //printf("Bloc Start: %i\n", i);
|
|
- //printf("Bloc Size : %i\n", h->len);
|
|
- //printf("\n");
|
|
- i += h->len + sizeof (struct fru_multirec_header);
|
|
- } while (!(h->format & 0x80) && ( last_off < fru->size));
|
|
+ p_new->next = NULL;
|
|
+ p_new->start = header.offsets[i] * 8;
|
|
+ p_new->size = fru->size - p_new->start;
|
|
|
|
- lprintf(LOG_DEBUG ,"Multi-Record area ends at: %i (%xh)",i,i);
|
|
+ strncpy((char *)p_new->blocId, section_id[i], sizeof(p_new->blocId));
|
|
+ /* Make sure string is null terminated */
|
|
+ p_new->blocId[sizeof(p_new->blocId)-1] = 0;
|
|
|
|
- if(fru->size > i)
|
|
- {
|
|
- // Bloc for remaining space
|
|
- num_bloc ++;
|
|
+ p_bloc->next = p_new;
|
|
+ p_bloc->size = p_new->start - p_bloc->start;
|
|
+ p_bloc = p_new;
|
|
}
|
|
}
|
|
- else
|
|
- {
|
|
- /* Since there is no multi-rec area and no end delimiter, the remaining
|
|
- space will be added to the last bloc */
|
|
- }
|
|
-
|
|
-
|
|
|
|
- /******************************************
|
|
- Malloc and fill up the bloc contents
|
|
- *******************************************/
|
|
- p_bloc = malloc( sizeof( t_ipmi_fru_bloc ) * num_bloc );
|
|
- if(!p_bloc)
|
|
- {
|
|
- lprintf(LOG_ERR, " Unable to get memory to build Fru bloc");
|
|
+ // Multi
|
|
+ if (header.offset.multi) {
|
|
+ off = header.offset.multi * 8;
|
|
|
|
- if (fru_data != NULL) {
|
|
- free(fru_data);
|
|
- fru_data = NULL;
|
|
- }
|
|
+ do {
|
|
+ /*
|
|
+ * check for odd offset for the case of fru devices
|
|
+ * accessed by words
|
|
+ */
|
|
+ if (fru->access && (off & 1)) {
|
|
+ lprintf(LOG_ERR, " Unaligned offset for a block: %d", off);
|
|
+ /* increment offset */
|
|
+ off++;
|
|
+ break;
|
|
+ }
|
|
|
|
- return NULL;
|
|
- }
|
|
+ if (read_fru_area(intf, fru, id, off, 5,
|
|
+ (uint8_t *) &rec_hdr) < 0) {
|
|
+ break;
|
|
+ }
|
|
|
|
- // Common header
|
|
- bloc_count = 0;
|
|
+ p_new = malloc(sizeof(struct ipmi_fru_bloc));
|
|
+ if (!p_new) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ free_fru_bloc(p_first);
|
|
+ return NULL;
|
|
+ }
|
|
|
|
- p_bloc[bloc_count].start= 0;
|
|
- p_bloc[bloc_count].size = 8;
|
|
- strcpy((char *)p_bloc[bloc_count].blocId, "Common Header Section");
|
|
- bloc_count ++;
|
|
+ p_new->next = NULL;
|
|
+ p_new->start = off;
|
|
+ p_new->size = fru->size - p_new->start;
|
|
+ sprintf((char *)p_new->blocId, "Multi-Rec Area: Type %i",
|
|
+ rec_hdr.type);
|
|
|
|
- // Internal
|
|
- if( header.offset.internal )
|
|
- {
|
|
- p_bloc[bloc_count].start = (header.offset.internal * 8);
|
|
- p_bloc[bloc_count].size = 0; // Will be fillup later
|
|
- strcpy((char *)p_bloc[bloc_count].blocId, "Internal Use Section");
|
|
- bloc_count ++;
|
|
- }
|
|
- // Chassis
|
|
- if( header.offset.chassis )
|
|
- {
|
|
- p_bloc[bloc_count].start = (header.offset.chassis * 8);
|
|
- p_bloc[bloc_count].size = 0; // Will be fillup later
|
|
- strcpy((char *)p_bloc[bloc_count].blocId, "Chassis Section");
|
|
- bloc_count ++;
|
|
- }
|
|
- // Board
|
|
- if( header.offset.board )
|
|
- {
|
|
- p_bloc[bloc_count].start = (header.offset.board * 8);
|
|
- p_bloc[bloc_count].size = 0; // Will be fillup later
|
|
- strcpy((char *)p_bloc[bloc_count].blocId, "Board Section");
|
|
- bloc_count ++;
|
|
- }
|
|
- // Product
|
|
- if( header.offset.product )
|
|
- {
|
|
- p_bloc[bloc_count].start = (header.offset.product * 8);
|
|
- p_bloc[bloc_count].size = 0; // Will be fillup later
|
|
- strcpy((char *)p_bloc[bloc_count].blocId, "Product Section");
|
|
- bloc_count ++;
|
|
- }
|
|
-
|
|
- // Multi-Record Area
|
|
- if(
|
|
- ( header.offset.multi )
|
|
- &&
|
|
- ( fru_data )
|
|
- )
|
|
- {
|
|
- uint32_t i = (header.offset.multi*8);
|
|
- struct fru_multirec_header * h;
|
|
+ p_bloc->next = p_new;
|
|
+ p_bloc->size = p_new->start - p_bloc->start;
|
|
+ p_bloc = p_new;
|
|
|
|
- do {
|
|
- h = (struct fru_multirec_header *) (fru_data + i);
|
|
+ off += rec_hdr.len + sizeof(struct fru_multirec_header);
|
|
|
|
- p_bloc[bloc_count].start = i;
|
|
- p_bloc[bloc_count].size = h->len + sizeof (struct fru_multirec_header);
|
|
- sprintf((char *)p_bloc[bloc_count].blocId, "Multi-Rec Aread: Type %i", h->type);
|
|
- bloc_count ++;
|
|
- /*printf("Bloc Start: %i\n", i);
|
|
- printf("Bloc Size : %i\n", h->len);
|
|
- printf("\n");*/
|
|
+ /* verify record header */
|
|
+ if (ipmi_csum((uint8_t *)&rec_hdr,
|
|
+ sizeof(struct fru_multirec_header))) {
|
|
+ /* can't reliably judge for the rest space */
|
|
+ break;
|
|
+ }
|
|
+ } while (!(rec_hdr.format & 0x80) && (off < fru->size));
|
|
|
|
- i += h->len + sizeof (struct fru_multirec_header);
|
|
+ lprintf(LOG_DEBUG,"Multi-Record area ends at: %i (%xh)", off, off);
|
|
|
|
- } while (!(h->format & 0x80) && ( bloc_count < num_bloc ) );
|
|
+ if (fru->size > off) {
|
|
+ // Bloc for remaining space
|
|
+ p_new = malloc(sizeof(struct ipmi_fru_bloc));
|
|
+ if (!p_new) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ free_fru_bloc(p_first);
|
|
+ return NULL;
|
|
+ }
|
|
|
|
- lprintf(LOG_DEBUG ,"Multi-Record area ends at: %i (%xh)",i,i);
|
|
- /* If last bloc size was defined and is not until the end, create a
|
|
- last bloc with the remaining unused space */
|
|
+ p_new->next = NULL;
|
|
+ p_new->start = off;
|
|
+ p_new->size = fru->size - p_new->start;
|
|
+ strcpy((char *)p_new->blocId, "Unused space");
|
|
|
|
- if((fru->size > i) && (bloc_count < num_bloc))
|
|
- {
|
|
- // Bloc for remaining space
|
|
- p_bloc[bloc_count].start = i;
|
|
- p_bloc[bloc_count].size = (fru->size - i);
|
|
- sprintf((char *)p_bloc[bloc_count].blocId, "Unused space");
|
|
- bloc_count ++;
|
|
+ p_bloc->next = p_new;
|
|
+ p_bloc->size = p_new->start - p_bloc->start;
|
|
}
|
|
-
|
|
}
|
|
|
|
- if (fru_data != NULL) {
|
|
- free(fru_data);
|
|
- fru_data = NULL;
|
|
+ /* Dump blocs */
|
|
+ for(p_bloc = p_first, i = 0; p_bloc; p_bloc = p_bloc->next) {
|
|
+ lprintf(LOG_DEBUG ,"Bloc Numb : %i", i++);
|
|
+ lprintf(LOG_DEBUG ,"Bloc Id : %s", p_bloc->blocId);
|
|
+ lprintf(LOG_DEBUG ,"Bloc Start: %i", p_bloc->start);
|
|
+ lprintf(LOG_DEBUG ,"Bloc Size : %i", p_bloc->size);
|
|
+ lprintf(LOG_DEBUG ,"");
|
|
}
|
|
|
|
- /* Fill up size for first bloc */
|
|
- {
|
|
- unsigned short counter;
|
|
- lprintf(LOG_DEBUG ,"\nNumber Bloc : %i\n", num_bloc);
|
|
- for(counter = 0; counter < (num_bloc); counter ++)
|
|
- {
|
|
- /* If size where not initialized, do it. */
|
|
- if( p_bloc[counter].size == 0)
|
|
- {
|
|
- /* If not the last bloc, use the next bloc to determine the end */
|
|
- if((counter+1) < num_bloc)
|
|
- {
|
|
- p_bloc[counter].size = (p_bloc[counter+1].start - p_bloc[counter].start);
|
|
- }
|
|
- else
|
|
- {
|
|
- p_bloc[counter].size = (fru->size - p_bloc[counter].start);
|
|
- }
|
|
- }
|
|
- lprintf(LOG_DEBUG ,"Bloc Numb : %i\n", counter);
|
|
- lprintf(LOG_DEBUG ,"Bloc Id : %s\n", p_bloc[counter].blocId);
|
|
- lprintf(LOG_DEBUG ,"Bloc Start: %i\n", p_bloc[counter].start);
|
|
- lprintf(LOG_DEBUG ,"Bloc Size : %i\n", p_bloc[counter].size);
|
|
- lprintf(LOG_DEBUG ,"\n");
|
|
- }
|
|
- }
|
|
+ return p_first;
|
|
+}
|
|
|
|
- (* ptr_number_bloc) = num_bloc;
|
|
+void
|
|
+free_fru_bloc(t_ipmi_fru_bloc *bloc)
|
|
+{
|
|
+ t_ipmi_fru_bloc * del;
|
|
|
|
- return p_bloc;
|
|
+ while (bloc) {
|
|
+ del = bloc;
|
|
+ bloc = bloc->next;
|
|
+ free(del);
|
|
+ del = NULL;
|
|
+ }
|
|
}
|
|
|
|
-
|
|
+/*
|
|
+ * write FRU[doffset:length] from the pFrubuf[soffset:length]
|
|
+ * rc=1 on success
|
|
+**/
|
|
int
|
|
write_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
|
|
uint16_t soffset, uint16_t doffset,
|
|
uint16_t length, uint8_t *pFrubuf)
|
|
-{ /*
|
|
- // fill in frubuf[offset:length] from the FRU[offset:length]
|
|
- // rc=1 on success
|
|
- */
|
|
- static uint16_t fru_data_rqst_size = 32;
|
|
- uint16_t off=0, tmp, finish;
|
|
+{
|
|
+ uint16_t tmp, finish;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
- uint8_t msg_data[256];
|
|
- uint8_t writeLength;
|
|
- uint16_t num_bloc;
|
|
+ uint8_t msg_data[255+3];
|
|
+ uint16_t writeLength;
|
|
+ uint16_t found_bloc = 0;
|
|
|
|
finish = doffset + length; /* destination offset */
|
|
if (finish > fru->size)
|
|
{
|
|
- lprintf(LOG_ERROR, "Return error\n");
|
|
+ lprintf(LOG_ERROR, "Return error");
|
|
return -1;
|
|
}
|
|
|
|
- t_ipmi_fru_bloc * fru_bloc = build_fru_bloc(intf, fru, id, &num_bloc);
|
|
-
|
|
- if (fru_bloc == NULL) {
|
|
- lprintf(LOG_ERROR, "Failed to build FRU bloc.");
|
|
+ if (fru->access && ((doffset & 1) || (length & 1))) {
|
|
+ lprintf(LOG_ERROR, "Odd offset or length specified");
|
|
return (-1);
|
|
}
|
|
|
|
+ t_ipmi_fru_bloc * fru_bloc = build_fru_bloc(intf, fru, id);
|
|
+ t_ipmi_fru_bloc * saved_fru_bloc = fru_bloc;
|
|
+
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_STORAGE;
|
|
req.msg.cmd = SET_FRU_DATA;
|
|
req.msg.data = msg_data;
|
|
|
|
-#ifdef LIMIT_ALL_REQUEST_SIZE
|
|
- if (fru_data_rqst_size > 16)
|
|
-#else
|
|
- if (fru->access && fru_data_rqst_size > 16)
|
|
-#endif
|
|
- fru_data_rqst_size = 16;
|
|
+ /* initialize request size only once */
|
|
+ if (fru->max_write_size == 0) {
|
|
+ if (intf->channel_buf_size != 0) {
|
|
+ /* subtract 1 byte for FRU ID an 2 bytes for offset */
|
|
+ fru->max_write_size = intf->channel_buf_size - 3;
|
|
+ } else {
|
|
+ /* subtract 1 byte for FRU ID an 2 bytes for offset */
|
|
+ fru->max_write_size = 32 - 3;
|
|
+ }
|
|
|
|
- /* Check if we receive size in parameters */
|
|
- if(intf->channel_buf_size != 0)
|
|
- {
|
|
- fru_data_rqst_size = intf->channel_buf_size - 5; /* Plan for overhead */
|
|
+ /* check word access */
|
|
+ if (fru->access) {
|
|
+ fru->max_write_size &= ~1;
|
|
+ }
|
|
}
|
|
|
|
do {
|
|
- /* Temp init end_bloc to the end, if not found */
|
|
- uint16_t end_bloc = finish;
|
|
+ uint16_t end_bloc;
|
|
uint8_t protected_bloc = 0;
|
|
- uint16_t found_bloc = 0xffff;
|
|
-
|
|
- /* real destination offset */
|
|
- tmp = fru->access ? (doffset+off) >> 1 : (doffset+off);
|
|
- msg_data[0] = id;
|
|
- msg_data[1] = (uint8_t)tmp;
|
|
- msg_data[2] = (uint8_t)(tmp >> 8);
|
|
|
|
/* Write per bloc, try to find the end of a bloc*/
|
|
- {
|
|
- uint16_t counter;
|
|
- for(counter = 0; counter < (num_bloc); counter ++)
|
|
- {
|
|
- if(
|
|
- (tmp >= fru_bloc[counter].start)
|
|
- &&
|
|
- (tmp < (fru_bloc[counter].start + fru_bloc[counter].size))
|
|
- )
|
|
- {
|
|
- found_bloc = counter;
|
|
- end_bloc = (fru_bloc[counter].start + fru_bloc[counter].size);
|
|
- counter = num_bloc;
|
|
- }
|
|
- }
|
|
+ while (fru_bloc && fru_bloc->start + fru_bloc->size <= doffset) {
|
|
+ fru_bloc = fru_bloc->next;
|
|
+ found_bloc++;
|
|
}
|
|
|
|
- tmp = end_bloc - (doffset+off); /* bytes remaining for the bloc */
|
|
- if (tmp > fru_data_rqst_size) {
|
|
- memcpy(&msg_data[3], pFrubuf + soffset + off, fru_data_rqst_size);
|
|
- req.msg.data_len = fru_data_rqst_size + 3;
|
|
- }
|
|
- else {
|
|
- memcpy(&msg_data[3], pFrubuf + soffset + off, (uint8_t)tmp);
|
|
- req.msg.data_len = tmp + 3;
|
|
- }
|
|
- if(found_bloc == 0)
|
|
- {
|
|
- lprintf(LOG_INFO,"Writing %d bytes", (req.msg.data_len-3));
|
|
- }
|
|
- else if(found_bloc != 0xFFFF)
|
|
- {
|
|
- lprintf(LOG_INFO,"Writing %d bytes (Bloc #%i: %s)",
|
|
- (req.msg.data_len-3),
|
|
- found_bloc, fru_bloc[found_bloc].blocId);
|
|
+ if (fru_bloc && fru_bloc->start + fru_bloc->size < finish) {
|
|
+ end_bloc = fru_bloc->start + fru_bloc->size;
|
|
+ } else {
|
|
+ end_bloc = finish;
|
|
}
|
|
|
|
- writeLength = req.msg.data_len-3;
|
|
+ /* calculate write length */
|
|
+ tmp = end_bloc - doffset;
|
|
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (!rsp) {
|
|
- break;
|
|
+ /* check that write length is more than maximum request size */
|
|
+ if (tmp > fru->max_write_size) {
|
|
+ writeLength = fru->max_write_size;
|
|
+ } else {
|
|
+ writeLength = tmp;
|
|
}
|
|
|
|
- if(rsp->ccode==0x80) // Write protected section
|
|
- {
|
|
- protected_bloc = 1;
|
|
- }
|
|
- else if ((rsp->ccode==0xc7 || rsp->ccode==0xc8 || rsp->ccode==0xca ) &&
|
|
- --fru_data_rqst_size > 8) {
|
|
- lprintf(LOG_NOTICE,"Bad CC -> %x\n", rsp->ccode);
|
|
- break; /*continue;*/
|
|
- }
|
|
- else if (rsp->ccode > 0)
|
|
- break;
|
|
+ /* copy fru data */
|
|
+ memcpy(&msg_data[3], pFrubuf + soffset, writeLength);
|
|
|
|
- if(protected_bloc == 0)
|
|
- {
|
|
- lprintf(LOG_INFO,"Wrote %d bytes", writeLength);
|
|
- off += writeLength; // Write OK, bloc not protected, continue
|
|
+ /* check word access */
|
|
+ if (fru->access) {
|
|
+ writeLength &= ~1;
|
|
}
|
|
- else
|
|
- {
|
|
- if(found_bloc != 0xffff)
|
|
- {
|
|
- // Bloc protected, advise user and jump over protected bloc
|
|
- lprintf(LOG_INFO,"Bloc [%s] protected at offset: %i (size %i bytes)",
|
|
- fru_bloc[found_bloc].blocId,
|
|
- fru_bloc[found_bloc].start,
|
|
- fru_bloc[found_bloc].size);
|
|
- lprintf(LOG_INFO,"Jumping over this bloc");
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_INFO,"Remaining FRU is protected following offset: %i",
|
|
- off);
|
|
|
|
- }
|
|
- off = end_bloc;
|
|
+ tmp = doffset;
|
|
+ if (fru->access) {
|
|
+ tmp >>= 1;
|
|
}
|
|
- } while ((doffset+off) < finish);
|
|
-
|
|
- free(fru_bloc);
|
|
- fru_bloc = NULL;
|
|
-
|
|
- return ((doffset+off) >= finish);
|
|
-}
|
|
-
|
|
-
|
|
-#if 0
|
|
-int
|
|
-write_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
|
|
- uint16_t soffset, uint16_t doffset,
|
|
- uint16_t length, uint8_t *pFrubuf)
|
|
-{ /*
|
|
- // fill in frubuf[offset:length] from the FRU[offset:length]
|
|
- // rc=1 on success
|
|
- */
|
|
- static uint16_t fru_data_rqst_size = 32;
|
|
- uint16_t off=0, tmp, finish;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- uint8_t msg_data[25];
|
|
- uint8_t writeLength;
|
|
-
|
|
- finish = doffset + length; /* destination offset */
|
|
- if (finish > fru->size)
|
|
- {
|
|
- printf("Return error\n");
|
|
- return -1;
|
|
- }
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_STORAGE;
|
|
- req.msg.cmd = SET_FRU_DATA;
|
|
- req.msg.data = msg_data;
|
|
-
|
|
-#ifdef LIMIT_ALL_REQUEST_SIZE
|
|
- if (fru_data_rqst_size > 16)
|
|
-#else
|
|
- if (fru->access && fru_data_rqst_size > 16)
|
|
-#endif
|
|
- fru_data_rqst_size = 16;
|
|
|
|
- do {
|
|
- /* real destination offset */
|
|
- tmp = fru->access ? (doffset+off) >> 1 : (doffset+off);
|
|
msg_data[0] = id;
|
|
msg_data[1] = (uint8_t)tmp;
|
|
msg_data[2] = (uint8_t)(tmp >> 8);
|
|
- tmp = finish - (doffset+off); /* bytes remaining */
|
|
- if (tmp > 16) {
|
|
- lprintf(LOG_INFO,"Writing 16 bytes");
|
|
- memcpy(&msg_data[3], pFrubuf + soffset + off, 16);
|
|
- req.msg.data_len = 16 + 3;
|
|
- }
|
|
- else {
|
|
- lprintf(LOG_INFO,"Writing %d bytes", tmp);
|
|
- memcpy(&msg_data[3], pFrubuf + soffset + off, (uint8_t)tmp);
|
|
- req.msg.data_len = tmp + 3;
|
|
- }
|
|
+ req.msg.data_len = writeLength + 3;
|
|
|
|
- writeLength = req.msg.data_len-3;
|
|
+ if(fru_bloc) {
|
|
+ lprintf(LOG_INFO,"Writing %d bytes (Bloc #%i: %s)",
|
|
+ writeLength, found_bloc, fru_bloc->blocId);
|
|
+ } else {
|
|
+ lprintf(LOG_INFO,"Writing %d bytes", writeLength);
|
|
+ }
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
if (!rsp) {
|
|
break;
|
|
}
|
|
- if ((rsp->ccode==0xc7 || rsp->ccode==0xc8 || rsp->ccode==0xca ) &&
|
|
- --fru_data_rqst_size > 8) {
|
|
- lprintf(LOG_NOTICE,"Bad CC -> %x\n", rsp->ccode);
|
|
- break; /*continue;*/
|
|
+
|
|
+ if (rsp->ccode == 0xc7 || rsp->ccode == 0xc8 || rsp->ccode == 0xca) {
|
|
+ if (fru->max_write_size > 8) {
|
|
+ fru->max_write_size -= 8;
|
|
+ lprintf(LOG_INFO, "Retrying FRU write with request size %d",
|
|
+ fru->max_write_size);
|
|
+ continue;
|
|
+ }
|
|
+ } else if(rsp->ccode == 0x80) {
|
|
+ rsp->ccode = 0;
|
|
+ // Write protected section
|
|
+ protected_bloc = 1;
|
|
}
|
|
+
|
|
if (rsp->ccode > 0)
|
|
break;
|
|
|
|
- off += writeLength;
|
|
- } while ((doffset+off) < finish);
|
|
+ if (protected_bloc == 0) {
|
|
+ // Write OK, bloc not protected, continue
|
|
+ lprintf(LOG_INFO,"Wrote %d bytes", writeLength);
|
|
+ doffset += writeLength;
|
|
+ soffset += writeLength;
|
|
+ } else {
|
|
+ if(fru_bloc) {
|
|
+ // Bloc protected, advise user and jump over protected bloc
|
|
+ lprintf(LOG_INFO,
|
|
+ "Bloc [%s] protected at offset: %i (size %i bytes)",
|
|
+ fru_bloc->blocId, fru_bloc->start, fru_bloc->size);
|
|
+ lprintf(LOG_INFO,"Jumping over this bloc");
|
|
+ } else {
|
|
+ lprintf(LOG_INFO,
|
|
+ "Remaining FRU is protected following offset: %i",
|
|
+ doffset);
|
|
+ }
|
|
+ soffset += end_bloc - doffset;
|
|
+ doffset = end_bloc;
|
|
+ }
|
|
+ } while (doffset < finish);
|
|
+
|
|
+ if (saved_fru_bloc) {
|
|
+ free_fru_bloc(saved_fru_bloc);
|
|
+ }
|
|
|
|
- return ((doffset+off) >= finish);
|
|
+ return doffset >= finish;
|
|
}
|
|
-#endif
|
|
|
|
/* read_fru_area - fill in frubuf[offset:length] from the FRU[offset:length]
|
|
*
|
|
@@ -749,7 +585,6 @@ int
|
|
read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
|
|
uint32_t offset, uint32_t length, uint8_t *frubuf)
|
|
{
|
|
- static uint32_t fru_data_rqst_size = 20;
|
|
uint32_t off = offset, tmp, finish;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
@@ -775,29 +610,24 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
|
|
req.msg.data = msg_data;
|
|
req.msg.data_len = 4;
|
|
|
|
-#ifdef LIMIT_ALL_REQUEST_SIZE
|
|
- if (fru_data_rqst_size > 16)
|
|
-#else
|
|
- if (fru->access && fru_data_rqst_size > 16)
|
|
-#endif
|
|
- fru_data_rqst_size = 16;
|
|
-
|
|
+ if (fru->max_read_size == 0) {
|
|
+ /* subtract 1 byte for completion code and 1 for byte count */
|
|
+ fru->max_read_size = 32 - 2;
|
|
|
|
- /* Check if we receive size in parameters */
|
|
- if(intf->channel_buf_size != 0)
|
|
- {
|
|
- fru_data_rqst_size = intf->channel_buf_size - 9; /* Plan for overhead */
|
|
+ /* check word access */
|
|
+ if (fru->access) {
|
|
+ fru->max_read_size &= ~1;
|
|
+ }
|
|
}
|
|
|
|
-
|
|
do {
|
|
tmp = fru->access ? off >> 1 : off;
|
|
msg_data[0] = id;
|
|
msg_data[1] = (uint8_t)(tmp & 0xff);
|
|
msg_data[2] = (uint8_t)(tmp >> 8);
|
|
tmp = finish - off;
|
|
- if (tmp > fru_data_rqst_size)
|
|
- msg_data[3] = (uint8_t)fru_data_rqst_size;
|
|
+ if (tmp > fru->max_read_size)
|
|
+ msg_data[3] = (uint8_t)fru->max_read_size;
|
|
else
|
|
msg_data[3] = (uint8_t)tmp;
|
|
|
|
@@ -807,33 +637,43 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
|
|
break;
|
|
}
|
|
if (rsp->ccode > 0) {
|
|
- /* if we get C7 or C8 or CA return code then we requested too
|
|
+ /* if we get C8h or CAh completion code then we requested too
|
|
* many bytes at once so try again with smaller size */
|
|
- if ((rsp->ccode == 0xc7 || rsp->ccode == 0xc8 || rsp->ccode == 0xca) &&
|
|
- (--fru_data_rqst_size > 8)) {
|
|
+ if ((rsp->ccode == 0xc8 || rsp->ccode == 0xca)
|
|
+ && fru->max_read_size > 8) {
|
|
+ if (fru->max_read_size > 32) {
|
|
+ /* subtract read length more aggressively */
|
|
+ fru->max_read_size -= 8;
|
|
+ } else {
|
|
+ /* subtract length less aggressively */
|
|
+ fru->max_read_size--;
|
|
+ }
|
|
+
|
|
lprintf(LOG_INFO, "Retrying FRU read with request size %d",
|
|
- fru_data_rqst_size);
|
|
+ fru->max_read_size);
|
|
continue;
|
|
}
|
|
+
|
|
lprintf(LOG_NOTICE, "FRU Read failed: %s",
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
break;
|
|
}
|
|
|
|
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
|
|
- memcpy((frubuf + off), rsp->data + 1, tmp);
|
|
+ memcpy(frubuf, rsp->data + 1, tmp);
|
|
off += tmp;
|
|
-
|
|
+ frubuf += tmp;
|
|
/* sometimes the size returned in the Info command
|
|
* is too large. return 0 so higher level function
|
|
* still attempts to parse what was returned */
|
|
- if (tmp == 0 && off < finish)
|
|
+ if (tmp == 0 && off < finish) {
|
|
return 0;
|
|
-
|
|
+ }
|
|
} while (off < finish);
|
|
|
|
- if (off < finish)
|
|
+ if (off < finish) {
|
|
return -1;
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
@@ -1009,40 +849,48 @@ fru_area_print_chassis(struct ipmi_intf * intf, struct fru_info * fru,
|
|
uint8_t id, uint32_t offset)
|
|
{
|
|
char * fru_area;
|
|
- uint8_t * fru_data = NULL;
|
|
- uint32_t fru_len, area_len, i;
|
|
+ uint8_t * fru_data;
|
|
+ uint32_t fru_len, i;
|
|
+ uint8_t tmp[2];
|
|
|
|
- i = offset;
|
|
fru_len = 0;
|
|
|
|
- fru_data = malloc(fru->size + 1);
|
|
- if (fru_data == NULL) {
|
|
- lprintf(LOG_ERR, " Out of memory!");
|
|
+ /* read enough to check length field */
|
|
+ if (read_fru_area(intf, fru, id, offset, 2, tmp) == 0) {
|
|
+ fru_len = 8 * tmp[1];
|
|
+ }
|
|
+
|
|
+ if (fru_len == 0) {
|
|
return;
|
|
}
|
|
- memset(fru_data, 0, fru->size + 1);
|
|
|
|
- /* read enough to check length field */
|
|
- if (read_fru_area(intf, fru, id, i, 2, fru_data) == 0)
|
|
- fru_len = 8 * fru_data[i + 1];
|
|
- if (fru_len <= 0) {
|
|
- free(fru_data);
|
|
- fru_data = NULL;
|
|
+ fru_data = malloc(fru_len);
|
|
+ if (fru_data == NULL) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
return;
|
|
}
|
|
|
|
+ memset(fru_data, 0, fru_len);
|
|
+
|
|
/* read in the full fru */
|
|
- if (read_fru_area(intf, fru, id, i, fru_len, fru_data) < 0) {
|
|
+ if (read_fru_area(intf, fru, id, offset, fru_len, fru_data) < 0) {
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
return;
|
|
}
|
|
|
|
- i++; /* skip fru area version */
|
|
- area_len = fru_data[i++] * 8; /* fru area length */
|
|
+ /*
|
|
+ * skip first two bytes which specify
|
|
+ * fru area version and fru area length
|
|
+ */
|
|
+ i = 2;
|
|
|
|
printf(" Chassis Type : %s\n",
|
|
- chassis_type_desc[fru_data[i++]]);
|
|
+ chassis_type_desc[fru_data[i] >
|
|
+ (sizeof(chassis_type_desc)/sizeof(chassis_type_desc[0])) - 1 ?
|
|
+ 2 : fru_data[i]]);
|
|
+
|
|
+ i++;
|
|
|
|
fru_area = get_fru_area_str(fru_data, &i);
|
|
if (fru_area != NULL) {
|
|
@@ -1063,7 +911,7 @@ fru_area_print_chassis(struct ipmi_intf * intf, struct fru_info * fru,
|
|
}
|
|
|
|
/* read any extra fields */
|
|
- while ((fru_data[i] != 0xc1) && (i < offset + area_len))
|
|
+ while ((fru_data[i] != 0xc1) && (i < fru_len))
|
|
{
|
|
int j = i;
|
|
fru_area = get_fru_area_str(fru_data, &i);
|
|
@@ -1074,8 +922,10 @@ fru_area_print_chassis(struct ipmi_intf * intf, struct fru_info * fru,
|
|
free(fru_area);
|
|
fru_area = NULL;
|
|
}
|
|
- if (i == j)
|
|
+
|
|
+ if (i == j) {
|
|
break;
|
|
+ }
|
|
}
|
|
|
|
if (fru_area != NULL) {
|
|
@@ -1096,39 +946,45 @@ fru_area_print_board(struct ipmi_intf * intf, struct fru_info * fru,
|
|
uint8_t id, uint32_t offset)
|
|
{
|
|
char * fru_area;
|
|
- uint8_t * fru_data = NULL;
|
|
- uint32_t fru_len, area_len, i;
|
|
+ uint8_t * fru_data;
|
|
+ uint32_t fru_len;
|
|
+ uint32_t i;
|
|
time_t tval;
|
|
+ uint8_t tmp[2];
|
|
|
|
- i = offset;
|
|
fru_len = 0;
|
|
|
|
- fru_data = malloc(fru->size + 1);
|
|
- if (fru_data == NULL) {
|
|
- lprintf(LOG_ERR, " Out of memory!");
|
|
- return;
|
|
+ /* read enough to check length field */
|
|
+ if (read_fru_area(intf, fru, id, offset, 2, tmp) == 0) {
|
|
+ fru_len = 8 * tmp[1];
|
|
}
|
|
- memset(fru_data, 0, fru->size + 1);
|
|
|
|
- /* read enough to check length field */
|
|
- if (read_fru_area(intf, fru, id, i, 2, fru_data) == 0)
|
|
- fru_len = 8 * fru_data[i + 1];
|
|
if (fru_len <= 0) {
|
|
- free(fru_data);
|
|
- fru_data = NULL;
|
|
return;
|
|
}
|
|
|
|
+ fru_data = malloc(fru_len);
|
|
+ if (fru_data == NULL) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ memset(fru_data, 0, fru_len);
|
|
+
|
|
/* read in the full fru */
|
|
- if (read_fru_area(intf, fru, id, i, fru_len, fru_data) < 0) {
|
|
+ if (read_fru_area(intf, fru, id, offset, fru_len, fru_data) < 0) {
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
return;
|
|
}
|
|
|
|
- i++; /* skip fru area version */
|
|
- area_len = fru_data[i++] * 8; /* fru area length */
|
|
- i++; /* skip fru board language */
|
|
+ /*
|
|
+ * skip first three bytes which specify
|
|
+ * fru area version, fru area length
|
|
+ * and fru board language
|
|
+ */
|
|
+ i = 3;
|
|
+
|
|
tval=((fru_data[i+2] << 16) + (fru_data[i+1] << 8) + (fru_data[i]));
|
|
tval=tval * 60;
|
|
tval=tval + secs_from_1970_1996;
|
|
@@ -1181,7 +1037,7 @@ fru_area_print_board(struct ipmi_intf * intf, struct fru_info * fru,
|
|
}
|
|
|
|
/* read any extra fields */
|
|
- while ((fru_data[i] != 0xc1) && (i < offset + area_len))
|
|
+ while ((fru_data[i] != 0xc1) && (i < fru_len))
|
|
{
|
|
int j = i;
|
|
fru_area = get_fru_area_str(fru_data, &i);
|
|
@@ -1213,39 +1069,44 @@ static void
|
|
fru_area_print_product(struct ipmi_intf * intf, struct fru_info * fru,
|
|
uint8_t id, uint32_t offset)
|
|
{
|
|
- char * fru_area = NULL;
|
|
- uint8_t * fru_data = NULL;
|
|
- uint32_t fru_len, area_len, i;
|
|
+ char * fru_area;
|
|
+ uint8_t * fru_data;
|
|
+ uint32_t fru_len, i;
|
|
+ uint8_t tmp[2];
|
|
|
|
- i = offset;
|
|
fru_len = 0;
|
|
|
|
- fru_data = malloc(fru->size + 1);
|
|
- if (fru_data == NULL) {
|
|
- lprintf(LOG_ERR, " Out of memory!");
|
|
+ /* read enough to check length field */
|
|
+ if (read_fru_area(intf, fru, id, offset, 2, tmp) == 0) {
|
|
+ fru_len = 8 * tmp[1];
|
|
+ }
|
|
+
|
|
+ if (fru_len == 0) {
|
|
return;
|
|
}
|
|
- memset(fru_data, 0, fru->size + 1);
|
|
|
|
- /* read enough to check length field */
|
|
- if (read_fru_area(intf, fru, id, i, 2, fru_data) == 0)
|
|
- fru_len = 8 * fru_data[i + 1];
|
|
- if (fru_len <= 0) {
|
|
- free(fru_data);
|
|
- fru_data = NULL;
|
|
+ fru_data = malloc(fru_len);
|
|
+ if (fru_data == NULL) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
return;
|
|
}
|
|
|
|
+ memset(fru_data, 0, fru_len);
|
|
+
|
|
+
|
|
/* read in the full fru */
|
|
- if (read_fru_area(intf, fru, id, i, fru_len, fru_data) < 0) {
|
|
+ if (read_fru_area(intf, fru, id, offset, fru_len, fru_data) < 0) {
|
|
free(fru_data);
|
|
fru_data = NULL;
|
|
return;
|
|
}
|
|
|
|
- i++; /* skip fru area version */
|
|
- area_len = fru_data[i++] * 8; /* fru area length */
|
|
- i++; /* skip fru board language */
|
|
+ /*
|
|
+ * skip first three bytes which specify
|
|
+ * fru area version, fru area length
|
|
+ * and fru board language
|
|
+ */
|
|
+ i = 3;
|
|
|
|
fru_area = get_fru_area_str(fru_data, &i);
|
|
if (fru_area != NULL) {
|
|
@@ -1311,7 +1172,7 @@ fru_area_print_product(struct ipmi_intf * intf, struct fru_info * fru,
|
|
}
|
|
|
|
/* read any extra fields */
|
|
- while ((fru_data[i] != 0xc1) && (i < offset + area_len))
|
|
+ while ((fru_data[i] != 0xc1) && (i < fru_len))
|
|
{
|
|
int j = i;
|
|
fru_area = get_fru_area_str(fru_data, &i);
|
|
@@ -1344,46 +1205,42 @@ fru_area_print_multirec(struct ipmi_intf * intf, struct fru_info * fru,
|
|
uint8_t id, uint32_t offset)
|
|
{
|
|
uint8_t * fru_data;
|
|
- uint32_t fru_len, i;
|
|
struct fru_multirec_header * h;
|
|
struct fru_multirec_powersupply * ps;
|
|
struct fru_multirec_dcoutput * dc;
|
|
struct fru_multirec_dcload * dl;
|
|
uint16_t peak_capacity;
|
|
uint8_t peak_hold_up_time;
|
|
- uint32_t last_off, len;
|
|
+ uint32_t last_off;
|
|
|
|
- i = last_off = offset;
|
|
- fru_len = 0;
|
|
+ last_off = offset;
|
|
|
|
- fru_data = malloc(fru->size + 1);
|
|
+ fru_data = malloc(FRU_MULTIREC_CHUNK_SIZE);
|
|
if (fru_data == NULL) {
|
|
- lprintf(LOG_ERR, " Out of memory!");
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
return;
|
|
}
|
|
- memset(fru_data, 0, fru->size + 1);
|
|
|
|
- do {
|
|
- h = (struct fru_multirec_header *) (fru_data + i);
|
|
+ memset(fru_data, 0, FRU_MULTIREC_CHUNK_SIZE);
|
|
|
|
- /* read area in (at most) FRU_MULTIREC_CHUNK_SIZE bytes at a time */
|
|
- if ((last_off < (i + sizeof(*h))) || (last_off < (i + h->len)))
|
|
- {
|
|
- len = fru->size - last_off;
|
|
- if (len > FRU_MULTIREC_CHUNK_SIZE)
|
|
- len = FRU_MULTIREC_CHUNK_SIZE;
|
|
+ h = (struct fru_multirec_header *) (fru_data);
|
|
|
|
- if (read_fru_area(intf, fru, id, last_off, len, fru_data) < 0)
|
|
- break;
|
|
+ do {
|
|
+ if (read_fru_area(intf, fru, id, last_off, sizeof(*h), fru_data) < 0) {
|
|
+ break;
|
|
+ }
|
|
|
|
- last_off += len;
|
|
+ if (h->len && read_fru_area(intf, fru, id,
|
|
+ last_off + sizeof(*h), h->len, fru_data + sizeof(*h)) < 0) {
|
|
+ break;
|
|
}
|
|
|
|
- switch (h->type)
|
|
- {
|
|
+ last_off += h->len + sizeof(*h);
|
|
+
|
|
+ switch (h->type) {
|
|
case FRU_RECORD_TYPE_POWER_SUPPLY_INFORMATION:
|
|
ps = (struct fru_multirec_powersupply *)
|
|
- (fru_data + i + sizeof (struct fru_multirec_header));
|
|
+ (fru_data + sizeof(struct fru_multirec_header));
|
|
|
|
#if WORDS_BIGENDIAN
|
|
ps->capacity = BSWAP_16(ps->capacity);
|
|
@@ -1441,7 +1298,7 @@ fru_area_print_multirec(struct ipmi_intf * intf, struct fru_info * fru,
|
|
|
|
case FRU_RECORD_TYPE_DC_OUTPUT:
|
|
dc = (struct fru_multirec_dcoutput *)
|
|
- (fru_data + i + sizeof (struct fru_multirec_header));
|
|
+ (fru_data + sizeof(struct fru_multirec_header));
|
|
|
|
#if WORDS_BIGENDIAN
|
|
dc->nominal_voltage = BSWAP_16(dc->nominal_voltage);
|
|
@@ -1473,7 +1330,7 @@ fru_area_print_multirec(struct ipmi_intf * intf, struct fru_info * fru,
|
|
|
|
case FRU_RECORD_TYPE_DC_LOAD:
|
|
dl = (struct fru_multirec_dcload *)
|
|
- (fru_data + i + sizeof (struct fru_multirec_header));
|
|
+ (fru_data + sizeof(struct fru_multirec_header));
|
|
|
|
#if WORDS_BIGENDIAN
|
|
dl->nominal_voltage = BSWAP_16(dl->nominal_voltage);
|
|
@@ -1503,7 +1360,7 @@ fru_area_print_multirec(struct ipmi_intf * intf, struct fru_info * fru,
|
|
case FRU_RECORD_TYPE_OEM_EXTENSION:
|
|
{
|
|
struct fru_multirec_oem_header *oh=(struct fru_multirec_oem_header *)
|
|
- &fru_data[i + sizeof(struct fru_multirec_header)];
|
|
+ &fru_data[sizeof(struct fru_multirec_header)];
|
|
uint32_t iana = oh->mfg_id[0] | oh->mfg_id[1]<<8 | oh->mfg_id[2]<<16;
|
|
|
|
/* Now makes sure this is really PICMG record */
|
|
@@ -1511,7 +1368,7 @@ fru_area_print_multirec(struct ipmi_intf * intf, struct fru_info * fru,
|
|
if( iana == IPMI_OEM_PICMG ){
|
|
printf(" PICMG Extension Record\n");
|
|
ipmi_fru_picmg_ext_print(fru_data,
|
|
- i + sizeof(struct fru_multirec_header),
|
|
+ sizeof(struct fru_multirec_header),
|
|
h->len);
|
|
}
|
|
/* FIXME: Add OEM record support here */
|
|
@@ -1521,13 +1378,11 @@ fru_area_print_multirec(struct ipmi_intf * intf, struct fru_info * fru,
|
|
}
|
|
break;
|
|
}
|
|
- i += h->len + sizeof (struct fru_multirec_header);
|
|
} while (!(h->format & 0x80));
|
|
|
|
- lprintf(LOG_DEBUG ,"Multi-Record area ends at: %i (%xh)",i,i);
|
|
+ lprintf(LOG_DEBUG ,"Multi-Record area ends at: %i (%xh)", last_off, last_off);
|
|
|
|
free(fru_data);
|
|
- fru_data = NULL;
|
|
}
|
|
|
|
/* ipmi_fru_query_new_value - Query new values to replace original FRU content
|
|
@@ -2309,7 +2164,7 @@ static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length)
|
|
minexp / 2, (minexp % 2) * 5);
|
|
} else {
|
|
printf(
|
|
- " Min Expected Voltage: -36V (actual invalid value 0x%x)\n",
|
|
+ " Min Expected Voltage: -%dV (actual invalid value 0x%x)\n",
|
|
36, minexp);
|
|
}
|
|
for (j=0; j < entries; j++) {
|
|
@@ -2986,6 +2841,7 @@ __ipmi_fru_print(struct ipmi_intf * intf, uint8_t id)
|
|
return -1;
|
|
}
|
|
|
|
+ memset(&fru, 0, sizeof(fru));
|
|
fru.size = (rsp->data[1] << 8) | rsp->data[0];
|
|
fru.access = rsp->data[2] & 0x1;
|
|
|
|
@@ -3088,7 +2944,8 @@ int
|
|
ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
|
|
{
|
|
char desc[17];
|
|
- uint32_t save_addr = 0;
|
|
+ uint8_t bridged_request = 0;
|
|
+ uint32_t save_addr;
|
|
uint32_t save_channel;
|
|
int rc = 0;
|
|
|
|
@@ -3131,6 +2988,7 @@ ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
|
|
case 0x02:
|
|
if (BRIDGE_TO_SENSOR(intf, fru->dev_slave_addr,
|
|
fru->channel_num)) {
|
|
+ bridged_request = 1;
|
|
save_addr = intf->target_addr;
|
|
intf->target_addr = fru->dev_slave_addr;
|
|
save_channel = intf->target_channel;
|
|
@@ -3138,7 +2996,7 @@ ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
|
|
}
|
|
/* print FRU */
|
|
rc = __ipmi_fru_print(intf, fru->device_id);
|
|
- if (save_addr) {
|
|
+ if (bridged_request) {
|
|
intf->target_addr = save_addr;
|
|
intf->target_channel = save_channel;
|
|
}
|
|
@@ -3316,6 +3174,8 @@ ipmi_fru_read_to_bin(struct ipmi_intf * intf,
|
|
printf (" Timeout accessing FRU info. (Device not present?)\n");
|
|
return;
|
|
}
|
|
+
|
|
+ memset(&fru, 0, sizeof(fru));
|
|
fru.size = (rsp->data[1] << 8) | rsp->data[0];
|
|
fru.access = rsp->data[2] & 0x1;
|
|
|
|
@@ -3382,6 +3242,8 @@ ipmi_fru_write_from_bin(struct ipmi_intf * intf,
|
|
printf(" Timeout accessing FRU info. (Device not present?)\n");
|
|
return;
|
|
}
|
|
+
|
|
+ memset(&fru, 0, sizeof(fru));
|
|
fru.size = (rsp->data[1] << 8) | rsp->data[0];
|
|
fru.access = rsp->data[2] & 0x1;
|
|
|
|
@@ -3501,6 +3363,7 @@ ipmi_fru_edit_multirec(struct ipmi_intf * intf, uint8_t id ,
|
|
return -1;
|
|
}
|
|
|
|
+ memset(&fru, 0, sizeof(fru));
|
|
fru.size = (rsp->data[1] << 8) | rsp->data[0];
|
|
fru.access = rsp->data[2] & 0x1;
|
|
|
|
@@ -3524,6 +3387,7 @@ ipmi_fru_edit_multirec(struct ipmi_intf * intf, uint8_t id ,
|
|
i = last_off = offset;
|
|
fru_len = 0;
|
|
|
|
+ memset(&fru, 0, sizeof(fru));
|
|
fru_data = malloc(fru.size + 1);
|
|
if (fru_data == NULL) {
|
|
lprintf(LOG_ERR, " Out of memory!");
|
|
@@ -3702,6 +3566,7 @@ ipmi_fru_get_multirec(struct ipmi_intf * intf, uint8_t id ,
|
|
return -1;
|
|
}
|
|
|
|
+ memset(&fru, 0, sizeof(fru));
|
|
fru.size = (rsp->data[1] << 8) | rsp->data[0];
|
|
fru.access = rsp->data[2] & 0x1;
|
|
|
|
@@ -4171,6 +4036,7 @@ ipmi_fru_get_internal_use_info( struct ipmi_intf * intf,
|
|
return -1;
|
|
}
|
|
|
|
+ memset(&fru, 0, sizeof(fru));
|
|
fru->size = (rsp->data[1] << 8) | rsp->data[0];
|
|
fru->access = rsp->data[2] & 0x1;
|
|
|
|
@@ -4755,6 +4621,7 @@ f_type, uint8_t f_index, char *f_string)
|
|
goto ipmi_fru_set_field_string_out;
|
|
}
|
|
|
|
+ memset(&fru, 0, sizeof(fru));
|
|
fru.size = (rsp->data[1] << 8) | rsp->data[0];
|
|
fru.access = rsp->data[2] & 0x1;
|
|
|
|
diff --git a/ipmitool/lib/ipmi_fwum.c b/ipmitool/lib/ipmi_fwum.c
|
|
index d9b562c..b666a2b 100644
|
|
--- a/ipmitool/lib/ipmi_fwum.c
|
|
+++ b/ipmitool/lib/ipmi_fwum.c
|
|
@@ -19,7 +19,7 @@
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
- * This software is provided "AS IS," without a warranty of any kind.
|
|
+ * This software is provided "AS IS," without a warranty of any kind.
|
|
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
|
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
|
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
|
@@ -33,7 +33,6 @@
|
|
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
*/
|
|
|
|
-
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
@@ -46,421 +45,259 @@
|
|
#include <ipmitool/ipmi_intf.h>
|
|
#include <ipmitool/ipmi_mc.h>
|
|
|
|
-/******************************************************************************
|
|
-* HISTORY
|
|
-* ===========================================================================
|
|
-* 2007-01-11 [FI]
|
|
-* - Incremented to version 1.3
|
|
-* - Added lan packet size reduction mechanism to workaround fact
|
|
-* that lan iface will not return C7 on excessive length
|
|
-*
|
|
-*****************************************************************************/
|
|
-
|
|
-#define VERSION_MAJ 1
|
|
-#define VERSION_MIN 3
|
|
-
|
|
-
|
|
-typedef enum eKFWUM_Task
|
|
-{
|
|
- KFWUM_TASK_INFO,
|
|
- KFWUM_TASK_STATUS,
|
|
- KFWUM_TASK_DOWNLOAD,
|
|
- KFWUM_TASK_UPGRADE,
|
|
- KFWUM_TASK_START_UPGRADE,
|
|
- KFWUM_TASK_ROLLBACK,
|
|
- KFWUM_TASK_TRACELOG
|
|
-}tKFWUM_Task;
|
|
-
|
|
-typedef enum eKFWUM_BoardList
|
|
-{
|
|
- KFWUM_BOARD_KONTRON_UNKNOWN = 0,
|
|
- KFWUM_BOARD_KONTRON_5002 = 5002,
|
|
-}tKFWUM_BoardList;
|
|
-
|
|
-typedef enum eKFWUM_IanaList
|
|
-{
|
|
- KFWUM_IANA_KONTRON = 15000,
|
|
-}tKFWUM_IanaList;
|
|
-
|
|
-typedef struct sKFWUM_BoardInfo
|
|
-{
|
|
- tKFWUM_BoardList boardId;
|
|
- tKFWUM_IanaList iana;
|
|
-}tKFWUM_BoardInfo;
|
|
-
|
|
-typedef enum eKFWUM_Status
|
|
-{
|
|
- KFWUM_STATUS_OK,
|
|
- KFWUM_STATUS_ERROR
|
|
-}tKFWUM_Status;
|
|
-
|
|
-typedef enum eKFWUM_DownloadType
|
|
-{
|
|
- KFWUM_DOWNLOAD_TYPE_ADDRESS = 0,
|
|
- KFWUM_DOWNLOAD_TYPE_SEQUENCE,
|
|
-}tKFWUM_DownloadType;
|
|
+extern int verbose;
|
|
+unsigned char firmBuf[1024*512];
|
|
+tKFWUM_SaveFirmwareInfo save_fw_nfo;
|
|
+
|
|
+int KfwumGetFileSize(const char *pFileName,
|
|
+ unsigned long *pFileSize);
|
|
+int KfwumSetupBuffersFromFile(const char *pFileName,
|
|
+ unsigned long fileSize);
|
|
+void KfwumShowProgress(const char *task, unsigned long current,
|
|
+ unsigned long total);
|
|
+unsigned short KfwumCalculateChecksumPadding(unsigned char *pBuffer,
|
|
+ unsigned long totalSize);
|
|
+int KfwumGetInfo(struct ipmi_intf *intf, unsigned char output,
|
|
+ unsigned char *pNumBank);
|
|
+int KfwumGetDeviceInfo(struct ipmi_intf *intf,
|
|
+ unsigned char output, tKFWUM_BoardInfo *pBoardInfo);
|
|
+int KfwumGetStatus(struct ipmi_intf *intf);
|
|
+int KfwumManualRollback(struct ipmi_intf *intf);
|
|
+int KfwumStartFirmwareImage(struct ipmi_intf *intf,
|
|
+ unsigned long length, unsigned short padding);
|
|
+int KfwumSaveFirmwareImage(struct ipmi_intf *intf,
|
|
+ unsigned char sequenceNumber, unsigned long address,
|
|
+ unsigned char *pFirmBuf, unsigned char *pInBufLength);
|
|
+int KfwumFinishFirmwareImage(struct ipmi_intf *intf,
|
|
+ tKFWUM_InFirmwareInfo firmInfo);
|
|
+int KfwumUploadFirmware(struct ipmi_intf *intf,
|
|
+ unsigned char *pBuffer, unsigned long totalSize);
|
|
+int KfwumStartFirmwareUpgrade(struct ipmi_intf *intf);
|
|
+int KfwumGetInfoFromFirmware(unsigned char *pBuf,
|
|
+ unsigned long bufSize, tKFWUM_InFirmwareInfo *pInfo);
|
|
+void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo *pInfo);
|
|
+int KfwumGetTraceLog(struct ipmi_intf *intf);
|
|
+int ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo,
|
|
+ tKFWUM_InFirmwareInfo firmInfo);
|
|
+
|
|
+int ipmi_fwum_fwupgrade(struct ipmi_intf *intf, char *file, int action);
|
|
+int ipmi_fwum_info(struct ipmi_intf *intf);
|
|
+int ipmi_fwum_status(struct ipmi_intf *intf);
|
|
+void printf_kfwum_help(void);
|
|
+void printf_kfwum_info(tKFWUM_BoardInfo boardInfo,
|
|
+ tKFWUM_InFirmwareInfo firmInfo);
|
|
|
|
-typedef enum eKFWUM_DownloadBuffferType
|
|
-{
|
|
- KFWUM_SMALL_BUFFER_TYPE = 0,
|
|
- KFUMW_BIG_BUFFER_TYPE
|
|
-}tKFWUM_DownloadBuffferType;
|
|
+/* String table */
|
|
+/* Must match eFWUM_CmdId */
|
|
+const char *CMD_ID_STRING[] = {
|
|
+ "GetFwInfo",
|
|
+ "KickWatchdog",
|
|
+ "GetLastAnswer",
|
|
+ "BootHandshake",
|
|
+ "ReportStatus",
|
|
+ "CtrlIPMBLine",
|
|
+ "SetFwState",
|
|
+ "GetFwStatus",
|
|
+ "GetSpiMemStatus",
|
|
+ "StartFwUpdate",
|
|
+ "StartFwImage",
|
|
+ "SaveFwImage",
|
|
+ "FinishFwImage",
|
|
+ "ReadFwImage",
|
|
+ "ManualRollback",
|
|
+ "GetTraceLog"
|
|
+};
|
|
|
|
-typedef struct sKFWUM_InFirmwareInfo
|
|
-{
|
|
- unsigned long fileSize;
|
|
- unsigned short checksum;
|
|
- unsigned short sumToRemoveFromChecksum;
|
|
- /* Since the checksum is added in the bin
|
|
- after the checksum is calculated, we
|
|
- need to remove the each byte value. This
|
|
- byte will contain the addition of both bytes*/
|
|
- tKFWUM_BoardList boardId;
|
|
- unsigned char deviceId;
|
|
- unsigned char tableVers;
|
|
- unsigned char implRev;
|
|
- unsigned char versMajor;
|
|
- unsigned char versMinor;
|
|
- unsigned char versSubMinor;
|
|
- unsigned char sdrRev;
|
|
- tKFWUM_IanaList iana;
|
|
-}tKFWUM_InFirmwareInfo;
|
|
-
|
|
-typedef struct sKFWUM_SaveFirmwareInfo
|
|
-{
|
|
- tKFWUM_DownloadType downloadType;
|
|
- unsigned char bufferSize;
|
|
- unsigned char overheadSize;
|
|
-}tKFWUM_SaveFirmwareInfo;
|
|
-
|
|
-#define KFWUM_SMALL_BUFFER 32 /* Minimum size (IPMB/IOL/old protocol) */
|
|
-#define KFWUM_BIG_BUFFER 32 /* Maximum size on KCS interface */
|
|
-
|
|
-#define KFWUM_OLD_CMD_OVERHEAD 6 /*3 address + 1 size + 1 checksum + 1 command*/
|
|
-#define KFWUM_NEW_CMD_OVERHEAD 4 /*1 sequence+ 1 size + 1 checksum + 1 command*/
|
|
-#define KFWUM_PAGE_SIZE 256
|
|
+const char *EXT_CMD_ID_STRING[] = {
|
|
+ "FwUpgradeLock",
|
|
+ "ProcessFwUpg",
|
|
+ "ProcessFwRb",
|
|
+ "WaitHSAfterUpg",
|
|
+ "WaitFirstHSUpg",
|
|
+ "FwInfoStateChange"
|
|
+};
|
|
|
|
-extern int verbose;
|
|
-static unsigned char fileName[512];
|
|
-static unsigned char firmBuf[1024*512];
|
|
-static tKFWUM_SaveFirmwareInfo saveFirmwareInfo;
|
|
-
|
|
-static void KfwumOutputHelp(void);
|
|
-static void KfwumMain(struct ipmi_intf * intf, tKFWUM_Task task);
|
|
-static tKFWUM_Status KfwumGetFileSize(unsigned char * pFileName,
|
|
- unsigned long * pFileSize);
|
|
-static tKFWUM_Status KfwumSetupBuffersFromFile(unsigned char * pFileName,
|
|
- unsigned long fileSize);
|
|
-static void KfwumShowProgress( const unsigned char * task,
|
|
- unsigned long current, unsigned long total);
|
|
-static unsigned short KfwumCalculateChecksumPadding(unsigned char * pBuffer,
|
|
- unsigned long totalSize);
|
|
-
|
|
-
|
|
-static tKFWUM_Status KfwumGetInfo(struct ipmi_intf * intf, unsigned char output,
|
|
- unsigned char *pNumBank);
|
|
-static tKFWUM_Status KfwumGetDeviceInfo(struct ipmi_intf * intf,
|
|
- unsigned char output, tKFWUM_BoardInfo * pBoardInfo);
|
|
-static tKFWUM_Status KfwumGetStatus(struct ipmi_intf * intf);
|
|
-static tKFWUM_Status KfwumManualRollback(struct ipmi_intf * intf);
|
|
-static tKFWUM_Status KfwumStartFirmwareImage(struct ipmi_intf * intf,
|
|
- unsigned long length,unsigned short padding);
|
|
-static tKFWUM_Status KfwumSaveFirmwareImage(struct ipmi_intf * intf,
|
|
- unsigned char sequenceNumber, unsigned long address,
|
|
- unsigned char *pFirmBuf, unsigned char * pInBufLength);
|
|
-static tKFWUM_Status KfwumFinishFirmwareImage(struct ipmi_intf * intf,
|
|
- tKFWUM_InFirmwareInfo firmInfo);
|
|
-static tKFWUM_Status KfwumUploadFirmware(struct ipmi_intf * intf,
|
|
- unsigned char * pBuffer, unsigned long totalSize);
|
|
-static tKFWUM_Status KfwumStartFirmwareUpgrade(struct ipmi_intf * intf);
|
|
-
|
|
-static tKFWUM_Status KfwumGetInfoFromFirmware(unsigned char * pBuf,
|
|
- unsigned long bufSize, tKFWUM_InFirmwareInfo * pInfo);
|
|
-static void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo);
|
|
-
|
|
-static tKFWUM_Status KfwumGetTraceLog(struct ipmi_intf * intf);
|
|
-
|
|
-tKFWUM_Status KfwumValidFirmwareForBoard(tKFWUM_BoardInfo boardInfo,
|
|
- tKFWUM_InFirmwareInfo firmInfo);
|
|
-static void KfwumOutputInfo(tKFWUM_BoardInfo boardInfo,
|
|
- tKFWUM_InFirmwareInfo firmInfo);
|
|
+const char *CMD_STATE_STRING[] = {
|
|
+ "Invalid",
|
|
+ "Begin",
|
|
+ "Progress",
|
|
+ "Completed"
|
|
+};
|
|
|
|
+const struct valstr bankStateValS[] = {
|
|
+ { 0x00, "Not programmed" },
|
|
+ { 0x01, "New firmware" },
|
|
+ { 0x02, "Wait for validation" },
|
|
+ { 0x03, "Last Known Good" },
|
|
+ { 0x04, "Previous Good" }
|
|
+};
|
|
|
|
/* ipmi_fwum_main - entry point for this ipmitool mode
|
|
*
|
|
- * @intf: ipmi interface
|
|
- * @arc : number of arguments
|
|
- * @argv : point to argument array
|
|
+ * @intf: ipmi interface
|
|
+ * @arc: number of arguments
|
|
+ * @argv: point to argument array
|
|
*
|
|
* returns 0 on success
|
|
* returns -1 on error
|
|
*/
|
|
-int ipmi_fwum_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
+int
|
|
+ipmi_fwum_main(struct ipmi_intf *intf, int argc, char **argv)
|
|
{
|
|
- printf("FWUM extension Version %d.%d\n", VERSION_MAJ, VERSION_MIN);
|
|
- if ((!argc) || ( !strncmp(argv[0], "help", 4)))
|
|
- {
|
|
- KfwumOutputHelp();
|
|
- }
|
|
- else
|
|
- {
|
|
- if (!strncmp(argv[0], "info", 4))
|
|
- {
|
|
- KfwumMain(intf, KFWUM_TASK_INFO);
|
|
- }
|
|
- else if (!strncmp(argv[0], "status", 6))
|
|
- {
|
|
- KfwumMain(intf, KFWUM_TASK_STATUS);
|
|
- }
|
|
- else if (!strncmp(argv[0], "rollback", 8))
|
|
- {
|
|
- KfwumMain(intf, KFWUM_TASK_ROLLBACK);
|
|
- }
|
|
- else if (!strncmp(argv[0], "download", 8))
|
|
- {
|
|
- if((argc >= 2) && (strlen(argv[1]) > 0))
|
|
- {
|
|
- /* There is a file name in the parameters */
|
|
- if(strlen(argv[1]) < 512)
|
|
- {
|
|
- strcpy((char *)fileName, argv[1]);
|
|
- printf("Firmware File Name : %s\n", fileName);
|
|
-
|
|
- KfwumMain(intf, KFWUM_TASK_DOWNLOAD);
|
|
- }
|
|
- else
|
|
- {
|
|
- fprintf(stderr,"File name must be smaller than 512 bytes\n");
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- fprintf(stderr,"A path and a file name must be specified\n");
|
|
- }
|
|
- }
|
|
- else if (!strncmp(argv[0], "upgrade", 7))
|
|
- {
|
|
- if((argc >= 2) && (strlen(argv[1]) > 0))
|
|
- {
|
|
- /* There is a file name in the parameters */
|
|
- if(strlen(argv[1]) < 512)
|
|
- {
|
|
- strcpy((char *)fileName, argv[1]);
|
|
- printf("Upgrading using file name %s\n", fileName);
|
|
- KfwumMain(intf, KFWUM_TASK_UPGRADE);
|
|
- }
|
|
- else
|
|
- {
|
|
- fprintf(stderr,"File name must be smaller than 512 bytes\n");
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- KfwumMain(intf, KFWUM_TASK_START_UPGRADE);
|
|
- }
|
|
-
|
|
- }
|
|
- else if (!strncmp(argv[0], "tracelog", 8))
|
|
- {
|
|
- KfwumMain(intf, KFWUM_TASK_TRACELOG);
|
|
- }
|
|
- else
|
|
- {
|
|
- printf("Invalid KFWUM command: %s\n", argv[0]);
|
|
- }
|
|
- }
|
|
- return 0;
|
|
+ int rc = 0;
|
|
+ printf("FWUM extension Version %d.%d\n", VER_MAJOR, VER_MINOR);
|
|
+ if (argc < 1) {
|
|
+ lprintf(LOG_ERR, "Not enough parameters given.");
|
|
+ printf_kfwum_help();
|
|
+ return (-1);
|
|
+ }
|
|
+ if (strncmp(argv[0], "help", 4) == 0) {
|
|
+ printf_kfwum_help();
|
|
+ rc = 0;
|
|
+ } else if (strncmp(argv[0], "info", 4) == 0) {
|
|
+ rc = ipmi_fwum_info(intf);
|
|
+ } else if (strncmp(argv[0], "status", 6) == 0) {
|
|
+ rc = ipmi_fwum_status(intf);
|
|
+ } else if (strncmp(argv[0], "rollback", 8) == 0) {
|
|
+ rc = KfwumManualRollback(intf);
|
|
+ } else if (strncmp(argv[0], "download", 8) == 0) {
|
|
+ if ((argc < 2) || (strlen(argv[1]) < 1)) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Path and file name must be specified.");
|
|
+ return (-1);
|
|
+ }
|
|
+ printf("Firmware File Name : %s\n", argv[1]);
|
|
+ rc = ipmi_fwum_fwupgrade(intf, argv[1], 0);
|
|
+ } else if (strncmp(argv[0], "upgrade", 7) == 0) {
|
|
+ if ((argc >= 2) && (strlen(argv[1]) > 0)) {
|
|
+ printf("Upgrading using file name %s\n", argv[1]);
|
|
+ rc = ipmi_fwum_fwupgrade(intf, argv[1], 1);
|
|
+ } else {
|
|
+ rc = KfwumStartFirmwareUpgrade(intf);
|
|
+ }
|
|
+ } else if (strncmp(argv[0], "tracelog", 8) == 0) {
|
|
+ rc = KfwumGetTraceLog(intf);
|
|
+ } else {
|
|
+ lprintf(LOG_ERR, "Invalid KFWUM command: %s", argv[0]);
|
|
+ printf_kfwum_help();
|
|
+ rc = (-1);
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-
|
|
-static void KfwumOutputHelp(void)
|
|
+void
|
|
+printf_kfwum_help(void)
|
|
{
|
|
- printf("KFWUM Commands: info status download upgrade rollback tracelog\n");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"KFWUM Commands: info status download upgrade rollback tracelog");
|
|
}
|
|
|
|
-
|
|
-/****************************************/
|
|
-/** private definitions and macros **/
|
|
-/****************************************/
|
|
+/* private definitions and macros */
|
|
typedef enum eFWUM_CmdId
|
|
{
|
|
- KFWUM_CMD_ID_GET_FIRMWARE_INFO = 0,
|
|
- KFWUM_CMD_ID_KICK_IPMC_WATCHDOG = 1,
|
|
- KFWUM_CMD_ID_GET_LAST_ANSWER = 2,
|
|
- KFWUM_CMD_ID_BOOT_HANDSHAKE = 3,
|
|
- KFWUM_CMD_ID_REPORT_STATUS = 4,
|
|
- KFWUM_CMD_ID_GET_FIRMWARE_STATUS = 7,
|
|
- KFWUM_CMD_ID_START_FIRMWARE_UPDATE = 9,
|
|
- KFWUM_CMD_ID_START_FIRMWARE_IMAGE = 0x0a,
|
|
- KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE = 0x0b,
|
|
- KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE = 0x0c,
|
|
- KFWUM_CMD_ID_READ_FIRMWARE_IMAGE = 0x0d,
|
|
- KFWUM_CMD_ID_MANUAL_ROLLBACK = 0x0e,
|
|
- KFWUM_CMD_ID_GET_TRACE_LOG = 0x0f,
|
|
- KFWUM_CMD_ID_STD_MAX_CMD,
|
|
- KFWUM_CMD_ID_EXTENDED_CMD = 0xC0
|
|
+ KFWUM_CMD_ID_GET_FIRMWARE_INFO = 0,
|
|
+ KFWUM_CMD_ID_KICK_IPMC_WATCHDOG = 1,
|
|
+ KFWUM_CMD_ID_GET_LAST_ANSWER = 2,
|
|
+ KFWUM_CMD_ID_BOOT_HANDSHAKE = 3,
|
|
+ KFWUM_CMD_ID_REPORT_STATUS = 4,
|
|
+ KFWUM_CMD_ID_GET_FIRMWARE_STATUS = 7,
|
|
+ KFWUM_CMD_ID_START_FIRMWARE_UPDATE = 9,
|
|
+ KFWUM_CMD_ID_START_FIRMWARE_IMAGE = 0x0a,
|
|
+ KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE = 0x0b,
|
|
+ KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE = 0x0c,
|
|
+ KFWUM_CMD_ID_READ_FIRMWARE_IMAGE = 0x0d,
|
|
+ KFWUM_CMD_ID_MANUAL_ROLLBACK = 0x0e,
|
|
+ KFWUM_CMD_ID_GET_TRACE_LOG = 0x0f,
|
|
+ KFWUM_CMD_ID_STD_MAX_CMD,
|
|
+ KFWUM_CMD_ID_EXTENDED_CMD = 0xC0
|
|
} tKFWUM_CmdId;
|
|
|
|
-
|
|
-
|
|
-/****************************************/
|
|
-/** global/static variables definition **/
|
|
-/****************************************/
|
|
-
|
|
-/****************************************/
|
|
-/** functions definition **/
|
|
-/****************************************/
|
|
-
|
|
-/*******************************************************************************
|
|
-*
|
|
-* Function Name: KfwumMain
|
|
-*
|
|
-* Description: This function implements the upload of the firware data
|
|
-* received as parameters.
|
|
-*
|
|
-* Restriction: Called only from main
|
|
-*
|
|
-* Input: unsigned char * pBuffer[] : The buffers
|
|
-* unsigned long bufSize : The size of the buffers
|
|
-*
|
|
-* Output: None
|
|
-*
|
|
-* Global: none
|
|
-*
|
|
-* Return: tIFWU_Status (success or failure)
|
|
-*
|
|
-*******************************************************************************/
|
|
-static void KfwumMain(struct ipmi_intf * intf, tKFWUM_Task task)
|
|
+int
|
|
+ipmi_fwum_info(struct ipmi_intf *intf)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
- tKFWUM_BoardInfo boardInfo;
|
|
- tKFWUM_InFirmwareInfo firmInfo = { 0 };
|
|
- unsigned long fileSize = 0;
|
|
- static unsigned short padding;
|
|
-
|
|
- if((status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_INFO))
|
|
- {
|
|
- unsigned char notUsed;
|
|
- if(verbose)
|
|
- {
|
|
- printf("Getting Kontron FWUM Info\n");
|
|
- }
|
|
- KfwumGetDeviceInfo(intf, 1, &boardInfo);
|
|
- KfwumGetInfo(intf, 1, ¬Used);
|
|
-
|
|
- }
|
|
-
|
|
-
|
|
- if((status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_STATUS))
|
|
- {
|
|
- if(verbose)
|
|
- {
|
|
- printf("Getting Kontron FWUM Status\n");
|
|
- }
|
|
- KfwumGetStatus(intf);
|
|
- }
|
|
-
|
|
- if( (status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_ROLLBACK) )
|
|
- {
|
|
- status = KfwumManualRollback(intf);
|
|
- }
|
|
-
|
|
- if(
|
|
- (status == KFWUM_STATUS_OK) &&
|
|
- (
|
|
- (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD)
|
|
- )
|
|
- )
|
|
- {
|
|
- status = KfwumGetFileSize(fileName, &fileSize);
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- status = KfwumSetupBuffersFromFile(fileName, fileSize);
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- padding = KfwumCalculateChecksumPadding(firmBuf, fileSize);
|
|
- }
|
|
- }
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- status = KfwumGetInfoFromFirmware(firmBuf, fileSize, &firmInfo);
|
|
- }
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- status = KfwumGetDeviceInfo(intf, 0, &boardInfo);
|
|
- }
|
|
-
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- status = KfwumValidFirmwareForBoard(boardInfo,firmInfo);
|
|
- }
|
|
-
|
|
- if (status == KFWUM_STATUS_OK)
|
|
- {
|
|
- unsigned char notUsed;
|
|
- KfwumGetInfo(intf, 0, ¬Used);
|
|
- }
|
|
-
|
|
- KfwumOutputInfo(boardInfo,firmInfo);
|
|
- }
|
|
-
|
|
- if(
|
|
- (status == KFWUM_STATUS_OK) &&
|
|
- (
|
|
- (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD)
|
|
- )
|
|
- )
|
|
- {
|
|
- status = KfwumStartFirmwareImage(intf, fileSize, padding);
|
|
- }
|
|
-
|
|
-
|
|
- if(
|
|
- (status == KFWUM_STATUS_OK) &&
|
|
- (
|
|
- (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD)
|
|
- )
|
|
- )
|
|
- {
|
|
- status = KfwumUploadFirmware(intf, firmBuf, fileSize);
|
|
- }
|
|
-
|
|
- if(
|
|
- (status == KFWUM_STATUS_OK) &&
|
|
- (
|
|
- (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD)
|
|
- )
|
|
- )
|
|
- {
|
|
- status = KfwumFinishFirmwareImage(intf, firmInfo);
|
|
- }
|
|
-
|
|
- if(
|
|
- (status == KFWUM_STATUS_OK) &&
|
|
- (
|
|
- (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD)
|
|
- )
|
|
- )
|
|
- {
|
|
- status = KfwumGetStatus(intf);
|
|
- }
|
|
-
|
|
- if(
|
|
- (status == KFWUM_STATUS_OK) &&
|
|
- (
|
|
- (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_START_UPGRADE)
|
|
- )
|
|
- )
|
|
- {
|
|
- status = KfwumStartFirmwareUpgrade(intf);
|
|
- }
|
|
-
|
|
- if((status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_TRACELOG))
|
|
- {
|
|
- status = KfwumGetTraceLog(intf);
|
|
- }
|
|
+ tKFWUM_BoardInfo b_info;
|
|
+ int rc = 0;
|
|
+ unsigned char not_used;
|
|
+ if (verbose) {
|
|
+ printf("Getting Kontron FWUM Info\n");
|
|
+ }
|
|
+ if (KfwumGetDeviceInfo(intf, 1, &b_info) != 0) {
|
|
+ rc = (-1);
|
|
+ }
|
|
+ if (KfwumGetInfo(intf, 1, ¬_used) != 0) {
|
|
+ rc = (-1);
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
|
|
+int
|
|
+ipmi_fwum_status(struct ipmi_intf *intf)
|
|
+{
|
|
+ if (verbose) {
|
|
+ printf("Getting Kontron FWUM Status\n");
|
|
+ }
|
|
+ if (KfwumGetStatus(intf) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
|
|
+/* ipmi_fwum_fwupgrade - function implements download/upload of the firmware
|
|
+ * data received as parameters
|
|
+ *
|
|
+ * @file: fw file
|
|
+ * @action: 0 = download, 1 = upload/start upload
|
|
+ *
|
|
+ * returns 0 on success, otherwise (-1)
|
|
+ */
|
|
+int
|
|
+ipmi_fwum_fwupgrade(struct ipmi_intf *intf, char *file, int action)
|
|
+{
|
|
+ tKFWUM_BoardInfo b_info;
|
|
+ tKFWUM_InFirmwareInfo fw_info = { 0 };
|
|
+ unsigned short padding;
|
|
+ unsigned long fsize = 0;
|
|
+ unsigned char not_used;
|
|
+ if (file == NULL) {
|
|
+ lprintf(LOG_ERR, "No file given.");
|
|
+ return (-1);
|
|
+ }
|
|
+ if (KfwumGetFileSize(file, &fsize) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (KfwumSetupBuffersFromFile(file, fsize) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ padding = KfwumCalculateChecksumPadding(firmBuf, fsize);
|
|
+ if (KfwumGetInfoFromFirmware(firmBuf, fsize, &fw_info) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (KfwumGetDeviceInfo(intf, 0, &b_info) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (ipmi_kfwum_checkfwcompat(b_info, fw_info) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ KfwumGetInfo(intf, 0, ¬_used);
|
|
+ printf_kfwum_info(b_info, fw_info);
|
|
+ if (KfwumStartFirmwareImage(intf, fsize, padding) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (KfwumUploadFirmware(intf, firmBuf, fsize) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (KfwumFinishFirmwareImage(intf, fw_info) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (KfwumGetStatus(intf) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (action != 0) {
|
|
+ if (KfwumStartFirmwareUpgrade(intf) != 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
}
|
|
|
|
/* KfwumGetFileSize - gets the file size
|
|
@@ -468,31 +305,24 @@ static void KfwumMain(struct ipmi_intf * intf, tKFWUM_Task task)
|
|
* @pFileName : filename ptr
|
|
* @pFileSize : output ptr for filesize
|
|
*
|
|
- * returns KFWUM_STATUS_OK or KFWUM_STATUS_ERROR
|
|
+ * returns 0 on success, otherwise (-1)
|
|
*/
|
|
-static tKFWUM_Status KfwumGetFileSize(unsigned char * pFileName,
|
|
- unsigned long * pFileSize)
|
|
+int
|
|
+KfwumGetFileSize(const char *pFileName, unsigned long *pFileSize)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_ERROR;
|
|
- FILE * pFileHandle;
|
|
-
|
|
- pFileHandle = fopen((const char *)pFileName, "rb");
|
|
-
|
|
- if(pFileHandle)
|
|
- {
|
|
- if (fseek(pFileHandle, 0L , SEEK_END) == 0)
|
|
- {
|
|
- *pFileSize = ftell(pFileHandle);
|
|
-
|
|
- if( *pFileSize != 0)
|
|
- {
|
|
- status = KFWUM_STATUS_OK;
|
|
- }
|
|
- }
|
|
- fclose(pFileHandle);
|
|
- }
|
|
-
|
|
- return(status);
|
|
+ FILE *pFileHandle = NULL;
|
|
+ pFileHandle = fopen(pFileName, "rb");
|
|
+ if (pFileHandle == NULL) {
|
|
+ return (-1);
|
|
+ }
|
|
+ if (fseek(pFileHandle, 0L , SEEK_END) == 0) {
|
|
+ *pFileSize = ftell(pFileHandle);
|
|
+ }
|
|
+ fclose(pFileHandle);
|
|
+ if (*pFileSize != 0) {
|
|
+ return 0;
|
|
+ }
|
|
+ return (-1);
|
|
}
|
|
|
|
/* KfwumSetupBuffersFromFile - small buffers are used to store the file data
|
|
@@ -500,1182 +330,803 @@ static tKFWUM_Status KfwumGetFileSize(unsigned char * pFileName,
|
|
* @pFileName : filename ptr
|
|
* unsigned long : filesize
|
|
*
|
|
- * returns KFWUM_STATUS_OK or KFWUM_STATUS_ERROR
|
|
+ * returns 0 on success, otherwise (-1)
|
|
*/
|
|
-#define MAX_BUFFER_SIZE 1024*16
|
|
-static tKFWUM_Status KfwumSetupBuffersFromFile(unsigned char * pFileName,
|
|
- unsigned long fileSize)
|
|
+int
|
|
+KfwumSetupBuffersFromFile(const char *pFileName, unsigned long fileSize)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_ERROR;
|
|
+ int rc = (-1);
|
|
FILE *pFileHandle = NULL;
|
|
int count;
|
|
int modulus;
|
|
int qty = 0;
|
|
|
|
- pFileHandle = fopen((const char *)pFileName, "rb");
|
|
+ pFileHandle = fopen(pFileName, "rb");
|
|
if (pFileHandle == NULL) {
|
|
lprintf(LOG_ERR, "Failed to open '%s' for reading.",
|
|
- (char *)pFileName);
|
|
- return KFWUM_STATUS_ERROR;
|
|
+ pFileName);
|
|
+ return (-1);
|
|
}
|
|
count = fileSize / MAX_BUFFER_SIZE;
|
|
modulus = fileSize % MAX_BUFFER_SIZE;
|
|
|
|
rewind(pFileHandle);
|
|
- for (qty=0; qty < count; qty++) {
|
|
- KfwumShowProgress((const unsigned char *)"Reading Firmware from File",
|
|
+ for (qty = 0; qty < count; qty++) {
|
|
+ KfwumShowProgress("Reading Firmware from File",
|
|
qty, count);
|
|
if (fread(&firmBuf[qty * MAX_BUFFER_SIZE], 1,
|
|
MAX_BUFFER_SIZE,
|
|
pFileHandle) == MAX_BUFFER_SIZE) {
|
|
- status = KFWUM_STATUS_OK;
|
|
+ rc = 0;
|
|
}
|
|
}
|
|
if (modulus) {
|
|
if (fread(&firmBuf[qty * MAX_BUFFER_SIZE], 1,
|
|
modulus, pFileHandle) == modulus) {
|
|
- status = KFWUM_STATUS_OK;
|
|
+ rc = 0;
|
|
}
|
|
}
|
|
- if (status == KFWUM_STATUS_OK) {
|
|
- KfwumShowProgress((const unsigned char *)"Reading Firmware from File",
|
|
- 100, 100);
|
|
+ if (rc == 0) {
|
|
+ KfwumShowProgress("Reading Firmware from File", 100, 100);
|
|
}
|
|
fclose(pFileHandle);
|
|
- return status;
|
|
+ return rc;
|
|
}
|
|
|
|
/* KfwumShowProgress - helper routine to display progress bar
|
|
*
|
|
* Converts current/total in percent
|
|
- *
|
|
+ *
|
|
* *task : string identifying current operation
|
|
* current: progress
|
|
- * total : limit
|
|
+ * total : limit
|
|
*/
|
|
-#define PROG_LENGTH 42
|
|
-void KfwumShowProgress( const unsigned char * task, unsigned long current ,
|
|
- unsigned long total)
|
|
+void
|
|
+KfwumShowProgress(const char *task, unsigned long current, unsigned long total)
|
|
{
|
|
- static unsigned long staticProgress=0xffffffff;
|
|
-
|
|
- unsigned char spaces[PROG_LENGTH + 1];
|
|
- unsigned short hash;
|
|
- float percent = ((float)current/total);
|
|
- unsigned long progress = 100*(percent);
|
|
-
|
|
- if(staticProgress == progress)
|
|
- {
|
|
- /* We displayed the same last time.. so don't do it */
|
|
- }
|
|
- else
|
|
- {
|
|
- staticProgress = progress;
|
|
-
|
|
-
|
|
- printf("%-25s : ",task); /* total 20 bytes */
|
|
-
|
|
- hash = ( percent * PROG_LENGTH );
|
|
- memset(spaces,'#', hash);
|
|
- spaces[ hash ] = '\0';
|
|
- printf("%s", spaces );
|
|
-
|
|
- memset(spaces,' ',( PROG_LENGTH - hash ) );
|
|
- spaces[ ( PROG_LENGTH - hash ) ] = '\0';
|
|
- printf("%s", spaces );
|
|
-
|
|
-
|
|
- printf(" %3ld %%\r",progress); /* total 7 bytes */
|
|
-
|
|
- if( progress == 100 )
|
|
- {
|
|
- printf("\n");
|
|
- }
|
|
- fflush(stdout);
|
|
- }
|
|
+# define PROG_LENGTH 42
|
|
+ static unsigned long staticProgress=0xffffffff;
|
|
+ unsigned char spaces[PROG_LENGTH + 1];
|
|
+ unsigned short hash;
|
|
+ float percent = ((float)current / total);
|
|
+ unsigned long progress = 100 * (percent);
|
|
+
|
|
+ if (staticProgress == progress) {
|
|
+ /* We displayed the same last time.. so don't do it */
|
|
+ return;
|
|
+ }
|
|
+ staticProgress = progress;
|
|
+ printf("%-25s : ", task); /* total 20 bytes */
|
|
+ hash = (percent * PROG_LENGTH);
|
|
+ memset(spaces, '#', hash);
|
|
+ spaces[hash] = '\0';
|
|
+
|
|
+ printf("%s", spaces);
|
|
+ memset(spaces, ' ', (PROG_LENGTH - hash));
|
|
+ spaces[(PROG_LENGTH - hash)] = '\0';
|
|
+ printf("%s", spaces );
|
|
+
|
|
+ printf(" %3ld %%\r", progress); /* total 7 bytes */
|
|
+ if (progress == 100) {
|
|
+ printf("\n");
|
|
+ }
|
|
+ fflush(stdout);
|
|
}
|
|
|
|
-/* KfwumCalculateChecksumPadding
|
|
- *
|
|
- * TBD
|
|
- *
|
|
+/* KfwumCalculateChecksumPadding - TBD
|
|
*/
|
|
-static unsigned short KfwumCalculateChecksumPadding(unsigned char * pBuffer,
|
|
- unsigned long totalSize)
|
|
+unsigned short
|
|
+KfwumCalculateChecksumPadding(unsigned char *pBuffer, unsigned long totalSize)
|
|
{
|
|
- unsigned short sumOfBytes = 0;
|
|
- unsigned short padding;
|
|
- unsigned long counter;
|
|
-
|
|
- for(counter = 0; counter < totalSize; counter ++ )
|
|
- {
|
|
- sumOfBytes += pBuffer[counter];
|
|
- }
|
|
-
|
|
- padding = 0 - sumOfBytes;
|
|
- return padding;
|
|
+ unsigned short sumOfBytes = 0;
|
|
+ unsigned short padding;
|
|
+ unsigned long counter;
|
|
+ for (counter = 0; counter < totalSize; counter ++) {
|
|
+ sumOfBytes += pBuffer[counter];
|
|
+ }
|
|
+ padding = 0 - sumOfBytes;
|
|
+ return padding;
|
|
}
|
|
|
|
-/******************************************************************************
|
|
-******************************* COMMANDS **************************************
|
|
-******************************************************************************/
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct KfwumGetInfoResp {
|
|
- unsigned char protocolRevision;
|
|
- unsigned char controllerDeviceId;
|
|
- struct
|
|
- {
|
|
- unsigned char mode:1;
|
|
- unsigned char seqAdd:1;
|
|
- unsigned char res : 6;
|
|
- } byte;
|
|
- unsigned char firmRev1;
|
|
- unsigned char firmRev2;
|
|
- unsigned char numBank;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-
|
|
-
|
|
/* KfwumGetInfo - Get Firmware Update Manager (FWUM) information
|
|
- *
|
|
- * * intf : IPMI interface
|
|
+ *
|
|
+ * *intf : IPMI interface
|
|
* output : when set to non zero, queried information is displayed
|
|
* pNumBank: output ptr for number of banks
|
|
+ *
|
|
+ * returns 0 on success, otherwise (-1)
|
|
*/
|
|
-static tKFWUM_Status KfwumGetInfo(struct ipmi_intf * intf, unsigned char output,
|
|
- unsigned char *pNumBank)
|
|
+int
|
|
+KfwumGetInfo(struct ipmi_intf *intf, unsigned char output,
|
|
+ unsigned char *pNumBank)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
- static struct KfwumGetInfoResp *pGetInfo;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
- req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_INFO;
|
|
- req.msg.data_len = 0;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if (!rsp)
|
|
- {
|
|
- printf("Error in FWUM Firmware Get Info Command\n");
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
- else if (rsp->ccode)
|
|
- {
|
|
- printf("FWUM Firmware Get Info returned %x\n", rsp->ccode);
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
-
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- pGetInfo = (struct KfwumGetInfoResp *) rsp->data;
|
|
- if(output)
|
|
- {
|
|
- printf("\nFWUM info\n");
|
|
- printf("=========\n");
|
|
- printf("Protocol Revision : %02Xh\n",
|
|
- pGetInfo->protocolRevision);
|
|
- printf("Controller Device Id : %02Xh\n",
|
|
- pGetInfo->controllerDeviceId);
|
|
- printf("Firmware Revision : %u.%u%u",
|
|
- pGetInfo->firmRev1, pGetInfo->firmRev2 >> 4,
|
|
- pGetInfo->firmRev2 & 0x0f);
|
|
- if(pGetInfo->byte.mode != 0)
|
|
- {
|
|
- printf(" - DEBUG BUILD\n");
|
|
- }
|
|
- else
|
|
- {
|
|
- printf("\n");
|
|
- }
|
|
- printf("Number Of Memory Bank : %u\n",pGetInfo->numBank);
|
|
- }
|
|
- * pNumBank = pGetInfo->numBank;
|
|
-
|
|
- /* Determine wich type of download to use: */
|
|
- /* Old FWUM or Old IPMC fw (data_len < 7) -->
|
|
- Address with small buffer size */
|
|
- if ( (pGetInfo->protocolRevision) <= 0x05 || (rsp->data_len < 7 ) )
|
|
- {
|
|
- saveFirmwareInfo.downloadType = KFWUM_DOWNLOAD_TYPE_ADDRESS;
|
|
- saveFirmwareInfo.bufferSize = KFWUM_SMALL_BUFFER;
|
|
- saveFirmwareInfo.overheadSize = KFWUM_OLD_CMD_OVERHEAD;
|
|
-
|
|
- if(verbose)
|
|
- {
|
|
- printf("Protocol Revision :");
|
|
- printf(" <= 5 detected, adjusting buffers\n");
|
|
- }
|
|
- }
|
|
- else /* Both fw are using the new protocol */
|
|
- {
|
|
- saveFirmwareInfo.downloadType = KFWUM_DOWNLOAD_TYPE_SEQUENCE;
|
|
- saveFirmwareInfo.overheadSize = KFWUM_NEW_CMD_OVERHEAD;
|
|
- /* Buffer size depending on access type (Local or remote) */
|
|
- /* Look if we run remote or locally */
|
|
-
|
|
- if(verbose)
|
|
- {
|
|
- printf("Protocol Revision :");
|
|
- printf(" > 5 optimizing buffers\n");
|
|
- }
|
|
-
|
|
- if(strstr(intf->name,"lan")!= NULL) /* also covers lanplus */
|
|
- {
|
|
- saveFirmwareInfo.bufferSize = KFWUM_SMALL_BUFFER;
|
|
- if(verbose)
|
|
- {
|
|
- printf("IOL payload size : %d\n" ,
|
|
- saveFirmwareInfo.bufferSize);
|
|
- }
|
|
- }
|
|
- else if
|
|
- (
|
|
- (strstr(intf->name,"open")!= NULL)
|
|
- &&
|
|
- intf->target_addr != IPMI_BMC_SLAVE_ADDR
|
|
- &&
|
|
- (
|
|
- intf->target_addr != intf->my_addr
|
|
- )
|
|
- )
|
|
- {
|
|
- saveFirmwareInfo.bufferSize = KFWUM_SMALL_BUFFER;
|
|
- if(verbose)
|
|
- {
|
|
- printf("IPMB payload size : %d\n" ,
|
|
- saveFirmwareInfo.bufferSize);
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- saveFirmwareInfo.bufferSize = KFWUM_BIG_BUFFER;
|
|
- if(verbose)
|
|
- {
|
|
- printf("SMI payload size : %d\n",
|
|
- saveFirmwareInfo.bufferSize);
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- return status;
|
|
+ int rc = 0;
|
|
+ static struct KfwumGetInfoResp *pGetInfo;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
+ req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_INFO;
|
|
+ req.msg.data_len = 0;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (!rsp) {
|
|
+ lprintf(LOG_ERR, "Error in FWUM Firmware Get Info Command.");
|
|
+ return (-1);
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "FWUM Firmware Get Info returned %x",
|
|
+ rsp->ccode);
|
|
+ return (-1);
|
|
+ }
|
|
+
|
|
+ pGetInfo = (struct KfwumGetInfoResp *)rsp->data;
|
|
+ if (output) {
|
|
+ printf("\nFWUM info\n");
|
|
+ printf("=========\n");
|
|
+ printf("Protocol Revision : %02Xh\n",
|
|
+ pGetInfo->protocolRevision);
|
|
+ printf("Controller Device Id : %02Xh\n",
|
|
+ pGetInfo->controllerDeviceId);
|
|
+ printf("Firmware Revision : %u.%u%u",
|
|
+ pGetInfo->firmRev1, pGetInfo->firmRev2 >> 4,
|
|
+ pGetInfo->firmRev2 & 0x0f);
|
|
+ if (pGetInfo->byte.mode != 0) {
|
|
+ printf(" - DEBUG BUILD\n");
|
|
+ } else {
|
|
+ printf("\n");
|
|
+ }
|
|
+ printf("Number Of Memory Bank : %u\n", pGetInfo->numBank);
|
|
+ }
|
|
+ *pNumBank = pGetInfo->numBank;
|
|
+ /* Determine wich type of download to use: */
|
|
+ /* Old FWUM or Old IPMC fw (data_len < 7)
|
|
+ * --> Address with small buffer size
|
|
+ */
|
|
+ if ((pGetInfo->protocolRevision) <= 0x05 || (rsp->data_len < 7 )) {
|
|
+ save_fw_nfo.downloadType = KFWUM_DOWNLOAD_TYPE_ADDRESS;
|
|
+ save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
|
|
+ save_fw_nfo.overheadSize = KFWUM_OLD_CMD_OVERHEAD;
|
|
+ if (verbose) {
|
|
+ printf("Protocol Revision :");
|
|
+ printf(" <= 5 detected, adjusting buffers\n");
|
|
+ }
|
|
+ } else {
|
|
+ /* Both fw are using the new protocol */
|
|
+ save_fw_nfo.downloadType = KFWUM_DOWNLOAD_TYPE_SEQUENCE;
|
|
+ save_fw_nfo.overheadSize = KFWUM_NEW_CMD_OVERHEAD;
|
|
+ /* Buffer size depending on access type (Local or remote) */
|
|
+ /* Look if we run remote or locally */
|
|
+ if (verbose) {
|
|
+ printf("Protocol Revision :");
|
|
+ printf(" > 5 optimizing buffers\n");
|
|
+ }
|
|
+ if (strstr(intf->name,"lan") != NULL) {
|
|
+ /* also covers lanplus */
|
|
+ save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
|
|
+ if (verbose) {
|
|
+ printf("IOL payload size : %d\n",
|
|
+ save_fw_nfo.bufferSize);
|
|
+ }
|
|
+ } else if ((strstr(intf->name,"open")!= NULL)
|
|
+ && intf->target_addr != IPMI_BMC_SLAVE_ADDR
|
|
+ && (intf->target_addr != intf->my_addr)) {
|
|
+ save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
|
|
+ if (verbose) {
|
|
+ printf("IPMB payload size : %d\n",
|
|
+ save_fw_nfo.bufferSize);
|
|
+ }
|
|
+ } else {
|
|
+ save_fw_nfo.bufferSize = KFWUM_BIG_BUFFER;
|
|
+ if (verbose) {
|
|
+ printf("SMI payload size : %d\n",
|
|
+ save_fw_nfo.bufferSize);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-/* KfwumGetDeviceInfo - Get IPMC/Board information
|
|
- *
|
|
- * * intf : IPMI interface
|
|
- * output : when set to non zero, queried information is displayed
|
|
+/* KfwumGetDeviceInfo - Get IPMC/Board information
|
|
+ *
|
|
+ * *intf: IPMI interface
|
|
+ * output: when set to non zero, queried information is displayed
|
|
* tKFWUM_BoardInfo: output ptr for IPMC/Board information
|
|
+ *
|
|
+ * returns 0 on success, otherwise (-1)
|
|
*/
|
|
-static tKFWUM_Status KfwumGetDeviceInfo(struct ipmi_intf * intf,
|
|
- unsigned char output, tKFWUM_BoardInfo * pBoardInfo)
|
|
+int
|
|
+KfwumGetDeviceInfo(struct ipmi_intf *intf, unsigned char output,
|
|
+ tKFWUM_BoardInfo *pBoardInfo)
|
|
{
|
|
- struct ipm_devid_rsp *pGetDevId;
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- /* Send Get Device Id */
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = BMC_GET_DEVICE_ID;
|
|
- req.msg.data_len = 0;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- if (!rsp)
|
|
- {
|
|
- printf("Error in Get Device Id Command\n");
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
- else if (rsp->ccode)
|
|
- {
|
|
- printf("Get Device Id returned %x\n", rsp->ccode);
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
- }
|
|
-
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- pGetDevId = (struct ipm_devid_rsp *) rsp->data;
|
|
- pBoardInfo->iana = IPM_DEV_MANUFACTURER_ID(pGetDevId->manufacturer_id);
|
|
- pBoardInfo->boardId = buf2short(pGetDevId->product_id);
|
|
- if(output)
|
|
- {
|
|
- printf("\nIPMC Info\n");
|
|
- printf("=========\n");
|
|
- printf("Manufacturer Id : %u\n",pBoardInfo->iana);
|
|
- printf("Board Id : %u\n",pBoardInfo->boardId);
|
|
- printf("Firmware Revision : %u.%u%u",
|
|
- pGetDevId->fw_rev1, pGetDevId->fw_rev2 >> 4,
|
|
- pGetDevId->fw_rev2 & 0x0f);
|
|
- if(
|
|
- (
|
|
- ( pBoardInfo->iana == KFWUM_IANA_KONTRON)
|
|
- &&
|
|
- (pBoardInfo->boardId = KFWUM_BOARD_KONTRON_5002)
|
|
- )
|
|
- )
|
|
- {
|
|
- printf(" SDR %u\n", pGetDevId->aux_fw_rev[0]);
|
|
- }
|
|
- else
|
|
- {
|
|
- printf("\n");
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- return status;
|
|
+ struct ipm_devid_rsp *pGetDevId;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ /* Send Get Device Id */
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = BMC_GET_DEVICE_ID;
|
|
+ req.msg.data_len = 0;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Error in Get Device Id Command");
|
|
+ return (-1);
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Get Device Id returned %x",
|
|
+ rsp->ccode);
|
|
+ return (-1);
|
|
+ }
|
|
+ pGetDevId = (struct ipm_devid_rsp *)rsp->data;
|
|
+ pBoardInfo->iana = IPM_DEV_MANUFACTURER_ID(pGetDevId->manufacturer_id);
|
|
+ pBoardInfo->boardId = buf2short(pGetDevId->product_id);
|
|
+ if (output) {
|
|
+ printf("\nIPMC Info\n");
|
|
+ printf("=========\n");
|
|
+ printf("Manufacturer Id : %u\n",
|
|
+ pBoardInfo->iana);
|
|
+ printf("Board Id : %u\n",
|
|
+ pBoardInfo->boardId);
|
|
+ printf("Firmware Revision : %u.%u%u",
|
|
+ pGetDevId->fw_rev1, pGetDevId->fw_rev2 >> 4,
|
|
+ pGetDevId->fw_rev2 & 0x0f);
|
|
+ if (((pBoardInfo->iana == IPMI_OEM_KONTRON)
|
|
+ && (pBoardInfo->boardId = KFWUM_BOARD_KONTRON_5002))) {
|
|
+ printf(" SDR %u", pGetDevId->aux_fw_rev[0]);
|
|
+ }
|
|
+ printf("\n");
|
|
+ }
|
|
+ return 0;
|
|
}
|
|
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct KfwumGetStatusResp {
|
|
- unsigned char bankState;
|
|
- unsigned char firmLengthLSB;
|
|
- unsigned char firmLengthMid;
|
|
- unsigned char firmLengthMSB;
|
|
- unsigned char firmRev1;
|
|
- unsigned char firmRev2;
|
|
- unsigned char firmRev3;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-
|
|
-const struct valstr bankStateValS[] = {
|
|
- { 0x00, "Not programmed" },
|
|
- { 0x01, "New firmware" },
|
|
- { 0x02, "Wait for validation" },
|
|
- { 0x03, "Last Known Good" },
|
|
- { 0x04, "Previous Good" }
|
|
-};
|
|
-
|
|
/* KfwumGetStatus - Get (and prints) FWUM banks information
|
|
- *
|
|
- * * intf : IPMI interface
|
|
+ *
|
|
+ * *intf : IPMI interface
|
|
+ *
|
|
+ * returns 0 on success, otherwise (-1)
|
|
*/
|
|
-static tKFWUM_Status KfwumGetStatus(struct ipmi_intf * intf)
|
|
+int
|
|
+KfwumGetStatus(struct ipmi_intf * intf)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- struct KfwumGetStatusResp *pGetStatus;
|
|
- unsigned char numBank;
|
|
- unsigned char counter;
|
|
-
|
|
- if(verbose)
|
|
- {
|
|
- printf(" Getting Status!\n");
|
|
- }
|
|
-
|
|
- /* Retreive the number of bank */
|
|
- status = KfwumGetInfo(intf, 0, &numBank);
|
|
-
|
|
- for(
|
|
- counter = 0;
|
|
- (counter < numBank) && (status == KFWUM_STATUS_OK);
|
|
- counter ++
|
|
- )
|
|
- {
|
|
- /* Retreive the status of each bank */
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
- req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_STATUS;
|
|
- req.msg.data = &counter;
|
|
- req.msg.data_len = 1;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if (!rsp)
|
|
- {
|
|
- printf("Error in FWUM Firmware Get Status Command\n");
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
- else if (rsp->ccode)
|
|
- {
|
|
- printf("FWUM Firmware Get Status returned %x\n", rsp->ccode);
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
-
|
|
-
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- pGetStatus = (struct KfwumGetStatusResp *) rsp->data;
|
|
- printf("\nBank State %d : %s\n", counter, val2str(
|
|
- pGetStatus->bankState, bankStateValS));
|
|
- if(pGetStatus->bankState)
|
|
- {
|
|
- unsigned long firmLength;
|
|
- firmLength = pGetStatus->firmLengthMSB;
|
|
- firmLength = firmLength << 8;
|
|
- firmLength |= pGetStatus->firmLengthMid;
|
|
- firmLength = firmLength << 8;
|
|
- firmLength |= pGetStatus->firmLengthLSB;
|
|
-
|
|
- printf("Firmware Length : %ld bytes\n", firmLength);
|
|
- printf("Firmware Revision : %u.%u%u SDR %u\n",
|
|
- pGetStatus->firmRev1, pGetStatus->firmRev2 >> 4,
|
|
- pGetStatus->firmRev2 & 0x0f, pGetStatus->firmRev3);
|
|
- }
|
|
- }
|
|
- }
|
|
- printf("\n");
|
|
- return status;
|
|
+ int rc = 0;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ struct KfwumGetStatusResp *pGetStatus;
|
|
+ unsigned char numBank;
|
|
+ unsigned char counter;
|
|
+ unsigned long firmLength;
|
|
+ if (verbose) {
|
|
+ printf(" Getting Status!\n");
|
|
+ }
|
|
+ /* Retreive the number of bank */
|
|
+ rc = KfwumGetInfo(intf, 0, &numBank);
|
|
+ for(counter = 0;
|
|
+ (counter < numBank) && (rc == 0);
|
|
+ counter ++) {
|
|
+ /* Retreive the status of each bank */
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
+ req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_STATUS;
|
|
+ req.msg.data = &counter;
|
|
+ req.msg.data_len = 1;
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error in FWUM Firmware Get Status Command.");
|
|
+ rc = (-1);
|
|
+ break;
|
|
+ } else if (rsp->ccode) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "FWUM Firmware Get Status returned %x",
|
|
+ rsp->ccode);
|
|
+ rc = (-1);
|
|
+ break;
|
|
+ }
|
|
+ pGetStatus = (struct KfwumGetStatusResp *) rsp->data;
|
|
+ printf("\nBank State %d : %s\n",
|
|
+ counter,
|
|
+ val2str(pGetStatus->bankState, bankStateValS));
|
|
+ if (!pGetStatus->bankState) {
|
|
+ continue;
|
|
+ }
|
|
+ firmLength = pGetStatus->firmLengthMSB;
|
|
+ firmLength = firmLength << 8;
|
|
+ firmLength |= pGetStatus->firmLengthMid;
|
|
+ firmLength = firmLength << 8;
|
|
+ firmLength |= pGetStatus->firmLengthLSB;
|
|
+ printf("Firmware Length : %ld bytes\n",
|
|
+ firmLength);
|
|
+ printf("Firmware Revision : %u.%u%u SDR %u\n",
|
|
+ pGetStatus->firmRev1,
|
|
+ pGetStatus->firmRev2 >> 4,
|
|
+ pGetStatus->firmRev2 & 0x0f,
|
|
+ pGetStatus->firmRev3);
|
|
+ }
|
|
+ printf("\n");
|
|
+ return rc;
|
|
}
|
|
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct KfwumManualRollbackReq{
|
|
- unsigned char type;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-
|
|
/* KfwumManualRollback - Ask IPMC to rollback to previous version
|
|
- *
|
|
- * * intf : IPMI interface
|
|
+ *
|
|
+ * *intf : IPMI interface
|
|
+ *
|
|
+ * returns 0 on success
|
|
+ * returns (-1) on error
|
|
*/
|
|
-static tKFWUM_Status KfwumManualRollback(struct ipmi_intf * intf)
|
|
+int
|
|
+KfwumManualRollback(struct ipmi_intf *intf)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- struct KfwumManualRollbackReq thisReq;
|
|
-
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
- req.msg.cmd = KFWUM_CMD_ID_MANUAL_ROLLBACK;
|
|
-
|
|
- thisReq.type = 0; /* Wait BMC shutdown */
|
|
-
|
|
- req.msg.data = (unsigned char *) &thisReq;
|
|
- req.msg.data_len = 1;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if (!rsp)
|
|
- {
|
|
- printf("Error in FWUM Manual Rollback Command\n");
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
- else if (rsp->ccode)
|
|
- {
|
|
- printf("Error in FWUM Manual Rollback Command returned %x\n",
|
|
- rsp->ccode);
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
-
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- printf("FWUM Starting Manual Rollback \n");
|
|
- }
|
|
- return status;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ struct KfwumManualRollbackReq thisReq;
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
+ req.msg.cmd = KFWUM_CMD_ID_MANUAL_ROLLBACK;
|
|
+ thisReq.type = 0; /* Wait BMC shutdown */
|
|
+ req.msg.data = (unsigned char *)&thisReq;
|
|
+ req.msg.data_len = 1;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Error in FWUM Manual Rollback Command.");
|
|
+ return (-1);
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error in FWUM Manual Rollback Command returned %x",
|
|
+ rsp->ccode);
|
|
+ return (-1);
|
|
+ }
|
|
+ printf("FWUM Starting Manual Rollback \n");
|
|
+ return 0;
|
|
}
|
|
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct KfwumStartFirmwareDownloadReq{
|
|
- unsigned char lengthLSB;
|
|
- unsigned char lengthMid;
|
|
- unsigned char lengthMSB;
|
|
- unsigned char paddingLSB;
|
|
- unsigned char paddingMSB;
|
|
- unsigned char useSequence;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct KfwumStartFirmwareDownloadResp {
|
|
- unsigned char bank;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-static tKFWUM_Status KfwumStartFirmwareImage(struct ipmi_intf * intf,
|
|
- unsigned long length,unsigned short padding)
|
|
+int
|
|
+KfwumStartFirmwareImage(struct ipmi_intf *intf, unsigned long length,
|
|
+ unsigned short padding)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- struct KfwumStartFirmwareDownloadResp *pResp;
|
|
- struct KfwumStartFirmwareDownloadReq thisReq;
|
|
-
|
|
- thisReq.lengthLSB = length & 0x000000ff;
|
|
- thisReq.lengthMid = (length >> 8) & 0x000000ff;
|
|
- thisReq.lengthMSB = (length >> 16) & 0x000000ff;
|
|
- thisReq.paddingLSB = padding & 0x00ff;
|
|
- thisReq.paddingMSB = (padding>> 8) & 0x00ff;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ struct KfwumStartFirmwareDownloadResp *pResp;
|
|
+ struct KfwumStartFirmwareDownloadReq thisReq;
|
|
+
|
|
+ thisReq.lengthLSB = length & 0x000000ff;
|
|
+ thisReq.lengthMid = (length >> 8) & 0x000000ff;
|
|
+ thisReq.lengthMSB = (length >> 16) & 0x000000ff;
|
|
+ thisReq.paddingLSB = padding & 0x00ff;
|
|
+ thisReq.paddingMSB = (padding>> 8) & 0x00ff;
|
|
thisReq.useSequence = 0x01;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
- req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_IMAGE;
|
|
- req.msg.data = (unsigned char *) &thisReq;
|
|
-
|
|
- /* Look for download type */
|
|
- if ( saveFirmwareInfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS )
|
|
- {
|
|
- req.msg.data_len = 5;
|
|
- }
|
|
- else
|
|
- {
|
|
- req.msg.data_len = 6;
|
|
- }
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if (!rsp)
|
|
- {
|
|
- printf("Error in FWUM Firmware Start Firmware Image Download Command\n");
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
- else if (rsp->ccode)
|
|
- {
|
|
- printf("FWUM Firmware Start Firmware Image Download returned %x\n",
|
|
- rsp->ccode);
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
-
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- pResp = (struct KfwumStartFirmwareDownloadResp *) rsp->data;
|
|
- printf("Bank holding new firmware : %d\n", pResp->bank);
|
|
- sleep(5);
|
|
- }
|
|
- return status;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
+ req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_IMAGE;
|
|
+ req.msg.data = (unsigned char *) &thisReq;
|
|
+ /* Look for download type */
|
|
+ if (save_fw_nfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS) {
|
|
+ req.msg.data_len = 5;
|
|
+ } else {
|
|
+ req.msg.data_len = 6;
|
|
+ }
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error in FWUM Firmware Start Firmware Image Download Command.");
|
|
+ return (-1);
|
|
+ } else if (rsp->ccode) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "FWUM Firmware Start Firmware Image Download returned %x",
|
|
+ rsp->ccode);
|
|
+ return (-1);
|
|
+ }
|
|
+ pResp = (struct KfwumStartFirmwareDownloadResp *)rsp->data;
|
|
+ printf("Bank holding new firmware : %d\n", pResp->bank);
|
|
+ sleep(5);
|
|
+ return 0;
|
|
}
|
|
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct KfwumSaveFirmwareAddressReq
|
|
+int
|
|
+KfwumSaveFirmwareImage(struct ipmi_intf *intf, unsigned char sequenceNumber,
|
|
+ unsigned long address, unsigned char *pFirmBuf,
|
|
+ unsigned char *pInBufLength)
|
|
{
|
|
- unsigned char addressLSB;
|
|
- unsigned char addressMid;
|
|
- unsigned char addressMSB;
|
|
- unsigned char numBytes;
|
|
- unsigned char txBuf[KFWUM_SMALL_BUFFER-KFWUM_OLD_CMD_OVERHEAD];
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct KfwumSaveFirmwareSequenceReq
|
|
-{
|
|
- unsigned char sequenceNumber;
|
|
- unsigned char txBuf[KFWUM_BIG_BUFFER];
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-
|
|
-#define FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT ((unsigned char)6)
|
|
+ int rc = 0;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ struct KfwumSaveFirmwareAddressReq addr_req;
|
|
+ struct KfwumSaveFirmwareSequenceReq seq_req;
|
|
+ int retry = 0;
|
|
+ int no_rsp = 0;
|
|
+ do {
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
+ req.msg.cmd = KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE;
|
|
+ if (save_fw_nfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS) {
|
|
+ addr_req.addressLSB = address & 0x000000ff;
|
|
+ addr_req.addressMid = (address >> 8) & 0x000000ff;
|
|
+ addr_req.addressMSB = (address >> 16) & 0x000000ff;
|
|
+ addr_req.numBytes = *pInBufLength;
|
|
+ memcpy(addr_req.txBuf, pFirmBuf, *pInBufLength);
|
|
+ req.msg.data = (unsigned char *)&addr_req;
|
|
+ req.msg.data_len = *pInBufLength + 4;
|
|
+ } else {
|
|
+ seq_req.sequenceNumber = sequenceNumber;
|
|
+ memcpy(seq_req.txBuf, pFirmBuf, *pInBufLength);
|
|
+ req.msg.data = (unsigned char *)&seq_req;
|
|
+ req.msg.data_len = *pInBufLength + sizeof(unsigned char);
|
|
+ /* + 1 => sequenceNumber*/
|
|
+ }
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error in FWUM Firmware Save Firmware Image Download Command.");
|
|
+ /* We don't receive "C7" on errors with IOL,
|
|
+ * instead we receive nothing
|
|
+ */
|
|
+ if (strstr(intf->name, "lan") != NULL) {
|
|
+ no_rsp++;
|
|
+ if (no_rsp < FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT) {
|
|
+ *pInBufLength -= 1;
|
|
+ continue;
|
|
+ }
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error, too many commands without response.");
|
|
+ *pInBufLength = 0;
|
|
+ break;
|
|
+ } /* For other interface keep trying */
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ if (rsp->ccode == 0xc0) {
|
|
+ sleep(1);
|
|
+ } else if ((rsp->ccode == 0xc7)
|
|
+ || ((rsp->ccode == 0xc3)
|
|
+ && (sequenceNumber == 0))) {
|
|
+ *pInBufLength -= 1;
|
|
+ retry = 1;
|
|
+ } else if (rsp->ccode == 0x82) {
|
|
+ /* Double sent, continue */
|
|
+ rc = 0;
|
|
+ break;
|
|
+ } else if (rsp->ccode == 0x83) {
|
|
+ if (retry == 0) {
|
|
+ retry = 1;
|
|
+ continue;
|
|
+ }
|
|
+ rc = (-1);
|
|
+ break;
|
|
+ } else if (rsp->ccode == 0xcf) {
|
|
+ /* Ok if receive duplicated request */
|
|
+ retry = 1;
|
|
+ } else if (rsp->ccode == 0xc3) {
|
|
+ if (retry == 0) {
|
|
+ retry = 1;
|
|
+ continue;
|
|
+ }
|
|
+ rc = (-1);
|
|
+ break;
|
|
+ } else {
|
|
+ lprintf(LOG_ERR,
|
|
+ "FWUM Firmware Save Firmware Image Download returned %x",
|
|
+ rsp->ccode);
|
|
+ rc = (-1);
|
|
+ break;
|
|
+ }
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ } while (1);
|
|
+ return rc;
|
|
+}
|
|
|
|
-static tKFWUM_Status KfwumSaveFirmwareImage(struct ipmi_intf * intf,
|
|
- unsigned char sequenceNumber, unsigned long address, unsigned char *pFirmBuf,
|
|
- unsigned char * pInBufLength)
|
|
+int
|
|
+KfwumFinishFirmwareImage(struct ipmi_intf *intf, tKFWUM_InFirmwareInfo firmInfo)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- unsigned char out = 0;
|
|
- unsigned char retry = 0;
|
|
- unsigned char noResponse = 0 ;
|
|
-
|
|
- struct KfwumSaveFirmwareAddressReq addressReq;
|
|
- struct KfwumSaveFirmwareSequenceReq sequenceReq;
|
|
-
|
|
- do
|
|
- {
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
- req.msg.cmd = KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE;
|
|
-
|
|
- if (saveFirmwareInfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS )
|
|
- {
|
|
- addressReq.addressLSB = address & 0x000000ff;
|
|
- addressReq.addressMid = (address >> 8) & 0x000000ff;
|
|
- addressReq.addressMSB = (address >> 16) & 0x000000ff;
|
|
- addressReq.numBytes = (* pInBufLength);
|
|
- memcpy(addressReq.txBuf, pFirmBuf, (* pInBufLength));
|
|
- req.msg.data = (unsigned char *) &addressReq;
|
|
- req.msg.data_len = (* pInBufLength)+4;
|
|
- }
|
|
- else
|
|
- {
|
|
- sequenceReq.sequenceNumber = sequenceNumber;
|
|
- memcpy(sequenceReq.txBuf, pFirmBuf, (* pInBufLength));
|
|
- req.msg.data = (unsigned char *) &sequenceReq;
|
|
- req.msg.data_len = (* pInBufLength)+sizeof(unsigned char); /* + 1 => sequenceNumber*/
|
|
- }
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if (!rsp)
|
|
- {
|
|
- printf("Error in FWUM Firmware Save Firmware Image Download Command\n");
|
|
-
|
|
- out = 0;
|
|
- status = KFWUM_STATUS_OK;
|
|
-
|
|
- /* With IOL, we don't receive "C7" on errors, instead we receive
|
|
- nothing */
|
|
- if(strstr(intf->name,"lan")!= NULL)
|
|
- {
|
|
- noResponse++;
|
|
-
|
|
- if(noResponse < FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT )
|
|
- {
|
|
- (* pInBufLength) -= 1;
|
|
- out = 0;
|
|
- }
|
|
- else
|
|
- {
|
|
- printf("Error, too many commands without response\n");
|
|
- (* pInBufLength) = 0 ;
|
|
- out = 1;
|
|
- }
|
|
- } /* For other interface keep trying */
|
|
- }
|
|
- else if (rsp->ccode)
|
|
- {
|
|
- if(rsp->ccode == 0xc0)
|
|
- {
|
|
- status = KFWUM_STATUS_OK;
|
|
- sleep(1);
|
|
- }
|
|
- else if(
|
|
- (rsp->ccode == 0xc7)
|
|
- ||
|
|
- (
|
|
- (rsp->ccode == 0xC3) &&
|
|
- (sequenceNumber == 0)
|
|
- )
|
|
- )
|
|
- {
|
|
- (* pInBufLength) -= 1;
|
|
- status = KFWUM_STATUS_OK;
|
|
- retry = 1;
|
|
- }
|
|
- else if(rsp->ccode == 0x82)
|
|
- {
|
|
- /* Double sent, continue */
|
|
- status = KFWUM_STATUS_OK;
|
|
- out = 1;
|
|
- }
|
|
- else if(rsp->ccode == 0x83)
|
|
- {
|
|
- if(retry == 0)
|
|
- {
|
|
- retry = 1;
|
|
- status = KFWUM_STATUS_OK;
|
|
- }
|
|
- else
|
|
- {
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- out = 1;
|
|
- }
|
|
- }
|
|
- else if(rsp->ccode == 0xcf) /* Ok if receive duplicated request */
|
|
- {
|
|
- retry = 1;
|
|
- status = KFWUM_STATUS_OK;
|
|
- }
|
|
- else if(rsp->ccode == 0xC3)
|
|
- {
|
|
- if(retry == 0)
|
|
- {
|
|
- retry = 1;
|
|
- status = KFWUM_STATUS_OK;
|
|
- }
|
|
- else
|
|
- {
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- out = 1;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- printf("FWUM Firmware Save Firmware Image Download returned %x\n",
|
|
- rsp->ccode);
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- out = 1;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- out = 1;
|
|
- }
|
|
- }while(out == 0);
|
|
- return status;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ struct KfwumFinishFirmwareDownloadReq thisReq;
|
|
+
|
|
+ thisReq.versionMaj = firmInfo.versMajor;
|
|
+ thisReq.versionMinSub = ((firmInfo.versMinor <<4)
|
|
+ | firmInfo.versSubMinor);
|
|
+ thisReq.versionSdr = firmInfo.sdrRev;
|
|
+ thisReq.reserved = 0;
|
|
+ /* Byte 4 reserved, write 0 */
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
+ req.msg.cmd = KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE;
|
|
+ req.msg.data = (unsigned char *)&thisReq;
|
|
+ req.msg.data_len = 4;
|
|
+ /* Infinite loop if BMC doesn't reply or replies 0xc0 every time. */
|
|
+ do {
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ } while (rsp == NULL || rsp->ccode == 0xc0);
|
|
+ if (!rsp) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error in FWUM Firmware Finish Firmware Image Download Command.");
|
|
+ return (-1);
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "FWUM Firmware Finish Firmware Image Download returned %x",
|
|
+ rsp->ccode);
|
|
+ return (-1);
|
|
+ }
|
|
+ return 0;
|
|
}
|
|
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct KfwumFinishFirmwareDownloadReq{
|
|
- unsigned char versionMaj;
|
|
- unsigned char versionMinSub;
|
|
- unsigned char versionSdr;
|
|
- unsigned char reserved;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-static tKFWUM_Status KfwumFinishFirmwareImage(struct ipmi_intf * intf,
|
|
- tKFWUM_InFirmwareInfo firmInfo)
|
|
+int
|
|
+KfwumUploadFirmware(struct ipmi_intf *intf, unsigned char *pBuffer,
|
|
+ unsigned long totalSize)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- struct KfwumFinishFirmwareDownloadReq thisReq;
|
|
-
|
|
- thisReq.versionMaj = firmInfo.versMajor;
|
|
- thisReq.versionMinSub = ((firmInfo.versMinor <<4) | firmInfo.versSubMinor);
|
|
- thisReq.versionSdr = firmInfo.sdrRev;
|
|
- thisReq.reserved = 0;
|
|
- /* Byte 4 reserved, write 0 */
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
- req.msg.cmd = KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE;
|
|
- req.msg.data = (unsigned char *) &thisReq;
|
|
- req.msg.data_len = 4;
|
|
-
|
|
- do
|
|
- {
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
- }while (rsp == NULL || rsp->ccode == 0xc0);
|
|
-
|
|
- if (!rsp)
|
|
- {
|
|
- printf("Error in FWUM Firmware Finish Firmware Image Download Command\n");
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
- else if (rsp->ccode)
|
|
- {
|
|
- printf("FWUM Firmware Finish Firmware Image Download returned %x\n",
|
|
- rsp->ccode);
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
-
|
|
- return status;
|
|
+ int rc = (-1);
|
|
+ unsigned long address = 0x0;
|
|
+ unsigned char writeSize;
|
|
+ unsigned char oldWriteSize;
|
|
+ unsigned long lastAddress = 0;
|
|
+ unsigned char sequenceNumber = 0;
|
|
+ unsigned char retry = FWUM_MAX_UPLOAD_RETRY;
|
|
+ unsigned char isLengthValid = 1;
|
|
+ do {
|
|
+ writeSize = save_fw_nfo.bufferSize - save_fw_nfo.overheadSize;
|
|
+ /* Reach the end */
|
|
+ if (address + writeSize > totalSize) {
|
|
+ writeSize = (totalSize - address);
|
|
+ } else if (((address % KFWUM_PAGE_SIZE)
|
|
+ + writeSize) > KFWUM_PAGE_SIZE) {
|
|
+ /* Reach boundary end */
|
|
+ writeSize = (KFWUM_PAGE_SIZE - (address % KFWUM_PAGE_SIZE));
|
|
+ }
|
|
+ oldWriteSize = writeSize;
|
|
+ rc = KfwumSaveFirmwareImage(intf, sequenceNumber,
|
|
+ address, &pBuffer[address], &writeSize);
|
|
+ if ((rc != 0) && (retry-- != 0)) {
|
|
+ address = lastAddress;
|
|
+ rc = 0;
|
|
+ } else if ( writeSize == 0) {
|
|
+ rc = (-1);
|
|
+ } else {
|
|
+ if (writeSize != oldWriteSize) {
|
|
+ printf("Adjusting length to %d bytes \n",
|
|
+ writeSize);
|
|
+ save_fw_nfo.bufferSize -= (oldWriteSize - writeSize);
|
|
+ }
|
|
+ retry = FWUM_MAX_UPLOAD_RETRY;
|
|
+ lastAddress = address;
|
|
+ address+= writeSize;
|
|
+ }
|
|
+ if (rc == 0) {
|
|
+ if ((address % 1024) == 0) {
|
|
+ KfwumShowProgress("Writting Firmware in Flash",
|
|
+ address, totalSize);
|
|
+ }
|
|
+ sequenceNumber++;
|
|
+ }
|
|
+ } while ((rc == 0) && (address < totalSize));
|
|
+ if (rc == 0) {
|
|
+ KfwumShowProgress("Writting Firmware in Flash",
|
|
+ 100, 100);
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-
|
|
-#define FWUM_MAX_UPLOAD_RETRY 6
|
|
-static tKFWUM_Status KfwumUploadFirmware(struct ipmi_intf * intf,
|
|
- unsigned char * pBuffer, unsigned long totalSize)
|
|
+int
|
|
+KfwumStartFirmwareUpgrade(struct ipmi_intf *intf)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_ERROR;
|
|
- unsigned long address = 0x0;
|
|
- unsigned char writeSize;
|
|
- unsigned char oldWriteSize;
|
|
- unsigned long lastAddress = 0;
|
|
- unsigned char sequenceNumber = 0;
|
|
- unsigned char retry = FWUM_MAX_UPLOAD_RETRY;
|
|
- unsigned char isLengthValid = 1;
|
|
-
|
|
- do
|
|
- {
|
|
- writeSize = saveFirmwareInfo.bufferSize - saveFirmwareInfo.overheadSize;
|
|
-
|
|
- /* Reach the end */
|
|
- if( address + writeSize > totalSize )
|
|
- {
|
|
- writeSize = (totalSize - address);
|
|
- }
|
|
- /* Reach boundary end */
|
|
- else if(((address % KFWUM_PAGE_SIZE) + writeSize) > KFWUM_PAGE_SIZE)
|
|
- {
|
|
- writeSize = (KFWUM_PAGE_SIZE - (address % KFWUM_PAGE_SIZE));
|
|
- }
|
|
-
|
|
- oldWriteSize = writeSize;
|
|
- status = KfwumSaveFirmwareImage(intf, sequenceNumber, address,
|
|
- &pBuffer[address], &writeSize);
|
|
-
|
|
- if((status != KFWUM_STATUS_OK) && (retry-- != 0))
|
|
- {
|
|
- address = lastAddress;
|
|
- status = KFWUM_STATUS_OK;
|
|
- }
|
|
- else if( writeSize == 0 )
|
|
- {
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
- else
|
|
- {
|
|
- if(writeSize != oldWriteSize)
|
|
- {
|
|
- printf("Adjusting length to %d bytes \n", writeSize);
|
|
- saveFirmwareInfo.bufferSize -= (oldWriteSize - writeSize);
|
|
- }
|
|
-
|
|
- retry = FWUM_MAX_UPLOAD_RETRY;
|
|
- lastAddress = address;
|
|
- address+= writeSize;
|
|
- }
|
|
-
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- if((address % 1024) == 0)
|
|
- {
|
|
- KfwumShowProgress((const unsigned char *)\
|
|
- "Writting Firmware in Flash",address,totalSize);
|
|
- }
|
|
- sequenceNumber++;
|
|
- }
|
|
-
|
|
- }while((status == KFWUM_STATUS_OK) && (address < totalSize ));
|
|
-
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- KfwumShowProgress((const unsigned char *)\
|
|
- "Writting Firmware in Flash", 100 , 100 );
|
|
- }
|
|
-
|
|
- return(status);
|
|
+ int rc = 0;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ /* Upgrade type, wait BMC shutdown */
|
|
+ unsigned char upgType = 0 ;
|
|
+
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
+ req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_UPDATE;
|
|
+ req.msg.data = (unsigned char *) &upgType;
|
|
+ req.msg.data_len = 1;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error in FWUM Firmware Start Firmware Upgrade Command");
|
|
+ rc = (-1);
|
|
+ } else if (rsp->ccode) {
|
|
+ if (rsp->ccode == 0xd5) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "No firmware available for upgrade. Download Firmware first.");
|
|
+ } else {
|
|
+ lprintf(LOG_ERR,
|
|
+ "FWUM Firmware Start Firmware Upgrade returned %x",
|
|
+ rsp->ccode);
|
|
+ }
|
|
+ rc = (-1);
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-static tKFWUM_Status KfwumStartFirmwareUpgrade(struct ipmi_intf * intf)
|
|
+int
|
|
+KfwumGetTraceLog(struct ipmi_intf *intf)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- unsigned char upgType = 0 ; /* Upgrade type, wait BMC shutdown */
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
- req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_UPDATE;
|
|
- req.msg.data = (unsigned char *) &upgType;
|
|
- req.msg.data_len = 1;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if (!rsp)
|
|
- {
|
|
- printf("Error in FWUM Firmware Start Firmware Upgrade Command\n");
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
- else if (rsp->ccode)
|
|
- {
|
|
- if(rsp->ccode == 0xd5)
|
|
- {
|
|
- printf("No firmware available for upgrade. Download Firmware first\n");
|
|
- }
|
|
- else
|
|
- {
|
|
- printf("FWUM Firmware Start Firmware Upgrade returned %x\n",
|
|
- rsp->ccode);
|
|
- }
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
-
|
|
- return status;
|
|
+ int rc = 0;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char chunkIdx;
|
|
+ unsigned char cmdIdx;
|
|
+ if (verbose) {
|
|
+ printf(" Getting Trace Log!\n");
|
|
+ }
|
|
+ for (chunkIdx = 0;
|
|
+ (chunkIdx < TRACE_LOG_CHUNK_COUNT)
|
|
+ && (rc == 0);
|
|
+ chunkIdx++) {
|
|
+ /* Retreive each log chunk and print it */
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
+ req.msg.cmd = KFWUM_CMD_ID_GET_TRACE_LOG;
|
|
+ req.msg.data = &chunkIdx;
|
|
+ req.msg.data_len = 1;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error in FWUM Firmware Get Trace Log Command");
|
|
+ rc = (-1);
|
|
+ break;
|
|
+ } else if (rsp->ccode) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "FWUM Firmware Get Trace Log returned %x",
|
|
+ rsp->ccode);
|
|
+ rc = (-1);
|
|
+ break;
|
|
+ }
|
|
+ for (cmdIdx=0; cmdIdx < TRACE_LOG_CHUNK_SIZE; cmdIdx++) {
|
|
+ /* Don't diplay commands with an invalid state */
|
|
+ if ((rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1] != 0)
|
|
+ && (rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx] < KFWUM_CMD_ID_STD_MAX_CMD)) {
|
|
+ printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
|
|
+ CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx]],
|
|
+ CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1]],
|
|
+ rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 2]);
|
|
+ } else if ((rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1] != 0)
|
|
+ && (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] >= KFWUM_CMD_ID_EXTENDED_CMD)) {
|
|
+ printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
|
|
+ EXT_CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx] - KFWUM_CMD_ID_EXTENDED_CMD],
|
|
+ CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1]],
|
|
+ rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 2]);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ printf("\n");
|
|
+ return rc;
|
|
}
|
|
|
|
-#define TRACE_LOG_CHUNK_COUNT 7
|
|
-#define TRACE_LOG_CHUNK_SIZE 7
|
|
-#define TRACE_LOG_ATT_COUNT 3
|
|
-/* String table */
|
|
-/* Must match eFWUM_CmdId */
|
|
-static const char* CMD_ID_STRING[] = {
|
|
- "GetFwInfo",
|
|
- "KickWatchdog",
|
|
- "GetLastAnswer",
|
|
- "BootHandshake",
|
|
- "ReportStatus",
|
|
- "CtrlIPMBLine",
|
|
- "SetFwState",
|
|
- "GetFwStatus",
|
|
- "GetSpiMemStatus",
|
|
- "StartFwUpdate",
|
|
- "StartFwImage",
|
|
- "SaveFwImage",
|
|
- "FinishFwImage",
|
|
- "ReadFwImage",
|
|
- "ManualRollback",
|
|
- "GetTraceLog" };
|
|
-
|
|
-static const char* EXT_CMD_ID_STRING[] = {
|
|
- "FwUpgradeLock",
|
|
- "ProcessFwUpg",
|
|
- "ProcessFwRb",
|
|
- "WaitHSAfterUpg",
|
|
- "WaitFirstHSUpg",
|
|
- "FwInfoStateChange" };
|
|
-
|
|
-
|
|
-static const char* CMD_STATE_STRING[] = {
|
|
- "Invalid",
|
|
- "Begin",
|
|
- "Progress",
|
|
- "Completed" };
|
|
-
|
|
-
|
|
-static tKFWUM_Status KfwumGetTraceLog(struct ipmi_intf * intf)
|
|
+int
|
|
+KfwumGetInfoFromFirmware(unsigned char *pBuf, unsigned long bufSize,
|
|
+ tKFWUM_InFirmwareInfo *pInfo)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
- struct ipmi_rs *rsp;
|
|
- struct ipmi_rq req;
|
|
- unsigned char chunkIdx;
|
|
- unsigned char cmdIdx;
|
|
-
|
|
- if(verbose)
|
|
- {
|
|
- printf(" Getting Trace Log!\n");
|
|
- }
|
|
-
|
|
- for( chunkIdx = 0; (chunkIdx < TRACE_LOG_CHUNK_COUNT) && (status == KFWUM_STATUS_OK); chunkIdx++ )
|
|
- {
|
|
- /* Retreive each log chunk and print it */
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_FIRMWARE;
|
|
- req.msg.cmd = KFWUM_CMD_ID_GET_TRACE_LOG;
|
|
- req.msg.data = &chunkIdx;
|
|
- req.msg.data_len = 1;
|
|
-
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if (!rsp)
|
|
- {
|
|
- printf("Error in FWUM Firmware Get Trace Log Command\n");
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
- else if (rsp->ccode)
|
|
- {
|
|
- printf("FWUM Firmware Get Trace Log returned %x\n", rsp->ccode);
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
-
|
|
- if(status == KFWUM_STATUS_OK)
|
|
- {
|
|
- for (cmdIdx=0; cmdIdx < TRACE_LOG_CHUNK_SIZE; cmdIdx++)
|
|
- {
|
|
- /* Don't diplay commands with an invalid state */
|
|
- if ( (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+1] != 0) &&
|
|
- (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] < KFWUM_CMD_ID_STD_MAX_CMD))
|
|
- {
|
|
- printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
|
|
- CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx]],
|
|
- CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+1]],
|
|
- rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+2]);
|
|
- }
|
|
- else if ( (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+1] != 0) &&
|
|
- (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] >= KFWUM_CMD_ID_EXTENDED_CMD))
|
|
- {
|
|
- printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
|
|
- EXT_CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] - KFWUM_CMD_ID_EXTENDED_CMD],
|
|
- CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+1]],
|
|
- rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+2]);
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- printf("\n");
|
|
- return status;
|
|
-}
|
|
+ unsigned long offset = 0;
|
|
+ if (bufSize < (IN_FIRMWARE_INFO_OFFSET_LOCATION + IN_FIRMWARE_INFO_SIZE)) {
|
|
+ return (-1);
|
|
+ }
|
|
+ offset = IN_FIRMWARE_INFO_OFFSET_LOCATION;
|
|
|
|
+ /* Now, fill the structure with read informations */
|
|
+ pInfo->checksum = (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + 0 + IN_FIRMWARE_INFO_OFFSET_CHECKSUM ) << 8;
|
|
|
|
-/*******************************************************************************
|
|
-* Function Name: KfwumGetInfoFromFirmware
|
|
-*
|
|
-* Description: This function retreive from the firmare the following info :
|
|
-*
|
|
-* o Checksum
|
|
-* o File size (expected)
|
|
-* o Board Id
|
|
-* o Device Id
|
|
-*
|
|
-* Restriction: None
|
|
-*
|
|
-* Input: char * fileName - File to get info from
|
|
-*
|
|
-* Output: pInfo - container that will hold all the informations gattered.
|
|
-* see structure for all details
|
|
-*
|
|
-* Global: None
|
|
-*
|
|
-* Return: IFWU_SUCCESS - file ok
|
|
-* IFWU_ERROR - file error
|
|
-*
|
|
-*******************************************************************************/
|
|
-#define IN_FIRMWARE_INFO_OFFSET_LOCATION 0x5a0
|
|
-#define IN_FIRMWARE_INFO_SIZE 20
|
|
-#define IN_FIRMWARE_INFO_OFFSET_FILE_SIZE 0
|
|
-#define IN_FIRMWARE_INFO_OFFSET_CHECKSUM 4
|
|
-#define IN_FIRMWARE_INFO_OFFSET_BOARD_ID 6
|
|
-#define IN_FIRMWARE_INFO_OFFSET_DEVICE_ID 8
|
|
-#define IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION 9
|
|
-#define IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV 10
|
|
-#define IN_FIRMWARE_INFO_OFFSET_VERSION_MAJOR 11
|
|
-#define IN_FIRMWARE_INFO_OFFSET_VERSION_MINSUB 12
|
|
-#define IN_FIRMWARE_INFO_OFFSET_SDR_REV 13
|
|
-#define IN_FIRMWARE_INFO_OFFSET_IANA0 14
|
|
-#define IN_FIRMWARE_INFO_OFFSET_IANA1 15
|
|
-#define IN_FIRMWARE_INFO_OFFSET_IANA2 16
|
|
-
|
|
-#define KWUM_GET_BYTE_AT_OFFSET(pBuffer,os) pBuffer[os]
|
|
-
|
|
-tKFWUM_Status KfwumGetInfoFromFirmware(unsigned char * pBuf,
|
|
- unsigned long bufSize, tKFWUM_InFirmwareInfo * pInfo)
|
|
-{
|
|
- tKFWUM_Status status = KFWUM_STATUS_ERROR;
|
|
-
|
|
- if(bufSize >= (IN_FIRMWARE_INFO_OFFSET_LOCATION + IN_FIRMWARE_INFO_SIZE))
|
|
- {
|
|
- unsigned long offset = IN_FIRMWARE_INFO_OFFSET_LOCATION;
|
|
-
|
|
- /* Now, fill the structure with read informations */
|
|
- pInfo->checksum = (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+0+IN_FIRMWARE_INFO_OFFSET_CHECKSUM ) << 8;
|
|
- pInfo->checksum |= (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+1+IN_FIRMWARE_INFO_OFFSET_CHECKSUM );
|
|
-
|
|
-
|
|
- pInfo->sumToRemoveFromChecksum=
|
|
- KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_CHECKSUM);
|
|
-
|
|
- pInfo->sumToRemoveFromChecksum+=
|
|
- KWUM_GET_BYTE_AT_OFFSET(pBuf ,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_CHECKSUM+1);
|
|
-
|
|
- pInfo->fileSize =
|
|
- KWUM_GET_BYTE_AT_OFFSET(pBuf ,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+0) << 24;
|
|
- pInfo->fileSize |=
|
|
- (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+1) << 16;
|
|
- pInfo->fileSize |=
|
|
- (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+2) << 8;
|
|
- pInfo->fileSize |=
|
|
- (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+3);
|
|
-
|
|
- pInfo->boardId =
|
|
- KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_BOARD_ID+0) << 8;
|
|
- pInfo->boardId |=
|
|
- KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_BOARD_ID+1);
|
|
-
|
|
- pInfo->deviceId =
|
|
- KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_DEVICE_ID);
|
|
-
|
|
- pInfo->tableVers =
|
|
- KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION);
|
|
- pInfo->implRev =
|
|
- KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV);
|
|
- pInfo->versMajor =
|
|
- (KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_VERSION_MAJOR)) & 0x0f;
|
|
- pInfo->versMinor =
|
|
- (KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_VERSION_MINSUB)>>4) & 0x0f;
|
|
- pInfo->versSubMinor =
|
|
- (KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_VERSION_MINSUB)) & 0x0f;
|
|
- pInfo->sdrRev =
|
|
- KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_SDR_REV);
|
|
- pInfo->iana =
|
|
- KWUM_GET_BYTE_AT_OFFSET(pBuf ,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_IANA2) << 16;
|
|
- pInfo->iana |=
|
|
- (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_IANA1) << 8;
|
|
- pInfo->iana |=
|
|
- (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
- offset+IN_FIRMWARE_INFO_OFFSET_IANA0);
|
|
-
|
|
- KfwumFixTableVersionForOldFirmware(pInfo);
|
|
-
|
|
- status = KFWUM_STATUS_OK;
|
|
- }
|
|
- return(status);
|
|
-}
|
|
+ pInfo->checksum|= (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + 1 + IN_FIRMWARE_INFO_OFFSET_CHECKSUM);
|
|
|
|
+ pInfo->sumToRemoveFromChecksum = KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_CHECKSUM);
|
|
|
|
-void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo)
|
|
-{
|
|
- switch(pInfo->boardId)
|
|
- {
|
|
- case KFWUM_BOARD_KONTRON_UNKNOWN:
|
|
- pInfo->tableVers = 0xff;
|
|
- break;
|
|
- default:
|
|
- /* pInfo->tableVers is already set for the right version */
|
|
- break;
|
|
- }
|
|
-}
|
|
+ pInfo->sumToRemoveFromChecksum+= KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_CHECKSUM + 1);
|
|
+
|
|
+ pInfo->fileSize = KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 0) << 24;
|
|
+
|
|
+ pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 1) << 16;
|
|
+
|
|
+ pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 2) << 8;
|
|
+
|
|
+ pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 3);
|
|
+
|
|
+ pInfo->boardId = KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_BOARD_ID + 0) << 8;
|
|
|
|
+ pInfo->boardId|= KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_BOARD_ID + 1);
|
|
|
|
-tKFWUM_Status KfwumValidFirmwareForBoard(tKFWUM_BoardInfo boardInfo,
|
|
- tKFWUM_InFirmwareInfo firmInfo)
|
|
+ pInfo->deviceId = KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_DEVICE_ID);
|
|
+
|
|
+ pInfo->tableVers = KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION);
|
|
+
|
|
+ pInfo->implRev = KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV);
|
|
+
|
|
+ pInfo->versMajor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset
|
|
+ + IN_FIRMWARE_INFO_OFFSET_VER_MAJOROR)) & 0x0f;
|
|
+
|
|
+ pInfo->versMinor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset
|
|
+ + IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB) >> 4) & 0x0f;
|
|
+
|
|
+ pInfo->versSubMinor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB)) & 0x0f;
|
|
+
|
|
+ pInfo->sdrRev = KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_SDR_REV);
|
|
+
|
|
+ pInfo->iana = KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_IANA2) << 16;
|
|
+
|
|
+ pInfo->iana|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_IANA1) << 8;
|
|
+
|
|
+ pInfo->iana|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
|
|
+ offset + IN_FIRMWARE_INFO_OFFSET_IANA0);
|
|
+
|
|
+ KfwumFixTableVersionForOldFirmware(pInfo);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void
|
|
+KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo)
|
|
{
|
|
- tKFWUM_Status status = KFWUM_STATUS_OK;
|
|
-
|
|
- if(boardInfo.iana != firmInfo.iana)
|
|
- {
|
|
- printf("Board IANA does not match firmware IANA\n");
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
-
|
|
- if(boardInfo.boardId != firmInfo.boardId)
|
|
- {
|
|
- printf("Board IANA does not match firmware IANA\n");
|
|
- status = KFWUM_STATUS_ERROR;
|
|
- }
|
|
-
|
|
-
|
|
- if(status == KFWUM_STATUS_ERROR)
|
|
- {
|
|
- printf("Firmware invalid for target board. Download of upgrade aborted\n");
|
|
- }
|
|
- return status;
|
|
+ switch(pInfo->boardId) {
|
|
+ case KFWUM_BOARD_KONTRON_UNKNOWN:
|
|
+ pInfo->tableVers = 0xff;
|
|
+ break;
|
|
+ default:
|
|
+ /* pInfo->tableVers is already set for
|
|
+ * the right version
|
|
+ */
|
|
+ break;
|
|
+ }
|
|
}
|
|
|
|
+/* ipmi_kfwum_checkfwcompat - check whether firmware we're about to upload is
|
|
+ * compatible with board.
|
|
+ *
|
|
+ * @boardInfo:
|
|
+ * @firmInfo:
|
|
+ *
|
|
+ * returns 0 if compatible, otherwise (-1)
|
|
+ */
|
|
+int
|
|
+ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo,
|
|
+ tKFWUM_InFirmwareInfo firmInfo)
|
|
+{
|
|
+ int compatible = 0;
|
|
+ if (boardInfo.iana != firmInfo.iana) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Board IANA does not match firmware IANA.");
|
|
+ compatible = (-1);
|
|
+ }
|
|
+ if (boardInfo.boardId != firmInfo.boardId) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Board IANA does not match firmware IANA.");
|
|
+ compatible = (-1);
|
|
+ }
|
|
+ if (compatible != 0) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Firmware invalid for target board. Download of upgrade aborted.");
|
|
+ }
|
|
+ return compatible;
|
|
+}
|
|
|
|
-static void KfwumOutputInfo(tKFWUM_BoardInfo boardInfo,
|
|
- tKFWUM_InFirmwareInfo firmInfo)
|
|
+void
|
|
+printf_kfwum_info(tKFWUM_BoardInfo boardInfo, tKFWUM_InFirmwareInfo firmInfo)
|
|
{
|
|
- printf("Target Board Id : %u\n",boardInfo.boardId);
|
|
- printf("Target IANA number : %u\n",boardInfo.iana);
|
|
- printf("File Size : %lu bytes\n",firmInfo.fileSize);
|
|
- printf("Firmware Version : %d.%d%d SDR %d\n",firmInfo.versMajor,
|
|
- firmInfo.versMinor, firmInfo.versSubMinor, firmInfo.sdrRev);
|
|
+ printf(
|
|
+"Target Board Id : %u\n", boardInfo.boardId);
|
|
+ printf(
|
|
+"Target IANA number : %u\n", boardInfo.iana);
|
|
+ printf(
|
|
+"File Size : %lu bytes\n", firmInfo.fileSize);
|
|
+ printf(
|
|
+"Firmware Version : %d.%d%d SDR %d\n", firmInfo.versMajor,
|
|
+firmInfo.versMinor, firmInfo.versSubMinor, firmInfo.sdrRev);
|
|
}
|
|
diff --git a/ipmitool/lib/ipmi_hpmfwupg.c b/ipmitool/lib/ipmi_hpmfwupg.c
|
|
index 630c0e7..0a56857 100644
|
|
--- a/ipmitool/lib/ipmi_hpmfwupg.c
|
|
+++ b/ipmitool/lib/ipmi_hpmfwupg.c
|
|
@@ -17,7 +17,7 @@
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
- * This software is provided "AS IS," without a warranty of any kind.
|
|
+ * This software is provided "AS IS," without a warranty of any kind.
|
|
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
|
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
|
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
|
@@ -40,3940 +40,2605 @@
|
|
#include "../src/plugins/lan/md5.h"
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
+#include <sys/param.h>
|
|
|
|
#if HAVE_CONFIG_H
|
|
- #include <config.h>
|
|
+# include <config.h>
|
|
#endif
|
|
|
|
-/****************************************************************************
|
|
-*
|
|
-* Copyright (c) 2006 Kontron Canada, Inc. All Rights Reserved.
|
|
-*
|
|
-* HPM.1
|
|
-* Hardware Platform Management
|
|
-* IPM Controller Firmware Upgrade Procedure
|
|
-*
|
|
-* This module implements an Upgrade Agent for the IPM Controller
|
|
-* Firmware Upgrade Procedure (HPM.1) specification version 1.0.
|
|
-*
|
|
-* author:
|
|
-* Frederic.Lelievre@ca.kontron.com
|
|
-* Francois.Isabelle@ca.kontron.com
|
|
-* Jean-Michel.Audet@ca.kontron.com
|
|
-* MarieJosee.Blais@ca.kontron.com
|
|
-*
|
|
-*****************************************************************************
|
|
-*
|
|
-* HISTORY
|
|
-* ===========================================================================
|
|
-* 2007-01-11
|
|
-*
|
|
-* - Incremented to version 0.2
|
|
-* - Added lan packet size reduction mechanism to workaround fact
|
|
-* that lan iface will not return C7 on excessive length
|
|
-* - Fixed some typos
|
|
-* - now uses lprintf()
|
|
-*
|
|
-* - Incremented to version 0.3
|
|
-* - added patch for openipmi si driver V39 (send message in driver does not
|
|
-* retry on 82/83 completion code and return 82/83 as response from target
|
|
-* [conditionnaly built with ENABLE_OPENIPMI_V39_PATCH]
|
|
-*
|
|
-* see: ipmi-fix-send-msg-retry.pacth in openipmi-developer mailing list
|
|
-*
|
|
-* 2007-01-16
|
|
-*
|
|
-* - Incremented to version 0.4
|
|
-* - Fixed lan iface inaccesiblity timeout handling. Waiting for firmware
|
|
-* activation completion (fixed sleep) before re-opening a session and
|
|
-* get the final firmware upgrade status.
|
|
-* - Fixed some user interface stuff.
|
|
-*
|
|
-* 2007-05-09
|
|
-*
|
|
-* - Incremented to version 1.0
|
|
-* - Modifications for compliancy with HPM.1 specification version 1.0
|
|
-*
|
|
-* 2007-06-05
|
|
-*
|
|
-* - Modified the display of upgrade of Firmware version.
|
|
-* - Added new options like "check" and "component" and "all" to hpm commands.
|
|
-* - By default we skip the upgrade if we have the same firmware version
|
|
-* as compared to the Image file (*.hpm).This will ensure that user does
|
|
-* not update the target incase its already been updated
|
|
-*
|
|
-* 2008-01-25
|
|
-* - Reduce buffer length more aggressively when no response from iol.
|
|
-* - Incremented version to 1.02
|
|
-*
|
|
-* 2009-02-11
|
|
-* - With multi-component HPM file, if one component need to be skipped because
|
|
-* the component is already up-to-date, ipmitool sends "Initiate upgrade
|
|
-* action / Upload for upgrade" anyway.
|
|
-*
|
|
-* If the component needs to be skipped, ipmitool will not send "Initiate
|
|
-* upgrade action / Upload for upgrade"
|
|
-*
|
|
-* - Incremented version to 1.03
|
|
-*
|
|
-* 2009-02-11
|
|
-* - Fixed side effect introduced by last version, "forced" update didn't
|
|
-* work anymore
|
|
-* - Incremented version to 1.04
|
|
-*
|
|
-* 2009-03-25
|
|
-* - Fix the case where ipmitool loses the iol connection during the upload
|
|
-* block process. Once IPMITool was successfully sent the first byte,
|
|
-* IPMITool will not resize the block size.
|
|
-*
|
|
-* 2009-03-26
|
|
-* - Fix the problem when we try to upgrade specific component and the component
|
|
-* is already updated, IPMITool sends a "prepare action" but IPMITool skips
|
|
-* the upload firmware block process.
|
|
-* So, if we specify a specific component, we want to force to upload this
|
|
-* specific component.
|
|
-* - Incremented version to 1.05
|
|
-*
|
|
-* 2009-04-20
|
|
-* - Reworked previous update, when 'component' is specified, the other
|
|
-* components are now skipped.
|
|
-* - Incremented version to 1.06
|
|
-*
|
|
-* ===========================================================================
|
|
-* TODO
|
|
-* ===========================================================================
|
|
-* 2007-01-11
|
|
-* - Add interpretation of GetSelftestResults
|
|
-* - Add interpretation of component ID string
|
|
-*
|
|
-*****************************************************************************/
|
|
-
|
|
extern int verbose;
|
|
|
|
-/*
|
|
- * Agent version
|
|
- */
|
|
-#define HPMFWUPG_VERSION_MAJOR 1
|
|
-#define HPMFWUPG_VERSION_MINOR 0
|
|
-#define HPMFWUPG_VERSION_SUBMINOR 8
|
|
-
|
|
-/*
|
|
- * HPM.1 FIRMWARE UPGRADE COMMANDS (part of PICMG)
|
|
- */
|
|
-
|
|
-#define HPMFWUPG_GET_TARGET_UPG_CAPABILITIES 0x2E
|
|
-#define HPMFWUPG_GET_COMPONENT_PROPERTIES 0x2F
|
|
-#define HPMFWUPG_ABORT_UPGRADE 0x30
|
|
-#define HPMFWUPG_INITIATE_UPGRADE_ACTION 0x31
|
|
-#define HPMFWUPG_UPLOAD_FIRMWARE_BLOCK 0x32
|
|
-#define HPMFWUPG_FINISH_FIRMWARE_UPLOAD 0x33
|
|
-#define HPMFWUPG_GET_UPGRADE_STATUS 0x34
|
|
-#define HPMFWUPG_ACTIVATE_FIRMWARE 0x35
|
|
-#define HPMFWUPG_QUERY_SELFTEST_RESULT 0x36
|
|
-#define HPMFWUPG_QUERY_ROLLBACK_STATUS 0x37
|
|
-#define HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK 0x38
|
|
-
|
|
-/*
|
|
- * HPM.1 SPECIFIC COMPLETION CODES
|
|
- */
|
|
-#define HPMFWUPG_ROLLBACK_COMPLETED 0x00
|
|
-#define HPMFWUPG_COMMAND_IN_PROGRESS 0x80
|
|
-#define HPMFWUPG_NOT_SUPPORTED 0x81
|
|
-#define HPMFWUPG_SIZE_MISMATCH 0x81
|
|
-#define HPMFWUPG_ROLLBACK_FAILURE 0x81
|
|
-#define HPMFWUPG_INV_COMP_MASK 0x81
|
|
-#define HPMFWUPG__ABORT_FAILURE 0x81
|
|
-#define HPMFWUPG_INV_COMP_ID 0x82
|
|
-#define HPMFWUPG_INT_CHECKSUM_ERROR 0x82
|
|
-#define HPMFWUPG_INV_UPLOAD_MODE 0x82
|
|
-#define HPMFWUPG_ROLLBACK_OVERRIDE 0x82
|
|
-#define HPMFWUPG_INV_COMP_PROP 0x83
|
|
-#define HPMFWUPG_FW_MISMATCH 0x83
|
|
-#define HPMFWUPG_ROLLBACK_DENIED 0x83
|
|
-
|
|
-/*
|
|
- * This error code is used as a temporary PATCH to
|
|
- * the latest Open ipmi driver. This PATCH
|
|
- * will be removed once a new Open IPMI driver is released.
|
|
- * (Buggy version = 39)
|
|
- */
|
|
-#define ENABLE_OPENIPMI_V39_PATCH
|
|
-
|
|
-#ifdef ENABLE_OPENIPMI_V39_PATCH
|
|
-
|
|
-#define RETRY_COUNT_MAX 3
|
|
-
|
|
-static int errorCount;
|
|
-
|
|
-#define HPMFWUPG_IS_RETRYABLE(error) \
|
|
-((((error==0x83)||(error==0x82)||(error==0x80)) && (errorCount++<RETRY_COUNT_MAX))?TRUE:FALSE)
|
|
-#else
|
|
-#define HPMFWUPG_IS_RETRYABLE(error) FALSE
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * HPM FIRMWARE UPGRADE GENERAL DEFINITIONS
|
|
- */
|
|
-
|
|
-#define HPMFWUPG_PICMG_IDENTIFIER 0
|
|
-#define HPMFWUPG_VERSION_SIZE 6
|
|
-#define HPMFWUPG_DESC_STRING_LENGTH 12
|
|
-#define HPMFWUPG_DEFAULT_INACCESS_TIMEOUT 60 /* sec */
|
|
-#define HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT 60 /* sec */
|
|
-#define HPMFWUPG_MD5_SIGNATURE_LENGTH 16
|
|
-
|
|
-/* Component IDs */
|
|
-typedef enum eHpmfwupgComponentId
|
|
-{
|
|
- HPMFWUPG_COMPONENT_ID_0 = 0,
|
|
- HPMFWUPG_COMPONENT_ID_1,
|
|
- HPMFWUPG_COMPONENT_ID_2,
|
|
- HPMFWUPG_COMPONENT_ID_3,
|
|
- HPMFWUPG_COMPONENT_ID_4,
|
|
- HPMFWUPG_COMPONENT_ID_5,
|
|
- HPMFWUPG_COMPONENT_ID_6,
|
|
- HPMFWUPG_COMPONENT_ID_7,
|
|
- HPMFWUPG_COMPONENT_ID_MAX
|
|
-} tHpmfwupgComponentId;
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgComponentBitMask
|
|
-{
|
|
- union
|
|
- {
|
|
- unsigned char byte;
|
|
- struct
|
|
- {
|
|
- #ifdef WORDS_BIGENDIAN
|
|
- unsigned char component7 : 1;
|
|
- unsigned char component6 : 1;
|
|
- unsigned char component5 : 1;
|
|
- unsigned char component4 : 1;
|
|
- unsigned char component3 : 1;
|
|
- unsigned char component2 : 1;
|
|
- unsigned char component1 : 1;
|
|
- unsigned char component0 : 1;
|
|
- #else
|
|
- unsigned char component0 : 1;
|
|
- unsigned char component1 : 1;
|
|
- unsigned char component2 : 1;
|
|
- unsigned char component3 : 1;
|
|
- unsigned char component4 : 1;
|
|
- unsigned char component5 : 1;
|
|
- unsigned char component6 : 1;
|
|
- unsigned char component7 : 1;
|
|
- #endif
|
|
- }ATTRIBUTE_PACKING bitField;
|
|
- }ATTRIBUTE_PACKING ComponentBits;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-
|
|
-static const int HPMFWUPG_SUCCESS = 0;
|
|
-static const int HPMFWUPG_ERROR = -1;
|
|
-/* Upload firmware specific error codes */
|
|
-static const int HPMFWUPG_UPLOAD_BLOCK_LENGTH = 1;
|
|
-static const int HPMFWUPG_UPLOAD_RETRY = 2;
|
|
-
|
|
-
|
|
-/*
|
|
- * TARGET UPGRADE CAPABILITIES DEFINITIONS
|
|
- */
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetTargetUpgCapabilitiesReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetTargetUpgCapabilitiesResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char hpmVersion;
|
|
- union
|
|
- {
|
|
- unsigned char byte;
|
|
- struct
|
|
- {
|
|
- #if WORDS_BIGENDIAN
|
|
- unsigned char fwUpgUndesirable : 1;
|
|
- unsigned char autRollbackOverride : 1;
|
|
- unsigned char ipmcDegradedDurinUpg: 1;
|
|
- unsigned char deferActivation : 1;
|
|
- unsigned char servAffectDuringUpg : 1;
|
|
- unsigned char manualRollback : 1;
|
|
- unsigned char autRollback : 1;
|
|
- unsigned char ipmcSelftestCap : 1;
|
|
- #else
|
|
- unsigned char ipmcSelftestCap : 1;
|
|
- unsigned char autRollback : 1;
|
|
- unsigned char manualRollback : 1;
|
|
- unsigned char servAffectDuringUpg : 1;
|
|
- unsigned char deferActivation : 1;
|
|
- unsigned char ipmcDegradedDurinUpg: 1;
|
|
- unsigned char autRollbackOverride : 1;
|
|
- unsigned char fwUpgUndesirable : 1;
|
|
- #endif
|
|
- }ATTRIBUTE_PACKING bitField;
|
|
- }ATTRIBUTE_PACKING GlobalCapabilities;
|
|
- unsigned char upgradeTimeout;
|
|
- unsigned char selftestTimeout;
|
|
- unsigned char rollbackTimeout;
|
|
- unsigned char inaccessTimeout;
|
|
- struct HpmfwupgComponentBitMask componentsPresent;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetTargetUpgCapabilitiesCtx
|
|
-{
|
|
- struct HpmfwupgGetTargetUpgCapabilitiesReq req;
|
|
- struct HpmfwupgGetTargetUpgCapabilitiesResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * COMPONENT PROPERTIES DEFINITIONS
|
|
- */
|
|
-
|
|
-typedef enum eHpmfwupgCompPropertiesSelect
|
|
-{
|
|
- HPMFWUPG_COMP_GEN_PROPERTIES = 0,
|
|
- HPMFWUPG_COMP_CURRENT_VERSION,
|
|
- HPMFWUPG_COMP_DESCRIPTION_STRING,
|
|
- HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION,
|
|
- HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION,
|
|
- HPMFWUPG_COMP_RESERVED,
|
|
- HPMFWUPG_COMP_OEM_PROPERTIES = 192
|
|
-} tHpmfwupgCompPropertiesSelect;
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetComponentPropertiesReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char componentId;
|
|
- unsigned char selector;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetGeneralPropResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
- union
|
|
- {
|
|
- unsigned char byte;
|
|
- struct
|
|
- {
|
|
- #if WORDS_BIGENDIAN
|
|
- unsigned char reserved : 2;
|
|
- unsigned char payloadColdReset : 1;
|
|
- unsigned char deferredActivation : 1;
|
|
- unsigned char comparisonSupport : 1;
|
|
- unsigned char preparationSupport : 1;
|
|
- unsigned char rollbackBackup : 2;
|
|
- #else
|
|
- unsigned char rollbackBackup : 2;
|
|
- unsigned char preparationSupport : 1;
|
|
- unsigned char comparisonSupport : 1;
|
|
- unsigned char deferredActivation : 1;
|
|
- unsigned char payloadColdReset : 1;
|
|
- unsigned char reserved : 2;
|
|
- #endif
|
|
- }ATTRIBUTE_PACKING bitfield;
|
|
- }ATTRIBUTE_PACKING GeneralCompProperties;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetCurrentVersionResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char currentVersion[HPMFWUPG_VERSION_SIZE];
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetDescStringResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
- char descString[HPMFWUPG_DESC_STRING_LENGTH];
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetRollbackFwVersionResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char rollbackFwVersion[HPMFWUPG_VERSION_SIZE];
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetDeferredFwVersionResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char deferredFwVersion[HPMFWUPG_VERSION_SIZE];
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * GetComponentProperties - OEM properties (192)
|
|
- */
|
|
-#define HPMFWUPG_OEM_LENGTH 4
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetOemProperties
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char oemRspData[HPMFWUPG_OEM_LENGTH];
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetComponentPropertiesResp
|
|
-{
|
|
- union
|
|
- {
|
|
- struct HpmfwupgGetGeneralPropResp generalPropResp;
|
|
- struct HpmfwupgGetCurrentVersionResp currentVersionResp;
|
|
- struct HpmfwupgGetDescStringResp descStringResp;
|
|
- struct HpmfwupgGetRollbackFwVersionResp rollbackFwVersionResp;
|
|
- struct HpmfwupgGetDeferredFwVersionResp deferredFwVersionResp;
|
|
- struct HpmfwupgGetOemProperties oemProperties;
|
|
- }ATTRIBUTE_PACKING Response;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetComponentPropertiesCtx
|
|
-{
|
|
- struct HpmfwupgGetComponentPropertiesReq req;
|
|
- struct HpmfwupgGetComponentPropertiesResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-
|
|
-/*
|
|
- * ABORT UPGRADE DEFINITIONS
|
|
- */
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgAbortUpgradeReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgAbortUpgradeResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgAbortUpgradeCtx
|
|
-{
|
|
- struct HpmfwupgAbortUpgradeReq req;
|
|
- struct HpmfwupgAbortUpgradeResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * UPGRADE ACTIONS DEFINITIONS
|
|
- */
|
|
-typedef enum eHpmfwupgUpgradeAction
|
|
-{
|
|
- HPMFWUPG_UPGRADE_ACTION_BACKUP = 0,
|
|
- HPMFWUPG_UPGRADE_ACTION_PREPARE,
|
|
- HPMFWUPG_UPGRADE_ACTION_UPGRADE,
|
|
- HPMFWUPG_UPGRADE_ACTION_COMPARE,
|
|
- HPMFWUPG_UPGRADE_ACTION_INVALID = 0xff
|
|
-} tHpmfwupgUpgradeAction;
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgInitiateUpgradeActionReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
- struct HpmfwupgComponentBitMask componentsMask;
|
|
- unsigned char upgradeAction;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgInitiateUpgradeActionResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgInitiateUpgradeActionCtx
|
|
-{
|
|
- struct HpmfwupgInitiateUpgradeActionReq req;
|
|
- struct HpmfwupgInitiateUpgradeActionResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * UPLOAD FIRMWARE BLOCK DEFINITIONS
|
|
- */
|
|
-
|
|
-#define HPMFWUPG_SEND_DATA_COUNT_MAX 256
|
|
-#define HPMFWUPG_SEND_DATA_COUNT_KCS 30
|
|
-#define HPMFWUPG_SEND_DATA_COUNT_LAN 25
|
|
-#define HPMFWUPG_SEND_DATA_COUNT_IPMB 26
|
|
-#define HPMFWUPG_SEND_DATA_COUNT_IPMBL 26
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgUploadFirmwareBlockReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char blockNumber;
|
|
- unsigned char data[HPMFWUPG_SEND_DATA_COUNT_MAX];
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgUploadFirmwareBlockResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgUploadFirmwareBlockCtx
|
|
-{
|
|
- struct HpmfwupgUploadFirmwareBlockReq req;
|
|
- struct HpmfwupgUploadFirmwareBlockResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-
|
|
-/*
|
|
- * FINISH FIRMWARE UPLOAD DEFINITIONS
|
|
- */
|
|
-
|
|
-#define HPMFWUPG_IMAGE_SIZE_BYTE_COUNT 4
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgFinishFirmwareUploadReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char componentId;
|
|
- unsigned char imageLength[HPMFWUPG_IMAGE_SIZE_BYTE_COUNT];
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgFinishFirmwareUploadResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgFinishFirmwareUploadCtx
|
|
-{
|
|
- struct HpmfwupgFinishFirmwareUploadReq req;
|
|
- struct HpmfwupgFinishFirmwareUploadResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * ACTIVATE FW DEFINITIONS
|
|
- */
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgActivateFirmwareReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char rollback_override;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgActivateFirmwareResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgActivateFirmwareCtx
|
|
-{
|
|
- struct HpmfwupgActivateFirmwareReq req;
|
|
- struct HpmfwupgActivateFirmwareResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-
|
|
-/*
|
|
- * GET UPGRADE STATUS DEFINITIONS
|
|
- */
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetUpgradeStatusReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetUpgradeStatusResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char cmdInProcess;
|
|
- unsigned char lastCmdCompCode;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgGetUpgradeStatusCtx
|
|
-{
|
|
- struct HpmfwupgGetUpgradeStatusReq req;
|
|
- struct HpmfwupgGetUpgradeStatusResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * MANUAL FW ROLLBACK DEFINITIONS
|
|
- */
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgManualFirmwareRollbackReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgManualFirmwareRollbackResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-struct HpmfwupgManualFirmwareRollbackCtx
|
|
-{
|
|
- struct HpmfwupgManualFirmwareRollbackReq req;
|
|
- struct HpmfwupgManualFirmwareRollbackResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * QUERY ROLLBACK STATUS DEFINITIONS
|
|
- */
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgQueryRollbackStatusReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgQueryRollbackStatusResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
- struct HpmfwupgComponentBitMask rollbackComp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgQueryRollbackStatusCtx
|
|
-{
|
|
- struct HpmfwupgQueryRollbackStatusReq req;
|
|
- struct HpmfwupgQueryRollbackStatusResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-/*
|
|
- * QUERY SELF TEST RESULT DEFINITIONS
|
|
- */
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgQuerySelftestResultReq
|
|
-{
|
|
- unsigned char picmgId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgQuerySelftestResultResp
|
|
-{
|
|
- unsigned char picmgId;
|
|
- unsigned char result1;
|
|
- unsigned char result2;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgQuerySelftestResultCtx
|
|
-{
|
|
- struct HpmfwupgQuerySelftestResultReq req;
|
|
- struct HpmfwupgQuerySelftestResultResp resp;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-/*
|
|
- * HPM.1 IMAGE DEFINITIONS
|
|
+int HpmfwupgUpgrade(struct ipmi_intf *intf, char *imageFilename,
|
|
+ int activate, int, int);
|
|
+int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx *pFwupgCtx);
|
|
+int HpmfwupgPreparationStage(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx, int option);
|
|
+int HpmfwupgUpgradeStage(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx, int option);
|
|
+int HpmfwupgActivationStage(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx);
|
|
+int HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx *pCtx);
|
|
+int HpmfwupgGetComponentProperties(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgGetComponentPropertiesCtx *pCtx);
|
|
+int HpmfwupgQuerySelftestResult(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgQuerySelftestResultCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx);
|
|
+int HpmfwupgQueryRollbackStatus(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgQueryRollbackStatusCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx);
|
|
+int HpmfwupgAbortUpgrade(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgAbortUpgradeCtx *pCtx);
|
|
+int HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgInitiateUpgradeActionCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx);
|
|
+int HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUploadFirmwareBlockCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx, int count,
|
|
+ unsigned int *pOffset, unsigned int *blockLen);
|
|
+int HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgFinishFirmwareUploadCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx, int option);
|
|
+int HpmfwupgActivateFirmware(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgActivateFirmwareCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx);
|
|
+int HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgGetUpgradeStatusCtx *pCtxstruct,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx, int silent);
|
|
+int HpmfwupgManualFirmwareRollback(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgManualFirmwareRollbackCtx *pCtx);
|
|
+void HpmfwupgPrintUsage(void);
|
|
+unsigned char HpmfwupgCalculateChecksum(unsigned char *pData,
|
|
+ unsigned int length);
|
|
+int HpmfwupgGetDeviceId(struct ipmi_intf *intf,
|
|
+ struct ipm_devid_rsp *pGetDevId);
|
|
+int HpmfwupgGetBufferFromFile(char *imageFilename,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx);
|
|
+int HpmfwupgWaitLongDurationCmd(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx);
|
|
+struct ipmi_rs *HpmfwupgSendCmd(struct ipmi_intf *intf,
|
|
+ struct ipmi_rq req, struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
+
|
|
+
|
|
+int HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components,
|
|
+ struct HpmfwupgUpgradeCtx* pFwupgCtx,
|
|
+ unsigned char **pImagePtr,
|
|
+ struct ipmi_intf *intf,
|
|
+ int option,
|
|
+ int *pFlagColdReset);
|
|
+
|
|
+/* HpmGetuserInput - get input from user
|
|
+ *
|
|
+ * returns TRUE if its Yes or FALSE if its No
|
|
*/
|
|
-
|
|
-#define HPMFWUPG_HEADER_SIGNATURE_LENGTH 8
|
|
-#define HPMFWUPG_MANUFATURER_ID_LENGTH 3
|
|
-#define HPMFWUPG_PRODUCT_ID_LENGTH 2
|
|
-#define HPMFWUPG_TIME_LENGTH 4
|
|
-#define HPMFWUPG_TIMEOUT_LENGTH 1
|
|
-#define HPMFWUPG_COMP_REVISION_LENGTH 2
|
|
-#define HPMFWUPG_FIRM_REVISION_LENGTH 6
|
|
-#define HPMFWUPG_IMAGE_HEADER_VERSION 0
|
|
-#define HPMFWUPG_IMAGE_SIGNATURE "PICMGFWU"
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgImageHeader
|
|
+int
|
|
+HpmGetUserInput(char *str)
|
|
{
|
|
- char signature[HPMFWUPG_HEADER_SIGNATURE_LENGTH];
|
|
- unsigned char formatVersion;
|
|
- unsigned char deviceId;
|
|
- unsigned char manId[HPMFWUPG_MANUFATURER_ID_LENGTH];
|
|
- unsigned char prodId[HPMFWUPG_PRODUCT_ID_LENGTH];
|
|
- unsigned char time[HPMFWUPG_TIME_LENGTH];
|
|
- union
|
|
- {
|
|
- struct
|
|
- {
|
|
- #if WORDS_BIGENDIAN
|
|
- unsigned char imageSelfTest : 1;
|
|
- unsigned char autRollback : 1;
|
|
- unsigned char manRollback : 1;
|
|
- unsigned char servAffected : 1;
|
|
- unsigned char reserved : 4;
|
|
- #else
|
|
- unsigned char reserved : 4;
|
|
- unsigned char servAffected : 1;
|
|
- unsigned char manRollback : 1;
|
|
- unsigned char autRollback : 1;
|
|
- unsigned char imageSelfTest : 1;
|
|
- #endif
|
|
- } ATTRIBUTE_PACKING bitField;
|
|
- unsigned char byte;
|
|
- }ATTRIBUTE_PACKING imageCapabilities;
|
|
- struct HpmfwupgComponentBitMask components;
|
|
- unsigned char selfTestTimeout;
|
|
- unsigned char rollbackTimeout;
|
|
- unsigned char inaccessTimeout;
|
|
- unsigned char compRevision[HPMFWUPG_COMP_REVISION_LENGTH];
|
|
- unsigned char firmRevision[HPMFWUPG_FIRM_REVISION_LENGTH];
|
|
- unsigned short oemDataLength;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
+ char userInput[2];
|
|
+ int ret;
|
|
|
|
-#define HPMFWUPG_DESCRIPTION_LENGTH 21
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgActionRecord
|
|
-{
|
|
- unsigned char actionType;
|
|
- struct HpmfwupgComponentBitMask components;
|
|
- unsigned char checksum;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#define HPMFWUPG_FIRMWARE_SIZE_LENGTH 4
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgFirmwareImage
|
|
-{
|
|
- unsigned char version[HPMFWUPG_FIRM_REVISION_LENGTH];
|
|
- char desc[HPMFWUPG_DESCRIPTION_LENGTH];
|
|
- unsigned char length[HPMFWUPG_FIRMWARE_SIZE_LENGTH];
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(1)
|
|
-#endif
|
|
-struct HpmfwupgUpgradeCtx
|
|
-{
|
|
- struct HpmfwupgComponentBitMask compUpdateMask;
|
|
- unsigned int imageSize;
|
|
- unsigned char* pImageData;
|
|
- unsigned char componentId;
|
|
- struct HpmfwupgGetTargetUpgCapabilitiesResp targetCap;
|
|
- struct HpmfwupgGetGeneralPropResp genCompProp[HPMFWUPG_COMPONENT_ID_MAX];
|
|
- struct ipm_devid_rsp devId;
|
|
-} ATTRIBUTE_PACKING;
|
|
-#ifdef HAVE_PRAGMA_PACK
|
|
-#pragma pack(0)
|
|
-#endif
|
|
-
|
|
-typedef enum eHpmfwupgActionType
|
|
-{
|
|
- HPMFWUPG_ACTION_BACKUP_COMPONENTS = 0,
|
|
- HPMFWUPG_ACTION_PREPARE_COMPONENTS,
|
|
- HPMFWUPG_ACTION_UPLOAD_FIRMWARE,
|
|
- HPMFWUPG_ACTION_RESERVED = 0xFF
|
|
-} tHpmfwupgActionType;
|
|
-
|
|
-/*
|
|
- * FUNCTIONS PROTOTYPES
|
|
- */
|
|
-#define HPMFWUPG_MAJORMINOR_VERSION_SIZE 2
|
|
-
|
|
-
|
|
-#define DEFAULT_COMPONENT_UPLOAD 0x0F
|
|
+ printf("%s", str);
|
|
+ ret = scanf("%s", userInput);
|
|
+ if (!ret) {
|
|
+ return 1;
|
|
+ }
|
|
+ if (toupper(userInput[0]) == 'Y') {
|
|
+ return 1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
|
|
-/*
|
|
- * Options added for user to check the version and to view both the FILE and TARGET Version
|
|
+/* HpmDisplayLine - display the line with the given character
|
|
*/
|
|
-#define VERSIONCHECK_MODE 0x01
|
|
-#define VIEW_MODE 0x02
|
|
-#define DEBUG_MODE 0x04
|
|
-#define FORCE_MODE_ALL 0x08
|
|
-#define FORCE_MODE_COMPONENT 0x10
|
|
-#define FORCE_MODE (FORCE_MODE_ALL|FORCE_MODE_COMPONENT)
|
|
-
|
|
-typedef struct _VERSIONINFO
|
|
-{
|
|
- unsigned char componentId;
|
|
- unsigned char targetMajor;
|
|
- unsigned char targetMinor;
|
|
- unsigned char targetAux[4];
|
|
- unsigned char rollbackMajor;
|
|
- unsigned char rollbackMinor;
|
|
- unsigned char rollbackAux[4];
|
|
- unsigned char deferredMajor;
|
|
- unsigned char deferredMinor;
|
|
- unsigned char deferredAux[4];
|
|
- unsigned char imageMajor;
|
|
- unsigned char imageMinor;
|
|
- unsigned char imageAux[4];
|
|
- unsigned char coldResetRequired;
|
|
- unsigned char rollbackSupported;
|
|
- char descString[15];
|
|
-}VERSIONINFO, *PVERSIONINFO;
|
|
-
|
|
-VERSIONINFO gVersionInfo[HPMFWUPG_COMPONENT_ID_MAX];
|
|
-
|
|
-#define TARGET_VER (0x01)
|
|
-#define ROLLBACK_VER (0x02)
|
|
-#define IMAGE_VER (0x04)
|
|
-
|
|
-
|
|
-
|
|
-
|
|
-static int HpmfwupgUpgrade(struct ipmi_intf *intf, char* imageFilename, int activate, int,int);
|
|
-static int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-static int HpmfwupgPreparationStage( struct ipmi_intf *intf,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx, int option);
|
|
-static int HpmfwupgUpgradeStage ( struct ipmi_intf *intf,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx, int compToUpload ,int option);
|
|
-static int HpmfwupgActivationStage(struct ipmi_intf *intf,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-static int HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf,
|
|
- struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx);
|
|
-static int HpmfwupgGetComponentProperties(struct ipmi_intf *intf,
|
|
- struct HpmfwupgGetComponentPropertiesCtx* pCtx);
|
|
-static int HpmfwupgQuerySelftestResult(struct ipmi_intf *intf,
|
|
- struct HpmfwupgQuerySelftestResultCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-static int HpmfwupgQueryRollbackStatus(struct ipmi_intf *intf,
|
|
- struct HpmfwupgQueryRollbackStatusCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-static int HpmfwupgAbortUpgrade(struct ipmi_intf *intf,
|
|
- struct HpmfwupgAbortUpgradeCtx* pCtx);
|
|
-static int HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf,
|
|
- struct HpmfwupgInitiateUpgradeActionCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-static int HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf,
|
|
- struct HpmfwupgUploadFirmwareBlockCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx, int count ,
|
|
- unsigned int *pOffset, unsigned int *blockLen);
|
|
-static int HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf,
|
|
- struct HpmfwupgFinishFirmwareUploadCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-static int HpmfwupgActivateFirmware(struct ipmi_intf *intf,
|
|
- struct HpmfwupgActivateFirmwareCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-static int HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf, struct HpmfwupgGetUpgradeStatusCtx* pCtxstruct, struct HpmfwupgUpgradeCtx* pFwupgCtx, int silent);
|
|
-static int HpmfwupgManualFirmwareRollback(struct ipmi_intf *intf,
|
|
- struct HpmfwupgManualFirmwareRollbackCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-static void HpmfwupgPrintUsage(void);
|
|
-static unsigned char HpmfwupgCalculateChecksum(unsigned char* pData, unsigned int length);
|
|
-static int HpmfwupgGetDeviceId(struct ipmi_intf *intf, struct ipm_devid_rsp* pGetDevId);
|
|
-static int HpmfwupgGetBufferFromFile(char* imageFilename, struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-static int HpmfwupgWaitLongDurationCmd(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-
|
|
-static struct ipmi_rs * HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
-
|
|
-
|
|
-static int HpmFwupgActionUploadFirmware
|
|
-(
|
|
- struct HpmfwupgComponentBitMask components,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx,
|
|
- unsigned char** pImagePtr,
|
|
- int componentToUpload,
|
|
- struct ipmi_intf *intf,
|
|
- int option,
|
|
- int* pFlagColdReset
|
|
-);
|
|
-
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmGetuserInput
|
|
-*
|
|
-* Description: This function gets input from user and returns TRUE if its Yes
|
|
-* or FALSE if its No
|
|
-*
|
|
-*****************************************************************************/
|
|
-int HpmGetUserInput(char *str)
|
|
-{
|
|
- char userInput[2];
|
|
- int ret;
|
|
-
|
|
- printf("%s", str);
|
|
- ret = scanf("%s", userInput);
|
|
- if (!ret) {
|
|
- return 1;
|
|
- }
|
|
-
|
|
- if (toupper(userInput[0]) == 'Y')
|
|
- {
|
|
- return 1;
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmDisplayLine
|
|
-*
|
|
-* Description: This is to display the line with the given character.
|
|
-*
|
|
-*****************************************************************************/
|
|
-void HpmDisplayLine(char *s, int n)
|
|
+void
|
|
+HpmDisplayLine(char *s, int n)
|
|
{
|
|
- while (n--) printf ("%c",*s);
|
|
- printf("\n");
|
|
+ while (n--) {
|
|
+ printf ("%c", *s);
|
|
+ }
|
|
+ printf("\n");
|
|
}
|
|
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmDisplayUpgradeHeader
|
|
-*
|
|
-* Description: This function the displays the Upgrade header information
|
|
-*
|
|
-*****************************************************************************/
|
|
-void HpmDisplayUpgradeHeader(void)
|
|
-{
|
|
- printf("\n");
|
|
- HpmDisplayLine("-",79 );
|
|
- printf(
|
|
- "|ID | Name | Versions | %% |\n");
|
|
- printf(
|
|
- "| | | Active | Backup | File | |\n");
|
|
- printf(
|
|
- "|----|-------------|-----------------|-----------------|-----------------|----|\n");
|
|
+/* HpmDisplayUpgradeHeader - display the Upgrade header information
|
|
+ */
|
|
+void
|
|
+HpmDisplayUpgradeHeader(void)
|
|
+{
|
|
+ printf("\n");
|
|
+ HpmDisplayLine("-", 79);
|
|
+ printf(
|
|
+"|ID | Name | Versions | %% |\n");
|
|
+ printf(
|
|
+"| | | Active | Backup | File | |\n");
|
|
+ printf(
|
|
+"|----|-------------|-----------------|-----------------|-----------------|----|\n");
|
|
}
|
|
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmDisplayUpgrade
|
|
-*
|
|
-* Description: This function displays the progress of the upgrade it prints the "."
|
|
-* every 5% of its completion.
|
|
-*
|
|
-*****************************************************************************/
|
|
-void HpmDisplayUpgrade( int skip, unsigned int totalSent,
|
|
- unsigned int displayFWLength,time_t timeElapsed)
|
|
-{
|
|
- int percent;
|
|
- static int old_percent=1;
|
|
- if (skip)
|
|
- {
|
|
- printf("Skip|\n");
|
|
- return;
|
|
- }
|
|
- fflush(stdout);
|
|
-
|
|
- percent = ((float)totalSent/displayFWLength)*100;
|
|
- if (percent != old_percent)
|
|
- {
|
|
- if ( percent == 0 ) printf(" 0%%|");
|
|
- else if (percent == 100) printf("\b\b\b\b\b100%%|\n");
|
|
- else printf("\b\b\b\b\b%3d%%|", percent);
|
|
- old_percent = percent;
|
|
- }
|
|
+/* HpmDisplayUpgrade - display the progress of the upgrade; prints the "."
|
|
+ * for every 5% of its completion.
|
|
+ */
|
|
+void
|
|
+HpmDisplayUpgrade(int skip, unsigned int totalSent,
|
|
+ unsigned int displayFWLength, time_t timeElapsed)
|
|
+{
|
|
+ int percent;
|
|
+ static int old_percent = -1;
|
|
+ if (skip) {
|
|
+ printf("Skip|\n");
|
|
+ return;
|
|
+ }
|
|
+ fflush(stdout);
|
|
|
|
- if (totalSent== displayFWLength)
|
|
- {
|
|
- /* Display the time taken to complete the upgrade */
|
|
- printf(
|
|
- "| |Upload Time: %02ld:%02ld | Image Size: %7d bytes |\n",
|
|
- timeElapsed/60,timeElapsed%60,totalSent);
|
|
- }
|
|
+ percent = ((float)totalSent / displayFWLength) * 100;
|
|
+ if (percent != old_percent) {
|
|
+ if (old_percent != -1) {
|
|
+ printf("\b\b\b\b\b");
|
|
+ }
|
|
+ printf("%3d%%|", percent);
|
|
+ old_percent = percent;
|
|
+ }
|
|
+ if (totalSent == displayFWLength) {
|
|
+ /* Display the time taken to complete the upgrade */
|
|
+ printf(
|
|
+"\n| |Upload Time: %02ld:%02ld | Image Size: %7d bytes |\n",
|
|
+ timeElapsed / 60, timeElapsed % 60, totalSent);
|
|
+ old_percent = -1;
|
|
+ }
|
|
}
|
|
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmDisplayVersionHeader
|
|
-*
|
|
-* Description: This function displays the information about version header
|
|
-*
|
|
-*****************************************************************************/
|
|
-void HpmDisplayVersionHeader(int mode)
|
|
-{
|
|
- if ( mode & IMAGE_VER)
|
|
- {
|
|
- HpmDisplayLine("-",74 );
|
|
- printf(
|
|
- "|ID | Name | Versions |\n");
|
|
- printf(
|
|
- "| | | Active | Backup | File |\n");
|
|
- HpmDisplayLine("-",74 );
|
|
- }
|
|
- else
|
|
- {
|
|
- HpmDisplayLine("-",74 );
|
|
- printf(
|
|
- "|ID | Name | Versions |\n");
|
|
- printf(
|
|
- "| | | Active | Backup | Deferred |\n");
|
|
- HpmDisplayLine("-",74 );
|
|
- }
|
|
+/* HpmDisplayVersionHeader - display the information about version header
|
|
+ */
|
|
+void
|
|
+HpmDisplayVersionHeader(int mode)
|
|
+{
|
|
+ if (mode & IMAGE_VER) {
|
|
+ HpmDisplayLine("-", 74);
|
|
+ printf(
|
|
+"|ID | Name | Versions |\n");
|
|
+ printf(
|
|
+"| | | Active | Backup | File |\n");
|
|
+ HpmDisplayLine("-", 74);
|
|
+ } else {
|
|
+ HpmDisplayLine("-",74 );
|
|
+ printf(
|
|
+"|ID | Name | Versions |\n");
|
|
+ printf(
|
|
+"| | | Active | Backup | Deferred |\n");
|
|
+ HpmDisplayLine("-", 74);
|
|
+ }
|
|
}
|
|
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmDisplayVersion
|
|
-*
|
|
-* Description: This function displays the version of the image and target
|
|
-*
|
|
-*****************************************************************************/
|
|
-void HpmDisplayVersion(int mode, VERSIONINFO *pVersion, int upgradable)
|
|
+/* HpmDisplayVersion - display the version of the image and target
|
|
+ */
|
|
+void
|
|
+HpmDisplayVersion(int mode, VERSIONINFO *pVersion, int upgradable)
|
|
{
|
|
- char descString[16];
|
|
-
|
|
- memset(&descString,0x00,sizeof(descString));
|
|
- /*
|
|
- * Added this to ensure that even if the description string
|
|
- * is more than required it does not give problem in displaying it
|
|
- */
|
|
- strncpy(descString,pVersion->descString,13);
|
|
-
|
|
/*
|
|
* If the cold reset is required then we can display * on it
|
|
* so that user is aware that he needs to do payload power
|
|
* cycle after upgrade
|
|
*/
|
|
printf("|%c%c%2d|%-13s|",
|
|
- pVersion->coldResetRequired?'*':' ',
|
|
- upgradable ? '^': ' ',
|
|
- pVersion->componentId,descString);
|
|
-
|
|
- if (mode & TARGET_VER)
|
|
- {
|
|
- if ((pVersion->targetMajor == 0xFF ||
|
|
- (pVersion->targetMajor == 0x7F)) &&
|
|
- pVersion->targetMinor == 0xFF)
|
|
+ pVersion->coldResetRequired ? '*' : ' ',
|
|
+ upgradable ? '^' : ' ',
|
|
+ pVersion->componentId, pVersion->descString);
|
|
+
|
|
+ if (mode & TARGET_VER) {
|
|
+ if ((pVersion->targetMajor == 0xFF
|
|
+ || (pVersion->targetMajor == 0x7F))
|
|
+ && pVersion->targetMinor == 0xFF) {
|
|
printf(" ---.-- -------- |");
|
|
- else
|
|
+ } else {
|
|
printf(" %3d.%02x %02X%02X%02X%02X |",
|
|
- pVersion->targetMajor,
|
|
- pVersion->targetMinor,
|
|
- pVersion->targetAux[0],
|
|
- pVersion->targetAux[1],
|
|
- pVersion->targetAux[2],
|
|
- pVersion->targetAux[3]);
|
|
-
|
|
- if (mode & ROLLBACK_VER)
|
|
- {
|
|
- if ((pVersion->rollbackMajor == 0xFF ||
|
|
- (pVersion->rollbackMajor == 0x7F)) &&
|
|
- pVersion->rollbackMinor == 0xFF)
|
|
+ pVersion->targetMajor,
|
|
+ pVersion->targetMinor,
|
|
+ pVersion->targetAux[0],
|
|
+ pVersion->targetAux[1],
|
|
+ pVersion->targetAux[2],
|
|
+ pVersion->targetAux[3]);
|
|
+ }
|
|
+ if (mode & ROLLBACK_VER) {
|
|
+ if ((pVersion->rollbackMajor == 0xFF
|
|
+ || (pVersion->rollbackMajor == 0x7F))
|
|
+ && pVersion->rollbackMinor == 0xFF) {
|
|
printf(" ---.-- -------- |");
|
|
- else
|
|
+ } else {
|
|
printf(" %3d.%02x %02X%02X%02X%02X |",
|
|
- pVersion->rollbackMajor,
|
|
- pVersion->rollbackMinor,
|
|
- pVersion->rollbackAux[0],
|
|
- pVersion->rollbackAux[1],
|
|
- pVersion->rollbackAux[2],
|
|
- pVersion->rollbackAux[3]);
|
|
+ pVersion->rollbackMajor,
|
|
+ pVersion->rollbackMinor,
|
|
+ pVersion->rollbackAux[0],
|
|
+ pVersion->rollbackAux[1],
|
|
+ pVersion->rollbackAux[2],
|
|
+ pVersion->rollbackAux[3]);
|
|
}
|
|
- else
|
|
+ } else {
|
|
printf(" ---.-- -------- |");
|
|
}
|
|
-
|
|
- if (mode & IMAGE_VER)
|
|
- {
|
|
- if ((pVersion->imageMajor == 0xFF ||
|
|
- (pVersion->imageMajor == 0x7F)) &&
|
|
- pVersion->imageMinor == 0xFF)
|
|
+ }
|
|
+ if (mode & IMAGE_VER) {
|
|
+ if ((pVersion->imageMajor == 0xFF
|
|
+ || (pVersion->imageMajor == 0x7F))
|
|
+ && pVersion->imageMinor == 0xFF) {
|
|
printf(" ---.-- |");
|
|
- else
|
|
+ } else {
|
|
printf(" %3d.%02x %02X%02X%02X%02X |",
|
|
- pVersion->imageMajor,
|
|
- pVersion->imageMinor,
|
|
- pVersion->imageAux[0],
|
|
- pVersion->imageAux[1],
|
|
- pVersion->imageAux[2],
|
|
- pVersion->imageAux[3]);
|
|
- }
|
|
- else
|
|
- {
|
|
- if ((pVersion->deferredMajor == 0xFF ||
|
|
- (pVersion->deferredMajor == 0x7F)) &&
|
|
- pVersion->deferredMinor == 0xFF)
|
|
+ pVersion->imageMajor,
|
|
+ pVersion->imageMinor,
|
|
+ pVersion->imageAux[0],
|
|
+ pVersion->imageAux[1],
|
|
+ pVersion->imageAux[2],
|
|
+ pVersion->imageAux[3]);
|
|
+ }
|
|
+ } else {
|
|
+ if ((pVersion->deferredMajor == 0xFF
|
|
+ || (pVersion->deferredMajor == 0x7F))
|
|
+ && pVersion->deferredMinor == 0xFF) {
|
|
printf(" ---.-- -------- |");
|
|
- else
|
|
+ } else {
|
|
printf(" %3d.%02x %02X%02X%02X%02X |",
|
|
- pVersion->deferredMajor,
|
|
- pVersion->deferredMinor,
|
|
- pVersion->deferredAux[0],
|
|
- pVersion->deferredAux[1],
|
|
- pVersion->deferredAux[2],
|
|
- pVersion->deferredAux[3]);
|
|
+ pVersion->deferredMajor,
|
|
+ pVersion->deferredMinor,
|
|
+ pVersion->deferredAux[0],
|
|
+ pVersion->deferredAux[1],
|
|
+ pVersion->deferredAux[2],
|
|
+ pVersion->deferredAux[3]);
|
|
}
|
|
-}
|
|
-
|
|
-
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmfwupgTargerCheck
|
|
-*
|
|
-* Description: This function gets the target information and displays it on the
|
|
-* screen
|
|
-*
|
|
-*****************************************************************************/
|
|
-int HpmfwupgTargetCheck(struct ipmi_intf * intf, int option)
|
|
-{
|
|
- struct HpmfwupgUpgradeCtx fwupgCtx;
|
|
- struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- int componentId = 0;
|
|
- int flagColdReset = FALSE;
|
|
- struct ipm_devid_rsp devIdrsp;
|
|
- struct HpmfwupgGetComponentPropertiesCtx getCompProp;
|
|
- int mode = 0;
|
|
-
|
|
-
|
|
- rc = HpmfwupgGetDeviceId(intf, &devIdrsp);
|
|
-
|
|
- if (rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Verify whether the Target board is present \n");
|
|
- return HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd);
|
|
- if (rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- /*
|
|
- * That indicates the target is not responding to the command
|
|
- * May be that there is no HPM support
|
|
- */
|
|
- lprintf(LOG_NOTICE,"Board might not be supporting the HPM.1 Standards\n");
|
|
- return rc;
|
|
- }
|
|
- if (option & VIEW_MODE)
|
|
- {
|
|
- lprintf(LOG_NOTICE,"-------Target Information-------");
|
|
- lprintf(LOG_NOTICE,"Device Id : 0x%x", devIdrsp.device_id);
|
|
- lprintf(LOG_NOTICE,"Device Revision : 0x%x", devIdrsp.device_revision);
|
|
- lprintf(LOG_NOTICE,"Product Id : 0x%04x", buf2short(devIdrsp.product_id));
|
|
- lprintf(LOG_NOTICE,"Manufacturer Id : 0x%04x (%s)\n\n", buf2short(devIdrsp.manufacturer_id),
|
|
- val2str(buf2short(devIdrsp.manufacturer_id),ipmi_oem_info));
|
|
- HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER);
|
|
- }
|
|
-
|
|
- for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX;
|
|
- componentId++ )
|
|
- {
|
|
- /* If the component is supported */
|
|
- if ( ((1 << componentId) & targetCapCmd.resp.componentsPresent.ComponentBits.byte) )
|
|
- {
|
|
- memset((PVERSIONINFO)&gVersionInfo[componentId],0x00,sizeof(VERSIONINFO));
|
|
-
|
|
- getCompProp.req.componentId = componentId;
|
|
- getCompProp.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES;
|
|
- rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
- if (rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Get CompGenProp Failed for component Id %d\n",componentId);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- gVersionInfo[componentId].rollbackSupported = getCompProp.resp.Response.
|
|
- generalPropResp.GeneralCompProperties.bitfield.rollbackBackup;
|
|
- gVersionInfo[componentId].coldResetRequired = getCompProp.resp.Response.
|
|
- generalPropResp.GeneralCompProperties.bitfield.payloadColdReset;
|
|
-
|
|
- getCompProp.req.selector = HPMFWUPG_COMP_DESCRIPTION_STRING;
|
|
- rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
- if (rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Get CompDescString Failed for component Id %d\n",componentId);
|
|
- return rc;
|
|
- }
|
|
- strcpy((char *)&gVersionInfo[componentId].descString,
|
|
- getCompProp.resp.Response.descStringResp.descString);
|
|
-
|
|
- getCompProp.req.selector = HPMFWUPG_COMP_CURRENT_VERSION;
|
|
- rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
- if (rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Get CompCurrentVersion Failed for component Id %d\n",componentId);
|
|
- return rc;
|
|
- }
|
|
-
|
|
- gVersionInfo[componentId].componentId = componentId;
|
|
- gVersionInfo[componentId].targetMajor = getCompProp.resp.Response.
|
|
- currentVersionResp.currentVersion[0];
|
|
- gVersionInfo[componentId].targetMinor = getCompProp.resp.Response.
|
|
- currentVersionResp.currentVersion[1];
|
|
- gVersionInfo[componentId].targetAux[0] = getCompProp.resp.Response.
|
|
- currentVersionResp.currentVersion[2];
|
|
- gVersionInfo[componentId].targetAux[1] = getCompProp.resp.Response.
|
|
- currentVersionResp.currentVersion[3];
|
|
- gVersionInfo[componentId].targetAux[2] = getCompProp.resp.Response.
|
|
- currentVersionResp.currentVersion[4];
|
|
- gVersionInfo[componentId].targetAux[3] = getCompProp.resp.Response.
|
|
- currentVersionResp.currentVersion[5];
|
|
- mode = TARGET_VER;
|
|
-
|
|
- if (gVersionInfo[componentId].rollbackSupported)
|
|
- {
|
|
- getCompProp.req.selector = HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION;
|
|
- rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
- if (rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Get CompRollbackVersion Failed for component Id %d\n",componentId);
|
|
- } else {
|
|
- gVersionInfo[componentId].rollbackMajor = getCompProp.resp
|
|
- .Response.rollbackFwVersionResp.rollbackFwVersion[0];
|
|
- gVersionInfo[componentId].rollbackMinor = getCompProp.resp
|
|
- .Response.rollbackFwVersionResp.rollbackFwVersion[1];
|
|
- gVersionInfo[componentId].rollbackAux[0] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[2];
|
|
- gVersionInfo[componentId].rollbackAux[1] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[3];
|
|
- gVersionInfo[componentId].rollbackAux[2] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[4];
|
|
- gVersionInfo[componentId].rollbackAux[3] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[5];
|
|
- }
|
|
-
|
|
- getCompProp.req.selector = HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION;
|
|
- rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
- if (rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Get CompRollbackVersion Failed for component Id %d\n",componentId);
|
|
- } else {
|
|
- gVersionInfo[componentId].deferredMajor = getCompProp.resp
|
|
- .Response.deferredFwVersionResp.deferredFwVersion[0];
|
|
- gVersionInfo[componentId].deferredMinor = getCompProp.resp
|
|
- .Response.deferredFwVersionResp.deferredFwVersion[1];
|
|
- gVersionInfo[componentId].deferredAux[0] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[2];
|
|
- gVersionInfo[componentId].deferredAux[1] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[3];
|
|
- gVersionInfo[componentId].deferredAux[2] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[4];
|
|
- gVersionInfo[componentId].deferredAux[3] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[5];
|
|
- }
|
|
- mode |= ROLLBACK_VER;
|
|
- }
|
|
- else
|
|
- {
|
|
- gVersionInfo[componentId].rollbackMajor = 0xff;
|
|
- gVersionInfo[componentId].rollbackMinor = 0xff;
|
|
- gVersionInfo[componentId].rollbackAux[0] = 0xff;
|
|
- gVersionInfo[componentId].rollbackAux[1] = 0xff;
|
|
- gVersionInfo[componentId].rollbackAux[2] = 0xff;
|
|
- gVersionInfo[componentId].rollbackAux[3] = 0xff;
|
|
-
|
|
- gVersionInfo[componentId].deferredMajor = 0xff;
|
|
- gVersionInfo[componentId].deferredMinor = 0xff;
|
|
- gVersionInfo[componentId].deferredAux[0] = 0xff;
|
|
- gVersionInfo[componentId].deferredAux[1] = 0xff;
|
|
- gVersionInfo[componentId].deferredAux[2] = 0xff;
|
|
- gVersionInfo[componentId].deferredAux[3] = 0xff;
|
|
- }
|
|
-
|
|
- if (gVersionInfo[componentId].coldResetRequired)
|
|
- {
|
|
- /*
|
|
- * If any of the component indicates that the Payload Cold reset is required
|
|
- * then set the flag
|
|
- */
|
|
- flagColdReset = TRUE;
|
|
- }
|
|
- if (option & VIEW_MODE)
|
|
- {
|
|
- HpmDisplayVersion(mode,&gVersionInfo[componentId], 0);
|
|
- printf("\n");
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if (option & VIEW_MODE)
|
|
- {
|
|
- HpmDisplayLine("-",74 );
|
|
- fflush(stdout);
|
|
- lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset");
|
|
- printf("\n\n");
|
|
- }
|
|
- return HPMFWUPG_SUCCESS;
|
|
-}
|
|
-
|
|
-/*****************************************************************************
|
|
-* Function Name: HpmfwupgUpgrade
|
|
-*
|
|
-* Description: This function performs the HPM.1 firmware upgrade procedure as
|
|
-* defined the IPM Controller Firmware Upgrade Specification
|
|
-* version 1.0
|
|
-*
|
|
-*****************************************************************************/
|
|
-int HpmfwupgUpgrade(struct ipmi_intf *intf, char* imageFilename,
|
|
- int activate,int componentToUpload, int option)
|
|
-{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct HpmfwupgImageHeader imageHeader;
|
|
- struct HpmfwupgUpgradeCtx fwupgCtx;
|
|
-
|
|
- /*
|
|
- * GET IMAGE BUFFER FROM FILE
|
|
- */
|
|
-
|
|
- rc = HpmfwupgGetBufferFromFile(imageFilename, &fwupgCtx);
|
|
-
|
|
- /*
|
|
- * VALIDATE IMAGE INTEGRITY
|
|
- */
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- printf("Validating firmware image integrity...");
|
|
- fflush(stdout);
|
|
- rc = HpmfwupgValidateImageIntegrity(&fwupgCtx);
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- printf("OK\n");
|
|
- fflush(stdout);
|
|
- }
|
|
- else
|
|
- {
|
|
- free(fwupgCtx.pImageData);
|
|
- fwupgCtx.pImageData = NULL;
|
|
- }
|
|
- }
|
|
-
|
|
- /*
|
|
- * PREPARATION STAGE
|
|
- */
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- printf("Performing preparation stage...");
|
|
- fflush(stdout);
|
|
- rc = HpmfwupgPreparationStage(intf, &fwupgCtx, option);
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- printf("OK\n");
|
|
- fflush(stdout);
|
|
- }
|
|
- else
|
|
- {
|
|
- free(fwupgCtx.pImageData);
|
|
- fwupgCtx.pImageData = NULL;
|
|
- }
|
|
- }
|
|
-
|
|
- /*
|
|
- * UPGRADE STAGE
|
|
- */
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- if (option & VIEW_MODE)
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\nComparing Target & Image File version");
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\nPerforming upgrade stage:");
|
|
- }
|
|
- if (option & VIEW_MODE)
|
|
- {
|
|
- rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,componentToUpload,VIEW_MODE);
|
|
- }
|
|
- else
|
|
- {
|
|
- rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,componentToUpload,option);
|
|
- if (rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- if( verbose ) {
|
|
- printf("Component update mask : 0x%02x\n", fwupgCtx.compUpdateMask.ComponentBits.byte);
|
|
- }
|
|
- rc = HpmfwupgUpgradeStage(intf, &fwupgCtx,componentToUpload,option);
|
|
- }
|
|
- }
|
|
-
|
|
- if ( rc != HPMFWUPG_SUCCESS )
|
|
- {
|
|
- free(fwupgCtx.pImageData);
|
|
- fwupgCtx.pImageData = NULL;
|
|
- }
|
|
- }
|
|
-
|
|
- /*
|
|
- * ACTIVATION STAGE
|
|
- */
|
|
- if ( rc == HPMFWUPG_SUCCESS && activate )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Performing activation stage: ");
|
|
- rc = HpmfwupgActivationStage(intf, &fwupgCtx);
|
|
- if ( rc != HPMFWUPG_SUCCESS )
|
|
- {
|
|
- free(fwupgCtx.pImageData);
|
|
- fwupgCtx.pImageData = NULL;
|
|
- }
|
|
- }
|
|
+ }
|
|
+}
|
|
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- if (option & VIEW_MODE)
|
|
- {
|
|
- // Dont display anything here in case we are just viewing it
|
|
- lprintf(LOG_NOTICE," ");
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\nFirmware upgrade procedure successful\n");
|
|
- }
|
|
- free(fwupgCtx.pImageData);
|
|
- fwupgCtx.pImageData = NULL;
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Firmware upgrade procedure failed\n");
|
|
- }
|
|
+/* HpmfwupgTargerCheck - get target information and displays it on the screen
|
|
+ */
|
|
+int
|
|
+HpmfwupgTargetCheck(struct ipmi_intf *intf, int option)
|
|
+{
|
|
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ int componentId = 0;
|
|
+ int flagColdReset = FALSE;
|
|
+ struct ipm_devid_rsp devIdrsp;
|
|
+ struct HpmfwupgGetComponentPropertiesCtx getCompProp;
|
|
+ int mode = 0;
|
|
+ rc = HpmfwupgGetDeviceId(intf, &devIdrsp);
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Verify whether the Target board is present \n");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd);
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ /* That indicates the target is not responding to the command
|
|
+ * May be that there is no HPM support
|
|
+ */
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Board might not be supporting the HPM.1 Standards\n");
|
|
+ return rc;
|
|
+ }
|
|
+ if (option & VIEW_MODE) {
|
|
+ lprintf(LOG_NOTICE, "-------Target Information-------");
|
|
+ lprintf(LOG_NOTICE, "Device Id : 0x%x",
|
|
+ devIdrsp.device_id);
|
|
+ lprintf(LOG_NOTICE, "Device Revision : 0x%x",
|
|
+ devIdrsp.device_revision);
|
|
+ lprintf(LOG_NOTICE, "Product Id : 0x%04x",
|
|
+ buf2short(devIdrsp.product_id));
|
|
+ lprintf(LOG_NOTICE, "Manufacturer Id : 0x%04x (%s)\n\n",
|
|
+ buf2short(devIdrsp.manufacturer_id),
|
|
+ val2str(buf2short(devIdrsp.manufacturer_id),ipmi_oem_info));
|
|
+ HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER);
|
|
+ }
|
|
+ for (componentId = HPMFWUPG_COMPONENT_ID_0;
|
|
+ componentId < HPMFWUPG_COMPONENT_ID_MAX;
|
|
+ componentId++ ) {
|
|
+ /* If the component is supported */
|
|
+ if (((1 << componentId) & targetCapCmd.resp.componentsPresent.ComponentBits.byte)) {
|
|
+ memset((PVERSIONINFO)&gVersionInfo[componentId], 0x00, sizeof(VERSIONINFO));
|
|
+ getCompProp.req.componentId = componentId;
|
|
+ getCompProp.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES;
|
|
+ rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ lprintf(LOG_NOTICE, "Get CompGenProp Failed for component Id %d\n",
|
|
+ componentId);
|
|
+ return rc;
|
|
+ }
|
|
+ gVersionInfo[componentId].rollbackSupported = getCompProp.resp.Response.
|
|
+ generalPropResp.GeneralCompProperties.bitfield.rollbackBackup;
|
|
+ gVersionInfo[componentId].coldResetRequired = getCompProp.resp.Response.
|
|
+ generalPropResp.GeneralCompProperties.bitfield.payloadColdReset;
|
|
+ getCompProp.req.selector = HPMFWUPG_COMP_DESCRIPTION_STRING;
|
|
+ rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Get CompDescString Failed for component Id %d\n",
|
|
+ componentId);
|
|
+ return rc;
|
|
+ }
|
|
+ memcpy(gVersionInfo[componentId].descString,
|
|
+ getCompProp.resp.Response.descStringResp.descString,
|
|
+ HPMFWUPG_DESC_STRING_LENGTH);
|
|
+ gVersionInfo[componentId].descString[HPMFWUPG_DESC_STRING_LENGTH] = '\0';
|
|
+ getCompProp.req.selector = HPMFWUPG_COMP_CURRENT_VERSION;
|
|
+ rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Get CompCurrentVersion Failed for component Id %d\n",
|
|
+ componentId);
|
|
+ return rc;
|
|
+ }
|
|
+ gVersionInfo[componentId].componentId = componentId;
|
|
+ gVersionInfo[componentId].targetMajor = getCompProp.resp.Response.
|
|
+ currentVersionResp.currentVersion[0];
|
|
+ gVersionInfo[componentId].targetMinor = getCompProp.resp.Response.
|
|
+ currentVersionResp.currentVersion[1];
|
|
+ gVersionInfo[componentId].targetAux[0] = getCompProp.resp.Response.
|
|
+ currentVersionResp.currentVersion[2];
|
|
+ gVersionInfo[componentId].targetAux[1] = getCompProp.resp.Response.
|
|
+ currentVersionResp.currentVersion[3];
|
|
+ gVersionInfo[componentId].targetAux[2] = getCompProp.resp.Response.
|
|
+ currentVersionResp.currentVersion[4];
|
|
+ gVersionInfo[componentId].targetAux[3] = getCompProp.resp.Response.
|
|
+ currentVersionResp.currentVersion[5];
|
|
+ mode = TARGET_VER;
|
|
+ if (gVersionInfo[componentId].rollbackSupported) {
|
|
+ getCompProp.req.selector = HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION;
|
|
+ rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Get CompRollbackVersion Failed for component Id %d\n",
|
|
+ componentId);
|
|
+ } else {
|
|
+ gVersionInfo[componentId].rollbackMajor = getCompProp.resp
|
|
+ .Response.rollbackFwVersionResp.rollbackFwVersion[0];
|
|
+ gVersionInfo[componentId].rollbackMinor = getCompProp.resp
|
|
+ .Response.rollbackFwVersionResp.rollbackFwVersion[1];
|
|
+ gVersionInfo[componentId].rollbackAux[0] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[2];
|
|
+ gVersionInfo[componentId].rollbackAux[1] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[3];
|
|
+ gVersionInfo[componentId].rollbackAux[2] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[4];
|
|
+ gVersionInfo[componentId].rollbackAux[3] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[5];
|
|
+ }
|
|
+ getCompProp.req.selector = HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION;
|
|
+ rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Get CompRollbackVersion Failed for component Id %d\n",
|
|
+ componentId);
|
|
+ } else {
|
|
+ gVersionInfo[componentId].deferredMajor = getCompProp.resp
|
|
+ .Response.deferredFwVersionResp.deferredFwVersion[0];
|
|
+ gVersionInfo[componentId].deferredMinor = getCompProp.resp
|
|
+ .Response.deferredFwVersionResp.deferredFwVersion[1];
|
|
+ gVersionInfo[componentId].deferredAux[0] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[2];
|
|
+ gVersionInfo[componentId].deferredAux[1] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[3];
|
|
+ gVersionInfo[componentId].deferredAux[2] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[4];
|
|
+ gVersionInfo[componentId].deferredAux[3] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[5];
|
|
+ }
|
|
+ mode |= ROLLBACK_VER;
|
|
+ } else {
|
|
+ gVersionInfo[componentId].rollbackMajor = 0xff;
|
|
+ gVersionInfo[componentId].rollbackMinor = 0xff;
|
|
+ gVersionInfo[componentId].rollbackAux[0] = 0xff;
|
|
+ gVersionInfo[componentId].rollbackAux[1] = 0xff;
|
|
+ gVersionInfo[componentId].rollbackAux[2] = 0xff;
|
|
+ gVersionInfo[componentId].rollbackAux[3] = 0xff;
|
|
+ gVersionInfo[componentId].deferredMajor = 0xff;
|
|
+ gVersionInfo[componentId].deferredMinor = 0xff;
|
|
+ gVersionInfo[componentId].deferredAux[0] = 0xff;
|
|
+ gVersionInfo[componentId].deferredAux[1] = 0xff;
|
|
+ gVersionInfo[componentId].deferredAux[2] = 0xff;
|
|
+ gVersionInfo[componentId].deferredAux[3] = 0xff;
|
|
+ }
|
|
+ if (gVersionInfo[componentId].coldResetRequired) {
|
|
+ /*
|
|
+ * If any of the component indicates that the Payload Cold reset is required
|
|
+ * then set the flag
|
|
+ */
|
|
+ flagColdReset = TRUE;
|
|
+ }
|
|
+ if (option & VIEW_MODE) {
|
|
+ HpmDisplayVersion(mode,
|
|
+ &gVersionInfo[componentId],
|
|
+ 0);
|
|
+ printf("\n");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (option & VIEW_MODE) {
|
|
+ HpmDisplayLine("-",74 );
|
|
+ fflush(stdout);
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "(*) Component requires Payload Cold Reset");
|
|
+ printf("\n\n");
|
|
+ }
|
|
+ return HPMFWUPG_SUCCESS;
|
|
+}
|
|
|
|
- return rc;
|
|
+/* HpmfwupgUpgrade - perform the HPM.1 firmware upgrade procedure as defined
|
|
+ * the IPM Controller Firmware Upgrade Specification version 1.0
|
|
+ */
|
|
+int
|
|
+HpmfwupgUpgrade(struct ipmi_intf *intf, char *imageFilename, int activate,
|
|
+ int componentMask, int option)
|
|
+{
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct HpmfwupgUpgradeCtx fwupgCtx;
|
|
+ /* INITIALIZE UPGRADE CONTEXT */
|
|
+ memset(&fwupgCtx, 0, sizeof (fwupgCtx));
|
|
+ /* GET IMAGE BUFFER FROM FILE */
|
|
+ rc = HpmfwupgGetBufferFromFile(imageFilename, &fwupgCtx);
|
|
+ /* VALIDATE IMAGE INTEGRITY */
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ printf("Validating firmware image integrity...");
|
|
+ fflush(stdout);
|
|
+ rc = HpmfwupgValidateImageIntegrity(&fwupgCtx);
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ printf("OK\n");
|
|
+ fflush(stdout);
|
|
+ }
|
|
+ }
|
|
+ /* PREPARATION STAGE */
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ printf("Performing preparation stage...");
|
|
+ fflush(stdout);
|
|
+ rc = HpmfwupgPreparationStage(intf, &fwupgCtx, option);
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ printf("OK\n");
|
|
+ fflush(stdout);
|
|
+ }
|
|
+ }
|
|
+ /* UPGRADE STAGE */
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ if (option & VIEW_MODE) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\nComparing Target & Image File version");
|
|
+ } else if (option & COMPARE_MODE) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\nPerforming upload for compare stage:");
|
|
+ } else {
|
|
+ lprintf(LOG_NOTICE, "\nPerforming upgrade stage:");
|
|
+ }
|
|
+ if (option & VIEW_MODE) {
|
|
+ rc = HpmfwupgPreUpgradeCheck(intf,
|
|
+ &fwupgCtx,componentMask, VIEW_MODE);
|
|
+ } else {
|
|
+ rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,
|
|
+ componentMask, option);
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ if (verbose) {
|
|
+ printf("Component update mask : 0x%02x\n",
|
|
+ fwupgCtx.compUpdateMask.ComponentBits.byte);
|
|
+ }
|
|
+ rc = HpmfwupgUpgradeStage(intf, &fwupgCtx, option);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /* ACTIVATION STAGE */
|
|
+ if (rc == HPMFWUPG_SUCCESS && activate) {
|
|
+ /* check if upgrade components mask is non-zero */
|
|
+ if (fwupgCtx.compUpdateMask.ComponentBits.byte) {
|
|
+ lprintf(LOG_NOTICE, "Performing activation stage: ");
|
|
+ rc = HpmfwupgActivationStage(intf, &fwupgCtx);
|
|
+ } else {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "No components updated. Skipping activation stage.\n");
|
|
+ }
|
|
+ }
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ if (option & VIEW_MODE) {
|
|
+ /* Dont display anything here in case we are just viewing it */
|
|
+ lprintf(LOG_NOTICE," ");
|
|
+ } else if (option & COMPARE_MODE) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\nFirmware comparison procedure complete\n");
|
|
+ } else {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\nFirmware upgrade procedure successful\n");
|
|
+ }
|
|
+ } else if (option & VIEW_MODE) {
|
|
+ /* Dont display anything here in case we are just viewing it */
|
|
+ lprintf(LOG_NOTICE," ");
|
|
+ } else if (option & COMPARE_MODE) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Firmware comparison procedure failed\n");
|
|
+ } else {
|
|
+ lprintf(LOG_NOTICE, "Firmware upgrade procedure failed\n");
|
|
+ }
|
|
+ if (fwupgCtx.pImageData) {
|
|
+ free(fwupgCtx.pImageData);
|
|
+ fwupgCtx.pImageData = NULL;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmfwupgValidateImageIntegrity
|
|
-*
|
|
-* Description: This function validates a HPM.1 firmware image file as defined
|
|
-* in section 4 of the IPM Controller Firmware Upgrade
|
|
-* Specification version 1.0
|
|
-*
|
|
-*****************************************************************************/
|
|
-int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
+/* HpmfwupgValidateImageIntegrity - validate a HPM.1 firmware image file as
|
|
+ * defined in section 4 of the IPM Controller Firmware Upgrade Specification
|
|
+ * version 1.0
|
|
+ */
|
|
+int
|
|
+HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx *pFwupgCtx)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
|
|
- pFwupgCtx->pImageData;
|
|
- md5_state_t ctx;
|
|
+ struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*)pFwupgCtx->pImageData;
|
|
+ md5_state_t ctx;
|
|
static unsigned char md[HPMFWUPG_MD5_SIGNATURE_LENGTH];
|
|
- unsigned char* pMd5Sig = pFwupgCtx->pImageData +
|
|
- (pFwupgCtx->imageSize -
|
|
- HPMFWUPG_MD5_SIGNATURE_LENGTH);
|
|
-
|
|
- /* Validate MD5 checksum */
|
|
- memset(md, 0, HPMFWUPG_MD5_SIGNATURE_LENGTH);
|
|
- memset(&ctx, 0, sizeof(md5_state_t));
|
|
- md5_init(&ctx);
|
|
- md5_append(&ctx, pFwupgCtx->pImageData, pFwupgCtx->imageSize -
|
|
- HPMFWUPG_MD5_SIGNATURE_LENGTH);
|
|
- md5_finish(&ctx, md);
|
|
- if ( memcmp(md, pMd5Sig,HPMFWUPG_MD5_SIGNATURE_LENGTH) != 0 )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\n Invalid MD5 signature");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- /* Validate Header signature */
|
|
- if( strncmp(pImageHeader->signature, HPMFWUPG_IMAGE_SIGNATURE, HPMFWUPG_HEADER_SIGNATURE_LENGTH) == 0 )
|
|
- {
|
|
- /* Validate Header image format version */
|
|
- if ( pImageHeader->formatVersion == HPMFWUPG_IMAGE_HEADER_VERSION )
|
|
- {
|
|
- /* Validate header checksum */
|
|
- if ( HpmfwupgCalculateChecksum((unsigned char*)pImageHeader,
|
|
- sizeof(struct HpmfwupgImageHeader) +
|
|
- pImageHeader->oemDataLength +
|
|
- sizeof(unsigned char)/*checksum*/) != 0 )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\n Invalid header checksum");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\n Unrecognized image version");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\n Invalid image signature");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- return rc;
|
|
+ unsigned char *pMd5Sig = pFwupgCtx->pImageData
|
|
+ + (pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH);
|
|
+ /* Validate MD5 checksum */
|
|
+ memset(md, 0, HPMFWUPG_MD5_SIGNATURE_LENGTH);
|
|
+ memset(&ctx, 0, sizeof(md5_state_t));
|
|
+ md5_init(&ctx);
|
|
+ md5_append(&ctx, pFwupgCtx->pImageData,
|
|
+ pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH);
|
|
+ md5_finish(&ctx, md);
|
|
+ if (memcmp(md, pMd5Sig, HPMFWUPG_MD5_SIGNATURE_LENGTH) != 0) {
|
|
+ lprintf(LOG_NOTICE, "\n Invalid MD5 signature");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Validate Header signature */
|
|
+ if(strncmp(pImageHeader->signature,
|
|
+ HPMFWUPG_IMAGE_SIGNATURE,
|
|
+ HPMFWUPG_HEADER_SIGNATURE_LENGTH) != 0) {
|
|
+ lprintf(LOG_NOTICE,"\n Invalid image signature");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Validate Header image format version */
|
|
+ if (pImageHeader->formatVersion != HPMFWUPG_IMAGE_HEADER_VERSION) {
|
|
+ lprintf(LOG_NOTICE,"\n Unrecognized image version");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Validate header checksum */
|
|
+ if (HpmfwupgCalculateChecksum((unsigned char*)pImageHeader,
|
|
+ sizeof(struct HpmfwupgImageHeader)
|
|
+ + pImageHeader->oemDataLength
|
|
+ + sizeof(unsigned char)/*checksum*/) != 0) {
|
|
+ lprintf(LOG_NOTICE,"\n Invalid header checksum");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ return HPMFWUPG_SUCCESS;
|
|
}
|
|
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmfwupgPreparationStage
|
|
-*
|
|
-* Description: This function the preperation stage of a firmware upgrade
|
|
-* procedure as defined in section 3.2 of the IPM Controller
|
|
-* Firmware Upgrade Specification version 1.0
|
|
-*
|
|
-*****************************************************************************/
|
|
-int HpmfwupgPreparationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx, int option)
|
|
-{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
|
|
- pFwupgCtx->pImageData;
|
|
-
|
|
- /* Get device ID */
|
|
- rc = HpmfwupgGetDeviceId(intf, &pFwupgCtx->devId);
|
|
-
|
|
- /* Match current IPMC IDs with upgrade image */
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- /* Validate device ID */
|
|
- if ( pImageHeader->deviceId == pFwupgCtx->devId.device_id )
|
|
- {
|
|
- /* Validate product ID */
|
|
- if ( memcmp(pImageHeader->prodId, pFwupgCtx->devId.product_id, HPMFWUPG_PRODUCT_ID_LENGTH ) == 0 )
|
|
- {
|
|
- /* Validate man ID */
|
|
- if ( memcmp(pImageHeader->manId, pFwupgCtx->devId.manufacturer_id,
|
|
- HPMFWUPG_MANUFATURER_ID_LENGTH ) != 0 )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\n Invalid image file for manufacturer %u",
|
|
- buf2short(pFwupgCtx->devId.manufacturer_id));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\n Invalid image file for product %u",
|
|
- buf2short(pFwupgCtx->devId.product_id));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\n Invalid device ID %x", pFwupgCtx->devId.device_id);
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- if (rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- /*
|
|
- * Giving one more chance to user to check whether its OK to continue even if the
|
|
- * product ID does not match. This is helpful as sometimes we just want to update
|
|
- * and dont care whether we have a different product Id. If the user says NO then
|
|
- * we need to just bail out from here
|
|
- */
|
|
- if ( (option & FORCE_MODE) || (option & VIEW_MODE) )
|
|
- {
|
|
- printf("\n Image Information");
|
|
- printf("\n Device Id : 0x%x",pImageHeader->deviceId);
|
|
- printf("\n Prod Id : 0x%02x%02x",pImageHeader->prodId[1], pImageHeader->prodId[0]);
|
|
- printf("\n Manuf Id : 0x%02x%02x%02x",pImageHeader->manId[2],
|
|
- pImageHeader->manId[1],pImageHeader->manId[0]);
|
|
- printf("\n Board Information");
|
|
- printf("\n Device Id : 0x%x", pFwupgCtx->devId.device_id);
|
|
- printf("\n Prod Id : 0x%02x%02x",pFwupgCtx->devId.product_id[1], pFwupgCtx->devId.product_id[0]);
|
|
- printf("\n Manuf Id : 0x%02x%02x%02x",pFwupgCtx->devId.manufacturer_id[2],
|
|
- pFwupgCtx->devId.manufacturer_id[1],pFwupgCtx->devId.manufacturer_id[0]);
|
|
- if (HpmGetUserInput("\n Continue ignoring DeviceID/ProductID/ManufacturingID (Y/N) :"))
|
|
- rc = HPMFWUPG_SUCCESS;
|
|
- }
|
|
- else
|
|
- {
|
|
- printf("\n\n Use \"force\" option for copying all the components\n");
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* Validate earliest compatible revision */
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- /* Validate major & minor revision */
|
|
- if ( pImageHeader->compRevision[0] < pFwupgCtx->devId.fw_rev1 )
|
|
- {
|
|
- /* Do nothing, upgrade accepted */
|
|
- }
|
|
- else if ( pImageHeader->compRevision[0] == pFwupgCtx->devId.fw_rev1 )
|
|
- {
|
|
- /* Must validate minor revision */
|
|
- if ( pImageHeader->compRevision[1] > pFwupgCtx->devId.fw_rev2 )
|
|
- {
|
|
- /* Version not compatible for upgrade */
|
|
- lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]);
|
|
- lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]);
|
|
- lprintf(LOG_NOTICE," Not compatible with ");
|
|
- lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1);
|
|
- lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2);
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- /* Version not compatible for upgrade */
|
|
- lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]);
|
|
- lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]);
|
|
- lprintf(LOG_NOTICE," Not compatible with ");
|
|
- lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1);
|
|
- lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2);
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- if (rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- /* Confirming it once again */
|
|
- if ( (option & FORCE_MODE) || (option & VIEW_MODE) )
|
|
- {
|
|
- if( HpmGetUserInput("\n Continue IGNORING Earliest compatibility (Y/N) :"))
|
|
- rc = HPMFWUPG_SUCCESS;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* Get target upgrade capabilities */
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
-
|
|
- rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd);
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- /* Copy response to context */
|
|
- memcpy(&pFwupgCtx->targetCap,
|
|
- &targetCapCmd.resp,
|
|
- sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp));
|
|
-
|
|
- if (option & VIEW_MODE)
|
|
- {
|
|
- return rc;
|
|
- }
|
|
- else
|
|
- {
|
|
- /* Make sure all component IDs defined in the upgrade
|
|
- image are supported by the IPMC */
|
|
- if ( (pImageHeader->components.ComponentBits.byte &
|
|
- pFwupgCtx->targetCap.componentsPresent.ComponentBits.byte ) !=
|
|
- pImageHeader->components.ComponentBits.byte )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\n Some components present in the image file are not supported by the IPMC");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- /* Make sure the upgrade is desirable rigth now */
|
|
- if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.fwUpgUndesirable == 1 )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"\n Upgrade undesirable at this moment");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- /* Get confimation from the user if he wants to continue when service
|
|
- affected during upgrade */
|
|
- if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.servAffectDuringUpg == 1 ||
|
|
- pImageHeader->imageCapabilities.bitField.servAffected == 1 )
|
|
- {
|
|
- if (HpmGetUserInput("\nServices may be affected during upgrade. Do you wish to continue? y/n "))
|
|
- {
|
|
- rc = HPMFWUPG_SUCCESS;
|
|
- }
|
|
- else
|
|
- {
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* Get the general properties of each component present in image */
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- int componentId;
|
|
-
|
|
- for ( componentId = HPMFWUPG_COMPONENT_ID_0;
|
|
- componentId < HPMFWUPG_COMPONENT_ID_MAX;
|
|
- componentId++ )
|
|
- {
|
|
- /* Reset component properties */
|
|
- memset(&pFwupgCtx->genCompProp[componentId], 0, sizeof (struct HpmfwupgGetGeneralPropResp));
|
|
-
|
|
- if ( (1 << componentId & pImageHeader->components.ComponentBits.byte) )
|
|
- {
|
|
- struct HpmfwupgGetComponentPropertiesCtx getCompPropCmd;
|
|
-
|
|
- /* Get general component properties */
|
|
- getCompPropCmd.req.componentId = componentId;
|
|
- getCompPropCmd.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES;
|
|
-
|
|
- rc = HpmfwupgGetComponentProperties(intf, &getCompPropCmd);
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- /* Copy response to context */
|
|
- memcpy(&pFwupgCtx->genCompProp[componentId],
|
|
- &getCompPropCmd.resp,
|
|
- sizeof(struct HpmfwupgGetGeneralPropResp));
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- return rc;
|
|
+/* HpmfwupgPreparationStage - prepere stage of a firmware upgrade procedure as
|
|
+ * defined in section 3.2 of the IPM Controller Firmware Upgrade Specification
|
|
+ * version 1.0
|
|
+ */
|
|
+int
|
|
+HpmfwupgPreparationStage(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx, int option)
|
|
+{
|
|
+ int componentId;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
+ struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*)
|
|
+ pFwupgCtx->pImageData;
|
|
+ /* Get device ID */
|
|
+ rc = HpmfwupgGetDeviceId(intf, &pFwupgCtx->devId);
|
|
+ /* Match current IPMC IDs with upgrade image */
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Validate device ID */
|
|
+ if (pImageHeader->deviceId == pFwupgCtx->devId.device_id) {
|
|
+ /* Validate product ID */
|
|
+ if (memcmp(pImageHeader->prodId,
|
|
+ pFwupgCtx->devId.product_id,
|
|
+ HPMFWUPG_PRODUCT_ID_LENGTH ) == 0) {
|
|
+ /* Validate man ID */
|
|
+ if (memcmp(pImageHeader->manId,
|
|
+ pFwupgCtx->devId.manufacturer_id,
|
|
+ HPMFWUPG_MANUFATURER_ID_LENGTH) != 0) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\n Invalid image file for manufacturer %u",
|
|
+ buf2short(pFwupgCtx->devId.manufacturer_id));
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ } else {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\n Invalid image file for product %u",
|
|
+ buf2short(pFwupgCtx->devId.product_id));
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ } else {
|
|
+ lprintf(LOG_NOTICE, "\n Invalid device ID %x",
|
|
+ pFwupgCtx->devId.device_id);
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ /* Giving one more chance to user to check whether its OK to continue even if the
|
|
+ * product ID does not match. This is helpful as sometimes we just want to update
|
|
+ * and dont care whether we have a different product Id. If the user says NO then
|
|
+ * we need to just bail out from here
|
|
+ */
|
|
+ if (!((option & FORCE_MODE) || (option & VIEW_MODE))) {
|
|
+ printf("\n\n Use \"force\" option for copying all the components\n");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ printf("\n Image Information");
|
|
+ printf("\n Device Id : 0x%x", pImageHeader->deviceId);
|
|
+ printf("\n Prod Id : 0x%02x%02x",
|
|
+ pImageHeader->prodId[1], pImageHeader->prodId[0]);
|
|
+ printf("\n Manuf Id : 0x%02x%02x%02x",
|
|
+ pImageHeader->manId[2],
|
|
+ pImageHeader->manId[1],
|
|
+ pImageHeader->manId[0]);
|
|
+ printf("\n Board Information");
|
|
+ printf("\n Device Id : 0x%x", pFwupgCtx->devId.device_id);
|
|
+ printf("\n Prod Id : 0x%02x%02x",
|
|
+ pFwupgCtx->devId.product_id[1], pFwupgCtx->devId.product_id[0]);
|
|
+ printf("\n Manuf Id : 0x%02x%02x%02x",
|
|
+ pFwupgCtx->devId.manufacturer_id[2],
|
|
+ pFwupgCtx->devId.manufacturer_id[1],
|
|
+ pFwupgCtx->devId.manufacturer_id[0]);
|
|
+ if (HpmGetUserInput("\n Continue ignoring DeviceID/ProductID/ManufacturingID (Y/N): ")) {
|
|
+ rc = HPMFWUPG_SUCCESS;
|
|
+ } else {
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ }
|
|
+ /* Validate earliest compatible revision */
|
|
+ /* Validate major & minor revision */
|
|
+ if (pImageHeader->compRevision[0] > pFwupgCtx->devId.fw_rev1
|
|
+ || (pImageHeader->compRevision[0] == pFwupgCtx->devId.fw_rev1
|
|
+ && pImageHeader->compRevision[1] > pFwupgCtx->devId.fw_rev2)) {
|
|
+ /* Version not compatible for upgrade */
|
|
+ lprintf(LOG_NOTICE, "\n Version: Major: %d", pImageHeader->compRevision[0]);
|
|
+ lprintf(LOG_NOTICE, " Minor: %x", pImageHeader->compRevision[1]);
|
|
+ lprintf(LOG_NOTICE, " Not compatible with ");
|
|
+ lprintf(LOG_NOTICE, " Version: Major: %d", pFwupgCtx->devId.fw_rev1);
|
|
+ lprintf(LOG_NOTICE, " Minor: %x", pFwupgCtx->devId.fw_rev2);
|
|
+ /* Confirming it once again */
|
|
+ if (!((option & FORCE_MODE) || (option & VIEW_MODE))) {
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if (HpmGetUserInput("\n Continue IGNORING Earliest compatibility (Y/N): ")) {
|
|
+ rc = HPMFWUPG_SUCCESS;
|
|
+ } else {
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ }
|
|
+ /* Get target upgrade capabilities */
|
|
+ rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd);
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Copy response to context */
|
|
+ memcpy(&pFwupgCtx->targetCap,
|
|
+ &targetCapCmd.resp,
|
|
+ sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp));
|
|
+ if (option & VIEW_MODE) {
|
|
+ /* do nothing */
|
|
+ } else {
|
|
+ /* Make sure all component IDs defined in the
|
|
+ * upgrade image are supported by the IPMC
|
|
+ */
|
|
+ if ((pImageHeader->components.ComponentBits.byte &
|
|
+ pFwupgCtx->targetCap.componentsPresent.ComponentBits.byte) !=
|
|
+ pImageHeader->components.ComponentBits.byte) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\n Some components present in the image file are not supported by the IPMC");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Make sure the upgrade is desirable rigth now */
|
|
+ if (pFwupgCtx->targetCap.GlobalCapabilities.bitField.fwUpgUndesirable == 1) {
|
|
+ lprintf(LOG_NOTICE, "\n Upgrade undesirable at this moment");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Get confimation from the user if he wants to continue when
|
|
+ * service affected during upgrade
|
|
+ */
|
|
+ if (!(option & COMPARE_MODE)
|
|
+ && (pFwupgCtx->targetCap.GlobalCapabilities.bitField.servAffectDuringUpg == 1
|
|
+ || pImageHeader->imageCapabilities.bitField.servAffected == 1)) {
|
|
+ if (HpmGetUserInput("\nServices may be affected during upgrade. Do you wish to continue? (y/n): ")) {
|
|
+ rc = HPMFWUPG_SUCCESS;
|
|
+ } else {
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /* Get the general properties of each component present in image */
|
|
+ for (componentId = HPMFWUPG_COMPONENT_ID_0;
|
|
+ componentId < HPMFWUPG_COMPONENT_ID_MAX;
|
|
+ componentId++) {
|
|
+ /* Reset component properties */
|
|
+ memset(&pFwupgCtx->genCompProp[componentId], 0,
|
|
+ sizeof (struct HpmfwupgGetGeneralPropResp));
|
|
+ if ((1 << componentId & pImageHeader->components.ComponentBits.byte)) {
|
|
+ struct HpmfwupgGetComponentPropertiesCtx getCompPropCmd;
|
|
+ /* Get general component properties */
|
|
+ getCompPropCmd.req.componentId = componentId;
|
|
+ getCompPropCmd.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES;
|
|
+ rc = HpmfwupgGetComponentProperties(intf, &getCompPropCmd);
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ /* Copy response to context */
|
|
+ memcpy(&pFwupgCtx->genCompProp[componentId],
|
|
+ &getCompPropCmd.resp,
|
|
+ sizeof(struct HpmfwupgGetGeneralPropResp));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-static int image_version_upgradable(VERSIONINFO *pVersionInfo)
|
|
+int
|
|
+image_version_upgradable(VERSIONINFO *pVersionInfo)
|
|
{
|
|
/* If the image and active target versions are different, then
|
|
* upgrade */
|
|
- if ((pVersionInfo->imageMajor != pVersionInfo->targetMajor) ||
|
|
- (pVersionInfo->imageMinor != pVersionInfo->targetMinor) ||
|
|
- (pVersionInfo->imageAux[0] != pVersionInfo->targetAux[0]) ||
|
|
- (pVersionInfo->imageAux[1] != pVersionInfo->targetAux[1]) ||
|
|
- (pVersionInfo->imageAux[2] != pVersionInfo->targetAux[2]) ||
|
|
- (pVersionInfo->imageAux[3] != pVersionInfo->targetAux[3]))
|
|
+ if ((pVersionInfo->imageMajor != pVersionInfo->targetMajor)
|
|
+ || (pVersionInfo->imageMinor != pVersionInfo->targetMinor)
|
|
+ || (pVersionInfo->imageAux[0] != pVersionInfo->targetAux[0])
|
|
+ || (pVersionInfo->imageAux[1] != pVersionInfo->targetAux[1])
|
|
+ || (pVersionInfo->imageAux[2] != pVersionInfo->targetAux[2])
|
|
+ || (pVersionInfo->imageAux[3] != pVersionInfo->targetAux[3])) {
|
|
return (1);
|
|
-
|
|
+ }
|
|
/* If the image and active target versions are the same and rollback
|
|
- * is not supported, then there's nothing to do, skip the upgrade */
|
|
- if (!pVersionInfo->rollbackSupported)
|
|
+ * is not supported, then there's nothing to do, skip the upgrade
|
|
+ */
|
|
+ if (!pVersionInfo->rollbackSupported) {
|
|
return (0);
|
|
-
|
|
+ }
|
|
/* If the image and rollback target versions are different, then
|
|
- * go ahead and upgrade */
|
|
- if ((pVersionInfo->imageMajor != pVersionInfo->rollbackMajor) ||
|
|
- (pVersionInfo->imageMinor != pVersionInfo->rollbackMinor) ||
|
|
- (pVersionInfo->imageAux[0] != pVersionInfo->rollbackAux[0]) ||
|
|
- (pVersionInfo->imageAux[1] != pVersionInfo->rollbackAux[1]) ||
|
|
- (pVersionInfo->imageAux[2] != pVersionInfo->rollbackAux[2]) ||
|
|
- (pVersionInfo->imageAux[3] != pVersionInfo->rollbackAux[3]))
|
|
+ * go ahead and upgrade
|
|
+ */
|
|
+ if ((pVersionInfo->imageMajor != pVersionInfo->rollbackMajor)
|
|
+ || (pVersionInfo->imageMinor != pVersionInfo->rollbackMinor)
|
|
+ || (pVersionInfo->imageAux[0] != pVersionInfo->rollbackAux[0])
|
|
+ || (pVersionInfo->imageAux[1] != pVersionInfo->rollbackAux[1])
|
|
+ || (pVersionInfo->imageAux[2] != pVersionInfo->rollbackAux[2])
|
|
+ || (pVersionInfo->imageAux[3] != pVersionInfo->rollbackAux[3])) {
|
|
return (1);
|
|
-
|
|
+ }
|
|
/* Image and rollback target versions are the same too, skip it */
|
|
return (0);
|
|
}
|
|
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmfwupgPreUpgradeCheck
|
|
-*
|
|
-* Description: This function the pre Upgrade check, this mainly helps in checking
|
|
-* which all version upgrade is skippable because the image version
|
|
-* is same as target version.
|
|
-*
|
|
-*****************************************************************************/
|
|
-int HpmfwupgPreUpgradeCheck(struct ipmi_intf *intf,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx,
|
|
- int componentToUpload, int option)
|
|
+/* HpmfwupgValidateActionRecordChecksum - validate checksum of the specified
|
|
+ * action record header.
|
|
+ */
|
|
+int
|
|
+HpmfwupgValidateActionRecordChecksum(struct HpmfwupgActionRecord *pActionRecord)
|
|
{
|
|
- unsigned char* pImagePtr;
|
|
- struct HpmfwupgActionRecord *pActionRecord;
|
|
- int flagColdReset = FALSE;
|
|
- struct HpmfwupgImageHeader *pImageHeader;
|
|
-
|
|
- pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData;
|
|
-
|
|
- /* Put pointer after image header */
|
|
- pImagePtr = (unsigned char*)
|
|
- (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) +
|
|
- pImageHeader->oemDataLength + sizeof(unsigned char)/*chksum*/);
|
|
-
|
|
- if (option & VIEW_MODE) {
|
|
- HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER|IMAGE_VER);
|
|
- }
|
|
-
|
|
- /* Perform actions defined in the image */
|
|
- while (pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize -
|
|
- HPMFWUPG_MD5_SIGNATURE_LENGTH)) {
|
|
- /* Get action record */
|
|
- pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr;
|
|
-
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
/* Validate action record checksum */
|
|
if (HpmfwupgCalculateChecksum((unsigned char*)pActionRecord,
|
|
- sizeof(struct HpmfwupgActionRecord)) != 0) {
|
|
- lprintf(LOG_NOTICE," Invalid Action record.");
|
|
- return HPMFWUPG_ERROR;
|
|
+ sizeof(struct HpmfwupgActionRecord)) != 0) {
|
|
+ /* Due to ambiguity in the HPM.1 specification, for the case of
|
|
+ * the Upload Firmware Image action type, the record header length
|
|
+ * might be thought as either the first 3 bytes, or the first 34 bytes
|
|
+ * which precede the firmware image data.
|
|
+ * For the latter case we re-calculate the Upload Firmware Image
|
|
+ * record checksum for the 34 byte header length.
|
|
+ */
|
|
+ if (pActionRecord->actionType != HPMFWUPG_ACTION_UPLOAD_FIRMWARE
|
|
+ || HpmfwupgCalculateChecksum((unsigned char*)pActionRecord,
|
|
+ sizeof(struct HpmfwupgActionRecord)
|
|
+ + sizeof(struct HpmfwupgFirmwareImage))) {
|
|
+ lprintf(LOG_NOTICE, " Invalid Action record.");
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
}
|
|
+ return rc;
|
|
+}
|
|
|
|
- switch( pActionRecord->actionType )
|
|
- {
|
|
- case HPMFWUPG_ACTION_BACKUP_COMPONENTS:
|
|
- {
|
|
- pImagePtr += sizeof(struct HpmfwupgActionRecord);
|
|
+/* HpmfwupgPreUpgradeCheck - make pre-Upgrade check, this mainly helps in
|
|
+ * checking which all version upgrade is skippable because the image version
|
|
+ * is same as target version.
|
|
+ */
|
|
+int
|
|
+HpmfwupgPreUpgradeCheck(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx,
|
|
+ int componentMask, int option)
|
|
+{
|
|
+ unsigned char *pImagePtr;
|
|
+ struct HpmfwupgActionRecord *pActionRecord;
|
|
+ struct HpmfwupgImageHeader *pImageHeader;
|
|
+ int componentId;
|
|
+ pImageHeader = (struct HpmfwupgImageHeader*)pFwupgCtx->pImageData;
|
|
+ /* Put pointer after image header */
|
|
+ pImagePtr = (unsigned char*)(pFwupgCtx->pImageData
|
|
+ + sizeof(struct HpmfwupgImageHeader)
|
|
+ + pImageHeader->oemDataLength
|
|
+ + sizeof(unsigned char)/*chksum*/);
|
|
+ if (option & VIEW_MODE) {
|
|
+ HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER|IMAGE_VER);
|
|
}
|
|
- break;
|
|
-
|
|
- case HPMFWUPG_ACTION_PREPARE_COMPONENTS:
|
|
- {
|
|
- if (componentToUpload != DEFAULT_COMPONENT_UPLOAD) {
|
|
- if (!((1 << componentToUpload) &
|
|
- pActionRecord->components.ComponentBits.byte)) {
|
|
- lprintf(LOG_NOTICE,
|
|
- "\nComponent Id given is not supported\n");
|
|
- return HPMFWUPG_ERROR;
|
|
- }
|
|
+ /* Perform actions defined in the image */
|
|
+ while (pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize
|
|
+ - HPMFWUPG_MD5_SIGNATURE_LENGTH)) {
|
|
+ /* Get action record */
|
|
+ pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr;
|
|
+ /* Validate action record checksum */
|
|
+ if (HpmfwupgValidateActionRecordChecksum(pActionRecord) != HPMFWUPG_SUCCESS) {
|
|
+ return HPMFWUPG_ERROR;
|
|
}
|
|
- pImagePtr += sizeof(struct HpmfwupgActionRecord);
|
|
- }
|
|
- break;
|
|
-
|
|
- case HPMFWUPG_ACTION_UPLOAD_FIRMWARE:
|
|
- /* Upload all firmware blocks */
|
|
- {
|
|
- struct HpmfwupgFirmwareImage *pFwImage;
|
|
- unsigned char *pData;
|
|
- unsigned int firmwareLength;
|
|
- unsigned char mode;
|
|
- unsigned char componentId;
|
|
- unsigned char componentIdByte;
|
|
- unsigned int upgrade_comp;
|
|
- VERSIONINFO *pVersionInfo;
|
|
- struct HpmfwupgGetComponentPropertiesCtx getCompProp;
|
|
-
|
|
- /* Save component ID on which the upload is done */
|
|
- componentIdByte = pActionRecord->components.ComponentBits.byte;
|
|
-
|
|
- componentId = 0;
|
|
- while ((componentIdByte >>= 1) !=0) {
|
|
- componentId++;
|
|
+ /* Validate affected components */
|
|
+ if (pActionRecord->components.ComponentBits.byte
|
|
+ && !pFwupgCtx->targetCap.componentsPresent.ComponentBits.byte) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ " Invalid action record. One or more affected components is not supported");
|
|
+ return HPMFWUPG_ERROR;
|
|
}
|
|
- pFwupgCtx->componentId = componentId;
|
|
-
|
|
- pFwImage = (struct HpmfwupgFirmwareImage*)(pImagePtr +
|
|
- sizeof(struct HpmfwupgActionRecord));
|
|
-
|
|
- pData = ((unsigned char*)pFwImage +
|
|
- sizeof(struct HpmfwupgFirmwareImage));
|
|
-
|
|
- /* Get firmware length */
|
|
- firmwareLength = pFwImage->length[0];
|
|
- firmwareLength |= (pFwImage->length[1] << 8) & 0xff00;
|
|
- firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000;
|
|
- firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000;
|
|
-
|
|
- pVersionInfo = &gVersionInfo[componentId];
|
|
-
|
|
- pVersionInfo->imageMajor = pFwImage->version[0];
|
|
- pVersionInfo->imageMinor = pFwImage->version[1];
|
|
- pVersionInfo->imageAux[0] = pFwImage->version[2];
|
|
- pVersionInfo->imageAux[1] = pFwImage->version[3];
|
|
- pVersionInfo->imageAux[2] = pFwImage->version[4];
|
|
- pVersionInfo->imageAux[3] = pFwImage->version[5];
|
|
-
|
|
- mode = TARGET_VER | IMAGE_VER;
|
|
-
|
|
- if (pVersionInfo->coldResetRequired)
|
|
- flagColdReset = TRUE;
|
|
-
|
|
- upgrade_comp = 0;
|
|
- if (option & FORCE_MODE_ALL) {
|
|
- upgrade_comp = 1;
|
|
- }
|
|
- else if ((option & FORCE_MODE_COMPONENT) &&
|
|
- (componentToUpload == componentId)) {
|
|
- upgrade_comp = 1;
|
|
- }
|
|
- else if (image_version_upgradable(pVersionInfo)) {
|
|
- upgrade_comp = 1;
|
|
- }
|
|
-
|
|
- if (verbose)
|
|
- lprintf(LOG_NOTICE,"%s component %d",
|
|
- (upgrade_comp ? "Updating" : "Skipping"),
|
|
- componentId);
|
|
-
|
|
- if (upgrade_comp)
|
|
- pFwupgCtx->compUpdateMask.ComponentBits.byte |=
|
|
- 1 << componentId;
|
|
-
|
|
- if (option & VIEW_MODE) {
|
|
- if (pVersionInfo->rollbackSupported)
|
|
- mode |= ROLLBACK_VER;
|
|
- HpmDisplayVersion(mode,pVersionInfo, upgrade_comp);
|
|
- printf("\n");
|
|
+ switch (pActionRecord->actionType) {
|
|
+ case HPMFWUPG_ACTION_BACKUP_COMPONENTS:
|
|
+ {
|
|
+ /* Make sure every component specified by
|
|
+ * this action record
|
|
+ * supports the backup operation
|
|
+ */
|
|
+ for (componentId = HPMFWUPG_COMPONENT_ID_0;
|
|
+ componentId < HPMFWUPG_COMPONENT_ID_MAX;
|
|
+ componentId++) {
|
|
+ if (((1 << componentId) & pActionRecord->components.ComponentBits.byte)
|
|
+ && pFwupgCtx->genCompProp[componentId].GeneralCompProperties.bitfield.rollbackBackup == 0) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ " Component ID %d does not support backup",
|
|
+ componentId);
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ }
|
|
+ pImagePtr += sizeof(struct HpmfwupgActionRecord);
|
|
+ }
|
|
+ break;
|
|
+ case HPMFWUPG_ACTION_PREPARE_COMPONENTS:
|
|
+ {
|
|
+ /* Make sure every components specified by
|
|
+ * this action
|
|
+ * supports the prepare operation
|
|
+ */
|
|
+ for (componentId = HPMFWUPG_COMPONENT_ID_0;
|
|
+ componentId < HPMFWUPG_COMPONENT_ID_MAX;
|
|
+ componentId++) {
|
|
+ if (((1 << componentId) & pActionRecord->components.ComponentBits.byte)
|
|
+ && pFwupgCtx->genCompProp[componentId].GeneralCompProperties.bitfield.preparationSupport == 0) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ " Component ID %d does not support preparation",
|
|
+ componentId);
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ }
|
|
+ pImagePtr += sizeof(struct HpmfwupgActionRecord);
|
|
+ }
|
|
+ break;
|
|
+ case HPMFWUPG_ACTION_UPLOAD_FIRMWARE:
|
|
+ /* Upload all firmware blocks */
|
|
+ {
|
|
+ struct HpmfwupgFirmwareImage *pFwImage;
|
|
+ unsigned char *pData;
|
|
+ unsigned int firmwareLength;
|
|
+ unsigned char mode;
|
|
+ unsigned char componentId;
|
|
+ unsigned char componentIdByte;
|
|
+ unsigned int upgrade_comp;
|
|
+ VERSIONINFO *pVersionInfo;
|
|
+ /* Save component ID on which the upload is done */
|
|
+ componentIdByte = pActionRecord->components.ComponentBits.byte;
|
|
+ componentId = 0;
|
|
+ while ((componentIdByte >>= 1) != 0) {
|
|
+ componentId++;
|
|
+ }
|
|
+ pFwImage = (struct HpmfwupgFirmwareImage*)(pImagePtr
|
|
+ + sizeof(struct HpmfwupgActionRecord));
|
|
+ pData = ((unsigned char*)pFwImage
|
|
+ + sizeof(struct HpmfwupgFirmwareImage));
|
|
+ /* Get firmware length */
|
|
+ firmwareLength = pFwImage->length[0];
|
|
+ firmwareLength |= (pFwImage->length[1] << 8) & 0xff00;
|
|
+ firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000;
|
|
+ firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000;
|
|
+
|
|
+ pVersionInfo = &gVersionInfo[componentId];
|
|
+
|
|
+ pVersionInfo->imageMajor = pFwImage->version[0];
|
|
+ pVersionInfo->imageMinor = pFwImage->version[1];
|
|
+ pVersionInfo->imageAux[0] = pFwImage->version[2];
|
|
+ pVersionInfo->imageAux[1] = pFwImage->version[3];
|
|
+ pVersionInfo->imageAux[2] = pFwImage->version[4];
|
|
+ pVersionInfo->imageAux[3] = pFwImage->version[5];
|
|
+
|
|
+ mode = TARGET_VER | IMAGE_VER;
|
|
+ /* check if component is selected for upgrade */
|
|
+ upgrade_comp = !componentMask
|
|
+ || (componentMask & pActionRecord->components.ComponentBits.byte);
|
|
+ /* check if current component version requires upgrade */
|
|
+ if (upgrade_comp && !(option & (FORCE_MODE|COMPARE_MODE))) {
|
|
+ upgrade_comp = image_version_upgradable(pVersionInfo);
|
|
+ }
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "%s component %d",
|
|
+ (upgrade_comp ? "Updating" : "Skipping"),
|
|
+ componentId);
|
|
+ }
|
|
+ if (upgrade_comp) {
|
|
+ pFwupgCtx->compUpdateMask.ComponentBits.byte|= 1 << componentId;
|
|
+ }
|
|
+ if (option & VIEW_MODE) {
|
|
+ if (pVersionInfo->rollbackSupported) {
|
|
+ mode|= ROLLBACK_VER;
|
|
+ }
|
|
+ HpmDisplayVersion(mode,pVersionInfo, upgrade_comp);
|
|
+ printf("\n");
|
|
+ }
|
|
+ pImagePtr = pData + firmwareLength;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ lprintf(LOG_NOTICE,
|
|
+ " Invalid Action type. Cannot continue");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ break;
|
|
}
|
|
- pImagePtr = pData + firmwareLength;
|
|
}
|
|
- break;
|
|
- default:
|
|
+ if (option & VIEW_MODE) {
|
|
+ HpmDisplayLine("-",74);
|
|
+ fflush(stdout);
|
|
lprintf(LOG_NOTICE,
|
|
- " Invalid Action type. Cannot continue");
|
|
- return HPMFWUPG_ERROR;
|
|
- break;
|
|
+ "(*) Component requires Payload Cold Reset");
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "(^) Indicates component would be upgraded");
|
|
}
|
|
- }
|
|
+ return HPMFWUPG_SUCCESS;
|
|
+}
|
|
|
|
- if (option & VIEW_MODE) {
|
|
- HpmDisplayLine("-",74);
|
|
+/* HpmfwupgUpgradeStage - upgrade stage of a firmware upgrade procedure as
|
|
+ * defined in section 3.3 of the IPM Controller Firmware Upgrade Specification
|
|
+ * version 1.0
|
|
+ */
|
|
+int
|
|
+HpmfwupgUpgradeStage(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx, int option)
|
|
+{
|
|
+ struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*)
|
|
+ pFwupgCtx->pImageData;
|
|
+ struct HpmfwupgActionRecord* pActionRecord;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ unsigned char *pImagePtr;
|
|
+ unsigned int actionsSize;
|
|
+ int flagColdReset = FALSE;
|
|
+ time_t start,end;
|
|
+ /* Put pointer after image header */
|
|
+ pImagePtr = (unsigned char*)
|
|
+ (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) +
|
|
+ pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/);
|
|
+ /* Deternime actions size */
|
|
+ actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader);
|
|
+ if (!(option & VIEW_MODE)) {
|
|
+ HpmDisplayUpgradeHeader();
|
|
+ }
|
|
+ /* Perform actions defined in the image */
|
|
+ while (( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize -
|
|
+ HPMFWUPG_MD5_SIGNATURE_LENGTH))
|
|
+ && (rc == HPMFWUPG_SUCCESS)) {
|
|
+ /* Get action record */
|
|
+ pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr;
|
|
+ /* Validate action record checksum */
|
|
+ rc = HpmfwupgValidateActionRecordChecksum(pActionRecord);
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ continue;
|
|
+ }
|
|
+ switch(pActionRecord->actionType) {
|
|
+ case HPMFWUPG_ACTION_BACKUP_COMPONENTS:
|
|
+ {
|
|
+ if (!(option & COMPARE_MODE)) {
|
|
+ /* Send Upgrade Action command */
|
|
+ struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd;
|
|
+ /* Affect only selected components */
|
|
+ initUpgActionCmd.req.componentsMask.ComponentBits.byte =
|
|
+ pFwupgCtx->compUpdateMask.ComponentBits.byte &
|
|
+ pActionRecord->components.ComponentBits.byte;
|
|
+ /* Action is prepare components */
|
|
+ if (initUpgActionCmd.req.componentsMask.ComponentBits.byte) {
|
|
+ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_BACKUP;
|
|
+ rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx);
|
|
+ }
|
|
+ }
|
|
+ pImagePtr+= sizeof(struct HpmfwupgActionRecord);
|
|
+ }
|
|
+ break;
|
|
+ case HPMFWUPG_ACTION_PREPARE_COMPONENTS:
|
|
+ {
|
|
+ if (!(option & COMPARE_MODE)) {
|
|
+ /* Send prepare components command */
|
|
+ struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd;
|
|
+ /* Affect only selected components */
|
|
+ initUpgActionCmd.req.componentsMask.ComponentBits.byte =
|
|
+ pFwupgCtx->compUpdateMask.ComponentBits.byte &
|
|
+ pActionRecord->components.ComponentBits.byte;
|
|
+ if (initUpgActionCmd.req.componentsMask.ComponentBits.byte) {
|
|
+ /* Action is prepare components */
|
|
+ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_PREPARE;
|
|
+ rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx);
|
|
+ }
|
|
+ }
|
|
+ pImagePtr+= sizeof(struct HpmfwupgActionRecord);
|
|
+ }
|
|
+ break;
|
|
+ case HPMFWUPG_ACTION_UPLOAD_FIRMWARE:
|
|
+ /* Upload all firmware blocks */
|
|
+ rc = HpmFwupgActionUploadFirmware(pActionRecord->components,
|
|
+ pFwupgCtx,
|
|
+ &pImagePtr,
|
|
+ intf,
|
|
+ option,
|
|
+ &flagColdReset);
|
|
+ break;
|
|
+ default:
|
|
+ lprintf(LOG_NOTICE, " Invalid Action type. Cannot continue");
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ HpmDisplayLine("-", 79);
|
|
fflush(stdout);
|
|
- lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset");
|
|
- lprintf(LOG_NOTICE,"(^) Indicates component would be upgraded");
|
|
- }
|
|
- return HPMFWUPG_SUCCESS;
|
|
+ lprintf(LOG_NOTICE, "(*) Component requires Payload Cold Reset");
|
|
+ return rc;
|
|
}
|
|
|
|
-
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmfwupgUpgradeStage
|
|
-*
|
|
-* Description: This function the upgrade stage of a firmware upgrade
|
|
-* procedure as defined in section 3.3 of the IPM Controller
|
|
-* Firmware Upgrade Specification version 1.0
|
|
-*
|
|
-*****************************************************************************/
|
|
-int HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx,
|
|
- int componentToUpload, int option)
|
|
-{
|
|
- struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
|
|
- pFwupgCtx->pImageData;
|
|
- struct HpmfwupgActionRecord* pActionRecord;
|
|
-
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- unsigned char* pImagePtr;
|
|
- unsigned int actionsSize;
|
|
- int flagColdReset = FALSE;
|
|
- time_t start,end;
|
|
-
|
|
- /* Put pointer after image header */
|
|
- pImagePtr = (unsigned char*)
|
|
- (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) +
|
|
- pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/);
|
|
-
|
|
- /* Deternime actions size */
|
|
- actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader);
|
|
-
|
|
- if (option & VERSIONCHECK_MODE || option & FORCE_MODE)
|
|
- {
|
|
- HpmDisplayUpgradeHeader();
|
|
- }
|
|
-
|
|
- /* Perform actions defined in the image */
|
|
- while( ( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize -
|
|
- HPMFWUPG_MD5_SIGNATURE_LENGTH)) &&
|
|
- ( rc == HPMFWUPG_SUCCESS) )
|
|
- {
|
|
- /* Get action record */
|
|
- pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr;
|
|
-
|
|
- /* Validate action record checksum */
|
|
- if ( HpmfwupgCalculateChecksum((unsigned char*)pActionRecord,
|
|
- sizeof(struct HpmfwupgActionRecord)) != 0 )
|
|
- {
|
|
- lprintf(LOG_NOTICE," Invalid Action record.");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- switch( pActionRecord->actionType )
|
|
- {
|
|
- case HPMFWUPG_ACTION_BACKUP_COMPONENTS:
|
|
- {
|
|
- /* Send prepare components command */
|
|
- struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd;
|
|
-
|
|
- initUpgActionCmd.req.componentsMask = pFwupgCtx->compUpdateMask;
|
|
- /* Action is prepare components */
|
|
- initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_BACKUP;
|
|
- rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx);
|
|
- pImagePtr += sizeof(struct HpmfwupgActionRecord);
|
|
-
|
|
- }
|
|
- break;
|
|
- case HPMFWUPG_ACTION_PREPARE_COMPONENTS:
|
|
- {
|
|
- int componentId;
|
|
- /* Make sure every components specified by this action
|
|
- supports the prepare components */
|
|
-
|
|
- /* Component 'filtering' is done in PreUpdateCheck() and pFwupgCtx is set accordiongly */
|
|
-
|
|
- for ( componentId = HPMFWUPG_COMPONENT_ID_0;
|
|
- componentId < HPMFWUPG_COMPONENT_ID_MAX;
|
|
- componentId++ )
|
|
- {
|
|
- if ( (1 << componentId & pFwupgCtx->compUpdateMask.ComponentBits.byte) )
|
|
- {
|
|
- if ( pFwupgCtx->genCompProp[componentId].GeneralCompProperties.bitfield.preparationSupport == 0 )
|
|
- {
|
|
- lprintf(LOG_NOTICE," Prepare component not supported by component ID %d", componentId);
|
|
- rc = HPMFWUPG_ERROR;
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- if ( pFwupgCtx->compUpdateMask.ComponentBits.byte != 0x00 )
|
|
- {
|
|
- /* Send prepare components command */
|
|
- struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd;
|
|
- initUpgActionCmd.req.componentsMask = pFwupgCtx->compUpdateMask;
|
|
- /* Action is prepare components */
|
|
- initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_PREPARE;
|
|
- rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx);
|
|
-
|
|
- }
|
|
- pImagePtr += sizeof(struct HpmfwupgActionRecord);
|
|
- }
|
|
- }
|
|
- break;
|
|
-
|
|
- case HPMFWUPG_ACTION_UPLOAD_FIRMWARE:
|
|
- /* Upload all firmware blocks */
|
|
- rc = HpmFwupgActionUploadFirmware
|
|
- (
|
|
- pActionRecord->components,
|
|
- pFwupgCtx,
|
|
- &pImagePtr,
|
|
- componentToUpload,
|
|
- intf,
|
|
- option,
|
|
- &flagColdReset
|
|
- );
|
|
-
|
|
- break;
|
|
- default:
|
|
- lprintf(LOG_NOTICE," Invalid Action type. Cannot continue");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- break;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- HpmDisplayLine("-",79);
|
|
-
|
|
- fflush(stdout);
|
|
- lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset");
|
|
-
|
|
- return rc;
|
|
+int
|
|
+get_max_rq_data_size(struct ipmi_intf *intf)
|
|
+{
|
|
+ int bufLength;
|
|
+ /* Check if we receive size in parameters */
|
|
+ if(intf->channel_buf_size != 0) {
|
|
+ /* Plan for overhead */
|
|
+ if (intf->target_addr == intf->my_addr) {
|
|
+ bufLength = intf->channel_buf_size - 9;
|
|
+ } else {
|
|
+ bufLength = intf->channel_buf_size - 11;
|
|
+ }
|
|
+ } else if (strstr(intf->name,"lan") != NULL) {
|
|
+ /* Find max buffer length according the connection
|
|
+ * parameters
|
|
+ */
|
|
+ bufLength = HPMFWUPG_SEND_DATA_COUNT_LAN - 2;
|
|
+ if (intf->transit_addr != intf->my_addr
|
|
+ && intf->transit_addr != 0) {
|
|
+ bufLength -= 8;
|
|
+ }
|
|
+ } else if (strstr(intf->name,"open") != NULL
|
|
+ && intf->target_addr == intf->my_addr) {
|
|
+ bufLength = HPMFWUPG_SEND_DATA_COUNT_KCS - 2;
|
|
+ } else if (intf->target_channel == 7) {
|
|
+ bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMBL;
|
|
+ } else {
|
|
+ bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMB;
|
|
+ }
|
|
+ return bufLength;
|
|
}
|
|
|
|
-static int HpmFwupgActionUploadFirmware
|
|
-(
|
|
- struct HpmfwupgComponentBitMask components,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx,
|
|
- unsigned char** pImagePtr,
|
|
- int componentToUpload,
|
|
- struct ipmi_intf *intf,
|
|
- int option,
|
|
- int *pFlagColdReset
|
|
-)
|
|
-{
|
|
- struct HpmfwupgFirmwareImage* pFwImage;
|
|
- struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd;
|
|
- struct HpmfwupgUploadFirmwareBlockCtx uploadCmd;
|
|
- struct HpmfwupgFinishFirmwareUploadCtx finishCmd;
|
|
- struct HpmfwupgGetComponentPropertiesCtx getCompProp;
|
|
- VERSIONINFO *pVersionInfo;
|
|
- time_t start,end;
|
|
-
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- int skip = TRUE;
|
|
- unsigned char* pData, *pDataInitial;
|
|
- unsigned char count;
|
|
- unsigned int totalSent = 0;
|
|
- unsigned char bufLength = 0;
|
|
- unsigned int firmwareLength = 0;
|
|
-
|
|
- unsigned int displayFWLength = 0;
|
|
- unsigned char *pDataTemp;
|
|
- unsigned int imageOffset = 0x00;
|
|
- unsigned int blockLength = 0x00;
|
|
- unsigned int lengthOfBlock = 0x00;
|
|
- unsigned int numTxPkts = 0;
|
|
- unsigned int numRxPkts = 0;
|
|
- unsigned char mode = 0;
|
|
- unsigned char componentId = 0x00;
|
|
- unsigned char componentIdByte = 0x00;
|
|
-
|
|
- /* Save component ID on which the upload is done */
|
|
- componentIdByte = components.ComponentBits.byte;
|
|
- while ((componentIdByte>>=1)!=0)
|
|
- {
|
|
- componentId++;
|
|
- }
|
|
- pFwupgCtx->componentId = componentId;
|
|
-
|
|
- pVersionInfo = (VERSIONINFO*) &gVersionInfo[componentId];
|
|
-
|
|
- pFwImage = (struct HpmfwupgFirmwareImage*)((*pImagePtr) +
|
|
- sizeof(struct HpmfwupgActionRecord));
|
|
-
|
|
- pDataInitial = ((unsigned char*)pFwImage + sizeof(struct HpmfwupgFirmwareImage));
|
|
- pData = pDataInitial;
|
|
-
|
|
- /* Get firmware length */
|
|
- firmwareLength = pFwImage->length[0];
|
|
- firmwareLength |= (pFwImage->length[1] << 8) & 0xff00;
|
|
- firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000;
|
|
- firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000;
|
|
-
|
|
- mode = TARGET_VER | IMAGE_VER;
|
|
-
|
|
- if (pVersionInfo->rollbackSupported)
|
|
- {
|
|
- mode |= ROLLBACK_VER;
|
|
+int
|
|
+HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx,
|
|
+ unsigned char **pImagePtr,
|
|
+ struct ipmi_intf *intf,
|
|
+ int option,
|
|
+ int *pFlagColdReset)
|
|
+{
|
|
+ struct HpmfwupgFirmwareImage *pFwImage;
|
|
+ struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd;
|
|
+ struct HpmfwupgUploadFirmwareBlockCtx uploadCmd;
|
|
+ struct HpmfwupgFinishFirmwareUploadCtx finishCmd;
|
|
+ VERSIONINFO *pVersionInfo;
|
|
+ time_t start,end;
|
|
+
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ int skip = TRUE;
|
|
+ unsigned char *pData, *pDataInitial;
|
|
+ unsigned short count;
|
|
+ unsigned int totalSent = 0;
|
|
+ unsigned short bufLength = 0;
|
|
+ unsigned short bufLengthIsSet = 0;
|
|
+ unsigned int firmwareLength = 0;
|
|
+
|
|
+ unsigned int displayFWLength = 0;
|
|
+ unsigned char *pDataTemp;
|
|
+ unsigned int imageOffset = 0x00;
|
|
+ unsigned int blockLength = 0x00;
|
|
+ unsigned int lengthOfBlock = 0x00;
|
|
+ unsigned int numTxPkts = 0;
|
|
+ unsigned int numRxPkts = 0;
|
|
+ unsigned char mode = 0;
|
|
+ unsigned char componentId = 0x00;
|
|
+ unsigned char componentIdByte = 0x00;
|
|
+ /* Save component ID on which the upload is done */
|
|
+ componentIdByte = components.ComponentBits.byte;
|
|
+ while ((componentIdByte>>= 1) != 0) {
|
|
+ componentId++;
|
|
}
|
|
-
|
|
- if ((option & DEBUG_MODE))
|
|
- {
|
|
- printf("\n\n Comp ID : %d [%-20s]\n",pVersionInfo->componentId,pFwImage->desc);
|
|
+ pFwupgCtx->componentId = componentId;
|
|
+ pVersionInfo = (VERSIONINFO *)&gVersionInfo[componentId];
|
|
+ pFwImage = (struct HpmfwupgFirmwareImage*)((*pImagePtr)
|
|
+ + sizeof(struct HpmfwupgActionRecord));
|
|
+ pDataInitial = ((unsigned char *)pFwImage
|
|
+ + sizeof(struct HpmfwupgFirmwareImage));
|
|
+ pData = pDataInitial;
|
|
+ /* Find max buffer length according the connection parameters */
|
|
+ bufLength = get_max_rq_data_size(intf);
|
|
+ /* Get firmware length */
|
|
+ firmwareLength = pFwImage->length[0];
|
|
+ firmwareLength|= (pFwImage->length[1] << 8) & 0xff00;
|
|
+ firmwareLength|= (pFwImage->length[2] << 16) & 0xff0000;
|
|
+ firmwareLength|= (pFwImage->length[3] << 24) & 0xff000000;
|
|
+ mode = TARGET_VER | IMAGE_VER;
|
|
+ if (pVersionInfo->rollbackSupported) {
|
|
+ mode |= ROLLBACK_VER;
|
|
}
|
|
- else
|
|
- {
|
|
- HpmDisplayVersion(mode,pVersionInfo, 0);
|
|
+ if ((option & DEBUG_MODE)) {
|
|
+ printf("\n\n Comp ID : %d [%-20s]\n",
|
|
+ pVersionInfo->componentId,
|
|
+ pFwImage->desc);
|
|
+ } else {
|
|
+ HpmDisplayVersion(mode, pVersionInfo, 0);
|
|
}
|
|
-
|
|
- if( (1 << componentId) & pFwupgCtx->compUpdateMask.ComponentBits.byte)
|
|
- {
|
|
- if( verbose ) {
|
|
- lprintf(LOG_NOTICE,"Do not skip %d" , componentId);
|
|
+ if ((1 << componentId) & pFwupgCtx->compUpdateMask.ComponentBits.byte) {
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE, "Do not skip %d",
|
|
+ componentId);
|
|
}
|
|
skip = FALSE;
|
|
}
|
|
-
|
|
- if(!skip)
|
|
- {
|
|
- HpmDisplayUpgrade(0,0,1,0);
|
|
- /* Initialize parameters */
|
|
- uploadCmd.req.blockNumber = 0;
|
|
-
|
|
- /* Check if we receive size in parameters */
|
|
- if(intf->channel_buf_size != 0)
|
|
- {
|
|
- if (intf->target_addr == intf->my_addr)
|
|
- {
|
|
- bufLength = intf->channel_buf_size - 9; /* Plan for overhead */
|
|
- }
|
|
- else
|
|
- {
|
|
- bufLength = intf->channel_buf_size - 11; /* Plan for overhead */
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- /* Find max buffer length according the connection parameters */
|
|
- if ( strstr(intf->name,"lan") != NULL )
|
|
- {
|
|
- bufLength = HPMFWUPG_SEND_DATA_COUNT_LAN - 2;
|
|
- if ( intf->transit_addr != intf->my_addr && intf->transit_addr != 0 )
|
|
- bufLength -= 8;
|
|
- }
|
|
- else
|
|
- {
|
|
- if
|
|
- (
|
|
- strstr(intf->name,"open") != NULL
|
|
- &&
|
|
- (
|
|
- intf->target_addr == intf->my_addr
|
|
- )
|
|
- )
|
|
- {
|
|
- bufLength = HPMFWUPG_SEND_DATA_COUNT_KCS - 2;
|
|
- }
|
|
- else
|
|
- {
|
|
- if ( intf->target_channel == 7 )
|
|
- {
|
|
- bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMBL;
|
|
- }
|
|
- else
|
|
- {
|
|
- bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMB;
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* Send Initiate Upgrade Action */
|
|
- initUpgActionCmd.req.componentsMask = components;
|
|
- /* Action is upgrade */
|
|
- initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_UPGRADE;
|
|
- rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx);
|
|
-
|
|
- if (rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- skip = TRUE;
|
|
- }
|
|
-
|
|
- if ( (pVersionInfo->coldResetRequired) && (!skip))
|
|
- {
|
|
- *pFlagColdReset = TRUE;
|
|
- }
|
|
- /* pDataInitial is the starting pointer of the image data */
|
|
- /* pDataTemp is one which we will move across */
|
|
- pData = pDataInitial;
|
|
- pDataTemp = pDataInitial;
|
|
- lengthOfBlock = firmwareLength;
|
|
- totalSent = 0x00;
|
|
- displayFWLength= firmwareLength;
|
|
- time(&start);
|
|
-
|
|
-
|
|
- while ( (pData < (pDataTemp+lengthOfBlock)) && (rc == HPMFWUPG_SUCCESS) )
|
|
- {
|
|
- if ( (pData+bufLength) <= (pDataTemp+lengthOfBlock) )
|
|
- {
|
|
- count = bufLength;
|
|
- }
|
|
- else
|
|
- {
|
|
- count = (unsigned char)((pDataTemp+lengthOfBlock) - pData);
|
|
- }
|
|
- memcpy(&uploadCmd.req.data, pData, bufLength);
|
|
-
|
|
- imageOffset = 0x00;
|
|
- blockLength = 0x00;
|
|
- numTxPkts++;
|
|
- rc = HpmfwupgUploadFirmwareBlock(intf, &uploadCmd, pFwupgCtx, count,
|
|
- &imageOffset,&blockLength);
|
|
- numRxPkts++;
|
|
-
|
|
- if ( rc != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- if ( rc == HPMFWUPG_UPLOAD_BLOCK_LENGTH )
|
|
- {
|
|
- /* Retry with a smaller buffer length */
|
|
- if ( strstr(intf->name,"lan") != NULL )
|
|
- {
|
|
- bufLength -= (unsigned char)8;
|
|
- lprintf(LOG_INFO,"Trying reduced buffer length: %d", bufLength);
|
|
- }
|
|
- else
|
|
- {
|
|
- bufLength -= (unsigned char)1;
|
|
- lprintf(LOG_INFO,"Trying reduced buffer length: %d", bufLength);
|
|
- }
|
|
- rc = HPMFWUPG_SUCCESS;
|
|
- }
|
|
- else if ( rc == HPMFWUPG_UPLOAD_RETRY )
|
|
- {
|
|
- rc = HPMFWUPG_SUCCESS;
|
|
- }
|
|
- else
|
|
- {
|
|
- fflush(stdout);
|
|
- lprintf(LOG_NOTICE,"\n Error in Upload FIRMWARE command [rc=%d]\n",rc);
|
|
- lprintf(LOG_NOTICE,"\n TotalSent:0x%x ",totalSent);
|
|
- /* Exiting from the function */
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- if (blockLength > firmwareLength)
|
|
- {
|
|
- /*
|
|
- * blockLength is the remaining length of the firmware to upload so
|
|
- * if its greater than the firmware length then its kind of error
|
|
- */
|
|
- lprintf(LOG_NOTICE,"\n Error in Upload FIRMWARE command [rc=%d]\n",rc);
|
|
- lprintf(LOG_NOTICE,"\n TotalSent:0x%x Img offset:0x%x Blk length:0x%x Fwlen:0x%x\n",
|
|
- totalSent,imageOffset,blockLength,firmwareLength);
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- totalSent += count;
|
|
- if (imageOffset != 0x00)
|
|
- {
|
|
- /* block Length is valid */
|
|
- lengthOfBlock = blockLength;
|
|
- pDataTemp = pDataInitial + imageOffset;
|
|
- pData = pDataTemp;
|
|
- if ( displayFWLength == firmwareLength)
|
|
- {
|
|
- /* This is basically used only to make sure that we display uptil 100% */
|
|
- displayFWLength = blockLength + totalSent;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- pData += count;
|
|
- }
|
|
- time(&end);
|
|
- /*
|
|
- * Just added debug mode in case we need to see exactly how many bytes have
|
|
- * gone through - Its a hidden option used mainly should be used for debugging
|
|
- */
|
|
- if ( option & DEBUG_MODE)
|
|
- {
|
|
- fflush(stdout);
|
|
- printf(" Blk Num : %02x Bytes : %05x ",
|
|
- uploadCmd.req.blockNumber,totalSent);
|
|
- if (imageOffset || blockLength)
|
|
- {
|
|
- printf("\n--> ImgOff : %x BlkLen : %x\n",imageOffset,blockLength);
|
|
- }
|
|
- if (displayFWLength == totalSent)
|
|
- {
|
|
- printf("\n Time Taken %02ld:%02ld",(end-start)/60, (end-start)%60);
|
|
- printf("\n\n");
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- HpmDisplayUpgrade(0,totalSent,displayFWLength,(end-start));
|
|
- }
|
|
- uploadCmd.req.blockNumber++;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if (skip)
|
|
- {
|
|
-
|
|
- HpmDisplayUpgrade(1,0,0,0);
|
|
- *pImagePtr = pDataInitial + firmwareLength;
|
|
- }
|
|
-
|
|
- if
|
|
- (
|
|
- (rc == HPMFWUPG_SUCCESS)
|
|
- &&
|
|
- (!skip)
|
|
- )
|
|
- {
|
|
- /* Send finish component */
|
|
- /* Set image length */
|
|
- finishCmd.req.componentId = componentId;
|
|
- /* We need to send the actual data that is sent
|
|
- * not the comlete firmware image length
|
|
- */
|
|
- finishCmd.req.imageLength[0] = totalSent & 0xFF;
|
|
- finishCmd.req.imageLength[1] = (totalSent >> 8) & 0xFF;
|
|
- finishCmd.req.imageLength[2] = (totalSent >> 16) & 0xFF;
|
|
- finishCmd.req.imageLength[3] = (totalSent >> 24) & 0xFF;
|
|
- rc = HpmfwupgFinishFirmwareUpload(intf, &finishCmd, pFwupgCtx);
|
|
- *pImagePtr = pDataInitial + firmwareLength;
|
|
- }
|
|
-
|
|
- return rc;
|
|
+ if (!skip) {
|
|
+ HpmDisplayUpgrade(0,0,1,0);
|
|
+ /* Initialize parameters */
|
|
+ uploadCmd.req = malloc(get_max_rq_data_size(intf)
|
|
+ + sizeof(struct HpmfwupgUploadFirmwareBlockReq));
|
|
+ if (!uploadCmd.req) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ uploadCmd.req->blockNumber = 0;
|
|
+ /* Send Initiate Upgrade Action */
|
|
+ initUpgActionCmd.req.componentsMask = components;
|
|
+ if (option & COMPARE_MODE) {
|
|
+ /* Action is compare */
|
|
+ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_COMPARE;
|
|
+ } else {
|
|
+ /* Action is upgrade */
|
|
+ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_UPGRADE;
|
|
+ }
|
|
+ rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx);
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ skip = TRUE;
|
|
+ }
|
|
+ if ((pVersionInfo->coldResetRequired) && (!skip)) {
|
|
+ *pFlagColdReset = TRUE;
|
|
+ }
|
|
+ /* pDataInitial is the starting pointer of the image data */
|
|
+ /* pDataTemp is one which we will move across */
|
|
+ pData = pDataInitial;
|
|
+ pDataTemp = pDataInitial;
|
|
+ lengthOfBlock = firmwareLength;
|
|
+ totalSent = 0x00;
|
|
+ displayFWLength= firmwareLength;
|
|
+ time(&start);
|
|
+ while ((pData < (pDataTemp+lengthOfBlock)) && (rc == HPMFWUPG_SUCCESS)) {
|
|
+ if ((pData+bufLength) <= (pDataTemp+lengthOfBlock)) {
|
|
+ count = bufLength;
|
|
+ } else {
|
|
+ count = (unsigned short)((pDataTemp+lengthOfBlock) - pData);
|
|
+ }
|
|
+ memcpy(&uploadCmd.req->data, pData, bufLength);
|
|
+ imageOffset = 0x00;
|
|
+ blockLength = 0x00;
|
|
+ numTxPkts++;
|
|
+ rc = HpmfwupgUploadFirmwareBlock(intf, &uploadCmd,
|
|
+ pFwupgCtx, count, &imageOffset,&blockLength);
|
|
+ numRxPkts++;
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ if (rc == HPMFWUPG_UPLOAD_BLOCK_LENGTH && !bufLengthIsSet) {
|
|
+ rc = HPMFWUPG_SUCCESS;
|
|
+ /* Retry with a smaller buffer length */
|
|
+ if (strstr(intf->name,"lan") != NULL && bufLength > 8) {
|
|
+ bufLength-= 8;
|
|
+ lprintf(LOG_INFO,
|
|
+ "Trying reduced buffer length: %d",
|
|
+ bufLength);
|
|
+ } else if (bufLength) {
|
|
+ bufLength-= 1;
|
|
+ lprintf(LOG_INFO,
|
|
+ "Trying reduced buffer length: %d",
|
|
+ bufLength);
|
|
+ } else {
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ } else if (rc == HPMFWUPG_UPLOAD_RETRY) {
|
|
+ rc = HPMFWUPG_SUCCESS;
|
|
+ } else {
|
|
+ fflush(stdout);
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\n Error in Upload FIRMWARE command [rc=%d]\n",
|
|
+ rc);
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\n TotalSent:0x%x ",
|
|
+ totalSent);
|
|
+ /* Exiting from the function */
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ } else {
|
|
+ /* success, buf length is valid */
|
|
+ bufLengthIsSet = 1;
|
|
+ if (blockLength > firmwareLength) {
|
|
+ /*
|
|
+ * blockLength is the remaining length of the firmware to upload so
|
|
+ * if its greater than the firmware length then its kind of error
|
|
+ */
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\n Error in Upload FIRMWARE command [rc=%d]\n",
|
|
+ rc);
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "\n TotalSent:0x%x Img offset:0x%x Blk length:0x%x Fwlen:0x%x\n",
|
|
+ totalSent,imageOffset,blockLength,firmwareLength);
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ totalSent += count;
|
|
+ if (imageOffset != 0x00) {
|
|
+ /* block Length is valid */
|
|
+ lengthOfBlock = blockLength;
|
|
+ pDataTemp = pDataInitial + imageOffset;
|
|
+ pData = pDataTemp;
|
|
+ if (displayFWLength == firmwareLength) {
|
|
+ /* This is basically used only to make sure that we display uptil 100% */
|
|
+ displayFWLength = blockLength + totalSent;
|
|
+ }
|
|
+ } else {
|
|
+ pData += count;
|
|
+ }
|
|
+ time(&end);
|
|
+ /*
|
|
+ * Just added debug mode in case we need to see exactly how many bytes have
|
|
+ * gone through - Its a hidden option used mainly should be used for debugging
|
|
+ */
|
|
+ if (option & DEBUG_MODE) {
|
|
+ fflush(stdout);
|
|
+ printf(" Blk Num : %02x Bytes : %05x ",
|
|
+ uploadCmd.req->blockNumber,totalSent);
|
|
+ if (imageOffset || blockLength) {
|
|
+ printf("\n--> ImgOff : %x BlkLen : %x\n",
|
|
+ imageOffset,blockLength);
|
|
+ }
|
|
+ if (displayFWLength == totalSent) {
|
|
+ printf("\n Time Taken %02ld:%02ld",
|
|
+ (end-start)/60, (end-start)%60);
|
|
+ printf("\n\n");
|
|
+ }
|
|
+ } else {
|
|
+ HpmDisplayUpgrade(0, totalSent,
|
|
+ displayFWLength, (end-start));
|
|
+ }
|
|
+ uploadCmd.req->blockNumber++;
|
|
+ }
|
|
+ }
|
|
+ /* free buffer */
|
|
+ free(uploadCmd.req);
|
|
+ uploadCmd.req = NULL;
|
|
+ }
|
|
+ if (skip) {
|
|
+ HpmDisplayUpgrade(1,0,0,0);
|
|
+ if ((option & COMPARE_MODE)
|
|
+ && !pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.comparisonSupport) {
|
|
+ printf("| |Comparison isn't supported for given compenent. |\n");
|
|
+ }
|
|
+ *pImagePtr = pDataInitial + firmwareLength;
|
|
+ }
|
|
+ if (rc == HPMFWUPG_SUCCESS && !skip) {
|
|
+ /* Send finish component */
|
|
+ /* Set image length */
|
|
+ finishCmd.req.componentId = componentId;
|
|
+ /* We need to send the actual data that is sent
|
|
+ * not the comlete firmware image length
|
|
+ */
|
|
+ finishCmd.req.imageLength[0] = totalSent & 0xFF;
|
|
+ finishCmd.req.imageLength[1] = (totalSent >> 8) & 0xFF;
|
|
+ finishCmd.req.imageLength[2] = (totalSent >> 16) & 0xFF;
|
|
+ finishCmd.req.imageLength[3] = (totalSent >> 24) & 0xFF;
|
|
+ rc = HpmfwupgFinishFirmwareUpload(intf, &finishCmd,
|
|
+ pFwupgCtx, option);
|
|
+ *pImagePtr = pDataInitial + firmwareLength;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-/****************************************************************************
|
|
-*
|
|
-* Function Name: HpmfwupgActivationStage
|
|
-*
|
|
-* Description: This function the validation stage of a firmware upgrade
|
|
-* procedure as defined in section 3.4 of the IPM Controller
|
|
-* Firmware Upgrade Specification version 1.0
|
|
-*
|
|
-*****************************************************************************/
|
|
-static int HpmfwupgActivationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
-{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct HpmfwupgActivateFirmwareCtx activateCmd;
|
|
- struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
|
|
- pFwupgCtx->pImageData;
|
|
-
|
|
- /* Print out stuf...*/
|
|
- printf(" ");
|
|
- fflush(stdout);
|
|
- /* Activate new firmware */
|
|
- rc = HpmfwupgActivateFirmware(intf, &activateCmd, pFwupgCtx);
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- /* Query self test result if supported by target and new image */
|
|
- if ( (pFwupgCtx->targetCap.GlobalCapabilities.bitField.ipmcSelftestCap == 1) ||
|
|
- (pImageHeader->imageCapabilities.bitField.imageSelfTest == 1) )
|
|
- {
|
|
- struct HpmfwupgQuerySelftestResultCtx selfTestCmd;
|
|
- rc = HpmfwupgQuerySelftestResult(intf, &selfTestCmd, pFwupgCtx);
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- /* Get the self test result */
|
|
- if ( selfTestCmd.resp.result1 != 0x55 )
|
|
- {
|
|
- /* Perform manual rollback if necessary */
|
|
- /* BACKUP/ MANUAL ROLLBACK not supported by this UA */
|
|
- lprintf(LOG_NOTICE," Self test failed:");
|
|
- lprintf(LOG_NOTICE," Result1 = %x", selfTestCmd.resp.result1);
|
|
- lprintf(LOG_NOTICE," Result2 = %x", selfTestCmd.resp.result2);
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- /* Perform manual rollback if necessary */
|
|
- /* BACKUP / MANUAL ROLLBACK not supported by this UA */
|
|
- lprintf(LOG_NOTICE," Self test failed.");
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* If activation / self test failed, query rollback status if automatic rollback supported */
|
|
- if ( rc == HPMFWUPG_ERROR )
|
|
- {
|
|
- if ( (pFwupgCtx->targetCap.GlobalCapabilities.bitField.autRollback == 1) &&
|
|
- (pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.rollbackBackup != 0x00) )
|
|
- {
|
|
- struct HpmfwupgQueryRollbackStatusCtx rollCmd;
|
|
- lprintf(LOG_NOTICE," Getting rollback status...");
|
|
- fflush(stdout);
|
|
- rc = HpmfwupgQueryRollbackStatus(intf, &rollCmd, pFwupgCtx);
|
|
- }
|
|
- }
|
|
-
|
|
- return rc;
|
|
+/* HpmfwupgActivationStage - validate stage of a firmware upgrade procedure as
|
|
+ * defined in section 3.4 of the IPM Controller Firmware Upgrade Specification
|
|
+ * version 1.0
|
|
+ */
|
|
+int
|
|
+HpmfwupgActivationStage(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx)
|
|
+{
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct HpmfwupgActivateFirmwareCtx activateCmd;
|
|
+ struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*)
|
|
+ pFwupgCtx->pImageData;
|
|
+ /* Print out stuf...*/
|
|
+ printf(" ");
|
|
+ fflush(stdout);
|
|
+ /* Activate new firmware */
|
|
+ activateCmd.req.rollback_override = 0;
|
|
+ rc = HpmfwupgActivateFirmware(intf, &activateCmd, pFwupgCtx);
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ /* Query self test result if supported by target and new image */
|
|
+ if ((pFwupgCtx->targetCap.GlobalCapabilities.bitField.ipmcSelftestCap == 1)
|
|
+ || (pImageHeader->imageCapabilities.bitField.imageSelfTest == 1)) {
|
|
+ struct HpmfwupgQuerySelftestResultCtx selfTestCmd;
|
|
+ rc = HpmfwupgQuerySelftestResult(intf, &selfTestCmd,
|
|
+ pFwupgCtx);
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ /* Get the self test result */
|
|
+ if (selfTestCmd.resp.result1 != 0x55) {
|
|
+ /* Perform manual rollback if necessary */
|
|
+ /* BACKUP/ MANUAL ROLLBACK not supported by this UA */
|
|
+ lprintf(LOG_NOTICE, " Self test failed:");
|
|
+ lprintf(LOG_NOTICE, " Result1 = %x",
|
|
+ selfTestCmd.resp.result1);
|
|
+ lprintf(LOG_NOTICE, " Result2 = %x",
|
|
+ selfTestCmd.resp.result2);
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ } else {
|
|
+ /* Perform manual rollback if necessary */
|
|
+ /* BACKUP / MANUAL ROLLBACK not supported by this UA */
|
|
+ lprintf(LOG_NOTICE," Self test failed.");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /* If activation / self test failed, query rollback
|
|
+ * status if automatic rollback supported
|
|
+ */
|
|
+ if (rc == HPMFWUPG_ERROR) {
|
|
+ if ((pFwupgCtx->targetCap.GlobalCapabilities.bitField.autRollback == 1)
|
|
+ && (pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.rollbackBackup != 0x00)) {
|
|
+ struct HpmfwupgQueryRollbackStatusCtx rollCmd;
|
|
+ lprintf(LOG_NOTICE," Getting rollback status...");
|
|
+ fflush(stdout);
|
|
+ rc = HpmfwupgQueryRollbackStatus(intf,
|
|
+ &rollCmd, pFwupgCtx);
|
|
+ }
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-int HpmfwupgGetBufferFromFile(char* imageFilename, struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
+int
|
|
+HpmfwupgGetBufferFromFile(char *imageFilename,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- int ret = 0;
|
|
- FILE* pImageFile = fopen(imageFilename, "rb");
|
|
-
|
|
- if ( pImageFile == NULL )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Cannot open image file %s", imageFilename);
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- /* Get the raw data in file */
|
|
- fseek(pImageFile, 0, SEEK_END);
|
|
- pFwupgCtx->imageSize = ftell(pImageFile);
|
|
- pFwupgCtx->pImageData = malloc(sizeof(unsigned char)*pFwupgCtx->imageSize);
|
|
- pFwupgCtx->compUpdateMask.ComponentBits.byte = 0;
|
|
- rewind(pImageFile);
|
|
- if ( pFwupgCtx->pImageData != NULL )
|
|
- {
|
|
- ret = fread(pFwupgCtx->pImageData, sizeof(unsigned char),
|
|
- pFwupgCtx->imageSize, pImageFile);
|
|
- if (ret != pFwupgCtx->imageSize) {
|
|
- lprintf(LOG_ERROR,"Failed to read file %s size %d",
|
|
- imageFilename, pFwupgCtx->imageSize);
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ int ret = 0;
|
|
+ FILE *pImageFile = fopen(imageFilename, "rb");
|
|
+ if (pImageFile == NULL) {
|
|
+ lprintf(LOG_ERR, "Cannot open image file '%s'",
|
|
+ imageFilename);
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Get the raw data in file */
|
|
+ fseek(pImageFile, 0, SEEK_END);
|
|
+ pFwupgCtx->imageSize = ftell(pImageFile);
|
|
+ pFwupgCtx->pImageData = malloc(sizeof(unsigned char)*pFwupgCtx->imageSize);
|
|
+ if (pFwupgCtx->pImageData == NULL) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ fclose(pImageFile);
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ rewind(pImageFile);
|
|
+ ret = fread(pFwupgCtx->pImageData,
|
|
+ sizeof(unsigned char),
|
|
+ pFwupgCtx->imageSize,
|
|
+ pImageFile);
|
|
+ if (ret != pFwupgCtx->imageSize) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Failed to read file %s size %d",
|
|
+ imageFilename,
|
|
+ pFwupgCtx->imageSize);
|
|
rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- fclose(pImageFile);
|
|
- }
|
|
-
|
|
- return rc;
|
|
+ }
|
|
+ fclose(pImageFile);
|
|
+ return rc;
|
|
}
|
|
|
|
-int HpmfwupgGetDeviceId(struct ipmi_intf *intf, struct ipm_devid_rsp* pGetDevId)
|
|
+int
|
|
+HpmfwupgGetDeviceId(struct ipmi_intf *intf, struct ipm_devid_rsp *pGetDevId)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = BMC_GET_DEVICE_ID;
|
|
- req.msg.data_len = 0;
|
|
-
|
|
- rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- if ( rsp->ccode == 0x00 )
|
|
- {
|
|
- memcpy(pGetDevId, rsp->data, sizeof(struct ipm_devid_rsp));
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error getting device ID");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error getting device ID\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- return rc;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = BMC_GET_DEVICE_ID;
|
|
+ req.msg.data_len = 0;
|
|
+ rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Error getting device ID.");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if (rsp->ccode != 0x00) {
|
|
+ lprintf(LOG_ERR, "Error getting device ID.");
|
|
+ lprintf(LOG_ERR, "compcode=0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ memcpy(pGetDevId, rsp->data, sizeof(struct ipm_devid_rsp));
|
|
+ return HPMFWUPG_SUCCESS;
|
|
}
|
|
|
|
-int HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf,
|
|
- struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx)
|
|
+int
|
|
+HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx *pCtx)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_GET_TARGET_UPG_CAPABILITIES;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_GET_TARGET_UPG_CAPABILITIES;
|
|
+ req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgGetTargetUpgCapabilitiesReq);
|
|
-
|
|
- rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- if ( rsp->ccode == 0x00 )
|
|
- {
|
|
- memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp));
|
|
- if ( verbose )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"TARGET UPGRADE CAPABILITIES");
|
|
- lprintf(LOG_NOTICE,"-------------------------------");
|
|
- lprintf(LOG_NOTICE,"HPM.1 version............%d ", pCtx->resp.hpmVersion);
|
|
- lprintf(LOG_NOTICE,"Component 0 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
|
|
- bitField.component0 ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Component 1 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
|
|
- bitField.component1 ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Component 2 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
|
|
- bitField.component2 ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Component 3 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
|
|
- bitField.component3 ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Component 4 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
|
|
- bitField.component4 ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Component 5 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
|
|
- bitField.component5 ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Component 6 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
|
|
- bitField.component6 ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Component 7 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
|
|
- bitField.component7 ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Upgrade undesirable.....[%c] ", pCtx->resp.GlobalCapabilities.
|
|
- bitField.fwUpgUndesirable ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Aut rollback override...[%c] ", pCtx->resp.GlobalCapabilities.
|
|
- bitField.autRollbackOverride ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"IPMC degraded...........[%c] ", pCtx->resp.GlobalCapabilities.
|
|
- bitField.ipmcDegradedDurinUpg ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Defered activation......[%c] ", pCtx->resp.GlobalCapabilities.
|
|
- bitField.deferActivation ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Service affected........[%c] ", pCtx->resp.GlobalCapabilities.
|
|
- bitField.servAffectDuringUpg ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Manual rollback.........[%c] ", pCtx->resp.GlobalCapabilities.
|
|
- bitField.manualRollback ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Automatic rollback......[%c] ", pCtx->resp.GlobalCapabilities.
|
|
- bitField.autRollback ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Self test...............[%c] ", pCtx->resp.GlobalCapabilities.
|
|
- bitField.ipmcSelftestCap ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Upgrade timeout.........[%d sec] ", pCtx->resp.upgradeTimeout*5);
|
|
- lprintf(LOG_NOTICE,"Self test timeout.......[%d sec] ", pCtx->resp.selftestTimeout*5);
|
|
- lprintf(LOG_NOTICE,"Rollback timeout........[%d sec] ", pCtx->resp.rollbackTimeout*5);
|
|
- lprintf(LOG_NOTICE,"Inaccessibility timeout.[%d sec] \n", pCtx->resp.inaccessTimeout*5);
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error getting target upgrade capabilities\n", rsp->ccode);
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error getting target upgrade capabilities\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
-
|
|
-
|
|
- return rc;
|
|
+ rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error getting target upgrade capabilities.");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if (rsp->ccode != 0x00) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error getting target upgrade capabilities, ccode: 0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ memcpy(&pCtx->resp, rsp->data,
|
|
+ sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp));
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE, "TARGET UPGRADE CAPABILITIES");
|
|
+ lprintf(LOG_NOTICE, "-------------------------------");
|
|
+ lprintf(LOG_NOTICE, "HPM.1 version............%d ",
|
|
+ pCtx->resp.hpmVersion);
|
|
+ lprintf(LOG_NOTICE, "Component 0 presence....[%c] ",
|
|
+ pCtx->resp.componentsPresent.ComponentBits.bitField.component0 ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Component 1 presence....[%c] ",
|
|
+ pCtx->resp.componentsPresent.ComponentBits.bitField.component1 ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Component 2 presence....[%c] ",
|
|
+ pCtx->resp.componentsPresent.ComponentBits.bitField.component2 ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Component 3 presence....[%c] ",
|
|
+ pCtx->resp.componentsPresent.ComponentBits.bitField.component3 ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Component 4 presence....[%c] ",
|
|
+ pCtx->resp.componentsPresent.ComponentBits.bitField.component4 ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Component 5 presence....[%c] ",
|
|
+ pCtx->resp.componentsPresent.ComponentBits.bitField.component5 ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Component 6 presence....[%c] ",
|
|
+ pCtx->resp.componentsPresent.ComponentBits.bitField.component6 ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Component 7 presence....[%c] ",
|
|
+ pCtx->resp.componentsPresent.ComponentBits.bitField.component7 ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Upgrade undesirable.....[%c] ",
|
|
+ pCtx->resp.GlobalCapabilities.bitField.fwUpgUndesirable ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Aut rollback override...[%c] ",
|
|
+ pCtx->resp.GlobalCapabilities.bitField.autRollbackOverride ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "IPMC degraded...........[%c] ",
|
|
+ pCtx->resp.GlobalCapabilities.bitField.ipmcDegradedDurinUpg ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Defered activation......[%c] ",
|
|
+ pCtx->resp.GlobalCapabilities.bitField.deferActivation ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Service affected........[%c] ",
|
|
+ pCtx->resp.GlobalCapabilities.bitField.servAffectDuringUpg ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Manual rollback.........[%c] ",
|
|
+ pCtx->resp.GlobalCapabilities.bitField.manualRollback ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Automatic rollback......[%c] ",
|
|
+ pCtx->resp.GlobalCapabilities.bitField.autRollback ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Self test...............[%c] ",
|
|
+ pCtx->resp.GlobalCapabilities.bitField.ipmcSelftestCap ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Upgrade timeout.........[%d sec] ",
|
|
+ pCtx->resp.upgradeTimeout*5);
|
|
+ lprintf(LOG_NOTICE, "Self test timeout.......[%d sec] ",
|
|
+ pCtx->resp.selftestTimeout*5);
|
|
+ lprintf(LOG_NOTICE, "Rollback timeout........[%d sec] ",
|
|
+ pCtx->resp.rollbackTimeout*5);
|
|
+ lprintf(LOG_NOTICE, "Inaccessibility timeout.[%d sec] \n",
|
|
+ pCtx->resp.inaccessTimeout*5);
|
|
+ }
|
|
+ return HPMFWUPG_SUCCESS;
|
|
}
|
|
|
|
-
|
|
-int HpmfwupgGetComponentProperties(struct ipmi_intf *intf, struct HpmfwupgGetComponentPropertiesCtx* pCtx)
|
|
+int
|
|
+HpmfwupgGetComponentProperties(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgGetComponentPropertiesCtx *pCtx)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_GET_COMPONENT_PROPERTIES;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct ipmi_rs * rsp;
|
|
+ struct ipmi_rq req;
|
|
+ pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_GET_COMPONENT_PROPERTIES;
|
|
+ req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgGetComponentPropertiesReq);
|
|
-
|
|
- rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- if ( rsp->ccode == 0x00 )
|
|
- {
|
|
- switch ( pCtx->req.selector )
|
|
- {
|
|
- case HPMFWUPG_COMP_GEN_PROPERTIES:
|
|
- memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetGeneralPropResp));
|
|
- if ( verbose )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"GENERAL PROPERTIES");
|
|
- lprintf(LOG_NOTICE,"-------------------------------");
|
|
- lprintf(LOG_NOTICE,"Payload cold reset req....[%c] ", pCtx->resp.Response.generalPropResp.
|
|
- GeneralCompProperties.bitfield.payloadColdReset ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Def. activation supported.[%c] ", pCtx->resp.Response.generalPropResp.
|
|
- GeneralCompProperties.bitfield.deferredActivation ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Comparison supported......[%c] ", pCtx->resp.Response.generalPropResp.
|
|
- GeneralCompProperties.bitfield.comparisonSupport ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Preparation supported.....[%c] ", pCtx->resp.Response.generalPropResp.
|
|
- GeneralCompProperties.bitfield.preparationSupport ? 'y' : 'n');
|
|
- lprintf(LOG_NOTICE,"Rollback supported........[%c] \n", pCtx->resp.Response.generalPropResp.
|
|
- GeneralCompProperties.bitfield.rollbackBackup ? 'y' : 'n');
|
|
- }
|
|
- break;
|
|
- case HPMFWUPG_COMP_CURRENT_VERSION:
|
|
- memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetCurrentVersionResp));
|
|
- if ( verbose )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Current Version: ");
|
|
- lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.currentVersionResp.currentVersion[0]);
|
|
- lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.currentVersionResp.currentVersion[1]);
|
|
- lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.currentVersionResp.currentVersion[2],
|
|
- pCtx->resp.Response.currentVersionResp.currentVersion[3],
|
|
- pCtx->resp.Response.currentVersionResp.currentVersion[4],
|
|
- pCtx->resp.Response.currentVersionResp.currentVersion[5]);
|
|
- }
|
|
- break;
|
|
- case HPMFWUPG_COMP_DESCRIPTION_STRING:
|
|
- memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDescStringResp));
|
|
- if ( verbose )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Description string: %s\n", pCtx->resp.Response.descStringResp.descString);
|
|
- }
|
|
- break;
|
|
- case HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION:
|
|
- memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetRollbackFwVersionResp));
|
|
- if ( verbose )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Rollback FW Version: ");
|
|
- lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[0]);
|
|
- lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[1]);
|
|
- lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[2],
|
|
- pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[3],
|
|
- pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[4],
|
|
- pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[5]);
|
|
- }
|
|
- break;
|
|
- case HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION:
|
|
- memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDeferredFwVersionResp));
|
|
- if ( verbose )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Deferred FW Version: ");
|
|
- lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[0]);
|
|
- lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[1]);
|
|
- lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[2],
|
|
- pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[3],
|
|
- pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[4],
|
|
- pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[5]);
|
|
- }
|
|
- break;
|
|
- // OEM Properties command
|
|
- case HPMFWUPG_COMP_OEM_PROPERTIES:
|
|
- memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetOemProperties));
|
|
- if ( verbose )
|
|
- {
|
|
- unsigned char i = 0;
|
|
- lprintf(LOG_NOTICE,"OEM Properties: ");
|
|
- for (i=0; i < HPMFWUPG_OEM_LENGTH; i++)
|
|
- {
|
|
- lprintf(LOG_NOTICE," 0x%x ", pCtx->resp.Response.oemProperties.oemRspData[i]);
|
|
- }
|
|
- }
|
|
- break;
|
|
- default:
|
|
- lprintf(LOG_NOTICE,"Unsupported component selector");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- break;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error getting component properties");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error getting component properties\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
-
|
|
- return rc;
|
|
+ rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Error getting component properties\n");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if (rsp->ccode != 0x00) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Error getting component properties");
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "compcode=0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ switch (pCtx->req.selector) {
|
|
+ case HPMFWUPG_COMP_GEN_PROPERTIES:
|
|
+ memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetGeneralPropResp));
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE, "GENERAL PROPERTIES");
|
|
+ lprintf(LOG_NOTICE, "-------------------------------");
|
|
+ lprintf(LOG_NOTICE, "Payload cold reset req....[%c] ",
|
|
+ pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.payloadColdReset ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Def. activation supported.[%c] ",
|
|
+ pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.deferredActivation ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Comparison supported......[%c] ",
|
|
+ pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.comparisonSupport ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Preparation supported.....[%c] ",
|
|
+ pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.preparationSupport ? 'y' : 'n');
|
|
+ lprintf(LOG_NOTICE, "Rollback supported........[%c] \n",
|
|
+ pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.rollbackBackup ? 'y' : 'n');
|
|
+ }
|
|
+ break;
|
|
+ case HPMFWUPG_COMP_CURRENT_VERSION:
|
|
+ memcpy(&pCtx->resp, rsp->data,
|
|
+ sizeof(struct HpmfwupgGetCurrentVersionResp));
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE, "Current Version: ");
|
|
+ lprintf(LOG_NOTICE, " Major: %d",
|
|
+ pCtx->resp.Response.currentVersionResp.currentVersion[0]);
|
|
+ lprintf(LOG_NOTICE, " Minor: %x",
|
|
+ pCtx->resp.Response.currentVersionResp.currentVersion[1]);
|
|
+ lprintf(LOG_NOTICE, " Aux : %03d %03d %03d %03d\n",
|
|
+ pCtx->resp.Response.currentVersionResp.currentVersion[2],
|
|
+ pCtx->resp.Response.currentVersionResp.currentVersion[3],
|
|
+ pCtx->resp.Response.currentVersionResp.currentVersion[4],
|
|
+ pCtx->resp.Response.currentVersionResp.currentVersion[5]);
|
|
+ }
|
|
+ break;
|
|
+ case HPMFWUPG_COMP_DESCRIPTION_STRING:
|
|
+ memcpy(&pCtx->resp, rsp->data,
|
|
+ sizeof(struct HpmfwupgGetDescStringResp));
|
|
+ if (verbose) {
|
|
+ char descString[HPMFWUPG_DESC_STRING_LENGTH + 1];
|
|
+ memcpy(descString,
|
|
+ pCtx->resp.Response.descStringResp.descString,
|
|
+ HPMFWUPG_DESC_STRING_LENGTH);
|
|
+ descString[HPMFWUPG_DESC_STRING_LENGTH] = '\0';
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Description string: %s\n",
|
|
+ descString);
|
|
+ }
|
|
+ break;
|
|
+ case HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION:
|
|
+ memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetRollbackFwVersionResp));
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE, "Rollback FW Version: ");
|
|
+ lprintf(LOG_NOTICE, " Major: %d",
|
|
+ pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[0]);
|
|
+ lprintf(LOG_NOTICE, " Minor: %x",
|
|
+ pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[1]);
|
|
+ lprintf(LOG_NOTICE, " Aux : %03d %03d %03d %03d\n",
|
|
+ pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[2],
|
|
+ pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[3],
|
|
+ pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[4],
|
|
+ pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[5]);
|
|
+ }
|
|
+ break;
|
|
+ case HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION:
|
|
+ memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDeferredFwVersionResp));
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE, "Deferred FW Version: ");
|
|
+ lprintf(LOG_NOTICE, " Major: %d",
|
|
+ pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[0]);
|
|
+ lprintf(LOG_NOTICE, " Minor: %x",
|
|
+ pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[1]);
|
|
+ lprintf(LOG_NOTICE, " Aux : %03d %03d %03d %03d\n",
|
|
+ pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[2],
|
|
+ pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[3],
|
|
+ pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[4],
|
|
+ pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[5]);
|
|
+ }
|
|
+ break;
|
|
+ case HPMFWUPG_COMP_OEM_PROPERTIES:
|
|
+ /* OEM Properties command */
|
|
+ memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetOemProperties));
|
|
+ if (verbose) {
|
|
+ unsigned char i = 0;
|
|
+ lprintf(LOG_NOTICE,"OEM Properties: ");
|
|
+ for (i=0; i < HPMFWUPG_OEM_LENGTH; i++) {
|
|
+ lprintf(LOG_NOTICE, " 0x%x ",
|
|
+ pCtx->resp.Response.oemProperties.oemRspData[i]);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ lprintf(LOG_NOTICE,"Unsupported component selector");
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ break;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-int HpmfwupgAbortUpgrade(struct ipmi_intf *intf, struct HpmfwupgAbortUpgradeCtx* pCtx)
|
|
+int
|
|
+HpmfwupgAbortUpgrade(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgAbortUpgradeCtx *pCtx)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_ABORT_UPGRADE;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_ABORT_UPGRADE;
|
|
+ req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgAbortUpgradeReq);
|
|
-
|
|
- rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- if ( rsp->ccode != 0x00 )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error aborting upgrade");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error aborting upgrade\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- return rc;
|
|
+ rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Error - aborting upgrade.");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if (rsp->ccode != 0x00) {
|
|
+ lprintf(LOG_ERR, "Error aborting upgrade");
|
|
+ lprintf(LOG_ERR, "compcode=0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-int HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf, struct HpmfwupgInitiateUpgradeActionCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
+int
|
|
+HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgInitiateUpgradeActionCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_INITIATE_UPGRADE_ACTION;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_INITIATE_UPGRADE_ACTION;
|
|
+ req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgInitiateUpgradeActionReq);
|
|
-
|
|
- rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- /* Long duration command handling */
|
|
- if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
|
|
- {
|
|
- rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
- }
|
|
- else if ( rsp->ccode != 0x00 )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error initiating upgrade action");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error initiating upgrade action\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- return rc;
|
|
+ rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Error initiating upgrade action.");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Long duration command handling */
|
|
+ if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) {
|
|
+ rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
+ } else if (rsp->ccode != 0x00) {
|
|
+ lprintf(LOG_NOTICE,"Error initiating upgrade action");
|
|
+ lprintf(LOG_NOTICE, "compcode=0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-int HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf, struct HpmfwupgUploadFirmwareBlockCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx, int count
|
|
- ,unsigned int *imageOffset, unsigned int *blockLength )
|
|
+int
|
|
+HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUploadFirmwareBlockCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx, int count,
|
|
+ unsigned int *imageOffset, unsigned int *blockLength)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_UPLOAD_FIRMWARE_BLOCK;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
- /* 2 is the size of the upload struct - data */
|
|
- req.msg.data_len = 2 + count;
|
|
-
|
|
- rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ||
|
|
- rsp->ccode == 0x00 )
|
|
- {
|
|
- /*
|
|
- * We need to check if the response also contains the next upload firmware offset
|
|
- * and the firmware length in its response - These are optional but very vital
|
|
- */
|
|
- if ( rsp->data_len > 1 )
|
|
- {
|
|
- /*
|
|
- * If the response data length is greater than 1 it should contain both the
|
|
- * the Section offset and section length. Because we cannot just have
|
|
- * Section offset without section length so the length should be 9
|
|
- */
|
|
- if ( rsp->data_len == 9 )
|
|
- {
|
|
- /* rsp->data[1] - LSB rsp->data[2] - rsp->data[3] = MSB */
|
|
- *imageOffset = (rsp->data[4] << 24) + (rsp->data[3] << 16) + (rsp->data[2] << 8) + rsp->data[1];
|
|
- *blockLength = (rsp->data[8] << 24) + (rsp->data[7] << 16) + (rsp->data[6] << 8) + rsp->data[5];
|
|
- }
|
|
- else
|
|
- {
|
|
- /*
|
|
- * The Spec does not say much for this kind of errors where the
|
|
- * firmware returned only offset and length so currently returning it
|
|
- * as 0x82 - Internal CheckSum Error
|
|
- */
|
|
- lprintf(LOG_NOTICE,"Error wrong rsp->datalen %d for Upload Firmware block command\n",rsp->data_len);
|
|
- rsp->ccode = HPMFWUPG_INT_CHECKSUM_ERROR;
|
|
- }
|
|
- }
|
|
- }
|
|
- /* Long duration command handling */
|
|
- if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
|
|
- {
|
|
- rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
- }
|
|
- else if (rsp->ccode != 0x00)
|
|
- {
|
|
- /*
|
|
- * PATCH --> This validation is to handle retryables errors codes on IPMB bus.
|
|
- * This will be fixed in the next release of open ipmi and this
|
|
- * check will have to be removed. (Buggy version = 39)
|
|
- */
|
|
- if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) )
|
|
- {
|
|
- lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected");
|
|
- rc = HPMFWUPG_UPLOAD_RETRY;
|
|
- }
|
|
- /*
|
|
- * If completion code = 0xc7, we will retry with a reduced buffer length.
|
|
- * Do not print error.
|
|
- */
|
|
- else if ( rsp->ccode == IPMI_CC_REQ_DATA_INV_LENGTH )
|
|
- {
|
|
- rc = HPMFWUPG_UPLOAD_BLOCK_LENGTH;
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error uploading firmware block");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error uploading firmware block\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- return rc;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ pCtx->req->picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_UPLOAD_FIRMWARE_BLOCK;
|
|
+ req.msg.data = (unsigned char *)pCtx->req;
|
|
+ /* 2 is the size of the upload struct - data */
|
|
+ req.msg.data_len = 2 + count;
|
|
+ rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_NOTICE, "Error uploading firmware block.");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS
|
|
+ || rsp->ccode == 0x00) {
|
|
+ /*
|
|
+ * We need to check if the response also contains the next upload firmware offset
|
|
+ * and the firmware length in its response - These are optional but very vital
|
|
+ */
|
|
+ if (rsp->data_len > 1) {
|
|
+ /*
|
|
+ * If the response data length is greater than 1 it should contain both the
|
|
+ * the Section offset and section length. Because we cannot just have
|
|
+ * Section offset without section length so the length should be 9
|
|
+ */
|
|
+ if (rsp->data_len == 9) {
|
|
+ /* rsp->data[1] - LSB rsp->data[2] - rsp->data[3] = MSB */
|
|
+ *imageOffset = (rsp->data[4] << 24) + (rsp->data[3] << 16) + (rsp->data[2] << 8) + rsp->data[1];
|
|
+ *blockLength = (rsp->data[8] << 24) + (rsp->data[7] << 16) + (rsp->data[6] << 8) + rsp->data[5];
|
|
+ } else {
|
|
+ /*
|
|
+ * The Spec does not say much for this kind of errors where the
|
|
+ * firmware returned only offset and length so currently returning it
|
|
+ * as 0x82 - Internal CheckSum Error
|
|
+ */
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Error wrong rsp->datalen %d for Upload Firmware block command\n",
|
|
+ rsp->data_len);
|
|
+ rsp->ccode = HPMFWUPG_INT_CHECKSUM_ERROR;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /* Long duration command handling */
|
|
+ if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) {
|
|
+ rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
+ } else if (rsp->ccode != 0x00) {
|
|
+ /* PATCH --> This validation is to handle retryables errors codes on IPMB bus.
|
|
+ * This will be fixed in the next release of open ipmi and this
|
|
+ * check will have to be removed. (Buggy version = 39)
|
|
+ */
|
|
+ if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) {
|
|
+ lprintf(LOG_DEBUG, "HPM: [PATCH]Retryable error detected");
|
|
+ rc = HPMFWUPG_UPLOAD_RETRY;
|
|
+ } else if (rsp->ccode == IPMI_CC_REQ_DATA_INV_LENGTH ||
|
|
+ rsp->ccode == IPMI_CC_REQ_DATA_FIELD_EXCEED) {
|
|
+ /* If completion code = 0xc7(0xc8), we will retry with a reduced buffer length.
|
|
+ * Do not print error.
|
|
+ */
|
|
+ rc = HPMFWUPG_UPLOAD_BLOCK_LENGTH;
|
|
+ } else {
|
|
+ lprintf(LOG_ERR, "Error uploading firmware block");
|
|
+ lprintf(LOG_ERR, "compcode=0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode,
|
|
+ completion_code_vals));
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-int HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf, struct HpmfwupgFinishFirmwareUploadCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
+int
|
|
+HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgFinishFirmwareUploadCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx, int option)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_FINISH_FIRMWARE_UPLOAD;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_FINISH_FIRMWARE_UPLOAD;
|
|
+ req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgFinishFirmwareUploadReq);
|
|
-
|
|
- rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- /* Long duration command handling */
|
|
- if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
|
|
- {
|
|
- rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
- }
|
|
- else if ( rsp->ccode != IPMI_CC_OK )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error finishing firmware upload");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error fininshing firmware upload\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- return rc;
|
|
+ rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Error fininshing firmware upload.");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Long duration command handling */
|
|
+ if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) {
|
|
+ rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
+ } else if ((option & COMPARE_MODE) && rsp->ccode == 0x83) {
|
|
+ printf("| |Component's active copy doesn't match the upgrade image |\n");
|
|
+ } else if ((option & COMPARE_MODE) && rsp->ccode == IPMI_CC_OK) {
|
|
+ printf("| |Comparison passed |\n");
|
|
+ } else if ( rsp->ccode != IPMI_CC_OK ) {
|
|
+ lprintf(LOG_ERR, "Error finishing firmware upload");
|
|
+ lprintf(LOG_ERR, "compcode=0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-int HpmfwupgActivateFirmware(struct ipmi_intf *intf, struct HpmfwupgActivateFirmwareCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
+int
|
|
+HpmfwupgActivateFirmware(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgActivateFirmwareCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_ACTIVATE_FIRMWARE;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
- req.msg.data_len = sizeof(struct HpmfwupgActivateFirmwareReq) -
|
|
- (!pCtx->req.rollback_override ? 1 : 0);
|
|
-
|
|
- rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- /* Long duration command handling */
|
|
- if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
|
|
- {
|
|
- printf("Waiting firmware activation...");
|
|
- fflush(stdout);
|
|
-
|
|
- rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
-
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"OK");
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Failed");
|
|
- }
|
|
- }
|
|
- else if ( rsp->ccode != IPMI_CC_OK )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error activating firmware");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error activating firmware\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- return rc;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_ACTIVATE_FIRMWARE;
|
|
+ req.msg.data = (unsigned char*)&pCtx->req;
|
|
+ req.msg.data_len = sizeof(struct HpmfwupgActivateFirmwareReq)
|
|
+ - (!pCtx->req.rollback_override ? 1 : 0);
|
|
+ rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Error activating firmware.");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Long duration command handling */
|
|
+ if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) {
|
|
+ printf("Waiting firmware activation...");
|
|
+ fflush(stdout);
|
|
+ rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ lprintf(LOG_NOTICE, "OK");
|
|
+ } else {
|
|
+ lprintf(LOG_NOTICE, "Failed");
|
|
+ }
|
|
+ } else if (rsp->ccode != IPMI_CC_OK) {
|
|
+ lprintf(LOG_ERR, "Error activating firmware");
|
|
+ lprintf(LOG_ERR, "compcode=0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-int HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf,
|
|
- struct HpmfwupgGetUpgradeStatusCtx *pCtx,
|
|
- struct HpmfwupgUpgradeCtx *pFwupgCtx,
|
|
- int silent)
|
|
+int
|
|
+HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgGetUpgradeStatusCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx,
|
|
+ int silent)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_GET_UPGRADE_STATUS;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_GET_UPGRADE_STATUS;
|
|
+ req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgGetUpgradeStatusReq);
|
|
-
|
|
rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
- if (!rsp){
|
|
+ if (!rsp) {
|
|
lprintf(LOG_NOTICE,
|
|
- "Error getting upgrade status. Failed to get response.");
|
|
+ "Error getting upgrade status. Failed to get response.");
|
|
return HPMFWUPG_ERROR;
|
|
}
|
|
-
|
|
- if ( rsp->ccode == 0x00 ) {
|
|
+ if (rsp->ccode == 0x00) {
|
|
memcpy(&pCtx->resp, rsp->data,
|
|
- sizeof(struct HpmfwupgGetUpgradeStatusResp));
|
|
- if (!silent)
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Upgrade status:");
|
|
- lprintf(LOG_NOTICE," Command in progress: %x",
|
|
- pCtx->resp.cmdInProcess);
|
|
- lprintf(LOG_NOTICE," Last command completion code: %x",
|
|
- pCtx->resp.lastCmdCompCode);
|
|
- }
|
|
- } else if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) {
|
|
- /*
|
|
- * PATCH --> This validation is to handle retryable errors
|
|
+ sizeof(struct HpmfwupgGetUpgradeStatusResp));
|
|
+ if (!silent) {
|
|
+ lprintf(LOG_NOTICE, "Upgrade status:");
|
|
+ lprintf(LOG_NOTICE,
|
|
+ " Command in progress: %x",
|
|
+ pCtx->resp.cmdInProcess);
|
|
+ lprintf(LOG_NOTICE,
|
|
+ " Last command completion code: %x",
|
|
+ pCtx->resp.lastCmdCompCode);
|
|
+ }
|
|
+ } else if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) {
|
|
+ /* PATCH --> This validation is to handle retryable errors
|
|
* codes on the IPMB bus.
|
|
* This will be fixed in the next release of
|
|
* open ipmi and this check can be removed.
|
|
* (Buggy version = 39)
|
|
*/
|
|
- if (!silent)
|
|
- {
|
|
- lprintf(LOG_DEBUG,"HPM: Retryable error detected");
|
|
- }
|
|
+ if (!silent) {
|
|
+ lprintf(LOG_DEBUG, "HPM: Retryable error detected");
|
|
+ }
|
|
pCtx->resp.lastCmdCompCode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
} else {
|
|
- lprintf(LOG_NOTICE,"Error getting upgrade status");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
+ lprintf(LOG_NOTICE, "Error getting upgrade status");
|
|
+ lprintf(LOG_NOTICE, "compcode=0x%x: %s", rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
return HPMFWUPG_ERROR;
|
|
}
|
|
-
|
|
return HPMFWUPG_SUCCESS;
|
|
}
|
|
|
|
-int HpmfwupgManualFirmwareRollback(struct ipmi_intf *intf, struct HpmfwupgManualFirmwareRollbackCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
-{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
-
|
|
- pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
+int
|
|
+HpmfwupgManualFirmwareRollback(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgManualFirmwareRollbackCtx *pCtx)
|
|
+{
|
|
+ struct HpmfwupgUpgradeCtx fwupgCtx;
|
|
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ /* prepare fake upgrade context */
|
|
+ memset(&fwupgCtx, 0, sizeof (fwupgCtx));
|
|
+ verbose--;
|
|
+ rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd);
|
|
+ verbose++;
|
|
+ if (rc != HPMFWUPG_SUCCESS) {
|
|
+ return rc;
|
|
+ }
|
|
+ memcpy(&fwupgCtx.targetCap, &targetCapCmd.resp, sizeof(targetCapCmd.resp));
|
|
+ pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK;
|
|
+ req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgManualFirmwareRollbackReq);
|
|
-
|
|
- rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- /* Long duration command handling */
|
|
- if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
|
|
- {
|
|
- struct HpmfwupgQueryRollbackStatusCtx resCmd;
|
|
- printf("Waiting firmware rollback...");
|
|
- fflush(stdout);
|
|
- rc = HpmfwupgQueryRollbackStatus(intf, &resCmd, pFwupgCtx);
|
|
- }
|
|
- else if ( rsp->ccode != 0x00 )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error sending manual rollback");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error sending manual rollback\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- return rc;
|
|
+ rsp = HpmfwupgSendCmd(intf, req, &fwupgCtx);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Error sending manual rollback.");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ /* Long duration command handling */
|
|
+ if (rsp->ccode == IPMI_CC_OK
|
|
+ || rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) {
|
|
+ struct HpmfwupgQueryRollbackStatusCtx resCmd;
|
|
+ printf("Waiting firmware rollback...");
|
|
+ fflush(stdout);
|
|
+ rc = HpmfwupgQueryRollbackStatus(intf, &resCmd, &fwupgCtx);
|
|
+ } else if ( rsp->ccode != 0x00 ) {
|
|
+ lprintf(LOG_ERR, "Error sending manual rollback");
|
|
+ lprintf(LOG_ERR, "compcode=0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-int HpmfwupgQueryRollbackStatus(struct ipmi_intf *intf, struct HpmfwupgQueryRollbackStatusCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
+int
|
|
+HpmfwupgQueryRollbackStatus(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgQueryRollbackStatusCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- unsigned int rollbackTimeout = 0;
|
|
- unsigned int timeoutSec1, timeoutSec2;
|
|
-
|
|
- pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_QUERY_ROLLBACK_STATUS;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned int rollbackTimeout = 0;
|
|
+ unsigned int timeoutSec1, timeoutSec2;
|
|
+ pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_QUERY_ROLLBACK_STATUS;
|
|
+ req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgQueryRollbackStatusReq);
|
|
-
|
|
- /*
|
|
- * If we are not in upgrade context, we use default timeout values
|
|
- */
|
|
- if ( pFwupgCtx != NULL )
|
|
- {
|
|
- rollbackTimeout = pFwupgCtx->targetCap.rollbackTimeout*5;
|
|
- }
|
|
- else
|
|
- {
|
|
- struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
- verbose--;
|
|
- rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd);
|
|
- verbose++;
|
|
- if ( rc == HPMFWUPG_SUCCESS )
|
|
- {
|
|
- rollbackTimeout = targetCapCmd.resp.rollbackTimeout *5;
|
|
- }
|
|
- else
|
|
- {
|
|
- rollbackTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
- }
|
|
- }
|
|
-
|
|
- /* Poll rollback status until completion or timeout */
|
|
- timeoutSec1 = time(NULL);
|
|
- timeoutSec2 = time(NULL);
|
|
- do
|
|
- {
|
|
- /* Must wait at least 100 ms between status requests */
|
|
- usleep(100000);
|
|
- rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
- /*
|
|
- * PATCH --> This validation is to handle retryables errors codes on IPMB bus.
|
|
- * This will be fixed in the next release of open ipmi and this
|
|
- * check will have to be removed. (Buggy version = 39)
|
|
- */
|
|
- if ( rsp )
|
|
- {
|
|
- if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) )
|
|
- {
|
|
- lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected");
|
|
- rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
- }
|
|
- }
|
|
- timeoutSec2 = time(NULL);
|
|
-
|
|
- }while( rsp &&
|
|
- ((rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) ||
|
|
- (rsp->ccode == IPMI_CC_TIMEOUT)) &&
|
|
- (timeoutSec2 - timeoutSec1 < rollbackTimeout ) );
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- if ( rsp->ccode == 0x00 )
|
|
- {
|
|
- memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgQueryRollbackStatusResp));
|
|
- if ( pCtx->resp.rollbackComp.ComponentBits.byte != 0 )
|
|
- {
|
|
- /* Rollback occured */
|
|
- lprintf(LOG_NOTICE,"Rollback occured on component mask: 0x%02x",
|
|
- pCtx->resp.rollbackComp.ComponentBits.byte);
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"No Firmware rollback occured");
|
|
- }
|
|
- }
|
|
- else if ( rsp->ccode == 0x81 )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Rollback failed on component mask: 0x%02x",
|
|
- pCtx->resp.rollbackComp.ComponentBits.byte);
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error getting rollback status");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error getting upgrade status\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- return rc;
|
|
+ /* If we are not in upgrade context, we use default timeout values */
|
|
+ if (pFwupgCtx != NULL) {
|
|
+ struct HpmfwupgImageHeader *pImageHeader;
|
|
+ if (pFwupgCtx->pImageData) {
|
|
+ pImageHeader = (struct HpmfwupgImageHeader*)pFwupgCtx->pImageData;
|
|
+ rollbackTimeout = pImageHeader->rollbackTimeout;
|
|
+ } else {
|
|
+ rollbackTimeout = 0;
|
|
+ }
|
|
+ /* Use the greater of the two timeouts (header and target caps) */
|
|
+ rollbackTimeout = MAX(rollbackTimeout,
|
|
+ pFwupgCtx->targetCap.rollbackTimeout) * 5;
|
|
+ } else {
|
|
+ rollbackTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
+ }
|
|
+ /* Poll rollback status until completion or timeout */
|
|
+ timeoutSec1 = time(NULL);
|
|
+ timeoutSec2 = time(NULL);
|
|
+ do {
|
|
+ /* Must wait at least 100 ms between status requests */
|
|
+ usleep(100000);
|
|
+ rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
+ /* PATCH --> This validation is to handle retryables errors codes on IPMB bus.
|
|
+ * This will be fixed in the next release of open ipmi and this
|
|
+ * check will have to be removed. (Buggy version = 39)
|
|
+ */
|
|
+ if (rsp) {
|
|
+ if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) {
|
|
+ lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected");
|
|
+ rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
+ }
|
|
+ }
|
|
+ timeoutSec2 = time(NULL);
|
|
+ } while (rsp
|
|
+ && ((rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS)
|
|
+ || (rsp->ccode == IPMI_CC_TIMEOUT))
|
|
+ && (timeoutSec2 - timeoutSec1 < rollbackTimeout));
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, "Error getting upgrade status.");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if (rsp->ccode == 0x00) {
|
|
+ memcpy(&pCtx->resp, rsp->data,
|
|
+ sizeof(struct HpmfwupgQueryRollbackStatusResp));
|
|
+ if (pCtx->resp.rollbackComp.ComponentBits.byte != 0) {
|
|
+ /* Rollback occured */
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Rollback occured on component mask: 0x%02x",
|
|
+ pCtx->resp.rollbackComp.ComponentBits.byte);
|
|
+ } else {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "No Firmware rollback occured");
|
|
+ }
|
|
+ } else if (rsp->ccode == 0x81) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Rollback failed on component mask: 0x%02x",
|
|
+ pCtx->resp.rollbackComp.ComponentBits.byte);
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ } else {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Error getting rollback status");
|
|
+ lprintf(LOG_ERR,
|
|
+ "compcode=0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-int HpmfwupgQuerySelftestResult(struct ipmi_intf *intf, struct HpmfwupgQuerySelftestResultCtx* pCtx,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
+int
|
|
+HpmfwupgQuerySelftestResult(struct ipmi_intf *intf, struct HpmfwupgQuerySelftestResultCtx *pCtx,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx)
|
|
{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- struct ipmi_rs * rsp;
|
|
- struct ipmi_rq req;
|
|
- unsigned char selfTestTimeout = 0;
|
|
- unsigned int timeoutSec1, timeoutSec2;
|
|
-
|
|
- pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
-
|
|
- /*
|
|
- * If we are not in upgrade context, we use default timeout values
|
|
- */
|
|
- if ( pFwupgCtx != NULL )
|
|
- {
|
|
- /* Getting selftest timeout from new image */
|
|
- struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
|
|
- pFwupgCtx->pImageData;
|
|
- selfTestTimeout = pImageHeader->selfTestTimeout;
|
|
- }
|
|
- else
|
|
- {
|
|
- selfTestTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
- }
|
|
-
|
|
- memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_PICMG;
|
|
- req.msg.cmd = HPMFWUPG_QUERY_SELFTEST_RESULT;
|
|
- req.msg.data = (unsigned char*)&pCtx->req;
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ unsigned char selfTestTimeout = 0;
|
|
+ unsigned int timeoutSec1, timeoutSec2;
|
|
+ pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
+ /* If we are not in upgrade context, we use default timeout values */
|
|
+ if (pFwupgCtx != NULL) {
|
|
+ /* Getting selftest timeout from new image */
|
|
+ struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*)
|
|
+ pFwupgCtx->pImageData;
|
|
+ selfTestTimeout = MAX(pImageHeader->selfTestTimeout,
|
|
+ pFwupgCtx->targetCap.selftestTimeout) * 5;
|
|
+ } else {
|
|
+ selfTestTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
+ }
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = IPMI_NETFN_PICMG;
|
|
+ req.msg.cmd = HPMFWUPG_QUERY_SELFTEST_RESULT;
|
|
+ req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgQuerySelftestResultReq);
|
|
-
|
|
-
|
|
- /* Poll rollback status until completion or timeout */
|
|
- timeoutSec1 = time(NULL);
|
|
- timeoutSec2 = time(NULL);
|
|
- do
|
|
- {
|
|
- /* Must wait at least 100 ms between status requests */
|
|
- usleep(100000);
|
|
- rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
- /*
|
|
- * PATCH --> This validation is to handle retryables errors codes on IPMB bus.
|
|
- * This will be fixed in the next release of open ipmi and this
|
|
- * check will have to be removed. (Buggy version = 39)
|
|
- */
|
|
- if ( rsp )
|
|
- {
|
|
- if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) )
|
|
- {
|
|
- lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected");
|
|
- rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
- }
|
|
- }
|
|
- timeoutSec2 = time(NULL);
|
|
-
|
|
- }while( rsp &&
|
|
- (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) &&
|
|
- (timeoutSec2 - timeoutSec1 < selfTestTimeout ) );
|
|
-
|
|
- if ( rsp )
|
|
- {
|
|
- if ( rsp->ccode == 0x00 )
|
|
- {
|
|
- memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgQuerySelftestResultResp));
|
|
- if ( verbose )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Self test results:");
|
|
- lprintf(LOG_NOTICE,"Result1 = %x", pCtx->resp.result1);
|
|
- lprintf(LOG_NOTICE,"Result2 = %x", pCtx->resp.result2);
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error getting self test results");
|
|
- lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
- rsp->ccode,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error getting upgrade status\n");
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- return rc;
|
|
+ /* Poll rollback status until completion or timeout */
|
|
+ timeoutSec1 = time(NULL);
|
|
+ timeoutSec2 = time(NULL);
|
|
+ do {
|
|
+ /* Must wait at least 100 ms between status requests */
|
|
+ usleep(100000);
|
|
+ rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
+ /* PATCH --> This validation is to handle retryables errors codes on IPMB bus.
|
|
+ * This will be fixed in the next release of open ipmi and this
|
|
+ * check will have to be removed. (Buggy version = 39)
|
|
+ */
|
|
+ if (rsp) {
|
|
+ if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) {
|
|
+ lprintf(LOG_DEBUG,
|
|
+ "HPM: [PATCH]Retryable error detected");
|
|
+ rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
+ }
|
|
+ }
|
|
+ timeoutSec2 = time(NULL);
|
|
+ } while (rsp
|
|
+ && (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS)
|
|
+ && (timeoutSec2 - timeoutSec1 < selfTestTimeout));
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_NOTICE, "Error getting upgrade status\n");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if (rsp->ccode == 0x00) {
|
|
+ memcpy(&pCtx->resp, rsp->data,
|
|
+ sizeof(struct HpmfwupgQuerySelftestResultResp));
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE, "Self test results:");
|
|
+ lprintf(LOG_NOTICE, "Result1 = %x",
|
|
+ pCtx->resp.result1);
|
|
+ lprintf(LOG_NOTICE, "Result2 = %x",
|
|
+ pCtx->resp.result2);
|
|
+ }
|
|
+ } else {
|
|
+ lprintf(LOG_NOTICE, "Error getting self test results");
|
|
+ lprintf(LOG_NOTICE, "compcode=0x%x: %s",
|
|
+ rsp->ccode,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-struct ipmi_rs * HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req,
|
|
- struct HpmfwupgUpgradeCtx* pFwupgCtx )
|
|
-{
|
|
- struct ipmi_rs * rsp;
|
|
- unsigned int inaccessTimeout = 0, inaccessTimeoutCounter = 0;
|
|
- unsigned int upgradeTimeout = 0, upgradeTimeoutCounter = 0;
|
|
- unsigned int timeoutSec1, timeoutSec2;
|
|
- unsigned char retry = 0;
|
|
-
|
|
- /*
|
|
- * If we are not in upgrade context, we use default timeout values
|
|
- */
|
|
- if ( pFwupgCtx != NULL )
|
|
- {
|
|
- inaccessTimeout = pFwupgCtx->targetCap.inaccessTimeout*5;
|
|
- upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5;
|
|
- }
|
|
- else
|
|
- {
|
|
- /* keeping the inaccessTimeout to 60 seconds results in almost 2900 retries
|
|
- * So if the target is not available it will be retrying the command for 2900
|
|
- * times which is not effecient -So reducing the Timout to 5 seconds which is
|
|
- * almost 200 retries if it continuously recieves 0xC3 as completion code.
|
|
- */
|
|
- inaccessTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
- upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
- }
|
|
-
|
|
- timeoutSec1 = time(NULL);
|
|
-
|
|
- do
|
|
- {
|
|
- static unsigned char isValidSize = FALSE;
|
|
- rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if( ( rsp == NULL ) )
|
|
- {
|
|
- #define HPM_LAN_PACKET_RESIZE_LIMIT 6
|
|
-
|
|
- if(strstr(intf->name,"lan")!= NULL) /* also covers lanplus */
|
|
- {
|
|
- static int errorCount=0;
|
|
- static struct ipmi_rs fakeRsp;
|
|
-
|
|
- lprintf(LOG_DEBUG,"HPM: no response available");
|
|
- lprintf(LOG_DEBUG,"HPM: the command may be rejected for " \
|
|
- "security reasons");
|
|
-
|
|
- if
|
|
- (
|
|
- req.msg.netfn == IPMI_NETFN_PICMG
|
|
- &&
|
|
- req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK
|
|
- &&
|
|
- errorCount < HPM_LAN_PACKET_RESIZE_LIMIT
|
|
- &&
|
|
- (!isValidSize)
|
|
- )
|
|
- {
|
|
- lprintf(LOG_DEBUG,"HPM: upload firmware block API called");
|
|
- lprintf(LOG_DEBUG,"HPM: returning length error to force resize");
|
|
-
|
|
- fakeRsp.ccode = IPMI_CC_REQ_DATA_INV_LENGTH;
|
|
- rsp = &fakeRsp;
|
|
- errorCount++;
|
|
- }
|
|
- else if
|
|
- (
|
|
- req.msg.netfn == IPMI_NETFN_PICMG
|
|
- &&
|
|
- ( req.msg.cmd == HPMFWUPG_ACTIVATE_FIRMWARE ||
|
|
- req.msg.cmd == HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK )
|
|
- )
|
|
- {
|
|
- /*
|
|
- * rsp == NULL and command activate firmware or manual firmware
|
|
- * rollback most likely occurs when we have sent a firmware activation
|
|
- * request. Fake a command in progress response.
|
|
- */
|
|
- lprintf(LOG_DEBUG,"HPM: activate/rollback firmware API called");
|
|
- lprintf(LOG_DEBUG,"HPM: returning in progress to handle IOL session lost");
|
|
-
|
|
- fakeRsp.ccode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
- rsp = &fakeRsp;
|
|
- }
|
|
- else if
|
|
- (
|
|
- req.msg.netfn == IPMI_NETFN_PICMG
|
|
- &&
|
|
- ( req.msg.cmd == HPMFWUPG_QUERY_ROLLBACK_STATUS ||
|
|
- req.msg.cmd == HPMFWUPG_GET_UPGRADE_STATUS )
|
|
- )
|
|
- {
|
|
- /*
|
|
- * rsp == NULL and command get upgrade status or query rollback
|
|
- * status most likely occurs when we are waiting for firmware
|
|
- * activation. Try to re-open the IOL session (re-open will work
|
|
- * once the IPMC recovers from firmware activation.
|
|
- */
|
|
-
|
|
- lprintf(LOG_DEBUG,"HPM: upg/rollback status firmware API called");
|
|
- lprintf(LOG_DEBUG,"HPM: try to re-open IOL session");
|
|
-
|
|
- {
|
|
- /* force session re-open */
|
|
- intf->opened = 0;
|
|
- intf->session->authtype = IPMI_SESSION_AUTHTYPE_NONE;
|
|
- intf->session->session_id = 0;
|
|
- intf->session->in_seq = 0;
|
|
- intf->session->out_seq = 0;
|
|
- intf->session->active = 0;
|
|
- intf->session->retry = 10;
|
|
-
|
|
- while
|
|
- (
|
|
- intf->open(intf) == HPMFWUPG_ERROR
|
|
- &&
|
|
- inaccessTimeoutCounter < inaccessTimeout
|
|
- )
|
|
- {
|
|
- inaccessTimeoutCounter += (time(NULL) - timeoutSec1);
|
|
- timeoutSec1 = time(NULL);
|
|
- }
|
|
- /* Fake timeout to retry command */
|
|
- fakeRsp.ccode = 0xc3;
|
|
- rsp = &fakeRsp;
|
|
- }
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* Handle inaccessibility timeout (rsp = NULL if IOL) */
|
|
- if ( rsp == NULL || rsp->ccode == 0xff || rsp->ccode == 0xc3 || rsp->ccode == 0xd3 )
|
|
- {
|
|
- if ( inaccessTimeoutCounter < inaccessTimeout )
|
|
- {
|
|
- timeoutSec2 = time(NULL);
|
|
- if ( timeoutSec2 > timeoutSec1 )
|
|
- {
|
|
- inaccessTimeoutCounter += timeoutSec2 - timeoutSec1;
|
|
- timeoutSec1 = time(NULL);
|
|
- }
|
|
- usleep(100000);
|
|
- retry = 1;
|
|
- }
|
|
- else
|
|
- {
|
|
- retry = 0;
|
|
- }
|
|
- }
|
|
- /* Handle node busy timeout */
|
|
- else if ( rsp->ccode == 0xc0 )
|
|
- {
|
|
- if ( upgradeTimeoutCounter < upgradeTimeout )
|
|
- {
|
|
- timeoutSec2 = time(NULL);
|
|
- if ( timeoutSec2 > timeoutSec1 )
|
|
- {
|
|
- timeoutSec1 = time(NULL);
|
|
- upgradeTimeoutCounter += timeoutSec2 - timeoutSec1;
|
|
- }
|
|
- usleep(100000);
|
|
- retry = 1;
|
|
- }
|
|
- else
|
|
- {
|
|
- retry = 0;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- #ifdef ENABLE_OPENIPMI_V39_PATCH
|
|
- if( rsp->ccode == IPMI_CC_OK )
|
|
- {
|
|
- errorCount = 0 ;
|
|
- }
|
|
- #endif
|
|
- retry = 0;
|
|
-
|
|
- if
|
|
- (
|
|
- req.msg.netfn == IPMI_NETFN_PICMG
|
|
- &&
|
|
- req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK
|
|
- &&
|
|
- (!isValidSize)
|
|
- )
|
|
- {
|
|
- lprintf(LOG_INFO,"Buffer length is now considered valid" );
|
|
-
|
|
- isValidSize = TRUE;
|
|
+struct ipmi_rs *
|
|
+HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ unsigned int inaccessTimeout = 0, inaccessTimeoutCounter = 0;
|
|
+ unsigned int upgradeTimeout = 0, upgradeTimeoutCounter = 0;
|
|
+ unsigned int timeoutSec1, timeoutSec2;
|
|
+ unsigned char retry = 0;
|
|
+ /* If we are not in upgrade context, we use default timeout values */
|
|
+ if (pFwupgCtx != NULL) {
|
|
+ inaccessTimeout = pFwupgCtx->targetCap.inaccessTimeout*5;
|
|
+ upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5;
|
|
+ } else {
|
|
+ /* keeping the inaccessTimeout to 60 seconds results in almost 2900 retries
|
|
+ * So if the target is not available it will be retrying the command for 2900
|
|
+ * times which is not effecient -So reducing the Timout to 5 seconds which is
|
|
+ * almost 200 retries if it continuously recieves 0xC3 as completion code.
|
|
+ */
|
|
+ inaccessTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
+ upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
}
|
|
- }
|
|
- }while( retry );
|
|
- return rsp;
|
|
+ timeoutSec1 = time(NULL);
|
|
+ do {
|
|
+ static unsigned char isValidSize = FALSE;
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ #define HPM_LAN_PACKET_RESIZE_LIMIT 6
|
|
+ /* also covers lanplus */
|
|
+ if (strstr(intf->name, "lan") != NULL) {
|
|
+ static int errorCount=0;
|
|
+ static struct ipmi_rs fakeRsp;
|
|
+ lprintf(LOG_DEBUG,
|
|
+ "HPM: no response available");
|
|
+ lprintf(LOG_DEBUG,
|
|
+ "HPM: the command may be rejected for security reasons");
|
|
+ if (req.msg.netfn == IPMI_NETFN_PICMG
|
|
+ && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK
|
|
+ && errorCount < HPM_LAN_PACKET_RESIZE_LIMIT
|
|
+ && (!isValidSize)) {
|
|
+ lprintf(LOG_DEBUG,
|
|
+ "HPM: upload firmware block API called");
|
|
+ lprintf(LOG_DEBUG,
|
|
+ "HPM: returning length error to force resize");
|
|
+ fakeRsp.ccode = IPMI_CC_REQ_DATA_INV_LENGTH;
|
|
+ rsp = &fakeRsp;
|
|
+ errorCount++;
|
|
+ } else if (req.msg.netfn == IPMI_NETFN_PICMG
|
|
+ && (req.msg.cmd == HPMFWUPG_ACTIVATE_FIRMWARE
|
|
+ || req.msg.cmd == HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK)) {
|
|
+ /*
|
|
+ * rsp == NULL and command activate firmware or manual firmware
|
|
+ * rollback most likely occurs when we have sent a firmware activation
|
|
+ * request. Fake a command in progress response.
|
|
+ */
|
|
+ lprintf(LOG_DEBUG,
|
|
+ "HPM: activate/rollback firmware API called");
|
|
+ lprintf(LOG_DEBUG,
|
|
+ "HPM: returning in progress to handle IOL session lost");
|
|
+ fakeRsp.ccode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
+ rsp = &fakeRsp;
|
|
+ } else if (req.msg.netfn == IPMI_NETFN_PICMG
|
|
+ && (req.msg.cmd == HPMFWUPG_QUERY_ROLLBACK_STATUS
|
|
+ || req.msg.cmd == HPMFWUPG_GET_UPGRADE_STATUS
|
|
+ || req.msg.cmd == HPMFWUPG_QUERY_SELFTEST_RESULT)
|
|
+ && ( !intf->target_addr || intf->target_addr == intf->my_addr)) {
|
|
+ /* reopen session only if target IPMC is directly accessed */
|
|
+ /*
|
|
+ * rsp == NULL and command get upgrade status or query rollback
|
|
+ * status most likely occurs when we are waiting for firmware
|
|
+ * activation. Try to re-open the IOL session (re-open will work
|
|
+ * once the IPMC recovers from firmware activation.
|
|
+ */
|
|
+ lprintf(LOG_DEBUG, "HPM: upg/rollback status firmware API called");
|
|
+ lprintf(LOG_DEBUG, "HPM: try to re-open IOL session");
|
|
+ {
|
|
+ /* force session re-open */
|
|
+ intf->opened = 0;
|
|
+ intf->session->authtype = IPMI_SESSION_AUTHTYPE_NONE;
|
|
+ intf->session->session_id = 0;
|
|
+ intf->session->in_seq = 0;
|
|
+ intf->session->out_seq = 0;
|
|
+ intf->session->active = 0;
|
|
+ intf->session->retry = 10;
|
|
+ while (intf->open(intf) == HPMFWUPG_ERROR
|
|
+ && inaccessTimeoutCounter < inaccessTimeout) {
|
|
+ inaccessTimeoutCounter += (time(NULL) - timeoutSec1);
|
|
+ timeoutSec1 = time(NULL);
|
|
+ }
|
|
+ /* Fake timeout to retry command */
|
|
+ fakeRsp.ccode = 0xc3;
|
|
+ rsp = &fakeRsp;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /* Handle inaccessibility timeout (rsp = NULL if IOL) */
|
|
+ if (rsp == NULL || rsp->ccode == 0xff || rsp->ccode == 0xc3 || rsp->ccode == 0xd3) {
|
|
+ if (inaccessTimeoutCounter < inaccessTimeout) {
|
|
+ timeoutSec2 = time(NULL);
|
|
+ if (timeoutSec2 > timeoutSec1) {
|
|
+ inaccessTimeoutCounter += timeoutSec2 - timeoutSec1;
|
|
+ timeoutSec1 = time(NULL);
|
|
+ }
|
|
+ usleep(100000);
|
|
+ retry = 1;
|
|
+ } else {
|
|
+ retry = 0;
|
|
+ }
|
|
+ } else if ( rsp->ccode == 0xc0 ) {
|
|
+ /* Handle node busy timeout */
|
|
+ if (upgradeTimeoutCounter < upgradeTimeout) {
|
|
+ timeoutSec2 = time(NULL);
|
|
+ if (timeoutSec2 > timeoutSec1) {
|
|
+ timeoutSec1 = time(NULL);
|
|
+ upgradeTimeoutCounter += timeoutSec2 - timeoutSec1;
|
|
+ }
|
|
+ usleep(100000);
|
|
+ retry = 1;
|
|
+ } else {
|
|
+ retry = 0;
|
|
+ }
|
|
+ } else {
|
|
+# ifdef ENABLE_OPENIPMI_V39_PATCH
|
|
+ if (rsp->ccode == IPMI_CC_OK) {
|
|
+ errorCount = 0 ;
|
|
+ }
|
|
+# endif
|
|
+ retry = 0;
|
|
+ if (req.msg.netfn == IPMI_NETFN_PICMG
|
|
+ && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK
|
|
+ && (!isValidSize)) {
|
|
+ lprintf(LOG_INFO,
|
|
+ "Buffer length is now considered valid");
|
|
+ isValidSize = TRUE;
|
|
+ }
|
|
+ }
|
|
+ } while (retry);
|
|
+ return rsp;
|
|
}
|
|
|
|
-int HpmfwupgWaitLongDurationCmd(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
-{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- unsigned int upgradeTimeout = 0;
|
|
- unsigned int timeoutSec1, timeoutSec2;
|
|
- struct HpmfwupgGetUpgradeStatusCtx upgStatusCmd;
|
|
-
|
|
- /*
|
|
- * If we are not in upgrade context, we use default timeout values
|
|
- */
|
|
- if ( pFwupgCtx != NULL )
|
|
- {
|
|
- upgradeTimeout = (unsigned int)(pFwupgCtx->targetCap.upgradeTimeout*5);
|
|
- if ( verbose )
|
|
- printf("Use File Upgrade Capabilities: %i seconds\n", upgradeTimeout);
|
|
- }
|
|
- else
|
|
- {
|
|
- /* Try to retreive from Caps */
|
|
- struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
-
|
|
- if(HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd) != HPMFWUPG_SUCCESS)
|
|
- {
|
|
- upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
-
|
|
- if ( verbose )
|
|
- printf("Use default timeout: %i seconds\n", upgradeTimeout);
|
|
- }
|
|
- else
|
|
- {
|
|
- upgradeTimeout = (unsigned int)(targetCapCmd.resp.upgradeTimeout * 5);
|
|
- if ( verbose )
|
|
- printf("Use Command Upgrade Capabilities Timeout: %i seconds\n", upgradeTimeout);
|
|
- }
|
|
- }
|
|
-
|
|
- if(rc == HPMFWUPG_SUCCESS)
|
|
- {
|
|
- /* Poll upgrade status until completion or timeout*/
|
|
- timeoutSec1 = time(NULL);
|
|
- timeoutSec2 = time(NULL);
|
|
- rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx, 1);
|
|
- }
|
|
-
|
|
- while(
|
|
- //With KCS: Cover the case where we sometime receive d5 (on the first get status) from the ipmi driver.
|
|
- (upgStatusCmd.resp.lastCmdCompCode != 0x00 ) &&
|
|
- ((timeoutSec2 - timeoutSec1) < upgradeTimeout ) &&
|
|
- (rc == HPMFWUPG_SUCCESS)
|
|
- )
|
|
- {
|
|
- /* Must wait at least 1000 ms between status requests */
|
|
- usleep(1000000);
|
|
- timeoutSec2 = time(NULL);
|
|
- rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx, 1);
|
|
- //printf("Get Status: %x - %x = %x _ %x [%x]\n", timeoutSec2, timeoutSec1,(timeoutSec2 - timeoutSec1),upgradeTimeout, rc);
|
|
- }
|
|
-
|
|
- if ( upgStatusCmd.resp.lastCmdCompCode != 0x00 )
|
|
- {
|
|
- if ( verbose )
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Error waiting for command %x, compcode = %x",
|
|
- upgStatusCmd.resp.cmdInProcess,
|
|
- upgStatusCmd.resp.lastCmdCompCode);
|
|
- }
|
|
- rc = HPMFWUPG_ERROR;
|
|
- }
|
|
-
|
|
- return rc;
|
|
+int
|
|
+HpmfwupgWaitLongDurationCmd(struct ipmi_intf *intf,
|
|
+ struct HpmfwupgUpgradeCtx *pFwupgCtx)
|
|
+{
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ unsigned int upgradeTimeout = 0;
|
|
+ unsigned int timeoutSec1, timeoutSec2;
|
|
+ struct HpmfwupgGetUpgradeStatusCtx upgStatusCmd;
|
|
+ /* If we are not in upgrade context, we use default timeout values */
|
|
+ if (pFwupgCtx != NULL) {
|
|
+ upgradeTimeout = (unsigned int)(pFwupgCtx->targetCap.upgradeTimeout*5);
|
|
+ if (verbose) {
|
|
+ printf("Use File Upgrade Capabilities: %i seconds\n",
|
|
+ upgradeTimeout);
|
|
+ }
|
|
+ } else {
|
|
+ /* Try to retreive from Caps */
|
|
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
+ if(HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd) != HPMFWUPG_SUCCESS) {
|
|
+ upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
+ if (verbose) {
|
|
+ printf("Use default timeout: %i seconds\n",
|
|
+ upgradeTimeout);
|
|
+ }
|
|
+ } else {
|
|
+ upgradeTimeout = (unsigned int)(targetCapCmd.resp.upgradeTimeout * 5);
|
|
+ if (verbose) {
|
|
+ printf("Use Command Upgrade Capabilities Timeout: %i seconds\n",
|
|
+ upgradeTimeout);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ /* Poll upgrade status until completion or timeout*/
|
|
+ timeoutSec1 = time(NULL);
|
|
+ timeoutSec2 = time(NULL);
|
|
+ rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd,
|
|
+ pFwupgCtx, 1);
|
|
+ }
|
|
+ while (
|
|
+ /* With KCS: Cover the case where we sometime
|
|
+ * receive d5 (on the first get status) from
|
|
+ * the ipmi driver.
|
|
+ */
|
|
+ (upgStatusCmd.resp.lastCmdCompCode != 0x00 )
|
|
+ && ((timeoutSec2 - timeoutSec1) < upgradeTimeout )
|
|
+ && (rc == HPMFWUPG_SUCCESS)) {
|
|
+ /* Must wait at least 1000 ms between status requests */
|
|
+ usleep(1000000);
|
|
+ timeoutSec2 = time(NULL);
|
|
+ rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx, 1);
|
|
+/*
|
|
+ * printf("Get Status: %x - %x = %x _ %x [%x]\n",
|
|
+ ( timeoutSec2, timeoutSec1,
|
|
+ * (timeoutSec2 - timeoutSec1),
|
|
+ * upgradeTimeout, rc);
|
|
+ */
|
|
+ }
|
|
+ if (upgStatusCmd.resp.lastCmdCompCode != 0x00) {
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Error waiting for command %x, compcode = %x",
|
|
+ upgStatusCmd.resp.cmdInProcess,
|
|
+ upgStatusCmd.resp.lastCmdCompCode);
|
|
+ }
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
-unsigned char HpmfwupgCalculateChecksum(unsigned char* pData, unsigned int length)
|
|
+unsigned char
|
|
+HpmfwupgCalculateChecksum(unsigned char *pData, unsigned int length)
|
|
{
|
|
- unsigned char checksum = 0;
|
|
- int dataIdx = 0;
|
|
-
|
|
- for ( dataIdx = 0; dataIdx < length; dataIdx++ )
|
|
- {
|
|
- checksum += pData[dataIdx];
|
|
- }
|
|
- return checksum;
|
|
+ unsigned char checksum = 0;
|
|
+ int dataIdx = 0;
|
|
+ for (dataIdx = 0; dataIdx < length; dataIdx++) {
|
|
+ checksum += pData[dataIdx];
|
|
+ }
|
|
+ return checksum;
|
|
}
|
|
|
|
-static void HpmfwupgPrintUsage(void)
|
|
-{
|
|
- lprintf(LOG_NOTICE,"help - This help menu.");
|
|
- lprintf(LOG_NOTICE,"");
|
|
- lprintf(LOG_NOTICE,"check - Check the target information.");
|
|
- lprintf(LOG_NOTICE,"check <file> - If the user is unsure of what update is going to be ");
|
|
- lprintf(LOG_NOTICE," This will display the existing target version and");
|
|
- lprintf(LOG_NOTICE," image version on the screen");
|
|
- lprintf(LOG_NOTICE,"");
|
|
- lprintf(LOG_NOTICE,"upgrade <file> - Copies all the components from a valid HPM.1");
|
|
- lprintf(LOG_NOTICE," image <file> to the target.");
|
|
- lprintf(LOG_NOTICE," This compares the versions from both the target");
|
|
- lprintf(LOG_NOTICE," and image and will only perform the copy");
|
|
- lprintf(LOG_NOTICE," if the versions differ.");
|
|
- lprintf(LOG_NOTICE,"upgrade <file> activate - Copy and activate the firmware using a valid HPM.1");
|
|
- lprintf(LOG_NOTICE," image <file>.");
|
|
- lprintf(LOG_NOTICE," This compares the versions from both the target");
|
|
- lprintf(LOG_NOTICE," and image and will only perform the copy and");
|
|
- lprintf(LOG_NOTICE," activation if the versions differ.");
|
|
- lprintf(LOG_NOTICE,"upgrade <file> force - Copies all the components present in <file>");
|
|
- lprintf(LOG_NOTICE," to the target board without checking the versions.");
|
|
- lprintf(LOG_NOTICE," Make sure to check the versions first using the");
|
|
- lprintf(LOG_NOTICE," \"check <file>\" command.");
|
|
- lprintf(LOG_NOTICE,"upgrade <file> component x - Copy only component <x> from the given <file>");
|
|
- lprintf(LOG_NOTICE," without checking if the versions differ.");
|
|
- lprintf(LOG_NOTICE," For example:");
|
|
- lprintf(LOG_NOTICE," component 0 = Bootloader");
|
|
- lprintf(LOG_NOTICE," component 1 = Firmware");
|
|
- lprintf(LOG_NOTICE," Make sure to check the versions first using the");
|
|
- lprintf(LOG_NOTICE," \"check <file>\" command.");
|
|
- lprintf(LOG_NOTICE,"upgstatus - Returns the status of the last long duration command.");
|
|
- lprintf(LOG_NOTICE,"");
|
|
- lprintf(LOG_NOTICE,"activate - Activate the newly uploaded firmware.");
|
|
- lprintf(LOG_NOTICE,"activate norollback - Activate the newly uploaded firmware but inform");
|
|
- lprintf(LOG_NOTICE," the target to not automatically rollback if ");
|
|
- lprintf(LOG_NOTICE," the upgrade fails.");
|
|
- lprintf(LOG_NOTICE,"");
|
|
- lprintf(LOG_NOTICE,"targetcap - Get the target upgrade capabilities.");
|
|
- lprintf(LOG_NOTICE,"");
|
|
- lprintf(LOG_NOTICE,"compprop <id> <prop> - Get specified component properties from the target.");
|
|
- lprintf(LOG_NOTICE," Valid component <id>: 0-7 ");
|
|
- lprintf(LOG_NOTICE," Properties <prop> can be one of the following: ");
|
|
- lprintf(LOG_NOTICE," 0- General properties");
|
|
- lprintf(LOG_NOTICE," 1- Current firmware version");
|
|
- lprintf(LOG_NOTICE," 2- Description string");
|
|
- lprintf(LOG_NOTICE," 3- Rollback firmware version");
|
|
- lprintf(LOG_NOTICE," 4- Deferred firmware version");
|
|
- lprintf(LOG_NOTICE,"");
|
|
- lprintf(LOG_NOTICE,"abort - Abort the on-going firmware upgrade.");
|
|
- lprintf(LOG_NOTICE,"");
|
|
- lprintf(LOG_NOTICE,"rollback - Performs a manual rollback on the IPM Controller.");
|
|
- lprintf(LOG_NOTICE," firmware");
|
|
- lprintf(LOG_NOTICE,"rollbackstatus - Query the rollback status.");
|
|
- lprintf(LOG_NOTICE,"");
|
|
- lprintf(LOG_NOTICE,"selftestresult - Query the self test results.\n");
|
|
+void
|
|
+HpmfwupgPrintUsage(void)
|
|
+{
|
|
+ lprintf(LOG_NOTICE,
|
|
+"help - This help menu.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"check - Check the target information.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"check <file> - If the user is unsure of what update is going to be ");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" This will display the existing target version and");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" image version on the screen");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"upgrade <file> [component x...] [force] [activate]");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" - Copies components from a valid HPM.1 image to the target.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" If one or more components specified by \"component\",");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" only the specified components are copied.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" Otherwise, all the image components are copied.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" Before copy, each image component undergoes a version check");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" and can be skipped if the target component version");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" is the same or more recent.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" Use \"force\" to bypass the version check results.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" Make sure to check the versions first using the");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" \"check <file>\" command.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" If \"activate\" is specified, the newly uploaded firmware");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" is activated.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"upgstatus - Returns the status of the last long duration command.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"compare <file> - Perform \"Comparison of the Active Copy\" action for all the");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" components present in the file.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"compare <file> component x - Compare only component <x> from the given <file>");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"activate - Activate the newly uploaded firmware.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"activate norollback - Activate the newly uploaded firmware but inform");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" the target to not automatically rollback if ");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" the upgrade fails.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"targetcap - Get the target upgrade capabilities.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"compprop <id> <prop> - Get specified component properties from the target.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" Valid component <id>: 0-7 ");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" Properties <prop> can be one of the following: ");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" 0- General properties");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" 1- Current firmware version");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" 2- Description string");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" 3- Rollback firmware version");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" 4- Deferred firmware version");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"abort - Abort the on-going firmware upgrade.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"rollback - Performs a manual rollback on the IPM Controller.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+" firmware");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"rollbackstatus - Query the rollback status.");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"");
|
|
+ lprintf(LOG_NOTICE,
|
|
+"selftestresult - Query the self test results.\n");
|
|
}
|
|
|
|
-int ipmi_hpmfwupg_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
-{
|
|
- int rc = HPMFWUPG_SUCCESS;
|
|
- int activateFlag = 0x00;
|
|
- int componentId = DEFAULT_COMPONENT_UPLOAD;
|
|
- int option = VERSIONCHECK_MODE;
|
|
-
|
|
- lprintf(LOG_DEBUG,"ipmi_hpmfwupg_main()");
|
|
-
|
|
-
|
|
- lprintf(LOG_NOTICE,"\nPICMG HPM.1 Upgrade Agent %d.%d.%d: \n",
|
|
- HPMFWUPG_VERSION_MAJOR, HPMFWUPG_VERSION_MINOR, HPMFWUPG_VERSION_SUBMINOR);
|
|
-
|
|
- if ( (argc == 0) || (strcmp(argv[0], "help") == 0) )
|
|
- {
|
|
- HpmfwupgPrintUsage();
|
|
- return HPMFWUPG_ERROR;
|
|
- }
|
|
- if ( (strcmp(argv[0], "check") == 0) )
|
|
- {
|
|
- /* hpm check */
|
|
- if (argv[1] == NULL)
|
|
- {
|
|
- rc = HpmfwupgTargetCheck(intf,VIEW_MODE);
|
|
- }
|
|
- else
|
|
- {
|
|
- /* hpm check <filename> */
|
|
- rc = HpmfwupgTargetCheck(intf,0);
|
|
- if (rc == HPMFWUPG_SUCCESS)
|
|
- {
|
|
- rc = HpmfwupgUpgrade(intf, argv[1],0,DEFAULT_COMPONENT_UPLOAD,VIEW_MODE);
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- else if ( strcmp(argv[0], "upgrade") == 0)
|
|
- {
|
|
- int i =0;
|
|
- for (i=1; i< argc ; i++)
|
|
- {
|
|
- if (strcmp(argv[i],"activate") == 0)
|
|
- {
|
|
- activateFlag = 1;
|
|
- }
|
|
- /* hpm upgrade <filename> force */
|
|
- if (strcmp(argv[i],"force") == 0)
|
|
- {
|
|
- option &= ~(VERSIONCHECK_MODE);
|
|
- option &= ~(VIEW_MODE);
|
|
- option |= FORCE_MODE_ALL;
|
|
- }
|
|
- /* hpm upgrade <filename> component <comp Id> */
|
|
- if (strcmp(argv[i],"component") == 0)
|
|
- {
|
|
- if (i+1 < argc)
|
|
- {
|
|
- if (str2int(argv[i+1], &componentId) != 0 ||
|
|
- componentId < 0 || componentId > 7) {
|
|
- lprintf(LOG_ERR, "Given Component ID '%s' is invalid.",
|
|
- argv[i+1]);
|
|
- lprintf(LOG_ERR, "Valid Compoment ID is: <0..7>");
|
|
- return (-1);
|
|
- }
|
|
- option &= ~(VERSIONCHECK_MODE);
|
|
- option &= ~(VIEW_MODE);
|
|
- option |= FORCE_MODE_COMPONENT;
|
|
-
|
|
- if( verbose ) {
|
|
- lprintf(LOG_NOTICE,"Component Id %d provided",componentId );
|
|
- }
|
|
-
|
|
- /* Error Checking */
|
|
- if (componentId >= HPMFWUPG_COMPONENT_ID_MAX)
|
|
- {
|
|
- lprintf(LOG_NOTICE,"Given component ID %d exceeds Max Comp ID %d\n",
|
|
- componentId, HPMFWUPG_COMPONENT_ID_MAX-1);
|
|
- return HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- if (componentId == DEFAULT_COMPONENT_UPLOAD)
|
|
- {
|
|
- /* That indicates the user has given component on console but not
|
|
- * given any ID */
|
|
- lprintf(LOG_NOTICE,"No component Id provided\n");
|
|
- return HPMFWUPG_ERROR;
|
|
- }
|
|
- }
|
|
- if (strcmp(argv[i],"debug") == 0)
|
|
- {
|
|
- option |= DEBUG_MODE;
|
|
- }
|
|
- }
|
|
- rc = HpmfwupgTargetCheck(intf,0);
|
|
- if (rc == HPMFWUPG_SUCCESS)
|
|
- {
|
|
- /* Call the Upgrade function to start the upgrade */
|
|
- rc = HpmfwupgUpgrade(intf, argv[1],activateFlag,componentId,option);
|
|
- }
|
|
- }
|
|
-
|
|
- else if ( (argc >= 1) && (strcmp(argv[0], "activate") == 0) )
|
|
- {
|
|
- struct HpmfwupgActivateFirmwareCtx cmdCtx;
|
|
- if ( (argc == 2) && (strcmp(argv[1], "norollback") == 0) )
|
|
- cmdCtx.req.rollback_override = 1;
|
|
- else
|
|
- cmdCtx.req.rollback_override = 0;
|
|
- rc = HpmfwupgActivateFirmware(intf, &cmdCtx, NULL);
|
|
- }
|
|
- else if ( (argc == 1) && (strcmp(argv[0], "targetcap") == 0) )
|
|
- {
|
|
- struct HpmfwupgGetTargetUpgCapabilitiesCtx cmdCtx;
|
|
- verbose++;
|
|
- rc = HpmfwupgGetTargetUpgCapabilities(intf, &cmdCtx);
|
|
- }
|
|
- else if ( (argc == 3) && (strcmp(argv[0], "compprop") == 0) )
|
|
- {
|
|
- struct HpmfwupgGetComponentPropertiesCtx cmdCtx;
|
|
- if (str2uchar(argv[1], &(cmdCtx.req.componentId)) != 0
|
|
- || cmdCtx.req.componentId > 7) {
|
|
- lprintf(LOG_ERR, "Given Component ID '%s' is invalid.", argv[1]);
|
|
- lprintf(LOG_ERR, "Valid Compoment ID is: <0..7>");
|
|
- return (-1);
|
|
- }
|
|
- if (str2uchar(argv[2], &(cmdCtx.req.selector)) != 0
|
|
- || cmdCtx.req.selector > 4) {
|
|
- lprintf(LOG_ERR, "Given Properties selector '%s' is invalid.",
|
|
- argv[2]);
|
|
- lprintf(LOG_ERR, "Valid Properties selector is: <0..4>");
|
|
- return (-1);
|
|
- }
|
|
- verbose++;
|
|
- rc = HpmfwupgGetComponentProperties(intf, &cmdCtx);
|
|
- }
|
|
- else if ( (argc == 1) && (strcmp(argv[0], "abort") == 0) )
|
|
- {
|
|
- struct HpmfwupgAbortUpgradeCtx cmdCtx;
|
|
- verbose++;
|
|
- rc = HpmfwupgAbortUpgrade(intf, &cmdCtx);
|
|
- }
|
|
- else if ( (argc == 1) && (strcmp(argv[0], "upgstatus") == 0) )
|
|
- {
|
|
- struct HpmfwupgGetUpgradeStatusCtx cmdCtx;
|
|
- verbose++;
|
|
- rc = HpmfwupgGetUpgradeStatus(intf, &cmdCtx, NULL, 0);
|
|
- }
|
|
- else if ( (argc == 1) && (strcmp(argv[0], "rollback") == 0) )
|
|
- {
|
|
- struct HpmfwupgManualFirmwareRollbackCtx cmdCtx;
|
|
- verbose++;
|
|
- rc = HpmfwupgManualFirmwareRollback(intf, &cmdCtx, NULL);
|
|
- }
|
|
- else if ( (argc == 1) && (strcmp(argv[0], "rollbackstatus") == 0) )
|
|
- {
|
|
- struct HpmfwupgQueryRollbackStatusCtx cmdCtx;
|
|
- verbose++;
|
|
- rc = HpmfwupgQueryRollbackStatus(intf, &cmdCtx, NULL);
|
|
- }
|
|
- else if ( (argc == 1) && (strcmp(argv[0], "selftestresult") == 0) )
|
|
- {
|
|
- struct HpmfwupgQuerySelftestResultCtx cmdCtx;
|
|
- verbose++;
|
|
- rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL);
|
|
- }
|
|
- else
|
|
- {
|
|
- HpmfwupgPrintUsage();
|
|
- }
|
|
-
|
|
- return rc;
|
|
+int
|
|
+ipmi_hpmfwupg_main(struct ipmi_intf *intf, int argc, char **argv)
|
|
+{
|
|
+ int rc = HPMFWUPG_SUCCESS;
|
|
+ int activateFlag = 0x00;
|
|
+ int componentMask = 0;
|
|
+ int componentId = 0;
|
|
+ int option = 0;
|
|
+
|
|
+ lprintf(LOG_DEBUG,"ipmi_hpmfwupg_main()");
|
|
+ lprintf(LOG_NOTICE, "\nPICMG HPM.1 Upgrade Agent %d.%d.%d: \n",
|
|
+ HPMFWUPG_VERSION_MAJOR, HPMFWUPG_VERSION_MINOR,
|
|
+ HPMFWUPG_VERSION_SUBMINOR);
|
|
+ if (argc < 1) {
|
|
+ lprintf(LOG_ERR, "Not enough parameters given.");
|
|
+ HpmfwupgPrintUsage();
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if (strcmp(argv[0], "help") == 0) {
|
|
+ HpmfwupgPrintUsage();
|
|
+ return HPMFWUPG_SUCCESS;
|
|
+ } else if ((strcmp(argv[0], "check") == 0)) {
|
|
+ /* hpm check */
|
|
+ if (argv[1] == NULL) {
|
|
+ rc = HpmfwupgTargetCheck(intf,VIEW_MODE);
|
|
+ } else {
|
|
+ /* hpm check <filename> */
|
|
+ rc = HpmfwupgTargetCheck(intf,0);
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ rc = HpmfwupgUpgrade(intf, argv[1], 0,
|
|
+ 0, VIEW_MODE);
|
|
+ }
|
|
+ }
|
|
+ } else if (strcmp(argv[0], "upgrade") == 0) {
|
|
+ int i =0;
|
|
+ for (i=1; i< argc ; i++) {
|
|
+ if (strcmp(argv[i],"activate") == 0) {
|
|
+ activateFlag = 1;
|
|
+ }
|
|
+ /* hpm upgrade <filename> force */
|
|
+ if (strcmp(argv[i],"force") == 0) {
|
|
+ option |= FORCE_MODE;
|
|
+ }
|
|
+ /* hpm upgrade <filename> component <comp Id> */
|
|
+ if (strcmp(argv[i],"component") == 0) {
|
|
+ if (i+1 < argc) {
|
|
+ /* Error Checking */
|
|
+ if (str2int(argv[i+1], &componentId) != 0
|
|
+ || componentId < 0
|
|
+ || componentId > HPMFWUPG_COMPONENT_ID_MAX) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Given Component ID '%s' is invalid.",
|
|
+ argv[i+1]);
|
|
+ lprintf(LOG_ERR,
|
|
+ "Valid Compoment ID is: <0..7>");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if( verbose ) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Component Id %d provided",
|
|
+ componentId );
|
|
+ }
|
|
+ componentMask |= 1 << componentId;
|
|
+ } else {
|
|
+ /* That indicates the user has
|
|
+ * given component on console but
|
|
+ * not given any ID
|
|
+ */
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "No component Id provided\n");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ }
|
|
+ if (strcmp(argv[i],"debug") == 0) {
|
|
+ option |= DEBUG_MODE;
|
|
+ }
|
|
+ }
|
|
+ rc = HpmfwupgTargetCheck(intf, 0);
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ /* Call the Upgrade function to start the upgrade */
|
|
+ rc = HpmfwupgUpgrade(intf, argv[1], activateFlag,
|
|
+ componentMask, option);
|
|
+ }
|
|
+ } else if (strcmp(argv[0], "compare") == 0) {
|
|
+ int i = 0;
|
|
+ for (i=1; i< argc; i++) {
|
|
+ /* hpm compare <file> [component x...] */
|
|
+ if (strcmp(argv[i],"component") == 0) {
|
|
+ if (i+1 < argc) {
|
|
+ /* Error Checking */
|
|
+ if (str2int(argv[i+1], &componentId) != 0
|
|
+ || componentId < 0
|
|
+ || componentId > HPMFWUPG_COMPONENT_ID_MAX) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Given Component ID '%s' is invalid.",
|
|
+ argv[i+1]);
|
|
+ lprintf(LOG_ERR,
|
|
+ "Valid Compoment ID is: <0..7>");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ if( verbose ) {
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "Component Id %d provided",
|
|
+ componentId);
|
|
+ }
|
|
+ componentMask|= 1 << componentId;
|
|
+ } else {
|
|
+ /* That indicates the user
|
|
+ * has given component on
|
|
+ * console but not
|
|
+ * given any ID
|
|
+ */
|
|
+ lprintf(LOG_NOTICE,
|
|
+ "No component Id provided\n");
|
|
+ return HPMFWUPG_ERROR;
|
|
+ }
|
|
+ } else if (strcmp(argv[i],"debug") == 0) {
|
|
+ option|= DEBUG_MODE;
|
|
+ }
|
|
+ }
|
|
+ option|= (COMPARE_MODE);
|
|
+ rc = HpmfwupgTargetCheck(intf, 0);
|
|
+ if (rc == HPMFWUPG_SUCCESS) {
|
|
+ rc = HpmfwupgUpgrade(intf, argv[1], 0,
|
|
+ componentMask, option);
|
|
+ }
|
|
+ } else if ((argc >= 1) && (strcmp(argv[0], "activate") == 0)) {
|
|
+ struct HpmfwupgActivateFirmwareCtx cmdCtx;
|
|
+ if ((argc == 2) && (strcmp(argv[1], "norollback") == 0)) {
|
|
+ cmdCtx.req.rollback_override = 1;
|
|
+ } else {
|
|
+ cmdCtx.req.rollback_override = 0;
|
|
+ }
|
|
+ rc = HpmfwupgActivateFirmware(intf, &cmdCtx, NULL);
|
|
+ } else if ((argc == 1) && (strcmp(argv[0], "targetcap") == 0)) {
|
|
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx cmdCtx;
|
|
+ verbose++;
|
|
+ rc = HpmfwupgGetTargetUpgCapabilities(intf, &cmdCtx);
|
|
+ } else if ((argc == 3) && (strcmp(argv[0], "compprop") == 0)) {
|
|
+ struct HpmfwupgGetComponentPropertiesCtx cmdCtx;
|
|
+ if (str2uchar(argv[1], &(cmdCtx.req.componentId)) != 0
|
|
+ || cmdCtx.req.componentId > 7) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Given Component ID '%s' is invalid.",
|
|
+ argv[1]);
|
|
+ lprintf(LOG_ERR,
|
|
+ "Valid Compoment ID is: <0..7>");
|
|
+ return (-1);
|
|
+ }
|
|
+ if (str2uchar(argv[2], &(cmdCtx.req.selector)) != 0
|
|
+ || cmdCtx.req.selector > 4) {
|
|
+ lprintf(LOG_ERR,
|
|
+ "Given Properties selector '%s' is invalid.",
|
|
+ argv[2]);
|
|
+ lprintf(LOG_ERR,
|
|
+ "Valid Properties selector is: <0..4>");
|
|
+ return (-1);
|
|
+ }
|
|
+ verbose++;
|
|
+ rc = HpmfwupgGetComponentProperties(intf, &cmdCtx);
|
|
+ } else if ((argc == 1) && (strcmp(argv[0], "abort") == 0)) {
|
|
+ struct HpmfwupgAbortUpgradeCtx cmdCtx;
|
|
+ verbose++;
|
|
+ rc = HpmfwupgAbortUpgrade(intf, &cmdCtx);
|
|
+ } else if ((argc == 1) && (strcmp(argv[0], "upgstatus") == 0)) {
|
|
+ struct HpmfwupgGetUpgradeStatusCtx cmdCtx;
|
|
+ verbose++;
|
|
+ rc = HpmfwupgGetUpgradeStatus(intf, &cmdCtx, NULL, 0);
|
|
+ } else if ((argc == 1) && (strcmp(argv[0], "rollback") == 0)) {
|
|
+ struct HpmfwupgManualFirmwareRollbackCtx cmdCtx;
|
|
+ verbose++;
|
|
+ rc = HpmfwupgManualFirmwareRollback(intf, &cmdCtx);
|
|
+ } else if ((argc == 1) && (strcmp(argv[0], "rollbackstatus") == 0)) {
|
|
+ struct HpmfwupgQueryRollbackStatusCtx cmdCtx;
|
|
+ verbose++;
|
|
+ rc = HpmfwupgQueryRollbackStatus(intf, &cmdCtx, NULL);
|
|
+ } else if ((argc == 1) && (strcmp(argv[0], "selftestresult") == 0)) {
|
|
+ struct HpmfwupgQuerySelftestResultCtx cmdCtx;
|
|
+ verbose++;
|
|
+ rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL);
|
|
+ } else {
|
|
+ lprintf(LOG_ERR, "Invalid HPM command: %s", argv[0]);
|
|
+ HpmfwupgPrintUsage();
|
|
+ rc = HPMFWUPG_ERROR;
|
|
+ }
|
|
+ return rc;
|
|
}
|
|
|
|
diff --git a/ipmitool/lib/ipmi_kontronoem.c b/ipmitool/lib/ipmi_kontronoem.c
|
|
index dac2ced..c154eda 100644
|
|
--- a/ipmitool/lib/ipmi_kontronoem.c
|
|
+++ b/ipmitool/lib/ipmi_kontronoem.c
|
|
@@ -350,6 +350,7 @@ ipmi_kontron_set_serial_number(struct ipmi_intf * intf)
|
|
return(-1);
|
|
}
|
|
|
|
+ memset(&fru, 0, sizeof(fru));
|
|
fru.size = (rsp->data[1] << 8) | rsp->data[0];
|
|
fru.access = rsp->data[2] & 0x1;
|
|
|
|
@@ -637,6 +638,7 @@ ipmi_kontron_set_mfg_date (struct ipmi_intf * intf)
|
|
return(-1);
|
|
}
|
|
|
|
+ memset(&fru, 0, sizeof(fru));
|
|
fru.size = (rsp->data[1] << 8) | rsp->data[0];
|
|
fru.access = rsp->data[2] & 0x1;
|
|
|
|
diff --git a/ipmitool/lib/ipmi_main.c b/ipmitool/lib/ipmi_main.c
|
|
index 54b80c0..3d0a3b8 100644
|
|
--- a/ipmitool/lib/ipmi_main.c
|
|
+++ b/ipmitool/lib/ipmi_main.c
|
|
@@ -894,9 +894,11 @@ ipmi_main(int argc, char ** argv,
|
|
|
|
/* Open the interface with the specified or default IPMB address */
|
|
ipmi_main_intf->my_addr = arg_addr ? arg_addr : IPMI_BMC_SLAVE_ADDR;
|
|
- if (ipmi_main_intf->open != NULL)
|
|
- ipmi_main_intf->open(ipmi_main_intf);
|
|
-
|
|
+ if (ipmi_main_intf->open != NULL) {
|
|
+ if (ipmi_main_intf->open(ipmi_main_intf) < 0) {
|
|
+ goto out_free;
|
|
+ }
|
|
+ }
|
|
/*
|
|
* Attempt picmg discovery of the actual interface address unless
|
|
* the users specified an address.
|
|
diff --git a/ipmitool/lib/ipmi_sdr.c b/ipmitool/lib/ipmi_sdr.c
|
|
index 093d1ec..d44bbbb 100644
|
|
--- a/ipmitool/lib/ipmi_sdr.c
|
|
+++ b/ipmitool/lib/ipmi_sdr.c
|
|
@@ -456,10 +456,12 @@ ipmi_sdr_get_sensor_thresholds(struct ipmi_intf *intf, uint8_t sensor,
|
|
{
|
|
struct ipmi_rq req;
|
|
struct ipmi_rs *rsp;
|
|
- uint32_t save_addr = 0;
|
|
+ uint8_t bridged_request = 0;
|
|
+ uint32_t save_addr;
|
|
uint32_t save_channel;
|
|
|
|
if ( BRIDGE_TO_SENSOR(intf, target, channel) ) {
|
|
+ bridged_request = 1;
|
|
save_addr = intf->target_addr;
|
|
intf->target_addr = target;
|
|
save_channel = intf->target_channel;
|
|
@@ -474,7 +476,7 @@ ipmi_sdr_get_sensor_thresholds(struct ipmi_intf *intf, uint8_t sensor,
|
|
req.msg.data_len = sizeof (sensor);
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
- if ( save_addr ) {
|
|
+ if (bridged_request) {
|
|
intf->target_addr = save_addr;
|
|
intf->target_channel = save_channel;
|
|
}
|
|
@@ -498,10 +500,12 @@ ipmi_sdr_get_sensor_hysteresis(struct ipmi_intf *intf, uint8_t sensor,
|
|
struct ipmi_rq req;
|
|
uint8_t rqdata[2];
|
|
struct ipmi_rs *rsp;
|
|
- uint32_t save_addr = 0;
|
|
+ uint8_t bridged_request = 0;
|
|
+ uint32_t save_addr;
|
|
uint32_t save_channel;
|
|
|
|
if ( BRIDGE_TO_SENSOR(intf, target, channel) ) {
|
|
+ bridged_request = 1;
|
|
save_addr = intf->target_addr;
|
|
intf->target_addr = target;
|
|
save_channel = intf->target_channel;
|
|
@@ -519,7 +523,7 @@ ipmi_sdr_get_sensor_hysteresis(struct ipmi_intf *intf, uint8_t sensor,
|
|
req.msg.data_len = 2;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
- if ( save_addr ) {
|
|
+ if (bridged_request) {
|
|
intf->target_addr = save_addr;
|
|
intf->target_channel = save_channel;
|
|
}
|
|
@@ -564,10 +568,17 @@ ipmi_sdr_get_sensor_reading_ipmb(struct ipmi_intf *intf, uint8_t sensor,
|
|
{
|
|
struct ipmi_rq req;
|
|
struct ipmi_rs *rsp;
|
|
- uint32_t save_addr = 0;
|
|
+ uint8_t bridged_request = 0;
|
|
+ uint32_t save_addr;
|
|
uint32_t save_channel;
|
|
|
|
if ( BRIDGE_TO_SENSOR(intf, target, channel) ) {
|
|
+ lprintf(LOG_DEBUG,
|
|
+ "Bridge to Sensor "
|
|
+ "Intf my/%#x tgt/%#x:%#x Sdr tgt/%#x:%#x\n",
|
|
+ intf->my_addr, intf->target_addr, intf->target_channel,
|
|
+ target, channel);
|
|
+ bridged_request = 1;
|
|
save_addr = intf->target_addr;
|
|
intf->target_addr = target;
|
|
save_channel = intf->target_channel;
|
|
@@ -581,7 +592,7 @@ ipmi_sdr_get_sensor_reading_ipmb(struct ipmi_intf *intf, uint8_t sensor,
|
|
req.msg.data_len = 1;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
- if ( save_addr ) {
|
|
+ if (bridged_request) {
|
|
intf->target_addr = save_addr;
|
|
intf->target_channel = save_channel;
|
|
}
|
|
@@ -604,10 +615,12 @@ ipmi_sdr_get_sensor_event_status(struct ipmi_intf *intf, uint8_t sensor,
|
|
{
|
|
struct ipmi_rq req;
|
|
struct ipmi_rs *rsp;
|
|
- uint32_t save_addr = 0;
|
|
+ uint8_t bridged_request = 0;
|
|
+ uint32_t save_addr;
|
|
uint32_t save_channel;
|
|
|
|
if ( BRIDGE_TO_SENSOR(intf, target, channel) ) {
|
|
+ bridged_request = 1;
|
|
save_addr = intf->target_addr;
|
|
intf->target_addr = target;
|
|
save_channel = intf->target_channel;
|
|
@@ -621,7 +634,7 @@ ipmi_sdr_get_sensor_event_status(struct ipmi_intf *intf, uint8_t sensor,
|
|
req.msg.data_len = 1;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
- if ( save_addr ) {
|
|
+ if (bridged_request) {
|
|
intf->target_addr = save_addr;
|
|
intf->target_channel = save_channel;
|
|
}
|
|
@@ -644,10 +657,12 @@ ipmi_sdr_get_sensor_event_enable(struct ipmi_intf *intf, uint8_t sensor,
|
|
{
|
|
struct ipmi_rq req;
|
|
struct ipmi_rs *rsp;
|
|
- uint32_t save_addr = 0;
|
|
+ uint8_t bridged_request = 0;
|
|
+ uint32_t save_addr;
|
|
uint32_t save_channel;
|
|
|
|
if ( BRIDGE_TO_SENSOR(intf, target, channel) ) {
|
|
+ bridged_request = 1;
|
|
save_addr = intf->target_addr;
|
|
intf->target_addr = target;
|
|
save_channel = intf->target_channel;
|
|
@@ -662,7 +677,7 @@ ipmi_sdr_get_sensor_event_enable(struct ipmi_intf *intf, uint8_t sensor,
|
|
req.msg.data_len = 1;
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
- if ( save_addr ) {
|
|
+ if (bridged_request) {
|
|
intf->target_addr = save_addr;
|
|
intf->target_channel = save_channel;
|
|
}
|
|
@@ -2407,6 +2422,7 @@ ipmi_sdr_print_sensor_oem_intel(struct ipmi_intf *intf,
|
|
("Power Redundancy | PS@%02xh | nr\n",
|
|
oem->data[8]);
|
|
}
|
|
+ break;
|
|
case 9: /* SR2300, non-redundant, PSx present */
|
|
if (verbose) {
|
|
printf("Power Redundancy : Yes\n");
|
|
diff --git a/ipmitool/lib/ipmi_sel.c b/ipmitool/lib/ipmi_sel.c
|
|
index b06a81a..63ecbcf 100644
|
|
--- a/ipmitool/lib/ipmi_sel.c
|
|
+++ b/ipmitool/lib/ipmi_sel.c
|
|
@@ -322,7 +322,6 @@ ipmi_get_oem(struct ipmi_intf * intf)
|
|
return IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id);
|
|
}
|
|
|
|
-
|
|
static int
|
|
ipmi_sel_add_entry(struct ipmi_intf * intf, struct sel_event_record * rec)
|
|
{
|
|
@@ -526,6 +525,115 @@ get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
|
|
return description;
|
|
}
|
|
|
|
+char *
|
|
+get_supermicro_evt_desc(struct ipmi_intf *intf, struct sel_event_record *rec)
|
|
+{
|
|
+ struct ipmi_rs *rsp;
|
|
+ struct ipmi_rq req;
|
|
+ char *desc = NULL;
|
|
+ char *str;
|
|
+ int chipset_type = 1;
|
|
+ int data1;
|
|
+ int data2;
|
|
+ int data3;
|
|
+ int length;
|
|
+ int sensor_type;
|
|
+ uint8_t i = 0;
|
|
+ uint16_t oem_id = 0;
|
|
+ /* Get the OEM event Bytes of the SEL Records byte 13, 14, 15 to
|
|
+ * data1,data2,data3
|
|
+ */
|
|
+ data1 = rec->sel_type.standard_type.event_data[0];
|
|
+ data2 = rec->sel_type.standard_type.event_data[1];
|
|
+ data3 = rec->sel_type.standard_type.event_data[2];
|
|
+ /* Check for the Standard Event type == 0x6F */
|
|
+ if (rec->sel_type.standard_type.event_type != 0x6F) {
|
|
+ return NULL;
|
|
+ }
|
|
+ /* Allocate mem for te Description string */
|
|
+ desc = (char *)malloc(SIZE_OF_DESC);
|
|
+ if (desc == NULL) {
|
|
+ lprintf(LOG_ERR, "ipmitool: malloc failure");
|
|
+ return NULL;
|
|
+ }
|
|
+ memset(desc,0,SIZE_OF_DESC);
|
|
+ sensor_type = rec->sel_type.standard_type.sensor_type;
|
|
+ switch (sensor_type) {
|
|
+ case SENSOR_TYPE_MEMORY:
|
|
+ memset(&req, 0, sizeof (req));
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.lun = 0;
|
|
+ req.msg.cmd = BMC_GET_DEVICE_ID;
|
|
+ req.msg.data = NULL;
|
|
+ req.msg.data_len = 0;
|
|
+
|
|
+ rsp = intf->sendrecv(intf, &req);
|
|
+ if (rsp == NULL) {
|
|
+ lprintf(LOG_ERR, " Error getting system info");
|
|
+ if (desc != NULL) {
|
|
+ free(desc);
|
|
+ desc = NULL;
|
|
+ }
|
|
+ return NULL;
|
|
+ } else if (rsp->ccode > 0) {
|
|
+ lprintf(LOG_ERR, " Error getting system info: %s",
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ if (desc != NULL) {
|
|
+ free(desc);
|
|
+ desc = NULL;
|
|
+ }
|
|
+ return NULL;
|
|
+ }
|
|
+ /* check the chipset type */
|
|
+ oem_id = ipmi_get_oem_id(intf);
|
|
+ if (oem_id == 0) {
|
|
+ return NULL;
|
|
+ }
|
|
+ length = sizeof(supermicro_X8);
|
|
+ for (i = 0; i < length; i++) {
|
|
+ if (oem_id == supermicro_X8[i]) {
|
|
+ chipset_type = 0;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ length = sizeof(supermicro_x9);
|
|
+ for (i = 0; i < length; i++) {
|
|
+ if (oem_id == supermicro_x9[i]) {
|
|
+ chipset_type = 2;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (chipset_type == 0) {
|
|
+ snprintf(desc, SIZE_OF_DESC, "@DIMM%2X(CPU%x)",
|
|
+ data2,
|
|
+ (data3 & 0x03) + 1);
|
|
+ } else if (chipset_type == 1) {
|
|
+ snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)",
|
|
+ (data2 >> 4) + 0x40 + (data3 & 0x3) * 4,
|
|
+ (data2 & 0xf) + 0x27, (data3 & 0x03) + 1);
|
|
+ } else if (chipset_type == 2) {
|
|
+ snprintf(desc, SIZE_OF_DESC, "@DIMM%c%c(CPU%x)",
|
|
+ (data2 >> 4) + 0x40 + (data3 & 0x3) * 3,
|
|
+ (data2 & 0xf) + 0x27, (data3 & 0x03) + 1);
|
|
+ } else {
|
|
+ snprintf(desc, SIZE_OF_DESC, "");
|
|
+ }
|
|
+ break;
|
|
+ case SENSOR_TYPE_SUPERMICRO_OEM:
|
|
+ if (data1 == 0x80 && data3 == 0xFF) {
|
|
+ if (data2 == 0x0) {
|
|
+ snprintf(desc, SIZE_OF_DESC, "BMC unexpected reset");
|
|
+ } else if (data2 == 0x1) {
|
|
+ snprintf(desc, SIZE_OF_DESC, "BMC cold reset");
|
|
+ } else if (data2 == 0x2) {
|
|
+ snprintf(desc, SIZE_OF_DESC, "BMC warm reset");
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ return desc;
|
|
+}
|
|
+
|
|
/*
|
|
* Function : Decoding the SEL OEM Bytes for the DELL Platforms.
|
|
* Description : The below fucntion will decode the SEL Events OEM Bytes for the Dell specific Sensors only.
|
|
@@ -1067,6 +1175,10 @@ ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
|
|
case IPMI_OEM_DELL: // Dell Decoding of the OEM Bytes from SEL Record.
|
|
desc = get_dell_evt_desc(intf, rec);
|
|
break;
|
|
+ case IPMI_OEM_SUPERMICRO:
|
|
+ case IPMI_OEM_SUPERMICRO_47488:
|
|
+ desc = get_supermicro_evt_desc(intf, rec);
|
|
+ break;
|
|
case IPMI_OEM_UNKNOWN:
|
|
default:
|
|
break;
|
|
@@ -1092,7 +1204,6 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
|
|
*desc = ipmi_get_oem_desc(intf, rec);
|
|
return;
|
|
} else if (rec->sel_type.standard_type.event_type == 0x6f) {
|
|
-
|
|
if( rec->sel_type.standard_type.sensor_type >= 0xC0 && rec->sel_type.standard_type.sensor_type < 0xF0) {
|
|
IPMI_OEM iana = ipmi_get_oem(intf);
|
|
|
|
@@ -1116,12 +1227,27 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
|
|
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 */
|
|
}
|
|
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;
|
|
+ }
|
|
}
|
|
if( evt == NULL ){
|
|
evt = sensor_specific_types;
|
|
@@ -1210,6 +1336,9 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
|
|
if(0x01 == offset)
|
|
flag = 0x01;
|
|
break;
|
|
+ case SENSOR_TYPE_SUPERMICRO_OEM:
|
|
+ flag = 0x02;
|
|
+ break;
|
|
default:
|
|
break;
|
|
}
|
|
@@ -1222,6 +1351,10 @@ ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char
|
|
return;
|
|
}
|
|
memset(*desc, 0, 48 + SIZE_OF_DESC);
|
|
+ if (flag == 0x02) {
|
|
+ sprintf(*desc, "%s", sfx);
|
|
+ return;
|
|
+ }
|
|
sprintf(*desc, "(%s)",sfx);
|
|
}
|
|
free(sfx);
|
|
@@ -1776,10 +1909,17 @@ ipmi_sel_print_std_entry(struct ipmi_intf * intf, struct sel_event_record * evt)
|
|
}
|
|
}
|
|
else if (evt->sel_type.standard_type.event_type == 0x6f) {
|
|
+ int print_sensor = 1;
|
|
+ switch (ipmi_get_oem(intf)) {
|
|
+ case IPMI_OEM_SUPERMICRO:
|
|
+ case IPMI_OEM_SUPERMICRO_47488:
|
|
+ print_sensor = 0;
|
|
+ break;
|
|
+ }
|
|
/*
|
|
* Sensor-Specific Discrete
|
|
*/
|
|
- if (evt->sel_type.standard_type.sensor_type == 0xC &&
|
|
+ if (print_sensor && evt->sel_type.standard_type.sensor_type == 0xC && /*TODO*/
|
|
evt->sel_type.standard_type.sensor_num == 0 &&
|
|
(evt->sel_type.standard_type.event_data[0] & 0x30) == 0x20) {
|
|
/* break down memory ECC reporting if we can */
|
|
diff --git a/ipmitool/lib/ipmi_sensor.c b/ipmitool/lib/ipmi_sensor.c
|
|
index 42e8853..4ef5138 100644
|
|
--- a/ipmitool/lib/ipmi_sensor.c
|
|
+++ b/ipmitool/lib/ipmi_sensor.c
|
|
@@ -110,7 +110,8 @@ ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf,
|
|
struct ipmi_rq req;
|
|
static struct sensor_set_thresh_rq set_thresh_rq;
|
|
struct ipmi_rs *rsp;
|
|
- uint32_t save_addr = 0;
|
|
+ uint8_t bridged_request = 0;
|
|
+ uint32_t save_addr;
|
|
uint32_t save_channel;
|
|
|
|
memset(&set_thresh_rq, 0, sizeof (set_thresh_rq));
|
|
@@ -132,6 +133,7 @@ ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf,
|
|
return NULL;
|
|
|
|
if (BRIDGE_TO_SENSOR(intf, target, channel)) {
|
|
+ bridged_request = 1;
|
|
save_addr = intf->target_addr;
|
|
intf->target_addr = target;
|
|
save_channel = intf->target_channel;
|
|
@@ -145,7 +147,7 @@ ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf,
|
|
req.msg.data_len = sizeof (set_thresh_rq);
|
|
|
|
rsp = intf->sendrecv(intf, &req);
|
|
- if (save_addr) {
|
|
+ if (bridged_request) {
|
|
intf->target_addr = save_addr;
|
|
intf->target_channel = save_channel;
|
|
}
|
|
diff --git a/ipmitool/lib/ipmi_sol.c b/ipmitool/lib/ipmi_sol.c
|
|
index b17b60e..4b829fc 100644
|
|
--- a/ipmitool/lib/ipmi_sol.c
|
|
+++ b/ipmitool/lib/ipmi_sol.c
|
|
@@ -71,7 +71,7 @@
|
|
#define SOL_PARAMETER_SOL_PAYLOAD_CHANNEL 0x07
|
|
#define SOL_PARAMETER_SOL_PAYLOAD_PORT 0x08
|
|
|
|
-#define MAX_SOL_RETRY 6
|
|
+#define MAX_SOL_RETRY 6
|
|
|
|
const struct valstr sol_parameter_vals[] = {
|
|
{ SOL_PARAMETER_SET_IN_PROGRESS, "Set In Progress (0)" },
|
|
@@ -100,47 +100,45 @@ extern int verbose;
|
|
* ipmi_sol_payload_access
|
|
*/
|
|
int
|
|
-ipmi_sol_payload_access(struct ipmi_intf * intf,
|
|
- uint8_t channel,
|
|
- uint8_t userid,
|
|
- int enable)
|
|
+ipmi_sol_payload_access(struct ipmi_intf * intf, uint8_t channel,
|
|
+ uint8_t userid, int enable)
|
|
{
|
|
struct ipmi_rq req;
|
|
struct ipmi_rs *rsp;
|
|
+ int rc = (-1);
|
|
uint8_t data[6];
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
- req.msg.netfn = IPMI_NETFN_APP;
|
|
- req.msg.cmd = IPMI_SET_USER_PAYLOAD_ACCESS;
|
|
- req.msg.data = data;
|
|
+ req.msg.netfn = IPMI_NETFN_APP;
|
|
+ req.msg.cmd = IPMI_SET_USER_PAYLOAD_ACCESS;
|
|
+ req.msg.data = data;
|
|
req.msg.data_len = 6;
|
|
|
|
memset(data, 0, 6);
|
|
-
|
|
- data[0] = channel & 0xf; /* channel */
|
|
- data[1] = userid & 0x3f; /* user id */
|
|
- if (!enable)
|
|
- data[1] |= 0x40; /* disable */
|
|
- data[2] = 0x02; /* payload 1 is SOL */
|
|
-
|
|
+ /* channel */
|
|
+ data[0] = channel & 0xf;
|
|
+ /* user id */
|
|
+ data[1] = userid & 0x3f;
|
|
+ if (!enable) {
|
|
+ /* disable */
|
|
+ data[1] |= 0x40;
|
|
+ }
|
|
+ /* payload 1 is SOL */
|
|
+ data[2] = 0x02;
|
|
rsp = intf->sendrecv(intf, &req);
|
|
-
|
|
- if (NULL != rsp) {
|
|
- switch (rsp->ccode) {
|
|
- case 0x00:
|
|
- return 0;
|
|
- default:
|
|
- lprintf(LOG_ERR, "Error %sabling SOL payload for user %d on channel %d: %s",
|
|
- enable ? "en" : "dis", userid, channel,
|
|
- val2str(rsp->ccode, completion_code_vals));
|
|
- break;
|
|
- }
|
|
- } else {
|
|
+ if (rsp == NULL) {
|
|
lprintf(LOG_ERR, "Error %sabling SOL payload for user %d on channel %d",
|
|
- enable ? "en" : "dis", userid, channel);
|
|
+ enable ? "en" : "dis", userid, channel);
|
|
+ rc = (-1);
|
|
+ } else if (rsp->ccode != 0) {
|
|
+ lprintf(LOG_ERR, "Error %sabling SOL payload for user %d on channel %d: %s",
|
|
+ enable ? "en" : "dis", userid, channel,
|
|
+ val2str(rsp->ccode, completion_code_vals));
|
|
+ rc = (-1);
|
|
+ } else {
|
|
+ rc = 0;
|
|
}
|
|
-
|
|
- return -1;
|
|
+ return rc;
|
|
}
|
|
|
|
int
|
|
@@ -1931,29 +1929,21 @@ print_sol_set_usage(void)
|
|
|
|
|
|
|
|
-/*
|
|
- * ipmi_sol_main
|
|
- */
|
|
+/* ipmi_sol_main */
|
|
int
|
|
ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
int retval = 0;
|
|
-
|
|
- /*
|
|
- * Help
|
|
- */
|
|
- if (!argc || !strncmp(argv[0], "help", 4))
|
|
+ if (!argc || !strncmp(argv[0], "help", 4)) {
|
|
+ /* Help */
|
|
print_sol_usage();
|
|
-
|
|
- /*
|
|
- * Info
|
|
- */
|
|
- else if (!strncmp(argv[0], "info", 4)) {
|
|
+ } else if (!strncmp(argv[0], "info", 4)) {
|
|
+ /* Info */
|
|
uint8_t channel;
|
|
-
|
|
- if (argc == 1)
|
|
- channel = 0x0E; /* Ask about the current channel */
|
|
- else if (argc == 2) {
|
|
+ if (argc == 1) {
|
|
+ /* Ask about the current channel */
|
|
+ channel = 0x0E;
|
|
+ } else if (argc == 2) {
|
|
if (is_ipmi_channel_num(argv[1], &channel) != 0) {
|
|
return (-1);
|
|
}
|
|
@@ -1961,110 +1951,71 @@ ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
print_sol_usage();
|
|
return -1;
|
|
}
|
|
-
|
|
retval = ipmi_print_sol_info(intf, channel);
|
|
- }
|
|
-
|
|
- /*
|
|
- * Payload enable or disable
|
|
- */
|
|
- else if (!strncmp(argv[0], "payload", 7)) {
|
|
+ } else if (!strncmp(argv[0], "payload", 7)) {
|
|
+ /* Payload enable or disable */
|
|
uint8_t channel = 0xe;
|
|
uint8_t userid = 1;
|
|
int enable = -1;
|
|
-
|
|
- if (argc == 1 || argc > 4)
|
|
- {
|
|
+ if (argc == 1 || argc > 4) {
|
|
print_sol_usage();
|
|
return -1;
|
|
}
|
|
-
|
|
- if (argc == 1 || argc > 4)
|
|
- {
|
|
+ if (argc == 1 || argc > 4) {
|
|
print_sol_usage();
|
|
return -1;
|
|
}
|
|
-
|
|
if (argc >= 3) {
|
|
if (is_ipmi_channel_num(argv[2], &channel) != 0) {
|
|
return (-1);
|
|
}
|
|
}
|
|
- if (argc == 4)
|
|
- {
|
|
+ if (argc == 4) {
|
|
if (is_ipmi_user_id(argv[3], &userid) != 0) {
|
|
return (-1);
|
|
}
|
|
}
|
|
-
|
|
- if (!strncmp(argv[1], "enable", 6))
|
|
- {
|
|
+ if (!strncmp(argv[1], "enable", 6)) {
|
|
enable = 1;
|
|
- }
|
|
- else if (!strncmp(argv[1], "disable", 7))
|
|
- {
|
|
+ } else if (!strncmp(argv[1], "disable", 7)) {
|
|
enable = 0;
|
|
- }
|
|
- else if (!strncmp(argv[1], "status", 6))
|
|
- {
|
|
+ } else if (!strncmp(argv[1], "status", 6)) {
|
|
return ipmi_sol_payload_access_status(intf, channel, userid);
|
|
- }
|
|
- else
|
|
- {
|
|
+ } else {
|
|
print_sol_usage();
|
|
return -1;
|
|
}
|
|
-
|
|
retval = ipmi_sol_payload_access(intf, channel, userid, enable);
|
|
- }
|
|
-
|
|
-
|
|
- /*
|
|
- * Set a parameter value
|
|
- */
|
|
- else if (!strncmp(argv[0], "set", 3)) {
|
|
+ } else if (!strncmp(argv[0], "set", 3)) {
|
|
+ /* Set a parameter value */
|
|
uint8_t channel = 0xe;
|
|
uint8_t guard = 1;
|
|
-
|
|
- if (argc == 3)
|
|
- {
|
|
+ if (argc == 3) {
|
|
channel = 0xe;
|
|
- }
|
|
- else if (argc == 4)
|
|
- {
|
|
- if (!strncmp(argv[3], "noguard", 7))
|
|
+ } else if (argc == 4) {
|
|
+ if (!strncmp(argv[3], "noguard", 7)) {
|
|
guard = 0;
|
|
- else {
|
|
+ } else {
|
|
if (is_ipmi_channel_num(argv[3], &channel) != 0) {
|
|
return (-1);
|
|
}
|
|
}
|
|
- }
|
|
- else if (argc == 5)
|
|
- {
|
|
+ } else if (argc == 5) {
|
|
if (is_ipmi_channel_num(argv[3], &channel) != 0) {
|
|
return (-1);
|
|
}
|
|
- if (!strncmp(argv[4], "noguard", 7))
|
|
+ if (!strncmp(argv[4], "noguard", 7)) {
|
|
guard = 0;
|
|
- }
|
|
- else
|
|
- {
|
|
+ }
|
|
+ } else {
|
|
print_sol_set_usage();
|
|
return -1;
|
|
}
|
|
-
|
|
retval = ipmi_sol_set_param(intf, channel, argv[1], argv[2], guard);
|
|
- }
|
|
-
|
|
-
|
|
- /*
|
|
- * Activate
|
|
- */
|
|
- else if (!strncmp(argv[0], "activate", 8)) {
|
|
+ } else if (!strncmp(argv[0], "activate", 8)) {
|
|
+ /* Activate */
|
|
int i;
|
|
uint8_t instance = 1;
|
|
-
|
|
for (i = 1; i < argc; i++) {
|
|
if (!strncmp(argv[i], "usesolkeepalive", 15)) {
|
|
_use_sol_for_keepalive = 1;
|
|
@@ -2082,20 +2033,16 @@ ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
}
|
|
}
|
|
retval = ipmi_sol_activate(intf, 0, 0, instance);
|
|
- }
|
|
-
|
|
-
|
|
- /*
|
|
- * Dectivate
|
|
- */
|
|
- else if (!strncmp(argv[0], "deactivate", 10)) {
|
|
+ } else if (!strncmp(argv[0], "deactivate", 10)) {
|
|
+ /* Dectivate */
|
|
int i;
|
|
uint8_t instance = 1;
|
|
-
|
|
for (i = 1; i < argc; i++) {
|
|
if (!strncmp(argv[i], "instance=", 9)) {
|
|
if (str2uchar(argv[i] + 9, &instance) != 0) {
|
|
- lprintf(LOG_ERR, "Given instance '%s' is invalid.", argv[i] + 9);
|
|
+ lprintf(LOG_ERR,
|
|
+ "Given instance '%s' is invalid.",
|
|
+ argv[i] + 9);
|
|
print_sol_usage();
|
|
return -1;
|
|
}
|
|
@@ -2105,66 +2052,58 @@ ipmi_sol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
}
|
|
}
|
|
retval = ipmi_sol_deactivate(intf, instance);
|
|
- }
|
|
-
|
|
- /*
|
|
- * SOL loop test: Activate and then Dectivate
|
|
- */
|
|
- else if (!strncmp(argv[0], "looptest", 8))
|
|
- {
|
|
+ } else if (!strncmp(argv[0], "looptest", 8)) {
|
|
+ /* SOL loop test: Activate and then Dectivate */
|
|
int cnt = 200;
|
|
int interval = 100; /* Unit is: ms */
|
|
- uint8_t instance;
|
|
-
|
|
- if (argc > 4)
|
|
- {
|
|
+ uint8_t instance = 1;
|
|
+ if (argc > 4) {
|
|
print_sol_usage();
|
|
return -1;
|
|
}
|
|
- if (argc != 1) /* at least 2 */
|
|
- {
|
|
+ if (argc != 1) {
|
|
+ /* at least 2 */
|
|
if (str2int(argv[1], &cnt) != 0) {
|
|
lprintf(LOG_ERR, "Given cnt '%s' is invalid.",
|
|
argv[1]);
|
|
return (-1);
|
|
}
|
|
- if(cnt <= 0) cnt = 200;
|
|
+ if (cnt <= 0) {
|
|
+ cnt = 200;
|
|
+ }
|
|
}
|
|
- if (argc >= 3)
|
|
- {
|
|
+ if (argc >= 3) {
|
|
if (str2int(argv[2], &interval) != 0) {
|
|
lprintf(LOG_ERR, "Given interval '%s' is invalid.",
|
|
argv[2]);
|
|
return (-1);
|
|
}
|
|
- if(interval < 0) interval = 0;
|
|
+ if (interval < 0) {
|
|
+ interval = 0;
|
|
+ }
|
|
}
|
|
if (argc >= 4) {
|
|
if (str2uchar(argv[3], &instance) != 0) {
|
|
- lprintf(LOG_ERR, "Given instance '%s' is invalid.", argv[3]);
|
|
+ lprintf(LOG_ERR, "Given instance '%s' is invalid.",
|
|
+ argv[3]);
|
|
print_sol_usage();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
- while (cnt > 0)
|
|
- {
|
|
+ while (cnt > 0) {
|
|
printf("remain loop test counter: %d\n", cnt);
|
|
retval = ipmi_sol_activate(intf, 1, interval, instance);
|
|
- if (retval)
|
|
- {
|
|
- printf("SOL looptest failed: %d\n", retval);
|
|
+ if (retval) {
|
|
+ printf("SOL looptest failed: %d\n",
|
|
+ retval);
|
|
break;
|
|
}
|
|
cnt -= 1;
|
|
}
|
|
- }
|
|
-
|
|
- else
|
|
- {
|
|
+ } else {
|
|
print_sol_usage();
|
|
retval = -1;
|
|
}
|
|
-
|
|
return retval;
|
|
}
|
|
diff --git a/ipmitool/lib/ipmi_tsol.c b/ipmitool/lib/ipmi_tsol.c
|
|
index be53236..94ea284 100644
|
|
--- a/ipmitool/lib/ipmi_tsol.c
|
|
+++ b/ipmitool/lib/ipmi_tsol.c
|
|
@@ -381,7 +381,7 @@ int
|
|
ipmi_tsol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
struct pollfd fds_wait[3], fds_data_wait[3], *fds;
|
|
- struct sockaddr_in sin, myaddr;
|
|
+ struct sockaddr_in sin, myaddr, *sa_in;
|
|
socklen_t mylen;
|
|
char *recvip = NULL;
|
|
char out_buff[IPMI_BUF_SIZE * 8], in_buff[IPMI_BUF_SIZE];
|
|
@@ -398,8 +398,11 @@ ipmi_tsol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
}
|
|
|
|
for (i = 0; i<argc; i++) {
|
|
- if (sscanf(argv[i], "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) == 4)
|
|
- recvip = strdup(argv[i]);
|
|
+ if (sscanf(argv[i], "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) == 4) {
|
|
+ /* not free'd ...*/
|
|
+ /* recvip = strdup(argv[i]); */
|
|
+ recvip = argv[i];
|
|
+ }
|
|
else if (sscanf(argv[i], "port=%d", &ip1) == 1)
|
|
port = ip1;
|
|
else if (sscanf(argv[i], "rows=%d", &ip1) == 1)
|
|
@@ -427,8 +430,9 @@ ipmi_tsol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
sin.sin_family = AF_INET;
|
|
sin.sin_port = htons(port);
|
|
|
|
+ sa_in = (struct sockaddr_in *)&intf->session->addr;
|
|
result = inet_pton(AF_INET, (const char *)intf->session->hostname,
|
|
- &intf->session->addr.sin_addr);
|
|
+ &sa_in->sin_addr);
|
|
|
|
if (result <= 0) {
|
|
struct hostent *host = gethostbyname((const char *)intf->session->hostname);
|
|
@@ -444,8 +448,8 @@ ipmi_tsol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
(host->h_addrtype == AF_INET6) ? "IPv6" : "Unknown");
|
|
return (-1);
|
|
}
|
|
- intf->session->addr.sin_family = host->h_addrtype;
|
|
- memcpy(&intf->session->addr.sin_addr, host->h_addr, host->h_length);
|
|
+ sa_in->sin_family = host->h_addrtype;
|
|
+ memcpy(&sa_in->sin_addr, host->h_addr, host->h_length);
|
|
}
|
|
|
|
fd_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
@@ -455,6 +459,7 @@ ipmi_tsol_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
}
|
|
if (-1 == bind(fd_socket, (struct sockaddr *)&sin, sizeof(sin))) {
|
|
lprintf(LOG_ERR, "Failed to bind socket.");
|
|
+ close(fd_socket);
|
|
return -1;
|
|
}
|
|
|
|
diff --git a/ipmitool/src/plugins/Makefile.am b/ipmitool/src/plugins/Makefile.am
|
|
index 9d5c2c2..19b5f11 100644
|
|
--- a/ipmitool/src/plugins/Makefile.am
|
|
+++ b/ipmitool/src/plugins/Makefile.am
|
|
@@ -32,8 +32,8 @@ MAINTAINERCLEANFILES = Makefile.in
|
|
|
|
INCLUDES = -I$(top_srcdir)/include
|
|
|
|
-SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@
|
|
-DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial
|
|
+SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@
|
|
+DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy
|
|
|
|
noinst_LTLIBRARIES = libintf.la
|
|
libintf_la_SOURCES = ipmi_intf.c
|
|
diff --git a/ipmitool/src/plugins/dummy/Makefile.am b/ipmitool/src/plugins/dummy/Makefile.am
|
|
new file mode 100644
|
|
index 0000000..8a53bbe
|
|
--- /dev/null
|
|
+++ b/ipmitool/src/plugins/dummy/Makefile.am
|
|
@@ -0,0 +1,8 @@
|
|
+MAINTAINERCLEANFILES = Makefile.in
|
|
+
|
|
+INCLUDES = -I$(top_srcdir)/include
|
|
+
|
|
+EXTRA_LTLIBRARIES = libintf_dummy.la
|
|
+noinst_LTLIBRARIES = @INTF_DUMMY_LIB@
|
|
+libintf_dummy_la_LIBADD = $(top_builddir)/lib/libipmitool.la
|
|
+libintf_dummy_la_SOURCES = dummy.c
|
|
diff --git a/ipmitool/src/plugins/dummy/dummy.c b/ipmitool/src/plugins/dummy/dummy.c
|
|
new file mode 100644
|
|
index 0000000..eb2d086
|
|
--- /dev/null
|
|
+++ b/ipmitool/src/plugins/dummy/dummy.c
|
|
@@ -0,0 +1,286 @@
|
|
+/* Copyright (c) 2013 Zdenek Styblik, All Rights Reserved
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions
|
|
+ * are met:
|
|
+ *
|
|
+ * Redistribution of source code must retain the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer.
|
|
+ *
|
|
+ * Redistribution in binary form must reproduce the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer in the
|
|
+ * documentation and/or other materials provided with the distribution.
|
|
+ *
|
|
+ * Neither the name of Zdenek Styblik or the names of
|
|
+ * contributors may be used to endorse or promote products derived
|
|
+ * from this software without specific prior written permission.
|
|
+ *
|
|
+ * This software is provided "AS IS," without a warranty of any kind.
|
|
+ * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
|
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
|
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
|
|
+ * Zdenek Styblik SHALL NOT BE LIABLE
|
|
+ * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
|
+ * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
|
|
+ * Zdenek Styblik BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
|
|
+ * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
|
|
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
|
|
+ * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
|
+ * EVEN IF Zdenek Styblik HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
+ */
|
|
+#include <errno.h>
|
|
+#include <limits.h>
|
|
+#include <stdio.h>
|
|
+#include <sys/socket.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/un.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+#include <ipmitool/ipmi.h>
|
|
+#include <ipmitool/ipmi_intf.h>
|
|
+#include <ipmitool/helper.h>
|
|
+#include <ipmitool/log.h>
|
|
+
|
|
+#include "dummy.h"
|
|
+
|
|
+#if defined(HAVE_CONFIG_H)
|
|
+# include <config.h>
|
|
+#endif
|
|
+
|
|
+extern int verbose;
|
|
+
|
|
+/* data_read - read data from socket
|
|
+ *
|
|
+ * @data_ptr - pointer to memory where to store read data
|
|
+ * @data_len - how much to read from socket
|
|
+ *
|
|
+ * return 0 on success, otherwise (-1)
|
|
+ */
|
|
+int
|
|
+data_read(int fd, void *data_ptr, int data_len)
|
|
+{
|
|
+ int rc = 0;
|
|
+ int data_read = 0;
|
|
+ int data_total = 0;
|
|
+ int try = 1;
|
|
+ int errno_save = 0;
|
|
+ if (data_len < 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ while (data_total < data_len && try < 4) {
|
|
+ errno = 0;
|
|
+ /* TODO - add poll() */
|
|
+ data_read = read(fd, data_ptr, data_len);
|
|
+ errno_save = errno;
|
|
+ if (data_read > 0) {
|
|
+ data_total+= data_read;
|
|
+ }
|
|
+ if (errno_save != 0) {
|
|
+ if (errno_save == EINTR || errno_save == EAGAIN) {
|
|
+ try++;
|
|
+ sleep(2);
|
|
+ continue;
|
|
+ } else {
|
|
+ errno = errno_save;
|
|
+ perror("dummy failed on read(): ");
|
|
+ rc = (-1);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (try > 3 && data_total != data_len) {
|
|
+ rc = (-1);
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/* data_write - write data to the socket
|
|
+ *
|
|
+ * @data_ptr - ptr to data to send
|
|
+ * @data_len - how long is the data to send
|
|
+ *
|
|
+ * returns 0 on success, otherwise (-1)
|
|
+ */
|
|
+int
|
|
+data_write(int fd, void *data_ptr, int data_len)
|
|
+{
|
|
+ int rc = 0;
|
|
+ int data_written = 0;
|
|
+ int data_total = 0;
|
|
+ int try = 1;
|
|
+ int errno_save = 0;
|
|
+ if (data_len < 0) {
|
|
+ return (-1);
|
|
+ }
|
|
+ while (data_total < data_len && try < 4) {
|
|
+ errno = 0;
|
|
+ /* TODO - add poll() */
|
|
+ data_written = write(fd, data_ptr, data_len);
|
|
+ errno_save = errno;
|
|
+ if (data_read > 0) {
|
|
+ data_total+= data_written;
|
|
+ }
|
|
+ if (errno_save != 0) {
|
|
+ if (errno_save == EINTR || errno_save == EAGAIN) {
|
|
+ try++;
|
|
+ sleep(2);
|
|
+ continue;
|
|
+ } else {
|
|
+ errno = errno_save;
|
|
+ perror("dummy failed on read(): ");
|
|
+ rc = (-1);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (try > 3 && data_total != data_len) {
|
|
+ rc = (-1);
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/* ipmi_dummyipmi_close - send "BYE" and close socket
|
|
+ *
|
|
+ * @intf - ptr to initialize ipmi_intf struct
|
|
+ *
|
|
+ * returns void
|
|
+ */
|
|
+static void
|
|
+ipmi_dummyipmi_close(struct ipmi_intf *intf)
|
|
+{
|
|
+ struct dummy_rq req;
|
|
+ int data_total = 0;
|
|
+ int data_written = 0;
|
|
+ int try = 0;
|
|
+ if (intf->fd < 0) {
|
|
+ return;
|
|
+ }
|
|
+ memset(&req, 0, sizeof(req));
|
|
+ req.msg.netfn = 0x3f;
|
|
+ req.msg.cmd = 0xff;
|
|
+ if (data_write(intf->fd, &req, sizeof(req)) != 0) {
|
|
+ lprintf(LOG_ERR, "dummy failed to send 'BYE'");
|
|
+ }
|
|
+ close(intf->fd);
|
|
+ intf->fd = (-1);
|
|
+ intf->opened = 0;
|
|
+}
|
|
+
|
|
+/* ipmi_dummyipmi_open - open socket and prepare ipmi_intf struct
|
|
+ *
|
|
+ * @intf - ptr to ipmi_inf struct
|
|
+ *
|
|
+ * returns 0 on success, (-1) on error
|
|
+ */
|
|
+static int
|
|
+ipmi_dummyipmi_open(struct ipmi_intf *intf)
|
|
+{
|
|
+ struct sockaddr_un address;
|
|
+ int len;
|
|
+ int rc;
|
|
+
|
|
+ if (intf->opened == 1) {
|
|
+ return intf->fd;
|
|
+ }
|
|
+ intf->fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
+ if (intf->fd == (-1)) {
|
|
+ lprintf(LOG_ERR, "dummy failed on socket()");
|
|
+ return (-1);
|
|
+ }
|
|
+ address.sun_family = AF_UNIX;
|
|
+ strcpy(address.sun_path, DUMMY_SOCKET_PATH);
|
|
+ len = sizeof(address);
|
|
+ rc = connect(intf->fd, (struct sockaddr *)&address, len);
|
|
+ if (rc != 0) {
|
|
+ perror("dummy failed on connect(): ");
|
|
+ return (-1);
|
|
+ }
|
|
+ intf->opened = 1;
|
|
+ return intf->fd;
|
|
+}
|
|
+
|
|
+/* ipmi_dummyipmi_send_cmd - send IPMI payload and await reply
|
|
+ *
|
|
+ * @intf - ptr to initialized ipmi_intf struct
|
|
+ * @req - ptr to ipmi_rq struct to send
|
|
+ *
|
|
+ * return pointer to struct ipmi_rs OR NULL on error
|
|
+ */
|
|
+static struct ipmi_rs*
|
|
+ipmi_dummyipmi_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
|
|
+{
|
|
+ static struct ipmi_rs rsp;
|
|
+ struct dummy_rq req_dummy;
|
|
+ struct dummy_rs rsp_dummy;
|
|
+ if (intf == NULL || intf->fd < 0 || intf->opened != 1) {
|
|
+ lprintf(LOG_ERR, "dummy failed on intf check.");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ memset(&req_dummy, 0, sizeof(req_dummy));
|
|
+ req_dummy.msg.netfn = req->msg.netfn;
|
|
+ req_dummy.msg.lun = req->msg.lun;
|
|
+ req_dummy.msg.cmd = req->msg.cmd;
|
|
+ req_dummy.msg.target_cmd = req->msg.target_cmd;
|
|
+ req_dummy.msg.data_len = req->msg.data_len;
|
|
+ req_dummy.msg.data = req->msg.data;
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE, ">>> IPMI req");
|
|
+ lprintf(LOG_NOTICE, "msg.data_len: %i",
|
|
+ req_dummy.msg.data_len);
|
|
+ lprintf(LOG_NOTICE, "msg.netfn: %x", req_dummy.msg.netfn);
|
|
+ lprintf(LOG_NOTICE, "msg.cmd: %x", req_dummy.msg.cmd);
|
|
+ lprintf(LOG_NOTICE, "msg.target_cmd: %x",
|
|
+ req_dummy.msg.target_cmd);
|
|
+ lprintf(LOG_NOTICE, "msg.lun: %x", req_dummy.msg.lun);
|
|
+ lprintf(LOG_NOTICE, ">>>");
|
|
+ }
|
|
+ if (data_write(intf->fd, &req_dummy,
|
|
+ sizeof(struct dummy_rq)) != 0) {
|
|
+ return NULL;
|
|
+ }
|
|
+ if (req->msg.data_len > 0) {
|
|
+ if (data_write(intf->fd, (uint8_t *)(req->msg.data),
|
|
+ req_dummy.msg.data_len) != 0) {
|
|
+ return NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ memset(&rsp_dummy, 0, sizeof(rsp_dummy));
|
|
+ if (data_read(intf->fd, &rsp_dummy, sizeof(struct dummy_rs)) != 0) {
|
|
+ return NULL;
|
|
+ }
|
|
+ if (rsp_dummy.data_len > 0) {
|
|
+ if (data_read(intf->fd, (uint8_t *)&rsp.data,
|
|
+ rsp_dummy.data_len) != 0) {
|
|
+ return NULL;
|
|
+ }
|
|
+ }
|
|
+ rsp.ccode = rsp_dummy.ccode;
|
|
+ rsp.data_len = rsp_dummy.data_len;
|
|
+ rsp.msg.netfn = rsp_dummy.msg.netfn;
|
|
+ rsp.msg.cmd = rsp_dummy.msg.cmd;
|
|
+ rsp.msg.seq = rsp_dummy.msg.seq;
|
|
+ rsp.msg.lun = rsp_dummy.msg.lun;
|
|
+ if (verbose) {
|
|
+ lprintf(LOG_NOTICE, "<<< IPMI rsp");
|
|
+ lprintf(LOG_NOTICE, "ccode: %x", rsp.ccode);
|
|
+ lprintf(LOG_NOTICE, "data_len: %i", rsp.data_len);
|
|
+ lprintf(LOG_NOTICE, "msg.netfn: %x", rsp.msg.netfn);
|
|
+ lprintf(LOG_NOTICE, "msg.cmd: %x", rsp.msg.cmd);
|
|
+ lprintf(LOG_NOTICE, "msg.seq: %x", rsp.msg.seq);
|
|
+ lprintf(LOG_NOTICE, "msg.lun: %x", rsp.msg.lun);
|
|
+ lprintf(LOG_NOTICE, "<<<");
|
|
+ }
|
|
+ return &rsp;
|
|
+}
|
|
+
|
|
+struct ipmi_intf ipmi_dummy_intf = {
|
|
+ name: "dummy",
|
|
+ desc: "Linux DummyIPMI Interface",
|
|
+ open: ipmi_dummyipmi_open,
|
|
+ close: ipmi_dummyipmi_close,
|
|
+ sendrecv: ipmi_dummyipmi_send_cmd,
|
|
+ my_addr: IPMI_BMC_SLAVE_ADDR,
|
|
+ target_addr: IPMI_BMC_SLAVE_ADDR,
|
|
+};
|
|
diff --git a/ipmitool/src/plugins/dummy/dummy.h b/ipmitool/src/plugins/dummy/dummy.h
|
|
new file mode 100644
|
|
index 0000000..dac9caa
|
|
--- /dev/null
|
|
+++ b/ipmitool/src/plugins/dummy/dummy.h
|
|
@@ -0,0 +1,30 @@
|
|
+#ifndef IPMI_DUMMYIPMI_H
|
|
+# define IPMI_DUMMYIPMI_H
|
|
+
|
|
+# define DUMMY_SOCKET_PATH "/tmp/.ipmi_dummy"
|
|
+
|
|
+struct dummy_rq {
|
|
+ struct {
|
|
+ uint8_t netfn;
|
|
+ uint8_t lun;
|
|
+ uint8_t cmd;
|
|
+ uint8_t target_cmd;
|
|
+ uint16_t data_len;
|
|
+ uint8_t *data;
|
|
+ } msg;
|
|
+};
|
|
+
|
|
+struct dummy_rs {
|
|
+ struct {
|
|
+ uint8_t netfn;
|
|
+ uint8_t cmd;
|
|
+ uint8_t seq;
|
|
+ uint8_t lun;
|
|
+ } msg;
|
|
+
|
|
+ uint8_t ccode;
|
|
+ int data_len;
|
|
+ uint8_t *data;
|
|
+};
|
|
+
|
|
+#endif
|
|
diff --git a/ipmitool/src/plugins/ipmi_intf.c b/ipmitool/src/plugins/ipmi_intf.c
|
|
index d0c483a..48e2b61 100644
|
|
--- a/ipmitool/src/plugins/ipmi_intf.c
|
|
+++ b/ipmitool/src/plugins/ipmi_intf.c
|
|
@@ -36,6 +36,18 @@
|
|
#if defined(HAVE_CONFIG_H)
|
|
# include <config.h>
|
|
#endif
|
|
+
|
|
+#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
|
|
+#include <sys/types.h>
|
|
+#include <sys/socket.h>
|
|
+#include <netinet/in.h>
|
|
+#include <arpa/inet.h>
|
|
+#include <ifaddrs.h>
|
|
+#include <unistd.h>
|
|
+#include <netdb.h>
|
|
+#endif
|
|
+
|
|
+
|
|
#include <ipmitool/ipmi_intf.h>
|
|
#include <ipmitool/ipmi.h>
|
|
#include <ipmitool/ipmi_sdr.h>
|
|
@@ -66,6 +78,9 @@ extern struct ipmi_intf ipmi_free_intf;
|
|
extern struct ipmi_intf ipmi_serial_term_intf;
|
|
extern struct ipmi_intf ipmi_serial_bm_intf;
|
|
#endif
|
|
+#ifdef IPMI_INTF_DUMMY
|
|
+extern struct ipmi_intf ipmi_dummy_intf;
|
|
+#endif
|
|
|
|
struct ipmi_intf * ipmi_intf_table[] = {
|
|
#ifdef IPMI_INTF_OPEN
|
|
@@ -93,6 +108,9 @@ struct ipmi_intf * ipmi_intf_table[] = {
|
|
&ipmi_serial_term_intf,
|
|
&ipmi_serial_bm_intf,
|
|
#endif
|
|
+#ifdef IPMI_INTF_DUMMY
|
|
+ &ipmi_dummy_intf,
|
|
+#endif
|
|
NULL
|
|
};
|
|
|
|
@@ -315,3 +333,167 @@ ipmi_cleanup(struct ipmi_intf * intf)
|
|
{
|
|
ipmi_sdr_list_empty(intf);
|
|
}
|
|
+
|
|
+#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS)
|
|
+int
|
|
+ipmi_intf_socket_connect(struct ipmi_intf * intf)
|
|
+{
|
|
+ struct ipmi_session *session;
|
|
+
|
|
+ struct sockaddr_storage addr;
|
|
+ struct addrinfo hints;
|
|
+ struct addrinfo *rp0 = NULL, *rp;
|
|
+ char service[NI_MAXSERV];
|
|
+ int rc;
|
|
+
|
|
+ if (!intf || intf->session == NULL) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ session = intf->session;
|
|
+
|
|
+ if (session->hostname == NULL || strlen((const char *)session->hostname) == 0) {
|
|
+ lprintf(LOG_ERR, "No hostname specified!");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /* open port to BMC */
|
|
+ memset(&addr, 0, sizeof(addr));
|
|
+
|
|
+ sprintf(service, "%d", session->port);
|
|
+ /* Obtain address(es) matching host/port */
|
|
+ memset(&hints, 0, sizeof(hints));
|
|
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
|
|
+ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
|
|
+ hints.ai_flags = 0; /* use AI_NUMERICSERV for no name resolution */
|
|
+ hints.ai_protocol = IPPROTO_UDP; /* */
|
|
+
|
|
+ if (getaddrinfo(session->hostname, service, &hints, &rp0) != 0) {
|
|
+ lprintf(LOG_ERR, "Address lookup for %s failed",
|
|
+ session->hostname);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ /* getaddrinfo() returns a list of address structures.
|
|
+ * Try each address until we successfully connect(2).
|
|
+ * If socket(2) (or connect(2)) fails, we (close the socket
|
|
+ * and) try the next address.
|
|
+ */
|
|
+
|
|
+ session->ai_family = AF_UNSPEC;
|
|
+ for (rp = rp0; rp != NULL; rp = rp->ai_next) {
|
|
+ /* We are only interested in IPv4 and IPv6 */
|
|
+ if ((rp->ai_family != AF_INET6) && (rp->ai_family != AF_INET)) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ intf->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
|
+ if (intf->fd == -1) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (rp->ai_family == AF_INET) {
|
|
+ if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
|
|
+ memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
|
|
+ session->addrlen = rp->ai_addrlen;
|
|
+ session->ai_family = rp->ai_family;
|
|
+ break; /* Success */
|
|
+ }
|
|
+ } else if (rp->ai_family == AF_INET6) {
|
|
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)rp->ai_addr;
|
|
+ char hbuf[NI_MAXHOST];
|
|
+ socklen_t len;
|
|
+
|
|
+ /* The scope was specified on the command line e.g. with -H FE80::219:99FF:FEA0:BD95%eth0 */
|
|
+ if (addr6->sin6_scope_id != 0) {
|
|
+ len = sizeof(struct sockaddr_in6);
|
|
+ if (getnameinfo((struct sockaddr *)addr6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
|
|
+ lprintf(LOG_DEBUG, "Trying address: %s scope=%d",
|
|
+ hbuf,
|
|
+ addr6->sin6_scope_id);
|
|
+ }
|
|
+ if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
|
|
+ memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
|
|
+ session->addrlen = rp->ai_addrlen;
|
|
+ session->ai_family = rp->ai_family;
|
|
+ break; /* Success */
|
|
+ }
|
|
+ } else {
|
|
+ /* No scope specified, try to get this from the list of interfaces */
|
|
+ struct ifaddrs *ifaddrs = NULL;
|
|
+ struct ifaddrs *ifa = NULL;
|
|
+
|
|
+ if (getifaddrs(&ifaddrs) < 0) {
|
|
+ lprintf(LOG_ERR, "Interface address lookup for %s failed",
|
|
+ session->hostname);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
|
+ if (ifa->ifa_addr == NULL) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (ifa->ifa_addr->sa_family == AF_INET6) {
|
|
+ struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
|
+
|
|
+ /* Skip unwanted addresses */
|
|
+ if (IN6_IS_ADDR_MULTICAST(&tmp6->sin6_addr)) {
|
|
+ continue;
|
|
+ }
|
|
+ if (IN6_IS_ADDR_LOOPBACK(&tmp6->sin6_addr)) {
|
|
+ continue;
|
|
+ }
|
|
+ len = sizeof(struct sockaddr_in6);
|
|
+ if ( getnameinfo((struct sockaddr *)tmp6, len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0) {
|
|
+ lprintf(LOG_DEBUG, "Testing %s interface address: %s scope=%d",
|
|
+ ifa->ifa_name != NULL ? ifa->ifa_name : "???",
|
|
+ hbuf,
|
|
+ tmp6->sin6_scope_id);
|
|
+ }
|
|
+
|
|
+ if (tmp6->sin6_scope_id != 0) {
|
|
+ addr6->sin6_scope_id = tmp6->sin6_scope_id;
|
|
+ } else {
|
|
+ /*
|
|
+ * No scope information in interface address information
|
|
+ * On some OS'es, getifaddrs() is returning out the 'kernel' representation
|
|
+ * of scoped addresses which stores the scope in the 3rd and 4th
|
|
+ * byte. See also this page:
|
|
+ * http://www.freebsd.org/doc/en/books/developers-handbook/ipv6.html
|
|
+ */
|
|
+ if (IN6_IS_ADDR_LINKLOCAL(&tmp6->sin6_addr)
|
|
+ && (tmp6->sin6_addr.s6_addr16[1] != 0)) {
|
|
+ addr6->sin6_scope_id = ntohs(tmp6->sin6_addr.s6_addr16[1]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* OK, now try to connect with the scope id from this interface address */
|
|
+ if (addr6->sin6_scope_id != 0) {
|
|
+ if (connect(intf->fd, rp->ai_addr, rp->ai_addrlen) != -1) {
|
|
+ memcpy(&session->addr, rp->ai_addr, rp->ai_addrlen);
|
|
+ session->addrlen = rp->ai_addrlen;
|
|
+ session->ai_family = rp->ai_family;
|
|
+ lprintf(LOG_DEBUG, "Successful connected on %s interface with scope id %d", ifa->ifa_name, tmp6->sin6_scope_id);
|
|
+ break; /* Success */
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ freeifaddrs(ifaddrs);
|
|
+ }
|
|
+ }
|
|
+ if (session->ai_family != AF_UNSPEC) {
|
|
+ break;
|
|
+ }
|
|
+ close(intf->fd);
|
|
+ intf->fd = -1;
|
|
+ }
|
|
+
|
|
+ /* No longer needed */
|
|
+ freeaddrinfo(rp0);
|
|
+
|
|
+ return ((intf->fd != -1) ? 0 : -1);
|
|
+}
|
|
+#endif
|
|
+
|
|
diff --git a/ipmitool/src/plugins/lan/lan.c b/ipmitool/src/plugins/lan/lan.c
|
|
index e088479..fc90000 100644
|
|
--- a/ipmitool/src/plugins/lan/lan.c
|
|
+++ b/ipmitool/src/plugins/lan/lan.c
|
|
@@ -2032,44 +2032,14 @@ ipmi_lan_open(struct ipmi_intf * intf)
|
|
|
|
intf->session->sol_data.sequence_number = 1;
|
|
|
|
- /* open port to BMC */
|
|
- memset(&s->addr, 0, sizeof(struct sockaddr_in));
|
|
- s->addr.sin_family = AF_INET;
|
|
- s->addr.sin_port = htons(s->port);
|
|
-
|
|
- rc = inet_pton(AF_INET, (const char *)s->hostname, &s->addr.sin_addr);
|
|
- if (rc <= 0) {
|
|
- struct hostent *host = gethostbyname((const char *)s->hostname);
|
|
- if (host == NULL) {
|
|
- lprintf(LOG_ERR, "Address lookup for %s failed",
|
|
- s->hostname);
|
|
- return -1;
|
|
- }
|
|
- if (host->h_addrtype != AF_INET) {
|
|
- lprintf(LOG_ERR,
|
|
- "Address lookup for %s failed. Got %s, expected IPv4 address.",
|
|
- s->hostname,
|
|
- (host->h_addrtype == AF_INET6) ? "IPv6" : "Unknown");
|
|
- return (-1);
|
|
- }
|
|
- s->addr.sin_family = host->h_addrtype;
|
|
- memcpy(&s->addr.sin_addr, host->h_addr, host->h_length);
|
|
- }
|
|
-
|
|
- lprintf(LOG_DEBUG, "IPMI LAN host %s port %d",
|
|
- s->hostname, ntohs(s->addr.sin_port));
|
|
-
|
|
- intf->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
- if (intf->fd < 0) {
|
|
- lperror(LOG_ERR, "Socket failed");
|
|
+ if (ipmi_intf_socket_connect (intf) == -1) {
|
|
+ lprintf(LOG_ERR, "Could not open socket!");
|
|
return -1;
|
|
}
|
|
|
|
- /* connect to UDP socket so we get async errors */
|
|
- rc = connect(intf->fd, (struct sockaddr *)&s->addr,
|
|
- sizeof(struct sockaddr_in));
|
|
- if (rc < 0) {
|
|
- lperror(LOG_ERR, "Connect failed");
|
|
+ if (intf->fd < 0) {
|
|
+ lperror(LOG_ERR, "Connect to %s failed",
|
|
+ s->hostname);
|
|
intf->close(intf);
|
|
return -1;
|
|
}
|
|
diff --git a/ipmitool/src/plugins/lanplus/lanplus.c b/ipmitool/src/plugins/lanplus/lanplus.c
|
|
index acf2410..17d42a4 100644
|
|
--- a/ipmitool/src/plugins/lanplus/lanplus.c
|
|
+++ b/ipmitool/src/plugins/lanplus/lanplus.c
|
|
@@ -84,14 +84,14 @@ static struct ipmi_rs * ipmi_lanplus_send_ipmi_cmd(struct ipmi_intf * intf, stru
|
|
static struct ipmi_rs * ipmi_lanplus_send_payload(struct ipmi_intf * intf,
|
|
struct ipmi_v2_payload * payload);
|
|
static void getIpmiPayloadWireRep(
|
|
- struct ipmi_intf * intf,
|
|
- struct ipmi_v2_payload * payload, /* in */
|
|
+ struct ipmi_intf * intf,
|
|
+ struct ipmi_v2_payload * payload, /* in */
|
|
uint8_t * out,
|
|
struct ipmi_rq * req,
|
|
uint8_t rq_seq,
|
|
- uint8_t curr_seq);
|
|
+ uint8_t curr_seq);
|
|
static void getSolPayloadWireRep(
|
|
- struct ipmi_intf * intf,
|
|
+ struct ipmi_intf * intf,
|
|
uint8_t * msg,
|
|
struct ipmi_v2_payload * payload);
|
|
static void read_open_session_response(struct ipmi_rs * rsp, int offset);
|
|
@@ -113,7 +113,7 @@ static void ack_sol_packet(
|
|
struct ipmi_intf * intf,
|
|
struct ipmi_rs * rsp);
|
|
|
|
-static uint8_t bridgePossible = 0;
|
|
+static uint8_t bridgePossible = 0;
|
|
|
|
struct ipmi_intf ipmi_lanplus_intf = {
|
|
name: "lanplus",
|
|
@@ -2174,7 +2174,8 @@ ipmi_lanplus_send_payload(
|
|
else if (payload->payload_type == IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST)
|
|
{
|
|
lprintf(LOG_DEBUG, ">> SENDING AN OPEN SESSION REQUEST\n");
|
|
- assert(session->v2_data.session_state == LANPLUS_STATE_PRESESSION);
|
|
+ assert(session->v2_data.session_state == LANPLUS_STATE_PRESESSION
|
|
+ || session->v2_data.session_state == LANPLUS_STATE_OPEN_SESSION_SENT);
|
|
|
|
ipmi_lanplus_build_v2x_msg(intf, /* in */
|
|
payload, /* in */
|
|
@@ -2858,7 +2859,10 @@ ipmi_lanplus_open_session(struct ipmi_intf * intf)
|
|
|
|
free(msg);
|
|
msg = NULL;
|
|
-
|
|
+ if (!rsp) {
|
|
+ lprintf(LOG_WARNING, "Error sending open session message.");
|
|
+ return -1;
|
|
+ }
|
|
if (verbose)
|
|
lanplus_dump_open_session_response(rsp);
|
|
|
|
@@ -3334,7 +3338,6 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
|
{
|
|
int rc;
|
|
struct get_channel_auth_cap_rsp auth_cap;
|
|
- struct sockaddr_in addr;
|
|
struct ipmi_session *session;
|
|
|
|
if (!intf || !intf->session)
|
|
@@ -3373,46 +3376,14 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
|
|
/* Kg is set in ipmi_intf */
|
|
//memset(session->v2_data.kg, 0, IPMI_KG_BUFFER_SIZE);
|
|
|
|
-
|
|
- /* open port to BMC */
|
|
- memset(&addr, 0, sizeof(struct sockaddr_in));
|
|
- addr.sin_family = AF_INET;
|
|
- addr.sin_port = htons(session->port);
|
|
-
|
|
- rc = inet_pton(AF_INET, (const char *)session->hostname, &addr.sin_addr);
|
|
- if (rc <= 0) {
|
|
- struct hostent *host = gethostbyname((const char *)session->hostname);
|
|
- if (host == NULL) {
|
|
- lprintf(LOG_ERR, "Address lookup for %s failed",
|
|
- session->hostname);
|
|
- return -1;
|
|
- }
|
|
- if (host->h_addrtype != AF_INET) {
|
|
- lprintf(LOG_ERR,
|
|
- "Address lookup for %s failed. Got %s, expected IPv4 address.",
|
|
- session->hostname,
|
|
- (host->h_addrtype == AF_INET6) ? "IPv6" : "Unknown");
|
|
- return (-1);
|
|
- }
|
|
- addr.sin_family = host->h_addrtype;
|
|
- memcpy(&addr.sin_addr, host->h_addr, host->h_length);
|
|
- }
|
|
-
|
|
- lprintf(LOG_DEBUG, "IPMI LAN host %s port %d",
|
|
- session->hostname, ntohs(addr.sin_port));
|
|
-
|
|
- intf->fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
- if (intf->fd < 0) {
|
|
- lperror(LOG_ERR, "Socket failed");
|
|
+ if (ipmi_intf_socket_connect (intf) == -1) {
|
|
+ lprintf(LOG_ERR, "Could not open socket!");
|
|
return -1;
|
|
}
|
|
|
|
-
|
|
- /* connect to UDP socket so we get async errors */
|
|
- rc = connect(intf->fd,
|
|
- (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
|
|
- if (rc < 0) {
|
|
- lperror(LOG_ERR, "Connect failed");
|
|
+ if (intf->fd < 0) {
|
|
+ lperror(LOG_ERR, "Connect to %s failed",
|
|
+ session->hostname);
|
|
intf->close(intf);
|
|
return -1;
|
|
}
|
|
diff --git a/ipmitool/src/plugins/open/open.c b/ipmitool/src/plugins/open/open.c
|
|
index 5567992..0fd8c9e 100644
|
|
--- a/ipmitool/src/plugins/open/open.c
|
|
+++ b/ipmitool/src/plugins/open/open.c
|
|
@@ -187,8 +187,9 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
/* use IPMB address if needed */
|
|
ipmb_addr.slave_addr = intf->target_addr;
|
|
ipmb_addr.lun = req->msg.lun;
|
|
- lprintf(LOG_DEBUG, "Sending request to "
|
|
+ lprintf(LOG_DEBUG, "Sending request 0x%x to "
|
|
"IPMB target @ 0x%x:0x%x (from 0x%x)",
|
|
+ req->msg.cmd,
|
|
intf->target_addr,intf->target_channel, intf->my_addr);
|
|
|
|
if(intf->transit_addr != 0 && intf->transit_addr != intf->my_addr) {
|
|
@@ -257,8 +258,8 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|
_req.addr_len = sizeof(ipmb_addr);
|
|
} else {
|
|
/* otherwise use system interface */
|
|
- lprintf(LOG_DEBUG+2, "Sending request to "
|
|
- "System Interface");
|
|
+ lprintf(LOG_DEBUG+2, "Sending request 0x%x to "
|
|
+ "System Interface", req->msg.cmd);
|
|
bmc_addr.lun = req->msg.lun;
|
|
_req.addr = (unsigned char *) &bmc_addr;
|
|
_req.addr_len = sizeof(bmc_addr);
|
|
diff --git a/ipmitool/src/plugins/serial/serial_basic.c b/ipmitool/src/plugins/serial/serial_basic.c
|
|
index 55681ab..23c98b7 100644
|
|
--- a/ipmitool/src/plugins/serial/serial_basic.c
|
|
+++ b/ipmitool/src/plugins/serial/serial_basic.c
|
|
@@ -266,8 +266,14 @@ serial_bm_open(struct ipmi_intf * intf)
|
|
|
|
/* no flow control */
|
|
ti.c_cflag &= ~CRTSCTS;
|
|
- ti.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC | INPCK | ISTRIP
|
|
+ ti.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | INPCK | ISTRIP
|
|
| IXON | IXOFF | IXANY);
|
|
+#ifdef IUCLC
|
|
+ /* Only disable uppercase-to-lowercase mapping on input for
|
|
+ platforms supporting the flag. */
|
|
+ ti.c_iflag &= ~(IUCLC);
|
|
+#endif
|
|
+
|
|
|
|
ti.c_oflag &= ~(OPOST);
|
|
ti.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | NOFLSH);
|
|
@@ -323,7 +329,13 @@ serial_bm_alloc_seq(void)
|
|
static int
|
|
serial_bm_flush(struct ipmi_intf * intf)
|
|
{
|
|
- return ioctl(intf->fd, TCFLSH, TCIOFLUSH);
|
|
+#if defined(TCFLSH)
|
|
+ return ioctl(intf->fd, TCFLSH, TCIOFLUSH);
|
|
+#elif defined(TIOCFLUSH)
|
|
+ return ioctl(intf->fd, TIOCFLUSH);
|
|
+#else
|
|
+# error "unsupported platform, missing flush support (TCFLSH/TIOCFLUSH)"
|
|
+#endif
|
|
}
|
|
|
|
/*
|
|
diff --git a/ipmitool/src/plugins/serial/serial_terminal.c b/ipmitool/src/plugins/serial/serial_terminal.c
|
|
index 10ed942..c82073e 100644
|
|
--- a/ipmitool/src/plugins/serial/serial_terminal.c
|
|
+++ b/ipmitool/src/plugins/serial/serial_terminal.c
|
|
@@ -211,8 +211,13 @@ ipmi_serial_term_open(struct ipmi_intf * intf)
|
|
|
|
/* no flow control */
|
|
ti.c_cflag &= ~CRTSCTS;
|
|
- ti.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC | INPCK | ISTRIP
|
|
+ ti.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | INPCK | ISTRIP
|
|
| IXON | IXOFF | IXANY);
|
|
+#ifdef IUCLC
|
|
+ /* Only disable uppercase-to-lowercase mapping on input for
|
|
+ platforms supporting the flag. */
|
|
+ ti.c_iflag &= ~(IUCLC);
|
|
+#endif
|
|
|
|
ti.c_oflag &= ~(OPOST);
|
|
ti.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | NOFLSH);
|
|
@@ -337,7 +342,14 @@ serial_write_line(struct ipmi_intf * intf, const char *str)
|
|
static int
|
|
serial_flush(struct ipmi_intf * intf)
|
|
{
|
|
+#if defined(TCFLSH)
|
|
return ioctl(intf->fd, TCFLSH, TCIOFLUSH);
|
|
+#elif defined(TIOCFLUSH)
|
|
+ return ioctl(intf->fd, TIOCFLUSH);
|
|
+#else
|
|
+# error "unsupported platform, missing flush support (TCFLSH/TIOCFLUSH)"
|
|
+#endif
|
|
+
|
|
}
|
|
|
|
/*
|