diff --git a/ipmitool/AUTHORS b/ipmitool/AUTHORS index 80ec56b..9589d87 100644 --- a/ipmitool/AUTHORS +++ b/ipmitool/AUTHORS @@ -2,3 +2,4 @@ Duncan Laurie Fredrik Öhrn Jon Cassorla Jeremy Ellington +Petter Reinholdtsen 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 +# Jordan Hargrave +# +# 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 #include +/* 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++ #include #include +#include #if HAVE_CONFIG_H # include @@ -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 #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 #include #include @@ -46,421 +45,259 @@ #include #include -/****************************************************************************** -* HISTORY -* =========================================================================== -* 2007-01-11 [FI] -* - Incremented to version 1.3 -* - Added lan packet size reduction mechanism to workaround fact -* that lan iface will not return C7 on excessive length -* -*****************************************************************************/ - -#define VERSION_MAJ 1 -#define VERSION_MIN 3 - - -typedef enum eKFWUM_Task -{ - KFWUM_TASK_INFO, - KFWUM_TASK_STATUS, - KFWUM_TASK_DOWNLOAD, - KFWUM_TASK_UPGRADE, - KFWUM_TASK_START_UPGRADE, - KFWUM_TASK_ROLLBACK, - KFWUM_TASK_TRACELOG -}tKFWUM_Task; - -typedef enum eKFWUM_BoardList -{ - KFWUM_BOARD_KONTRON_UNKNOWN = 0, - KFWUM_BOARD_KONTRON_5002 = 5002, -}tKFWUM_BoardList; - -typedef enum eKFWUM_IanaList -{ - KFWUM_IANA_KONTRON = 15000, -}tKFWUM_IanaList; - -typedef struct sKFWUM_BoardInfo -{ - tKFWUM_BoardList boardId; - tKFWUM_IanaList iana; -}tKFWUM_BoardInfo; - -typedef enum eKFWUM_Status -{ - KFWUM_STATUS_OK, - KFWUM_STATUS_ERROR -}tKFWUM_Status; - -typedef enum eKFWUM_DownloadType -{ - KFWUM_DOWNLOAD_TYPE_ADDRESS = 0, - KFWUM_DOWNLOAD_TYPE_SEQUENCE, -}tKFWUM_DownloadType; +extern int verbose; +unsigned char firmBuf[1024*512]; +tKFWUM_SaveFirmwareInfo save_fw_nfo; + +int KfwumGetFileSize(const char *pFileName, + unsigned long *pFileSize); +int KfwumSetupBuffersFromFile(const char *pFileName, + unsigned long fileSize); +void KfwumShowProgress(const char *task, unsigned long current, + unsigned long total); +unsigned short KfwumCalculateChecksumPadding(unsigned char *pBuffer, + unsigned long totalSize); +int KfwumGetInfo(struct ipmi_intf *intf, unsigned char output, + unsigned char *pNumBank); +int KfwumGetDeviceInfo(struct ipmi_intf *intf, + unsigned char output, tKFWUM_BoardInfo *pBoardInfo); +int KfwumGetStatus(struct ipmi_intf *intf); +int KfwumManualRollback(struct ipmi_intf *intf); +int KfwumStartFirmwareImage(struct ipmi_intf *intf, + unsigned long length, unsigned short padding); +int KfwumSaveFirmwareImage(struct ipmi_intf *intf, + unsigned char sequenceNumber, unsigned long address, + unsigned char *pFirmBuf, unsigned char *pInBufLength); +int KfwumFinishFirmwareImage(struct ipmi_intf *intf, + tKFWUM_InFirmwareInfo firmInfo); +int KfwumUploadFirmware(struct ipmi_intf *intf, + unsigned char *pBuffer, unsigned long totalSize); +int KfwumStartFirmwareUpgrade(struct ipmi_intf *intf); +int KfwumGetInfoFromFirmware(unsigned char *pBuf, + unsigned long bufSize, tKFWUM_InFirmwareInfo *pInfo); +void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo *pInfo); +int KfwumGetTraceLog(struct ipmi_intf *intf); +int ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo, + tKFWUM_InFirmwareInfo firmInfo); + +int ipmi_fwum_fwupgrade(struct ipmi_intf *intf, char *file, int action); +int ipmi_fwum_info(struct ipmi_intf *intf); +int ipmi_fwum_status(struct ipmi_intf *intf); +void printf_kfwum_help(void); +void printf_kfwum_info(tKFWUM_BoardInfo boardInfo, + tKFWUM_InFirmwareInfo firmInfo); -typedef enum eKFWUM_DownloadBuffferType -{ - KFWUM_SMALL_BUFFER_TYPE = 0, - KFUMW_BIG_BUFFER_TYPE -}tKFWUM_DownloadBuffferType; +/* String table */ +/* Must match eFWUM_CmdId */ +const char *CMD_ID_STRING[] = { + "GetFwInfo", + "KickWatchdog", + "GetLastAnswer", + "BootHandshake", + "ReportStatus", + "CtrlIPMBLine", + "SetFwState", + "GetFwStatus", + "GetSpiMemStatus", + "StartFwUpdate", + "StartFwImage", + "SaveFwImage", + "FinishFwImage", + "ReadFwImage", + "ManualRollback", + "GetTraceLog" +}; -typedef struct sKFWUM_InFirmwareInfo -{ - unsigned long fileSize; - unsigned short checksum; - unsigned short sumToRemoveFromChecksum; - /* Since the checksum is added in the bin - after the checksum is calculated, we - need to remove the each byte value. This - byte will contain the addition of both bytes*/ - tKFWUM_BoardList boardId; - unsigned char deviceId; - unsigned char tableVers; - unsigned char implRev; - unsigned char versMajor; - unsigned char versMinor; - unsigned char versSubMinor; - unsigned char sdrRev; - tKFWUM_IanaList iana; -}tKFWUM_InFirmwareInfo; - -typedef struct sKFWUM_SaveFirmwareInfo -{ - tKFWUM_DownloadType downloadType; - unsigned char bufferSize; - unsigned char overheadSize; -}tKFWUM_SaveFirmwareInfo; - -#define KFWUM_SMALL_BUFFER 32 /* Minimum size (IPMB/IOL/old protocol) */ -#define KFWUM_BIG_BUFFER 32 /* Maximum size on KCS interface */ - -#define KFWUM_OLD_CMD_OVERHEAD 6 /*3 address + 1 size + 1 checksum + 1 command*/ -#define KFWUM_NEW_CMD_OVERHEAD 4 /*1 sequence+ 1 size + 1 checksum + 1 command*/ -#define KFWUM_PAGE_SIZE 256 +const char *EXT_CMD_ID_STRING[] = { + "FwUpgradeLock", + "ProcessFwUpg", + "ProcessFwRb", + "WaitHSAfterUpg", + "WaitFirstHSUpg", + "FwInfoStateChange" +}; -extern int verbose; -static unsigned char fileName[512]; -static unsigned char firmBuf[1024*512]; -static tKFWUM_SaveFirmwareInfo saveFirmwareInfo; - -static void KfwumOutputHelp(void); -static void KfwumMain(struct ipmi_intf * intf, tKFWUM_Task task); -static tKFWUM_Status KfwumGetFileSize(unsigned char * pFileName, - unsigned long * pFileSize); -static tKFWUM_Status KfwumSetupBuffersFromFile(unsigned char * pFileName, - unsigned long fileSize); -static void KfwumShowProgress( const unsigned char * task, - unsigned long current, unsigned long total); -static unsigned short KfwumCalculateChecksumPadding(unsigned char * pBuffer, - unsigned long totalSize); - - -static tKFWUM_Status KfwumGetInfo(struct ipmi_intf * intf, unsigned char output, - unsigned char *pNumBank); -static tKFWUM_Status KfwumGetDeviceInfo(struct ipmi_intf * intf, - unsigned char output, tKFWUM_BoardInfo * pBoardInfo); -static tKFWUM_Status KfwumGetStatus(struct ipmi_intf * intf); -static tKFWUM_Status KfwumManualRollback(struct ipmi_intf * intf); -static tKFWUM_Status KfwumStartFirmwareImage(struct ipmi_intf * intf, - unsigned long length,unsigned short padding); -static tKFWUM_Status KfwumSaveFirmwareImage(struct ipmi_intf * intf, - unsigned char sequenceNumber, unsigned long address, - unsigned char *pFirmBuf, unsigned char * pInBufLength); -static tKFWUM_Status KfwumFinishFirmwareImage(struct ipmi_intf * intf, - tKFWUM_InFirmwareInfo firmInfo); -static tKFWUM_Status KfwumUploadFirmware(struct ipmi_intf * intf, - unsigned char * pBuffer, unsigned long totalSize); -static tKFWUM_Status KfwumStartFirmwareUpgrade(struct ipmi_intf * intf); - -static tKFWUM_Status KfwumGetInfoFromFirmware(unsigned char * pBuf, - unsigned long bufSize, tKFWUM_InFirmwareInfo * pInfo); -static void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo); - -static tKFWUM_Status KfwumGetTraceLog(struct ipmi_intf * intf); - -tKFWUM_Status KfwumValidFirmwareForBoard(tKFWUM_BoardInfo boardInfo, - tKFWUM_InFirmwareInfo firmInfo); -static void KfwumOutputInfo(tKFWUM_BoardInfo boardInfo, - tKFWUM_InFirmwareInfo firmInfo); +const char *CMD_STATE_STRING[] = { + "Invalid", + "Begin", + "Progress", + "Completed" +}; +const struct valstr bankStateValS[] = { + { 0x00, "Not programmed" }, + { 0x01, "New firmware" }, + { 0x02, "Wait for validation" }, + { 0x03, "Last Known Good" }, + { 0x04, "Previous Good" } +}; /* ipmi_fwum_main - entry point for this ipmitool mode * - * @intf: ipmi interface - * @arc : number of arguments - * @argv : point to argument array + * @intf: ipmi interface + * @arc: number of arguments + * @argv: point to argument array * * returns 0 on success * returns -1 on error */ -int ipmi_fwum_main(struct ipmi_intf * intf, int argc, char ** argv) +int +ipmi_fwum_main(struct ipmi_intf *intf, int argc, char **argv) { - printf("FWUM extension Version %d.%d\n", VERSION_MAJ, VERSION_MIN); - if ((!argc) || ( !strncmp(argv[0], "help", 4))) - { - KfwumOutputHelp(); - } - else - { - if (!strncmp(argv[0], "info", 4)) - { - KfwumMain(intf, KFWUM_TASK_INFO); - } - else if (!strncmp(argv[0], "status", 6)) - { - KfwumMain(intf, KFWUM_TASK_STATUS); - } - else if (!strncmp(argv[0], "rollback", 8)) - { - KfwumMain(intf, KFWUM_TASK_ROLLBACK); - } - else if (!strncmp(argv[0], "download", 8)) - { - if((argc >= 2) && (strlen(argv[1]) > 0)) - { - /* There is a file name in the parameters */ - if(strlen(argv[1]) < 512) - { - strcpy((char *)fileName, argv[1]); - printf("Firmware File Name : %s\n", fileName); - - KfwumMain(intf, KFWUM_TASK_DOWNLOAD); - } - else - { - fprintf(stderr,"File name must be smaller than 512 bytes\n"); - } - } - else - { - fprintf(stderr,"A path and a file name must be specified\n"); - } - } - else if (!strncmp(argv[0], "upgrade", 7)) - { - if((argc >= 2) && (strlen(argv[1]) > 0)) - { - /* There is a file name in the parameters */ - if(strlen(argv[1]) < 512) - { - strcpy((char *)fileName, argv[1]); - printf("Upgrading using file name %s\n", fileName); - KfwumMain(intf, KFWUM_TASK_UPGRADE); - } - else - { - fprintf(stderr,"File name must be smaller than 512 bytes\n"); - } - } - else - { - KfwumMain(intf, KFWUM_TASK_START_UPGRADE); - } - - } - else if (!strncmp(argv[0], "tracelog", 8)) - { - KfwumMain(intf, KFWUM_TASK_TRACELOG); - } - else - { - printf("Invalid KFWUM command: %s\n", argv[0]); - } - } - return 0; + int rc = 0; + printf("FWUM extension Version %d.%d\n", VER_MAJOR, VER_MINOR); + if (argc < 1) { + lprintf(LOG_ERR, "Not enough parameters given."); + printf_kfwum_help(); + return (-1); + } + if (strncmp(argv[0], "help", 4) == 0) { + printf_kfwum_help(); + rc = 0; + } else if (strncmp(argv[0], "info", 4) == 0) { + rc = ipmi_fwum_info(intf); + } else if (strncmp(argv[0], "status", 6) == 0) { + rc = ipmi_fwum_status(intf); + } else if (strncmp(argv[0], "rollback", 8) == 0) { + rc = KfwumManualRollback(intf); + } else if (strncmp(argv[0], "download", 8) == 0) { + if ((argc < 2) || (strlen(argv[1]) < 1)) { + lprintf(LOG_ERR, + "Path and file name must be specified."); + return (-1); + } + printf("Firmware File Name : %s\n", argv[1]); + rc = ipmi_fwum_fwupgrade(intf, argv[1], 0); + } else if (strncmp(argv[0], "upgrade", 7) == 0) { + if ((argc >= 2) && (strlen(argv[1]) > 0)) { + printf("Upgrading using file name %s\n", argv[1]); + rc = ipmi_fwum_fwupgrade(intf, argv[1], 1); + } else { + rc = KfwumStartFirmwareUpgrade(intf); + } + } else if (strncmp(argv[0], "tracelog", 8) == 0) { + rc = KfwumGetTraceLog(intf); + } else { + lprintf(LOG_ERR, "Invalid KFWUM command: %s", argv[0]); + printf_kfwum_help(); + rc = (-1); + } + return rc; } - -static void KfwumOutputHelp(void) +void +printf_kfwum_help(void) { - printf("KFWUM Commands: info status download upgrade rollback tracelog\n"); + lprintf(LOG_NOTICE, +"KFWUM Commands: info status download upgrade rollback tracelog"); } - -/****************************************/ -/** private definitions and macros **/ -/****************************************/ +/* private definitions and macros */ typedef enum eFWUM_CmdId { - KFWUM_CMD_ID_GET_FIRMWARE_INFO = 0, - KFWUM_CMD_ID_KICK_IPMC_WATCHDOG = 1, - KFWUM_CMD_ID_GET_LAST_ANSWER = 2, - KFWUM_CMD_ID_BOOT_HANDSHAKE = 3, - KFWUM_CMD_ID_REPORT_STATUS = 4, - KFWUM_CMD_ID_GET_FIRMWARE_STATUS = 7, - KFWUM_CMD_ID_START_FIRMWARE_UPDATE = 9, - KFWUM_CMD_ID_START_FIRMWARE_IMAGE = 0x0a, - KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE = 0x0b, - KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE = 0x0c, - KFWUM_CMD_ID_READ_FIRMWARE_IMAGE = 0x0d, - KFWUM_CMD_ID_MANUAL_ROLLBACK = 0x0e, - KFWUM_CMD_ID_GET_TRACE_LOG = 0x0f, - KFWUM_CMD_ID_STD_MAX_CMD, - KFWUM_CMD_ID_EXTENDED_CMD = 0xC0 + KFWUM_CMD_ID_GET_FIRMWARE_INFO = 0, + KFWUM_CMD_ID_KICK_IPMC_WATCHDOG = 1, + KFWUM_CMD_ID_GET_LAST_ANSWER = 2, + KFWUM_CMD_ID_BOOT_HANDSHAKE = 3, + KFWUM_CMD_ID_REPORT_STATUS = 4, + KFWUM_CMD_ID_GET_FIRMWARE_STATUS = 7, + KFWUM_CMD_ID_START_FIRMWARE_UPDATE = 9, + KFWUM_CMD_ID_START_FIRMWARE_IMAGE = 0x0a, + KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE = 0x0b, + KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE = 0x0c, + KFWUM_CMD_ID_READ_FIRMWARE_IMAGE = 0x0d, + KFWUM_CMD_ID_MANUAL_ROLLBACK = 0x0e, + KFWUM_CMD_ID_GET_TRACE_LOG = 0x0f, + KFWUM_CMD_ID_STD_MAX_CMD, + KFWUM_CMD_ID_EXTENDED_CMD = 0xC0 } tKFWUM_CmdId; - - -/****************************************/ -/** global/static variables definition **/ -/****************************************/ - -/****************************************/ -/** functions definition **/ -/****************************************/ - -/******************************************************************************* -* -* Function Name: KfwumMain -* -* Description: This function implements the upload of the firware data -* received as parameters. -* -* Restriction: Called only from main -* -* Input: unsigned char * pBuffer[] : The buffers -* unsigned long bufSize : The size of the buffers -* -* Output: None -* -* Global: none -* -* Return: tIFWU_Status (success or failure) -* -*******************************************************************************/ -static void KfwumMain(struct ipmi_intf * intf, tKFWUM_Task task) +int +ipmi_fwum_info(struct ipmi_intf *intf) { - tKFWUM_Status status = KFWUM_STATUS_OK; - tKFWUM_BoardInfo boardInfo; - tKFWUM_InFirmwareInfo firmInfo = { 0 }; - unsigned long fileSize = 0; - static unsigned short padding; - - if((status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_INFO)) - { - unsigned char notUsed; - if(verbose) - { - printf("Getting Kontron FWUM Info\n"); - } - KfwumGetDeviceInfo(intf, 1, &boardInfo); - KfwumGetInfo(intf, 1, ¬Used); - - } - - - if((status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_STATUS)) - { - if(verbose) - { - printf("Getting Kontron FWUM Status\n"); - } - KfwumGetStatus(intf); - } - - if( (status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_ROLLBACK) ) - { - status = KfwumManualRollback(intf); - } - - if( - (status == KFWUM_STATUS_OK) && - ( - (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD) - ) - ) - { - status = KfwumGetFileSize(fileName, &fileSize); - if(status == KFWUM_STATUS_OK) - { - status = KfwumSetupBuffersFromFile(fileName, fileSize); - if(status == KFWUM_STATUS_OK) - { - padding = KfwumCalculateChecksumPadding(firmBuf, fileSize); - } - } - if(status == KFWUM_STATUS_OK) - { - status = KfwumGetInfoFromFirmware(firmBuf, fileSize, &firmInfo); - } - if(status == KFWUM_STATUS_OK) - { - status = KfwumGetDeviceInfo(intf, 0, &boardInfo); - } - - if(status == KFWUM_STATUS_OK) - { - status = KfwumValidFirmwareForBoard(boardInfo,firmInfo); - } - - if (status == KFWUM_STATUS_OK) - { - unsigned char notUsed; - KfwumGetInfo(intf, 0, ¬Used); - } - - KfwumOutputInfo(boardInfo,firmInfo); - } - - if( - (status == KFWUM_STATUS_OK) && - ( - (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD) - ) - ) - { - status = KfwumStartFirmwareImage(intf, fileSize, padding); - } - - - if( - (status == KFWUM_STATUS_OK) && - ( - (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD) - ) - ) - { - status = KfwumUploadFirmware(intf, firmBuf, fileSize); - } - - if( - (status == KFWUM_STATUS_OK) && - ( - (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD) - ) - ) - { - status = KfwumFinishFirmwareImage(intf, firmInfo); - } - - if( - (status == KFWUM_STATUS_OK) && - ( - (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_DOWNLOAD) - ) - ) - { - status = KfwumGetStatus(intf); - } - - if( - (status == KFWUM_STATUS_OK) && - ( - (task == KFWUM_TASK_UPGRADE) || (task == KFWUM_TASK_START_UPGRADE) - ) - ) - { - status = KfwumStartFirmwareUpgrade(intf); - } - - if((status == KFWUM_STATUS_OK) && (task == KFWUM_TASK_TRACELOG)) - { - status = KfwumGetTraceLog(intf); - } + tKFWUM_BoardInfo b_info; + int rc = 0; + unsigned char not_used; + if (verbose) { + printf("Getting Kontron FWUM Info\n"); + } + if (KfwumGetDeviceInfo(intf, 1, &b_info) != 0) { + rc = (-1); + } + if (KfwumGetInfo(intf, 1, ¬_used) != 0) { + rc = (-1); + } + return rc; +} +int +ipmi_fwum_status(struct ipmi_intf *intf) +{ + if (verbose) { + printf("Getting Kontron FWUM Status\n"); + } + if (KfwumGetStatus(intf) != 0) { + return (-1); + } + return 0; +} +/* ipmi_fwum_fwupgrade - function implements download/upload of the firmware + * data received as parameters + * + * @file: fw file + * @action: 0 = download, 1 = upload/start upload + * + * returns 0 on success, otherwise (-1) + */ +int +ipmi_fwum_fwupgrade(struct ipmi_intf *intf, char *file, int action) +{ + tKFWUM_BoardInfo b_info; + tKFWUM_InFirmwareInfo fw_info = { 0 }; + unsigned short padding; + unsigned long fsize = 0; + unsigned char not_used; + if (file == NULL) { + lprintf(LOG_ERR, "No file given."); + return (-1); + } + if (KfwumGetFileSize(file, &fsize) != 0) { + return (-1); + } + if (KfwumSetupBuffersFromFile(file, fsize) != 0) { + return (-1); + } + padding = KfwumCalculateChecksumPadding(firmBuf, fsize); + if (KfwumGetInfoFromFirmware(firmBuf, fsize, &fw_info) != 0) { + return (-1); + } + if (KfwumGetDeviceInfo(intf, 0, &b_info) != 0) { + return (-1); + } + if (ipmi_kfwum_checkfwcompat(b_info, fw_info) != 0) { + return (-1); + } + KfwumGetInfo(intf, 0, ¬_used); + printf_kfwum_info(b_info, fw_info); + if (KfwumStartFirmwareImage(intf, fsize, padding) != 0) { + return (-1); + } + if (KfwumUploadFirmware(intf, firmBuf, fsize) != 0) { + return (-1); + } + if (KfwumFinishFirmwareImage(intf, fw_info) != 0) { + return (-1); + } + if (KfwumGetStatus(intf) != 0) { + return (-1); + } + if (action != 0) { + if (KfwumStartFirmwareUpgrade(intf) != 0) { + return (-1); + } + } + return 0; } /* KfwumGetFileSize - gets the file size @@ -468,31 +305,24 @@ static void KfwumMain(struct ipmi_intf * intf, tKFWUM_Task task) * @pFileName : filename ptr * @pFileSize : output ptr for filesize * - * returns KFWUM_STATUS_OK or KFWUM_STATUS_ERROR + * returns 0 on success, otherwise (-1) */ -static tKFWUM_Status KfwumGetFileSize(unsigned char * pFileName, - unsigned long * pFileSize) +int +KfwumGetFileSize(const char *pFileName, unsigned long *pFileSize) { - tKFWUM_Status status = KFWUM_STATUS_ERROR; - FILE * pFileHandle; - - pFileHandle = fopen((const char *)pFileName, "rb"); - - if(pFileHandle) - { - if (fseek(pFileHandle, 0L , SEEK_END) == 0) - { - *pFileSize = ftell(pFileHandle); - - if( *pFileSize != 0) - { - status = KFWUM_STATUS_OK; - } - } - fclose(pFileHandle); - } - - return(status); + FILE *pFileHandle = NULL; + pFileHandle = fopen(pFileName, "rb"); + if (pFileHandle == NULL) { + return (-1); + } + if (fseek(pFileHandle, 0L , SEEK_END) == 0) { + *pFileSize = ftell(pFileHandle); + } + fclose(pFileHandle); + if (*pFileSize != 0) { + return 0; + } + return (-1); } /* KfwumSetupBuffersFromFile - small buffers are used to store the file data @@ -500,1182 +330,803 @@ static tKFWUM_Status KfwumGetFileSize(unsigned char * pFileName, * @pFileName : filename ptr * unsigned long : filesize * - * returns KFWUM_STATUS_OK or KFWUM_STATUS_ERROR + * returns 0 on success, otherwise (-1) */ -#define MAX_BUFFER_SIZE 1024*16 -static tKFWUM_Status KfwumSetupBuffersFromFile(unsigned char * pFileName, - unsigned long fileSize) +int +KfwumSetupBuffersFromFile(const char *pFileName, unsigned long fileSize) { - tKFWUM_Status status = KFWUM_STATUS_ERROR; + int rc = (-1); FILE *pFileHandle = NULL; int count; int modulus; int qty = 0; - pFileHandle = fopen((const char *)pFileName, "rb"); + pFileHandle = fopen(pFileName, "rb"); if (pFileHandle == NULL) { lprintf(LOG_ERR, "Failed to open '%s' for reading.", - (char *)pFileName); - return KFWUM_STATUS_ERROR; + pFileName); + return (-1); } count = fileSize / MAX_BUFFER_SIZE; modulus = fileSize % MAX_BUFFER_SIZE; rewind(pFileHandle); - for (qty=0; qty < count; qty++) { - KfwumShowProgress((const unsigned char *)"Reading Firmware from File", + for (qty = 0; qty < count; qty++) { + KfwumShowProgress("Reading Firmware from File", qty, count); if (fread(&firmBuf[qty * MAX_BUFFER_SIZE], 1, MAX_BUFFER_SIZE, pFileHandle) == MAX_BUFFER_SIZE) { - status = KFWUM_STATUS_OK; + rc = 0; } } if (modulus) { if (fread(&firmBuf[qty * MAX_BUFFER_SIZE], 1, modulus, pFileHandle) == modulus) { - status = KFWUM_STATUS_OK; + rc = 0; } } - if (status == KFWUM_STATUS_OK) { - KfwumShowProgress((const unsigned char *)"Reading Firmware from File", - 100, 100); + if (rc == 0) { + KfwumShowProgress("Reading Firmware from File", 100, 100); } fclose(pFileHandle); - return status; + return rc; } /* KfwumShowProgress - helper routine to display progress bar * * Converts current/total in percent - * + * * *task : string identifying current operation * current: progress - * total : limit + * total : limit */ -#define PROG_LENGTH 42 -void KfwumShowProgress( const unsigned char * task, unsigned long current , - unsigned long total) +void +KfwumShowProgress(const char *task, unsigned long current, unsigned long total) { - static unsigned long staticProgress=0xffffffff; - - unsigned char spaces[PROG_LENGTH + 1]; - unsigned short hash; - float percent = ((float)current/total); - unsigned long progress = 100*(percent); - - if(staticProgress == progress) - { - /* We displayed the same last time.. so don't do it */ - } - else - { - staticProgress = progress; - - - printf("%-25s : ",task); /* total 20 bytes */ - - hash = ( percent * PROG_LENGTH ); - memset(spaces,'#', hash); - spaces[ hash ] = '\0'; - printf("%s", spaces ); - - memset(spaces,' ',( PROG_LENGTH - hash ) ); - spaces[ ( PROG_LENGTH - hash ) ] = '\0'; - printf("%s", spaces ); - - - printf(" %3ld %%\r",progress); /* total 7 bytes */ - - if( progress == 100 ) - { - printf("\n"); - } - fflush(stdout); - } +# define PROG_LENGTH 42 + static unsigned long staticProgress=0xffffffff; + unsigned char spaces[PROG_LENGTH + 1]; + unsigned short hash; + float percent = ((float)current / total); + unsigned long progress = 100 * (percent); + + if (staticProgress == progress) { + /* We displayed the same last time.. so don't do it */ + return; + } + staticProgress = progress; + printf("%-25s : ", task); /* total 20 bytes */ + hash = (percent * PROG_LENGTH); + memset(spaces, '#', hash); + spaces[hash] = '\0'; + + printf("%s", spaces); + memset(spaces, ' ', (PROG_LENGTH - hash)); + spaces[(PROG_LENGTH - hash)] = '\0'; + printf("%s", spaces ); + + printf(" %3ld %%\r", progress); /* total 7 bytes */ + if (progress == 100) { + printf("\n"); + } + fflush(stdout); } -/* KfwumCalculateChecksumPadding - * - * TBD - * +/* KfwumCalculateChecksumPadding - TBD */ -static unsigned short KfwumCalculateChecksumPadding(unsigned char * pBuffer, - unsigned long totalSize) +unsigned short +KfwumCalculateChecksumPadding(unsigned char *pBuffer, unsigned long totalSize) { - unsigned short sumOfBytes = 0; - unsigned short padding; - unsigned long counter; - - for(counter = 0; counter < totalSize; counter ++ ) - { - sumOfBytes += pBuffer[counter]; - } - - padding = 0 - sumOfBytes; - return padding; + unsigned short sumOfBytes = 0; + unsigned short padding; + unsigned long counter; + for (counter = 0; counter < totalSize; counter ++) { + sumOfBytes += pBuffer[counter]; + } + padding = 0 - sumOfBytes; + return padding; } -/****************************************************************************** -******************************* COMMANDS ************************************** -******************************************************************************/ -#ifdef HAVE_PRAGMA_PACK -#pragma pack(1) -#endif -struct KfwumGetInfoResp { - unsigned char protocolRevision; - unsigned char controllerDeviceId; - struct - { - unsigned char mode:1; - unsigned char seqAdd:1; - unsigned char res : 6; - } byte; - unsigned char firmRev1; - unsigned char firmRev2; - unsigned char numBank; -} ATTRIBUTE_PACKING; -#ifdef HAVE_PRAGMA_PACK -#pragma pack(0) -#endif - - - /* KfwumGetInfo - Get Firmware Update Manager (FWUM) information - * - * * intf : IPMI interface + * + * *intf : IPMI interface * output : when set to non zero, queried information is displayed * pNumBank: output ptr for number of banks + * + * returns 0 on success, otherwise (-1) */ -static tKFWUM_Status KfwumGetInfo(struct ipmi_intf * intf, unsigned char output, - unsigned char *pNumBank) +int +KfwumGetInfo(struct ipmi_intf *intf, unsigned char output, + unsigned char *pNumBank) { - tKFWUM_Status status = KFWUM_STATUS_OK; - static struct KfwumGetInfoResp *pGetInfo; - struct ipmi_rs * rsp; - struct ipmi_rq req; - - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_FIRMWARE; - req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_INFO; - req.msg.data_len = 0; - - rsp = intf->sendrecv(intf, &req); - - if (!rsp) - { - printf("Error in FWUM Firmware Get Info Command\n"); - status = KFWUM_STATUS_ERROR; - } - else if (rsp->ccode) - { - printf("FWUM Firmware Get Info returned %x\n", rsp->ccode); - status = KFWUM_STATUS_ERROR; - } - - if(status == KFWUM_STATUS_OK) - { - pGetInfo = (struct KfwumGetInfoResp *) rsp->data; - if(output) - { - printf("\nFWUM info\n"); - printf("=========\n"); - printf("Protocol Revision : %02Xh\n", - pGetInfo->protocolRevision); - printf("Controller Device Id : %02Xh\n", - pGetInfo->controllerDeviceId); - printf("Firmware Revision : %u.%u%u", - pGetInfo->firmRev1, pGetInfo->firmRev2 >> 4, - pGetInfo->firmRev2 & 0x0f); - if(pGetInfo->byte.mode != 0) - { - printf(" - DEBUG BUILD\n"); - } - else - { - printf("\n"); - } - printf("Number Of Memory Bank : %u\n",pGetInfo->numBank); - } - * pNumBank = pGetInfo->numBank; - - /* Determine wich type of download to use: */ - /* Old FWUM or Old IPMC fw (data_len < 7) --> - Address with small buffer size */ - if ( (pGetInfo->protocolRevision) <= 0x05 || (rsp->data_len < 7 ) ) - { - saveFirmwareInfo.downloadType = KFWUM_DOWNLOAD_TYPE_ADDRESS; - saveFirmwareInfo.bufferSize = KFWUM_SMALL_BUFFER; - saveFirmwareInfo.overheadSize = KFWUM_OLD_CMD_OVERHEAD; - - if(verbose) - { - printf("Protocol Revision :"); - printf(" <= 5 detected, adjusting buffers\n"); - } - } - else /* Both fw are using the new protocol */ - { - saveFirmwareInfo.downloadType = KFWUM_DOWNLOAD_TYPE_SEQUENCE; - saveFirmwareInfo.overheadSize = KFWUM_NEW_CMD_OVERHEAD; - /* Buffer size depending on access type (Local or remote) */ - /* Look if we run remote or locally */ - - if(verbose) - { - printf("Protocol Revision :"); - printf(" > 5 optimizing buffers\n"); - } - - if(strstr(intf->name,"lan")!= NULL) /* also covers lanplus */ - { - saveFirmwareInfo.bufferSize = KFWUM_SMALL_BUFFER; - if(verbose) - { - printf("IOL payload size : %d\n" , - saveFirmwareInfo.bufferSize); - } - } - else if - ( - (strstr(intf->name,"open")!= NULL) - && - intf->target_addr != IPMI_BMC_SLAVE_ADDR - && - ( - intf->target_addr != intf->my_addr - ) - ) - { - saveFirmwareInfo.bufferSize = KFWUM_SMALL_BUFFER; - if(verbose) - { - printf("IPMB payload size : %d\n" , - saveFirmwareInfo.bufferSize); - } - } - else - { - saveFirmwareInfo.bufferSize = KFWUM_BIG_BUFFER; - if(verbose) - { - printf("SMI payload size : %d\n", - saveFirmwareInfo.bufferSize); - } - } - } - } - return status; + int rc = 0; + static struct KfwumGetInfoResp *pGetInfo; + struct ipmi_rs *rsp; + struct ipmi_rq req; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_FIRMWARE; + req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_INFO; + req.msg.data_len = 0; + + rsp = intf->sendrecv(intf, &req); + if (!rsp) { + lprintf(LOG_ERR, "Error in FWUM Firmware Get Info Command."); + return (-1); + } else if (rsp->ccode != 0) { + lprintf(LOG_ERR, "FWUM Firmware Get Info returned %x", + rsp->ccode); + return (-1); + } + + pGetInfo = (struct KfwumGetInfoResp *)rsp->data; + if (output) { + printf("\nFWUM info\n"); + printf("=========\n"); + printf("Protocol Revision : %02Xh\n", + pGetInfo->protocolRevision); + printf("Controller Device Id : %02Xh\n", + pGetInfo->controllerDeviceId); + printf("Firmware Revision : %u.%u%u", + pGetInfo->firmRev1, pGetInfo->firmRev2 >> 4, + pGetInfo->firmRev2 & 0x0f); + if (pGetInfo->byte.mode != 0) { + printf(" - DEBUG BUILD\n"); + } else { + printf("\n"); + } + printf("Number Of Memory Bank : %u\n", pGetInfo->numBank); + } + *pNumBank = pGetInfo->numBank; + /* Determine wich type of download to use: */ + /* Old FWUM or Old IPMC fw (data_len < 7) + * --> Address with small buffer size + */ + if ((pGetInfo->protocolRevision) <= 0x05 || (rsp->data_len < 7 )) { + save_fw_nfo.downloadType = KFWUM_DOWNLOAD_TYPE_ADDRESS; + save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER; + save_fw_nfo.overheadSize = KFWUM_OLD_CMD_OVERHEAD; + if (verbose) { + printf("Protocol Revision :"); + printf(" <= 5 detected, adjusting buffers\n"); + } + } else { + /* Both fw are using the new protocol */ + save_fw_nfo.downloadType = KFWUM_DOWNLOAD_TYPE_SEQUENCE; + save_fw_nfo.overheadSize = KFWUM_NEW_CMD_OVERHEAD; + /* Buffer size depending on access type (Local or remote) */ + /* Look if we run remote or locally */ + if (verbose) { + printf("Protocol Revision :"); + printf(" > 5 optimizing buffers\n"); + } + if (strstr(intf->name,"lan") != NULL) { + /* also covers lanplus */ + save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER; + if (verbose) { + printf("IOL payload size : %d\n", + save_fw_nfo.bufferSize); + } + } else if ((strstr(intf->name,"open")!= NULL) + && intf->target_addr != IPMI_BMC_SLAVE_ADDR + && (intf->target_addr != intf->my_addr)) { + save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER; + if (verbose) { + printf("IPMB payload size : %d\n", + save_fw_nfo.bufferSize); + } + } else { + save_fw_nfo.bufferSize = KFWUM_BIG_BUFFER; + if (verbose) { + printf("SMI payload size : %d\n", + save_fw_nfo.bufferSize); + } + } + } + return rc; } -/* KfwumGetDeviceInfo - Get IPMC/Board information - * - * * intf : IPMI interface - * output : when set to non zero, queried information is displayed +/* KfwumGetDeviceInfo - Get IPMC/Board information + * + * *intf: IPMI interface + * output: when set to non zero, queried information is displayed * tKFWUM_BoardInfo: output ptr for IPMC/Board information + * + * returns 0 on success, otherwise (-1) */ -static tKFWUM_Status KfwumGetDeviceInfo(struct ipmi_intf * intf, - unsigned char output, tKFWUM_BoardInfo * pBoardInfo) +int +KfwumGetDeviceInfo(struct ipmi_intf *intf, unsigned char output, + tKFWUM_BoardInfo *pBoardInfo) { - struct ipm_devid_rsp *pGetDevId; - tKFWUM_Status status = KFWUM_STATUS_OK; - struct ipmi_rs * rsp; - struct ipmi_rq req; - - /* Send Get Device Id */ - if(status == KFWUM_STATUS_OK) - { - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_APP; - req.msg.cmd = BMC_GET_DEVICE_ID; - req.msg.data_len = 0; - - rsp = intf->sendrecv(intf, &req); - if (!rsp) - { - printf("Error in Get Device Id Command\n"); - status = KFWUM_STATUS_ERROR; - } - else if (rsp->ccode) - { - printf("Get Device Id returned %x\n", rsp->ccode); - status = KFWUM_STATUS_ERROR; - } - } - - if(status == KFWUM_STATUS_OK) - { - pGetDevId = (struct ipm_devid_rsp *) rsp->data; - pBoardInfo->iana = IPM_DEV_MANUFACTURER_ID(pGetDevId->manufacturer_id); - pBoardInfo->boardId = buf2short(pGetDevId->product_id); - if(output) - { - printf("\nIPMC Info\n"); - printf("=========\n"); - printf("Manufacturer Id : %u\n",pBoardInfo->iana); - printf("Board Id : %u\n",pBoardInfo->boardId); - printf("Firmware Revision : %u.%u%u", - pGetDevId->fw_rev1, pGetDevId->fw_rev2 >> 4, - pGetDevId->fw_rev2 & 0x0f); - if( - ( - ( pBoardInfo->iana == KFWUM_IANA_KONTRON) - && - (pBoardInfo->boardId = KFWUM_BOARD_KONTRON_5002) - ) - ) - { - printf(" SDR %u\n", pGetDevId->aux_fw_rev[0]); - } - else - { - printf("\n"); - } - } - } - - return status; + struct ipm_devid_rsp *pGetDevId; + struct ipmi_rs *rsp; + struct ipmi_rq req; + /* Send Get Device Id */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_APP; + req.msg.cmd = BMC_GET_DEVICE_ID; + req.msg.data_len = 0; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Error in Get Device Id Command"); + return (-1); + } else if (rsp->ccode != 0) { + lprintf(LOG_ERR, "Get Device Id returned %x", + rsp->ccode); + return (-1); + } + pGetDevId = (struct ipm_devid_rsp *)rsp->data; + pBoardInfo->iana = IPM_DEV_MANUFACTURER_ID(pGetDevId->manufacturer_id); + pBoardInfo->boardId = buf2short(pGetDevId->product_id); + if (output) { + printf("\nIPMC Info\n"); + printf("=========\n"); + printf("Manufacturer Id : %u\n", + pBoardInfo->iana); + printf("Board Id : %u\n", + pBoardInfo->boardId); + printf("Firmware Revision : %u.%u%u", + pGetDevId->fw_rev1, pGetDevId->fw_rev2 >> 4, + pGetDevId->fw_rev2 & 0x0f); + if (((pBoardInfo->iana == IPMI_OEM_KONTRON) + && (pBoardInfo->boardId = KFWUM_BOARD_KONTRON_5002))) { + printf(" SDR %u", pGetDevId->aux_fw_rev[0]); + } + printf("\n"); + } + return 0; } - -#ifdef HAVE_PRAGMA_PACK -#pragma pack(1) -#endif -struct KfwumGetStatusResp { - unsigned char bankState; - unsigned char firmLengthLSB; - unsigned char firmLengthMid; - unsigned char firmLengthMSB; - unsigned char firmRev1; - unsigned char firmRev2; - unsigned char firmRev3; -} ATTRIBUTE_PACKING; -#ifdef HAVE_PRAGMA_PACK -#pragma pack(0) -#endif - - -const struct valstr bankStateValS[] = { - { 0x00, "Not programmed" }, - { 0x01, "New firmware" }, - { 0x02, "Wait for validation" }, - { 0x03, "Last Known Good" }, - { 0x04, "Previous Good" } -}; - /* KfwumGetStatus - Get (and prints) FWUM banks information - * - * * intf : IPMI interface + * + * *intf : IPMI interface + * + * returns 0 on success, otherwise (-1) */ -static tKFWUM_Status KfwumGetStatus(struct ipmi_intf * intf) +int +KfwumGetStatus(struct ipmi_intf * intf) { - tKFWUM_Status status = KFWUM_STATUS_OK; - struct ipmi_rs * rsp; - struct ipmi_rq req; - struct KfwumGetStatusResp *pGetStatus; - unsigned char numBank; - unsigned char counter; - - if(verbose) - { - printf(" Getting Status!\n"); - } - - /* Retreive the number of bank */ - status = KfwumGetInfo(intf, 0, &numBank); - - for( - counter = 0; - (counter < numBank) && (status == KFWUM_STATUS_OK); - counter ++ - ) - { - /* Retreive the status of each bank */ - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_FIRMWARE; - req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_STATUS; - req.msg.data = &counter; - req.msg.data_len = 1; - - rsp = intf->sendrecv(intf, &req); - - if (!rsp) - { - printf("Error in FWUM Firmware Get Status Command\n"); - status = KFWUM_STATUS_ERROR; - } - else if (rsp->ccode) - { - printf("FWUM Firmware Get Status returned %x\n", rsp->ccode); - status = KFWUM_STATUS_ERROR; - } - - - if(status == KFWUM_STATUS_OK) - { - pGetStatus = (struct KfwumGetStatusResp *) rsp->data; - printf("\nBank State %d : %s\n", counter, val2str( - pGetStatus->bankState, bankStateValS)); - if(pGetStatus->bankState) - { - unsigned long firmLength; - firmLength = pGetStatus->firmLengthMSB; - firmLength = firmLength << 8; - firmLength |= pGetStatus->firmLengthMid; - firmLength = firmLength << 8; - firmLength |= pGetStatus->firmLengthLSB; - - printf("Firmware Length : %ld bytes\n", firmLength); - printf("Firmware Revision : %u.%u%u SDR %u\n", - pGetStatus->firmRev1, pGetStatus->firmRev2 >> 4, - pGetStatus->firmRev2 & 0x0f, pGetStatus->firmRev3); - } - } - } - printf("\n"); - return status; + int rc = 0; + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct KfwumGetStatusResp *pGetStatus; + unsigned char numBank; + unsigned char counter; + unsigned long firmLength; + if (verbose) { + printf(" Getting Status!\n"); + } + /* Retreive the number of bank */ + rc = KfwumGetInfo(intf, 0, &numBank); + for(counter = 0; + (counter < numBank) && (rc == 0); + counter ++) { + /* Retreive the status of each bank */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_FIRMWARE; + req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_STATUS; + req.msg.data = &counter; + req.msg.data_len = 1; + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, + "Error in FWUM Firmware Get Status Command."); + rc = (-1); + break; + } else if (rsp->ccode) { + lprintf(LOG_ERR, + "FWUM Firmware Get Status returned %x", + rsp->ccode); + rc = (-1); + break; + } + pGetStatus = (struct KfwumGetStatusResp *) rsp->data; + printf("\nBank State %d : %s\n", + counter, + val2str(pGetStatus->bankState, bankStateValS)); + if (!pGetStatus->bankState) { + continue; + } + firmLength = pGetStatus->firmLengthMSB; + firmLength = firmLength << 8; + firmLength |= pGetStatus->firmLengthMid; + firmLength = firmLength << 8; + firmLength |= pGetStatus->firmLengthLSB; + printf("Firmware Length : %ld bytes\n", + firmLength); + printf("Firmware Revision : %u.%u%u SDR %u\n", + pGetStatus->firmRev1, + pGetStatus->firmRev2 >> 4, + pGetStatus->firmRev2 & 0x0f, + pGetStatus->firmRev3); + } + printf("\n"); + return rc; } -#ifdef HAVE_PRAGMA_PACK -#pragma pack(1) -#endif -struct KfwumManualRollbackReq{ - unsigned char type; -} ATTRIBUTE_PACKING; -#ifdef HAVE_PRAGMA_PACK -#pragma pack(0) -#endif - - /* KfwumManualRollback - Ask IPMC to rollback to previous version - * - * * intf : IPMI interface + * + * *intf : IPMI interface + * + * returns 0 on success + * returns (-1) on error */ -static tKFWUM_Status KfwumManualRollback(struct ipmi_intf * intf) +int +KfwumManualRollback(struct ipmi_intf *intf) { - tKFWUM_Status status = KFWUM_STATUS_OK; - struct ipmi_rs * rsp; - struct ipmi_rq req; - struct KfwumManualRollbackReq thisReq; - - - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_FIRMWARE; - req.msg.cmd = KFWUM_CMD_ID_MANUAL_ROLLBACK; - - thisReq.type = 0; /* Wait BMC shutdown */ - - req.msg.data = (unsigned char *) &thisReq; - req.msg.data_len = 1; - - rsp = intf->sendrecv(intf, &req); - - if (!rsp) - { - printf("Error in FWUM Manual Rollback Command\n"); - status = KFWUM_STATUS_ERROR; - } - else if (rsp->ccode) - { - printf("Error in FWUM Manual Rollback Command returned %x\n", - rsp->ccode); - status = KFWUM_STATUS_ERROR; - } - - if(status == KFWUM_STATUS_OK) - { - printf("FWUM Starting Manual Rollback \n"); - } - return status; + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct KfwumManualRollbackReq thisReq; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_FIRMWARE; + req.msg.cmd = KFWUM_CMD_ID_MANUAL_ROLLBACK; + thisReq.type = 0; /* Wait BMC shutdown */ + req.msg.data = (unsigned char *)&thisReq; + req.msg.data_len = 1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, "Error in FWUM Manual Rollback Command."); + return (-1); + } else if (rsp->ccode != 0) { + lprintf(LOG_ERR, + "Error in FWUM Manual Rollback Command returned %x", + rsp->ccode); + return (-1); + } + printf("FWUM Starting Manual Rollback \n"); + return 0; } -#ifdef HAVE_PRAGMA_PACK -#pragma pack(1) -#endif -struct KfwumStartFirmwareDownloadReq{ - unsigned char lengthLSB; - unsigned char lengthMid; - unsigned char lengthMSB; - unsigned char paddingLSB; - unsigned char paddingMSB; - unsigned char useSequence; -} ATTRIBUTE_PACKING; -#ifdef HAVE_PRAGMA_PACK -#pragma pack(0) -#endif - -#ifdef HAVE_PRAGMA_PACK -#pragma pack(1) -#endif -struct KfwumStartFirmwareDownloadResp { - unsigned char bank; -} ATTRIBUTE_PACKING; -#ifdef HAVE_PRAGMA_PACK -#pragma pack(0) -#endif - -static tKFWUM_Status KfwumStartFirmwareImage(struct ipmi_intf * intf, - unsigned long length,unsigned short padding) +int +KfwumStartFirmwareImage(struct ipmi_intf *intf, unsigned long length, + unsigned short padding) { - tKFWUM_Status status = KFWUM_STATUS_OK; - struct ipmi_rs * rsp; - struct ipmi_rq req; - struct KfwumStartFirmwareDownloadResp *pResp; - struct KfwumStartFirmwareDownloadReq thisReq; - - thisReq.lengthLSB = length & 0x000000ff; - thisReq.lengthMid = (length >> 8) & 0x000000ff; - thisReq.lengthMSB = (length >> 16) & 0x000000ff; - thisReq.paddingLSB = padding & 0x00ff; - thisReq.paddingMSB = (padding>> 8) & 0x00ff; + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct KfwumStartFirmwareDownloadResp *pResp; + struct KfwumStartFirmwareDownloadReq thisReq; + + thisReq.lengthLSB = length & 0x000000ff; + thisReq.lengthMid = (length >> 8) & 0x000000ff; + thisReq.lengthMSB = (length >> 16) & 0x000000ff; + thisReq.paddingLSB = padding & 0x00ff; + thisReq.paddingMSB = (padding>> 8) & 0x00ff; thisReq.useSequence = 0x01; - - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_FIRMWARE; - req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_IMAGE; - req.msg.data = (unsigned char *) &thisReq; - - /* Look for download type */ - if ( saveFirmwareInfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS ) - { - req.msg.data_len = 5; - } - else - { - req.msg.data_len = 6; - } - - rsp = intf->sendrecv(intf, &req); - - if (!rsp) - { - printf("Error in FWUM Firmware Start Firmware Image Download Command\n"); - status = KFWUM_STATUS_ERROR; - } - else if (rsp->ccode) - { - printf("FWUM Firmware Start Firmware Image Download returned %x\n", - rsp->ccode); - status = KFWUM_STATUS_ERROR; - } - - if(status == KFWUM_STATUS_OK) - { - pResp = (struct KfwumStartFirmwareDownloadResp *) rsp->data; - printf("Bank holding new firmware : %d\n", pResp->bank); - sleep(5); - } - return status; + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_FIRMWARE; + req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_IMAGE; + req.msg.data = (unsigned char *) &thisReq; + /* Look for download type */ + if (save_fw_nfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS) { + req.msg.data_len = 5; + } else { + req.msg.data_len = 6; + } + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, + "Error in FWUM Firmware Start Firmware Image Download Command."); + return (-1); + } else if (rsp->ccode) { + lprintf(LOG_ERR, + "FWUM Firmware Start Firmware Image Download returned %x", + rsp->ccode); + return (-1); + } + pResp = (struct KfwumStartFirmwareDownloadResp *)rsp->data; + printf("Bank holding new firmware : %d\n", pResp->bank); + sleep(5); + return 0; } -#ifdef HAVE_PRAGMA_PACK -#pragma pack(1) -#endif -struct KfwumSaveFirmwareAddressReq +int +KfwumSaveFirmwareImage(struct ipmi_intf *intf, unsigned char sequenceNumber, + unsigned long address, unsigned char *pFirmBuf, + unsigned char *pInBufLength) { - unsigned char addressLSB; - unsigned char addressMid; - unsigned char addressMSB; - unsigned char numBytes; - unsigned char txBuf[KFWUM_SMALL_BUFFER-KFWUM_OLD_CMD_OVERHEAD]; -} ATTRIBUTE_PACKING; -#ifdef HAVE_PRAGMA_PACK -#pragma pack(0) -#endif - -#ifdef HAVE_PRAGMA_PACK -#pragma pack(1) -#endif -struct KfwumSaveFirmwareSequenceReq -{ - unsigned char sequenceNumber; - unsigned char txBuf[KFWUM_BIG_BUFFER]; -} ATTRIBUTE_PACKING; -#ifdef HAVE_PRAGMA_PACK -#pragma pack(0) -#endif - - -#define FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT ((unsigned char)6) + int rc = 0; + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct KfwumSaveFirmwareAddressReq addr_req; + struct KfwumSaveFirmwareSequenceReq seq_req; + int retry = 0; + int no_rsp = 0; + do { + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_FIRMWARE; + req.msg.cmd = KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE; + if (save_fw_nfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS) { + addr_req.addressLSB = address & 0x000000ff; + addr_req.addressMid = (address >> 8) & 0x000000ff; + addr_req.addressMSB = (address >> 16) & 0x000000ff; + addr_req.numBytes = *pInBufLength; + memcpy(addr_req.txBuf, pFirmBuf, *pInBufLength); + req.msg.data = (unsigned char *)&addr_req; + req.msg.data_len = *pInBufLength + 4; + } else { + seq_req.sequenceNumber = sequenceNumber; + memcpy(seq_req.txBuf, pFirmBuf, *pInBufLength); + req.msg.data = (unsigned char *)&seq_req; + req.msg.data_len = *pInBufLength + sizeof(unsigned char); + /* + 1 => sequenceNumber*/ + } + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, + "Error in FWUM Firmware Save Firmware Image Download Command."); + /* We don't receive "C7" on errors with IOL, + * instead we receive nothing + */ + if (strstr(intf->name, "lan") != NULL) { + no_rsp++; + if (no_rsp < FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT) { + *pInBufLength -= 1; + continue; + } + lprintf(LOG_ERR, + "Error, too many commands without response."); + *pInBufLength = 0; + break; + } /* For other interface keep trying */ + } else if (rsp->ccode != 0) { + if (rsp->ccode == 0xc0) { + sleep(1); + } else if ((rsp->ccode == 0xc7) + || ((rsp->ccode == 0xc3) + && (sequenceNumber == 0))) { + *pInBufLength -= 1; + retry = 1; + } else if (rsp->ccode == 0x82) { + /* Double sent, continue */ + rc = 0; + break; + } else if (rsp->ccode == 0x83) { + if (retry == 0) { + retry = 1; + continue; + } + rc = (-1); + break; + } else if (rsp->ccode == 0xcf) { + /* Ok if receive duplicated request */ + retry = 1; + } else if (rsp->ccode == 0xc3) { + if (retry == 0) { + retry = 1; + continue; + } + rc = (-1); + break; + } else { + lprintf(LOG_ERR, + "FWUM Firmware Save Firmware Image Download returned %x", + rsp->ccode); + rc = (-1); + break; + } + } else { + break; + } + } while (1); + return rc; +} -static tKFWUM_Status KfwumSaveFirmwareImage(struct ipmi_intf * intf, - unsigned char sequenceNumber, unsigned long address, unsigned char *pFirmBuf, - unsigned char * pInBufLength) +int +KfwumFinishFirmwareImage(struct ipmi_intf *intf, tKFWUM_InFirmwareInfo firmInfo) { - tKFWUM_Status status = KFWUM_STATUS_OK; - struct ipmi_rs * rsp; - struct ipmi_rq req; - unsigned char out = 0; - unsigned char retry = 0; - unsigned char noResponse = 0 ; - - struct KfwumSaveFirmwareAddressReq addressReq; - struct KfwumSaveFirmwareSequenceReq sequenceReq; - - do - { - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_FIRMWARE; - req.msg.cmd = KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE; - - if (saveFirmwareInfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS ) - { - addressReq.addressLSB = address & 0x000000ff; - addressReq.addressMid = (address >> 8) & 0x000000ff; - addressReq.addressMSB = (address >> 16) & 0x000000ff; - addressReq.numBytes = (* pInBufLength); - memcpy(addressReq.txBuf, pFirmBuf, (* pInBufLength)); - req.msg.data = (unsigned char *) &addressReq; - req.msg.data_len = (* pInBufLength)+4; - } - else - { - sequenceReq.sequenceNumber = sequenceNumber; - memcpy(sequenceReq.txBuf, pFirmBuf, (* pInBufLength)); - req.msg.data = (unsigned char *) &sequenceReq; - req.msg.data_len = (* pInBufLength)+sizeof(unsigned char); /* + 1 => sequenceNumber*/ - } - - rsp = intf->sendrecv(intf, &req); - - if (!rsp) - { - printf("Error in FWUM Firmware Save Firmware Image Download Command\n"); - - out = 0; - status = KFWUM_STATUS_OK; - - /* With IOL, we don't receive "C7" on errors, instead we receive - nothing */ - if(strstr(intf->name,"lan")!= NULL) - { - noResponse++; - - if(noResponse < FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT ) - { - (* pInBufLength) -= 1; - out = 0; - } - else - { - printf("Error, too many commands without response\n"); - (* pInBufLength) = 0 ; - out = 1; - } - } /* For other interface keep trying */ - } - else if (rsp->ccode) - { - if(rsp->ccode == 0xc0) - { - status = KFWUM_STATUS_OK; - sleep(1); - } - else if( - (rsp->ccode == 0xc7) - || - ( - (rsp->ccode == 0xC3) && - (sequenceNumber == 0) - ) - ) - { - (* pInBufLength) -= 1; - status = KFWUM_STATUS_OK; - retry = 1; - } - else if(rsp->ccode == 0x82) - { - /* Double sent, continue */ - status = KFWUM_STATUS_OK; - out = 1; - } - else if(rsp->ccode == 0x83) - { - if(retry == 0) - { - retry = 1; - status = KFWUM_STATUS_OK; - } - else - { - status = KFWUM_STATUS_ERROR; - out = 1; - } - } - else if(rsp->ccode == 0xcf) /* Ok if receive duplicated request */ - { - retry = 1; - status = KFWUM_STATUS_OK; - } - else if(rsp->ccode == 0xC3) - { - if(retry == 0) - { - retry = 1; - status = KFWUM_STATUS_OK; - } - else - { - status = KFWUM_STATUS_ERROR; - out = 1; - } - } - else - { - printf("FWUM Firmware Save Firmware Image Download returned %x\n", - rsp->ccode); - status = KFWUM_STATUS_ERROR; - out = 1; - } - } - else - { - out = 1; - } - }while(out == 0); - return status; + struct ipmi_rs *rsp; + struct ipmi_rq req; + struct KfwumFinishFirmwareDownloadReq thisReq; + + thisReq.versionMaj = firmInfo.versMajor; + thisReq.versionMinSub = ((firmInfo.versMinor <<4) + | firmInfo.versSubMinor); + thisReq.versionSdr = firmInfo.sdrRev; + thisReq.reserved = 0; + /* Byte 4 reserved, write 0 */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_FIRMWARE; + req.msg.cmd = KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE; + req.msg.data = (unsigned char *)&thisReq; + req.msg.data_len = 4; + /* Infinite loop if BMC doesn't reply or replies 0xc0 every time. */ + do { + rsp = intf->sendrecv(intf, &req); + } while (rsp == NULL || rsp->ccode == 0xc0); + if (!rsp) { + lprintf(LOG_ERR, + "Error in FWUM Firmware Finish Firmware Image Download Command."); + return (-1); + } else if (rsp->ccode != 0) { + lprintf(LOG_ERR, + "FWUM Firmware Finish Firmware Image Download returned %x", + rsp->ccode); + return (-1); + } + return 0; } -#ifdef HAVE_PRAGMA_PACK -#pragma pack(1) -#endif -struct KfwumFinishFirmwareDownloadReq{ - unsigned char versionMaj; - unsigned char versionMinSub; - unsigned char versionSdr; - unsigned char reserved; -} ATTRIBUTE_PACKING; -#ifdef HAVE_PRAGMA_PACK -#pragma pack(0) -#endif - -static tKFWUM_Status KfwumFinishFirmwareImage(struct ipmi_intf * intf, - tKFWUM_InFirmwareInfo firmInfo) +int +KfwumUploadFirmware(struct ipmi_intf *intf, unsigned char *pBuffer, + unsigned long totalSize) { - tKFWUM_Status status = KFWUM_STATUS_OK; - struct ipmi_rs * rsp; - struct ipmi_rq req; - struct KfwumFinishFirmwareDownloadReq thisReq; - - thisReq.versionMaj = firmInfo.versMajor; - thisReq.versionMinSub = ((firmInfo.versMinor <<4) | firmInfo.versSubMinor); - thisReq.versionSdr = firmInfo.sdrRev; - thisReq.reserved = 0; - /* Byte 4 reserved, write 0 */ - - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_FIRMWARE; - req.msg.cmd = KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE; - req.msg.data = (unsigned char *) &thisReq; - req.msg.data_len = 4; - - do - { - rsp = intf->sendrecv(intf, &req); - }while (rsp == NULL || rsp->ccode == 0xc0); - - if (!rsp) - { - printf("Error in FWUM Firmware Finish Firmware Image Download Command\n"); - status = KFWUM_STATUS_ERROR; - } - else if (rsp->ccode) - { - printf("FWUM Firmware Finish Firmware Image Download returned %x\n", - rsp->ccode); - status = KFWUM_STATUS_ERROR; - } - - return status; + int rc = (-1); + unsigned long address = 0x0; + unsigned char writeSize; + unsigned char oldWriteSize; + unsigned long lastAddress = 0; + unsigned char sequenceNumber = 0; + unsigned char retry = FWUM_MAX_UPLOAD_RETRY; + unsigned char isLengthValid = 1; + do { + writeSize = save_fw_nfo.bufferSize - save_fw_nfo.overheadSize; + /* Reach the end */ + if (address + writeSize > totalSize) { + writeSize = (totalSize - address); + } else if (((address % KFWUM_PAGE_SIZE) + + writeSize) > KFWUM_PAGE_SIZE) { + /* Reach boundary end */ + writeSize = (KFWUM_PAGE_SIZE - (address % KFWUM_PAGE_SIZE)); + } + oldWriteSize = writeSize; + rc = KfwumSaveFirmwareImage(intf, sequenceNumber, + address, &pBuffer[address], &writeSize); + if ((rc != 0) && (retry-- != 0)) { + address = lastAddress; + rc = 0; + } else if ( writeSize == 0) { + rc = (-1); + } else { + if (writeSize != oldWriteSize) { + printf("Adjusting length to %d bytes \n", + writeSize); + save_fw_nfo.bufferSize -= (oldWriteSize - writeSize); + } + retry = FWUM_MAX_UPLOAD_RETRY; + lastAddress = address; + address+= writeSize; + } + if (rc == 0) { + if ((address % 1024) == 0) { + KfwumShowProgress("Writting Firmware in Flash", + address, totalSize); + } + sequenceNumber++; + } + } while ((rc == 0) && (address < totalSize)); + if (rc == 0) { + KfwumShowProgress("Writting Firmware in Flash", + 100, 100); + } + return rc; } - -#define FWUM_MAX_UPLOAD_RETRY 6 -static tKFWUM_Status KfwumUploadFirmware(struct ipmi_intf * intf, - unsigned char * pBuffer, unsigned long totalSize) +int +KfwumStartFirmwareUpgrade(struct ipmi_intf *intf) { - tKFWUM_Status status = KFWUM_STATUS_ERROR; - unsigned long address = 0x0; - unsigned char writeSize; - unsigned char oldWriteSize; - unsigned long lastAddress = 0; - unsigned char sequenceNumber = 0; - unsigned char retry = FWUM_MAX_UPLOAD_RETRY; - unsigned char isLengthValid = 1; - - do - { - writeSize = saveFirmwareInfo.bufferSize - saveFirmwareInfo.overheadSize; - - /* Reach the end */ - if( address + writeSize > totalSize ) - { - writeSize = (totalSize - address); - } - /* Reach boundary end */ - else if(((address % KFWUM_PAGE_SIZE) + writeSize) > KFWUM_PAGE_SIZE) - { - writeSize = (KFWUM_PAGE_SIZE - (address % KFWUM_PAGE_SIZE)); - } - - oldWriteSize = writeSize; - status = KfwumSaveFirmwareImage(intf, sequenceNumber, address, - &pBuffer[address], &writeSize); - - if((status != KFWUM_STATUS_OK) && (retry-- != 0)) - { - address = lastAddress; - status = KFWUM_STATUS_OK; - } - else if( writeSize == 0 ) - { - status = KFWUM_STATUS_ERROR; - } - else - { - if(writeSize != oldWriteSize) - { - printf("Adjusting length to %d bytes \n", writeSize); - saveFirmwareInfo.bufferSize -= (oldWriteSize - writeSize); - } - - retry = FWUM_MAX_UPLOAD_RETRY; - lastAddress = address; - address+= writeSize; - } - - if(status == KFWUM_STATUS_OK) - { - if((address % 1024) == 0) - { - KfwumShowProgress((const unsigned char *)\ - "Writting Firmware in Flash",address,totalSize); - } - sequenceNumber++; - } - - }while((status == KFWUM_STATUS_OK) && (address < totalSize )); - - if(status == KFWUM_STATUS_OK) - { - KfwumShowProgress((const unsigned char *)\ - "Writting Firmware in Flash", 100 , 100 ); - } - - return(status); + int rc = 0; + struct ipmi_rs *rsp; + struct ipmi_rq req; + /* Upgrade type, wait BMC shutdown */ + unsigned char upgType = 0 ; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_FIRMWARE; + req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_UPDATE; + req.msg.data = (unsigned char *) &upgType; + req.msg.data_len = 1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, + "Error in FWUM Firmware Start Firmware Upgrade Command"); + rc = (-1); + } else if (rsp->ccode) { + if (rsp->ccode == 0xd5) { + lprintf(LOG_ERR, + "No firmware available for upgrade. Download Firmware first."); + } else { + lprintf(LOG_ERR, + "FWUM Firmware Start Firmware Upgrade returned %x", + rsp->ccode); + } + rc = (-1); + } + return rc; } -static tKFWUM_Status KfwumStartFirmwareUpgrade(struct ipmi_intf * intf) +int +KfwumGetTraceLog(struct ipmi_intf *intf) { - tKFWUM_Status status = KFWUM_STATUS_OK; - struct ipmi_rs * rsp; - struct ipmi_rq req; - unsigned char upgType = 0 ; /* Upgrade type, wait BMC shutdown */ - - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_FIRMWARE; - req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_UPDATE; - req.msg.data = (unsigned char *) &upgType; - req.msg.data_len = 1; - - rsp = intf->sendrecv(intf, &req); - - if (!rsp) - { - printf("Error in FWUM Firmware Start Firmware Upgrade Command\n"); - status = KFWUM_STATUS_ERROR; - } - else if (rsp->ccode) - { - if(rsp->ccode == 0xd5) - { - printf("No firmware available for upgrade. Download Firmware first\n"); - } - else - { - printf("FWUM Firmware Start Firmware Upgrade returned %x\n", - rsp->ccode); - } - status = KFWUM_STATUS_ERROR; - } - - return status; + int rc = 0; + struct ipmi_rs *rsp; + struct ipmi_rq req; + unsigned char chunkIdx; + unsigned char cmdIdx; + if (verbose) { + printf(" Getting Trace Log!\n"); + } + for (chunkIdx = 0; + (chunkIdx < TRACE_LOG_CHUNK_COUNT) + && (rc == 0); + chunkIdx++) { + /* Retreive each log chunk and print it */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_FIRMWARE; + req.msg.cmd = KFWUM_CMD_ID_GET_TRACE_LOG; + req.msg.data = &chunkIdx; + req.msg.data_len = 1; + + rsp = intf->sendrecv(intf, &req); + if (rsp == NULL) { + lprintf(LOG_ERR, + "Error in FWUM Firmware Get Trace Log Command"); + rc = (-1); + break; + } else if (rsp->ccode) { + lprintf(LOG_ERR, + "FWUM Firmware Get Trace Log returned %x", + rsp->ccode); + rc = (-1); + break; + } + for (cmdIdx=0; cmdIdx < TRACE_LOG_CHUNK_SIZE; cmdIdx++) { + /* Don't diplay commands with an invalid state */ + if ((rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1] != 0) + && (rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx] < KFWUM_CMD_ID_STD_MAX_CMD)) { + printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n", + CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx]], + CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1]], + rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 2]); + } else if ((rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1] != 0) + && (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] >= KFWUM_CMD_ID_EXTENDED_CMD)) { + printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n", + EXT_CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx] - KFWUM_CMD_ID_EXTENDED_CMD], + CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1]], + rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 2]); + } + } + } + printf("\n"); + return rc; } -#define TRACE_LOG_CHUNK_COUNT 7 -#define TRACE_LOG_CHUNK_SIZE 7 -#define TRACE_LOG_ATT_COUNT 3 -/* String table */ -/* Must match eFWUM_CmdId */ -static const char* CMD_ID_STRING[] = { - "GetFwInfo", - "KickWatchdog", - "GetLastAnswer", - "BootHandshake", - "ReportStatus", - "CtrlIPMBLine", - "SetFwState", - "GetFwStatus", - "GetSpiMemStatus", - "StartFwUpdate", - "StartFwImage", - "SaveFwImage", - "FinishFwImage", - "ReadFwImage", - "ManualRollback", - "GetTraceLog" }; - -static const char* EXT_CMD_ID_STRING[] = { - "FwUpgradeLock", - "ProcessFwUpg", - "ProcessFwRb", - "WaitHSAfterUpg", - "WaitFirstHSUpg", - "FwInfoStateChange" }; - - -static const char* CMD_STATE_STRING[] = { - "Invalid", - "Begin", - "Progress", - "Completed" }; - - -static tKFWUM_Status KfwumGetTraceLog(struct ipmi_intf * intf) +int +KfwumGetInfoFromFirmware(unsigned char *pBuf, unsigned long bufSize, + tKFWUM_InFirmwareInfo *pInfo) { - tKFWUM_Status status = KFWUM_STATUS_OK; - struct ipmi_rs *rsp; - struct ipmi_rq req; - unsigned char chunkIdx; - unsigned char cmdIdx; - - if(verbose) - { - printf(" Getting Trace Log!\n"); - } - - for( chunkIdx = 0; (chunkIdx < TRACE_LOG_CHUNK_COUNT) && (status == KFWUM_STATUS_OK); chunkIdx++ ) - { - /* Retreive each log chunk and print it */ - memset(&req, 0, sizeof(req)); - req.msg.netfn = IPMI_NETFN_FIRMWARE; - req.msg.cmd = KFWUM_CMD_ID_GET_TRACE_LOG; - req.msg.data = &chunkIdx; - req.msg.data_len = 1; - - rsp = intf->sendrecv(intf, &req); - - if (!rsp) - { - printf("Error in FWUM Firmware Get Trace Log Command\n"); - status = KFWUM_STATUS_ERROR; - } - else if (rsp->ccode) - { - printf("FWUM Firmware Get Trace Log returned %x\n", rsp->ccode); - status = KFWUM_STATUS_ERROR; - } - - if(status == KFWUM_STATUS_OK) - { - for (cmdIdx=0; cmdIdx < TRACE_LOG_CHUNK_SIZE; cmdIdx++) - { - /* Don't diplay commands with an invalid state */ - if ( (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+1] != 0) && - (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] < KFWUM_CMD_ID_STD_MAX_CMD)) - { - printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n", - CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx]], - CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+1]], - rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+2]); - } - else if ( (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+1] != 0) && - (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] >= KFWUM_CMD_ID_EXTENDED_CMD)) - { - printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n", - EXT_CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] - KFWUM_CMD_ID_EXTENDED_CMD], - CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+1]], - rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx+2]); - } - } - } - } - printf("\n"); - return status; -} + unsigned long offset = 0; + if (bufSize < (IN_FIRMWARE_INFO_OFFSET_LOCATION + IN_FIRMWARE_INFO_SIZE)) { + return (-1); + } + offset = IN_FIRMWARE_INFO_OFFSET_LOCATION; + /* Now, fill the structure with read informations */ + pInfo->checksum = (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + 0 + IN_FIRMWARE_INFO_OFFSET_CHECKSUM ) << 8; -/******************************************************************************* -* Function Name: KfwumGetInfoFromFirmware -* -* Description: This function retreive from the firmare the following info : -* -* o Checksum -* o File size (expected) -* o Board Id -* o Device Id -* -* Restriction: None -* -* Input: char * fileName - File to get info from -* -* Output: pInfo - container that will hold all the informations gattered. -* see structure for all details -* -* Global: None -* -* Return: IFWU_SUCCESS - file ok -* IFWU_ERROR - file error -* -*******************************************************************************/ -#define IN_FIRMWARE_INFO_OFFSET_LOCATION 0x5a0 -#define IN_FIRMWARE_INFO_SIZE 20 -#define IN_FIRMWARE_INFO_OFFSET_FILE_SIZE 0 -#define IN_FIRMWARE_INFO_OFFSET_CHECKSUM 4 -#define IN_FIRMWARE_INFO_OFFSET_BOARD_ID 6 -#define IN_FIRMWARE_INFO_OFFSET_DEVICE_ID 8 -#define IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION 9 -#define IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV 10 -#define IN_FIRMWARE_INFO_OFFSET_VERSION_MAJOR 11 -#define IN_FIRMWARE_INFO_OFFSET_VERSION_MINSUB 12 -#define IN_FIRMWARE_INFO_OFFSET_SDR_REV 13 -#define IN_FIRMWARE_INFO_OFFSET_IANA0 14 -#define IN_FIRMWARE_INFO_OFFSET_IANA1 15 -#define IN_FIRMWARE_INFO_OFFSET_IANA2 16 - -#define KWUM_GET_BYTE_AT_OFFSET(pBuffer,os) pBuffer[os] - -tKFWUM_Status KfwumGetInfoFromFirmware(unsigned char * pBuf, - unsigned long bufSize, tKFWUM_InFirmwareInfo * pInfo) -{ - tKFWUM_Status status = KFWUM_STATUS_ERROR; - - if(bufSize >= (IN_FIRMWARE_INFO_OFFSET_LOCATION + IN_FIRMWARE_INFO_SIZE)) - { - unsigned long offset = IN_FIRMWARE_INFO_OFFSET_LOCATION; - - /* Now, fill the structure with read informations */ - pInfo->checksum = (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+0+IN_FIRMWARE_INFO_OFFSET_CHECKSUM ) << 8; - pInfo->checksum |= (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+1+IN_FIRMWARE_INFO_OFFSET_CHECKSUM ); - - - pInfo->sumToRemoveFromChecksum= - KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_CHECKSUM); - - pInfo->sumToRemoveFromChecksum+= - KWUM_GET_BYTE_AT_OFFSET(pBuf , - offset+IN_FIRMWARE_INFO_OFFSET_CHECKSUM+1); - - pInfo->fileSize = - KWUM_GET_BYTE_AT_OFFSET(pBuf , - offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+0) << 24; - pInfo->fileSize |= - (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+1) << 16; - pInfo->fileSize |= - (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+2) << 8; - pInfo->fileSize |= - (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_FILE_SIZE+3); - - pInfo->boardId = - KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_BOARD_ID+0) << 8; - pInfo->boardId |= - KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_BOARD_ID+1); - - pInfo->deviceId = - KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_DEVICE_ID); - - pInfo->tableVers = - KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION); - pInfo->implRev = - KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV); - pInfo->versMajor = - (KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_VERSION_MAJOR)) & 0x0f; - pInfo->versMinor = - (KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_VERSION_MINSUB)>>4) & 0x0f; - pInfo->versSubMinor = - (KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_VERSION_MINSUB)) & 0x0f; - pInfo->sdrRev = - KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_SDR_REV); - pInfo->iana = - KWUM_GET_BYTE_AT_OFFSET(pBuf , - offset+IN_FIRMWARE_INFO_OFFSET_IANA2) << 16; - pInfo->iana |= - (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_IANA1) << 8; - pInfo->iana |= - (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf, - offset+IN_FIRMWARE_INFO_OFFSET_IANA0); - - KfwumFixTableVersionForOldFirmware(pInfo); - - status = KFWUM_STATUS_OK; - } - return(status); -} + pInfo->checksum|= (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + 1 + IN_FIRMWARE_INFO_OFFSET_CHECKSUM); + pInfo->sumToRemoveFromChecksum = KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_CHECKSUM); -void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo) -{ - switch(pInfo->boardId) - { - case KFWUM_BOARD_KONTRON_UNKNOWN: - pInfo->tableVers = 0xff; - break; - default: - /* pInfo->tableVers is already set for the right version */ - break; - } -} + pInfo->sumToRemoveFromChecksum+= KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_CHECKSUM + 1); + + pInfo->fileSize = KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 0) << 24; + + pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 1) << 16; + + pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 2) << 8; + + pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 3); + + pInfo->boardId = KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_BOARD_ID + 0) << 8; + pInfo->boardId|= KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_BOARD_ID + 1); -tKFWUM_Status KfwumValidFirmwareForBoard(tKFWUM_BoardInfo boardInfo, - tKFWUM_InFirmwareInfo firmInfo) + pInfo->deviceId = KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_DEVICE_ID); + + pInfo->tableVers = KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION); + + pInfo->implRev = KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV); + + pInfo->versMajor = (KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + + IN_FIRMWARE_INFO_OFFSET_VER_MAJOROR)) & 0x0f; + + pInfo->versMinor = (KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + + IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB) >> 4) & 0x0f; + + pInfo->versSubMinor = (KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB)) & 0x0f; + + pInfo->sdrRev = KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_SDR_REV); + + pInfo->iana = KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_IANA2) << 16; + + pInfo->iana|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_IANA1) << 8; + + pInfo->iana|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf, + offset + IN_FIRMWARE_INFO_OFFSET_IANA0); + + KfwumFixTableVersionForOldFirmware(pInfo); + return 0; +} + +void +KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo) { - tKFWUM_Status status = KFWUM_STATUS_OK; - - if(boardInfo.iana != firmInfo.iana) - { - printf("Board IANA does not match firmware IANA\n"); - status = KFWUM_STATUS_ERROR; - } - - if(boardInfo.boardId != firmInfo.boardId) - { - printf("Board IANA does not match firmware IANA\n"); - status = KFWUM_STATUS_ERROR; - } - - - if(status == KFWUM_STATUS_ERROR) - { - printf("Firmware invalid for target board. Download of upgrade aborted\n"); - } - return status; + switch(pInfo->boardId) { + case KFWUM_BOARD_KONTRON_UNKNOWN: + pInfo->tableVers = 0xff; + break; + default: + /* pInfo->tableVers is already set for + * the right version + */ + break; + } } +/* ipmi_kfwum_checkfwcompat - check whether firmware we're about to upload is + * compatible with board. + * + * @boardInfo: + * @firmInfo: + * + * returns 0 if compatible, otherwise (-1) + */ +int +ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo, + tKFWUM_InFirmwareInfo firmInfo) +{ + int compatible = 0; + if (boardInfo.iana != firmInfo.iana) { + lprintf(LOG_ERR, + "Board IANA does not match firmware IANA."); + compatible = (-1); + } + if (boardInfo.boardId != firmInfo.boardId) { + lprintf(LOG_ERR, + "Board IANA does not match firmware IANA."); + compatible = (-1); + } + if (compatible != 0) { + lprintf(LOG_ERR, + "Firmware invalid for target board. Download of upgrade aborted."); + } + return compatible; +} -static void KfwumOutputInfo(tKFWUM_BoardInfo boardInfo, - tKFWUM_InFirmwareInfo firmInfo) +void +printf_kfwum_info(tKFWUM_BoardInfo boardInfo, tKFWUM_InFirmwareInfo firmInfo) { - printf("Target Board Id : %u\n",boardInfo.boardId); - printf("Target IANA number : %u\n",boardInfo.iana); - printf("File Size : %lu bytes\n",firmInfo.fileSize); - printf("Firmware Version : %d.%d%d SDR %d\n",firmInfo.versMajor, - firmInfo.versMinor, firmInfo.versSubMinor, firmInfo.sdrRev); + printf( +"Target Board Id : %u\n", boardInfo.boardId); + printf( +"Target IANA number : %u\n", boardInfo.iana); + printf( +"File Size : %lu bytes\n", firmInfo.fileSize); + printf( +"Firmware Version : %d.%d%d SDR %d\n", firmInfo.versMajor, +firmInfo.versMinor, firmInfo.versSubMinor, firmInfo.sdrRev); } diff --git a/ipmitool/lib/ipmi_hpmfwupg.c b/ipmitool/lib/ipmi_hpmfwupg.c index 630c0e7..0a56857 100644 --- a/ipmitool/lib/ipmi_hpmfwupg.c +++ b/ipmitool/lib/ipmi_hpmfwupg.c @@ -17,7 +17,7 @@ * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * - * This software is provided "AS IS," without a warranty of any kind. + * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. @@ -40,3940 +40,2605 @@ #include "../src/plugins/lan/md5.h" #include #include +#include #if HAVE_CONFIG_H - #include +# include #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++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 - 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 - Copies all the components from a valid HPM.1"); - lprintf(LOG_NOTICE," image 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 activate - Copy and activate the firmware using a valid HPM.1"); - lprintf(LOG_NOTICE," image ."); - 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 force - Copies all the components present in "); - 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 \" command."); - lprintf(LOG_NOTICE,"upgrade component x - Copy only component from the given "); - 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 \" 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 - Get specified component properties from the target."); - lprintf(LOG_NOTICE," Valid component : 0-7 "); - lprintf(LOG_NOTICE," Properties 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 - 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 [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 \" 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 - Perform \"Comparison of the Active Copy\" action for all the"); + lprintf(LOG_NOTICE, +" components present in the file."); + lprintf(LOG_NOTICE, +"compare component x - Compare only component from the given "); + 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 - Get specified component properties from the target."); + lprintf(LOG_NOTICE, +" Valid component : 0-7 "); + lprintf(LOG_NOTICE, +" Properties 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 */ - 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 force */ - if (strcmp(argv[i],"force") == 0) - { - option &= ~(VERSIONCHECK_MODE); - option &= ~(VIEW_MODE); - option |= FORCE_MODE_ALL; - } - /* hpm upgrade component */ - 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 */ + 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 force */ + if (strcmp(argv[i],"force") == 0) { + option |= FORCE_MODE; + } + /* hpm upgrade component */ + 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 [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; isession->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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dummy.h" + +#if defined(HAVE_CONFIG_H) +# include +#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 #endif + +#if defined(IPMI_INTF_LAN) || defined (IPMI_INTF_LANPLUS) +#include +#include +#include +#include +#include +#include +#include +#endif + + #include #include #include @@ -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 + } /*