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, &notUsed);
-
-   }
-
-
-   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, &notUsed);
-      }
-
-      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, &not_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, &not_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
+
 }
 
 /*