diff -Naur ipmitool-1.8.13-1_ORIG/config.h.in ipmitool-1.8.13-1/config.h.in --- ipmitool-1.8.13-1_ORIG/config.h.in 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/config.h.in 2015-09-18 04:00:17.677667563 -0400 @@ -176,6 +176,9 @@ /* Define to 1 to enable serial interface. */ #undef IPMI_INTF_SERIAL +/* Define to 1 to enable USB interface. */ +#undef IPMI_INTF_USB + /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR diff -Naur ipmitool-1.8.13-1_ORIG/configure ipmitool-1.8.13-1/configure --- ipmitool-1.8.13-1_ORIG/configure 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/configure 2015-09-18 04:00:51.466650916 -0400 @@ -630,6 +630,8 @@ INTF_SERIAL INTF_LANPLUS_LIB INTF_LANPLUS +INTF_USB_LIB +INTF_USB INTF_LAN_LIB INTF_LAN BASEDIR @@ -766,6 +768,7 @@ enable_solaris_opt enable_internal_md5 enable_intf_lan +enable_intf_usb enable_intf_lanplus enable_intf_serial with_kerneldir @@ -1418,6 +1421,7 @@ --enable-solaris-opt enable all options for Solaris [default=no] --enable-internal-md5 enable internal MD5 library [default=no] --enable-intf-lan enable IPMIv1.5 LAN interface [default=yes] + --enable-intf-usb enable IPMI USB interface [default=yes] --enable-intf-lanplus enable IPMIv2.0 RMCP+ LAN interface [default=auto] --enable-intf-serial enable direct Serial Basic/Terminal mode interface [default=yes] @@ -12562,6 +12566,27 @@ IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB lan/libintf_lan.la" fi +# Check whether --enable-intf-usb was given. +if test "${enable_intf_usb+set}" = set; then : + enableval=$enable_intf_usb; +else + enable_intf_usb=yes +fi + +if test "x$enable_intf_usb" = "xstatic" || test "x$enable_intf_usb" = "xplugin"; then + enable_intf_usb=yes +fi +if test "x$enable_intf_usb" = "xyes";then + +$as_echo "#define IPMI_INTF_USB 1" >>confdefs.h + + INTF_USB=usb + + INTF_USB_LIB=libintf_usb.la + + IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB usb/libintf_usb.la" +fi + # Check whether --enable-intf-lanplus was given. if test "${enable_intf_lanplus+set}" = set; then : enableval=$enable_intf_lanplus; xenable_intf_lanplus=$enableval @@ -13615,7 +13640,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_config_files="$ac_config_files Makefile doc/Makefile contrib/Makefile control/Makefile control/pkginfo control/prototype control/rpmmacros control/ipmitool.spec lib/Makefile include/Makefile include/ipmitool/Makefile src/Makefile src/plugins/Makefile src/plugins/lan/Makefile src/plugins/lanplus/Makefile src/plugins/open/Makefile src/plugins/free/Makefile src/plugins/imb/Makefile src/plugins/bmc/Makefile src/plugins/lipmi/Makefile src/plugins/serial/Makefile" +ac_config_files="$ac_config_files Makefile doc/Makefile contrib/Makefile control/Makefile control/pkginfo control/prototype control/rpmmacros control/ipmitool.spec lib/Makefile include/Makefile include/ipmitool/Makefile src/Makefile src/plugins/Makefile src/plugins/lan/Makefile src/plugins/lanplus/Makefile src/plugins/open/Makefile src/plugins/free/Makefile src/plugins/imb/Makefile src/plugins/bmc/Makefile src/plugins/usb/Makefile src/plugins/lipmi/Makefile src/plugins/serial/Makefile" cat >confcache <<\_ACEOF @@ -14647,6 +14672,7 @@ "src/plugins/free/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/free/Makefile" ;; "src/plugins/imb/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/imb/Makefile" ;; "src/plugins/bmc/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/bmc/Makefile" ;; + "src/plugins/usb/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/usb/Makefile" ;; "src/plugins/lipmi/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/lipmi/Makefile" ;; "src/plugins/serial/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/serial/Makefile" ;; @@ -16028,6 +16054,8 @@ $as_echo " imb : $xenable_intf_imb" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: bmc : $xenable_intf_bmc" >&5 $as_echo " bmc : $xenable_intf_bmc" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: usb : $enable_intf_usb" >&5 +$as_echo " usb : $enable_intf_usb" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: lipmi : $xenable_intf_lipmi" >&5 $as_echo " lipmi : $xenable_intf_lipmi" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: serial : $xenable_intf_serial" >&5 diff -Naur ipmitool-1.8.13-1_ORIG/configure.in ipmitool-1.8.13-1/configure.in --- ipmitool-1.8.13-1_ORIG/configure.in 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/configure.in 2015-09-18 04:01:04.101874864 -0400 @@ -172,6 +172,21 @@ IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB lan/libintf_lan.la" fi +dnl enable IPMI USB interface +AC_ARG_ENABLE([intf-usb], + [AC_HELP_STRING([--enable-intf-usb], + [enable IPMI USB interface [default=yes]])], + [], [enable_intf_usb=yes]) +if test "x$enable_intf_usb" = "xstatic" || test "x$enable_intf_usb" = "xplugin"; then + enable_intf_usb=yes +fi +if test "x$enable_intf_usb" = "xyes";then + AC_DEFINE(IPMI_INTF_USB, [1], [Define to 1 to enable USB interface.]) + AC_SUBST(INTF_USB, [usb]) + AC_SUBST(INTF_USB_LIB, [libintf_usb.la]) + IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB usb/libintf_usb.la" +fi + dnl enable IPMIv2.0 RMCP+ LAN interface AC_ARG_ENABLE([intf-lanplus], [AC_HELP_STRING([--enable-intf-lanplus], @@ -601,6 +616,7 @@ src/plugins/free/Makefile src/plugins/imb/Makefile src/plugins/bmc/Makefile + src/plugins/usb/Makefile src/plugins/lipmi/Makefile src/plugins/serial/Makefile]) @@ -616,6 +632,7 @@ AC_MSG_RESULT([ free : $xenable_intf_free]) AC_MSG_RESULT([ imb : $xenable_intf_imb]) AC_MSG_RESULT([ bmc : $xenable_intf_bmc]) +AC_MSG_RESULT([ usb : $enable_intf_usb]) AC_MSG_RESULT([ lipmi : $xenable_intf_lipmi]) AC_MSG_RESULT([ serial : $xenable_intf_serial]) AC_MSG_RESULT([]) diff -Naur ipmitool-1.8.13-1_ORIG/contrib/Makefile.in ipmitool-1.8.13-1/contrib/Makefile.in --- ipmitool-1.8.13-1_ORIG/contrib/Makefile.in 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/contrib/Makefile.in 2015-09-21 00:29:41.994975160 -0400 @@ -157,6 +157,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/control/Makefile.in ipmitool-1.8.13-1/control/Makefile.in --- ipmitool-1.8.13-1_ORIG/control/Makefile.in 2015-09-18 03:59:15.220042750 -0400 +++ ipmitool-1.8.13-1/control/Makefile.in 2015-09-21 00:29:34.983426760 -0400 @@ -128,6 +128,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/doc/Makefile.in ipmitool-1.8.13-1/doc/Makefile.in --- ipmitool-1.8.13-1_ORIG/doc/Makefile.in 2015-09-18 03:59:15.224042771 -0400 +++ ipmitool-1.8.13-1/doc/Makefile.in 2015-09-21 00:29:27.173519281 -0400 @@ -158,6 +158,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/include/ipmitool/helper.h ipmitool-1.8.13-1/include/ipmitool/helper.h --- ipmitool-1.8.13-1_ORIG/include/ipmitool/helper.h 2015-09-18 03:59:15.224042771 -0400 +++ ipmitool-1.8.13-1/include/ipmitool/helper.h 2015-09-18 04:04:31.307736776 -0400 @@ -99,6 +99,7 @@ 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 -Naur ipmitool-1.8.13-1_ORIG/include/ipmitool/hpm2.h ipmitool-1.8.13-1/include/ipmitool/hpm2.h --- ipmitool-1.8.13-1_ORIG/include/ipmitool/hpm2.h 1969-12-31 19:00:00.000000000 -0500 +++ ipmitool-1.8.13-1/include/ipmitool/hpm2.h 2015-09-17 05:13:53.417979600 -0400 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2012 Pigeon Point Systems. 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 Pigeon Point Systems nor 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. + * PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL + * PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, + * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include + +/* Global HPM.2 defines */ +#define HPM2_REVISION 0x01 +#define HPM3_REVISION 0x01 +#define HPM2_LAN_PARAMS_REV 0x01 +#define HPM2_SOL_PARAMS_REV 0x01 +#define HPM3_LAN_PARAMS_REV 0x01 + +/* HPM.2 capabilities */ +#define HPM2_CAPS_SOL_EXTENSION 0x01 +#define HPM2_CAPS_PACKET_TRACE 0x02 +#define HPM2_CAPS_EXT_MANAGEMENT 0x04 +#define HPM2_CAPS_VERSION_SENSOR 0x08 +#define HPM2_CAPS_DYNAMIC_SESSIONS 0x10 + +#if HAVE_PRAGMA_PACK +#pragma pack(push, 1) +#endif + +/* HPM.2 LAN attach capabilities */ +struct hpm2_lan_attach_capabilities { + uint8_t hpm2_revision_id; + uint16_t lan_channel_mask; + uint8_t hpm2_caps; + uint8_t hpm2_lan_params_start; + uint8_t hpm2_lan_params_rev; + uint8_t hpm2_sol_params_start; + uint8_t hpm2_sol_params_rev; +} ATTRIBUTE_PACKING; + +/* HPM.2 LAN channel capabilities */ +struct hpm2_lan_channel_capabilities { + uint8_t capabilities; + uint8_t attach_type; + uint8_t bandwidth_class; + uint16_t max_inbound_pld_size; + uint16_t max_outbound_pld_size; +} ATTRIBUTE_PACKING; + +#if HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif + +/* HPM.2 command assignments */ +#define HPM2_GET_LAN_ATTACH_CAPABILITIES 0x3E + +extern int hpm2_get_capabilities(struct ipmi_intf * intf, + struct hpm2_lan_attach_capabilities * caps); +extern int hpm2_get_lan_channel_capabilities(struct ipmi_intf * intf, + uint8_t hpm2_lan_params_start, + struct hpm2_lan_channel_capabilities * caps); +extern int hpm2_detect_max_payload_size(struct ipmi_intf * intf); diff -Naur ipmitool-1.8.13-1_ORIG/include/ipmitool/ipmi_fru.h ipmitool-1.8.13-1/include/ipmitool/ipmi_fru.h --- ipmitool-1.8.13-1_ORIG/include/ipmitool/ipmi_fru.h 2015-09-18 03:59:15.224042771 -0400 +++ ipmitool-1.8.13-1/include/ipmitool/ipmi_fru.h 2015-09-18 04:04:40.147996178 -0400 @@ -63,6 +63,8 @@ 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 @@ #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 @@ "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 -Naur ipmitool-1.8.13-1_ORIG/include/ipmitool/ipmi_hpmfwupg.h ipmitool-1.8.13-1/include/ipmitool/ipmi_hpmfwupg.h --- ipmitool-1.8.13-1_ORIG/include/ipmitool/ipmi_hpmfwupg.h 2015-09-18 03:59:15.224042771 -0400 +++ ipmitool-1.8.13-1/include/ipmitool/ipmi_hpmfwupg.h 2015-09-18 04:04:48.592210531 -0400 @@ -38,4 +38,772 @@ 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 @@ 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 @@ 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 -Naur ipmitool-1.8.13-1_ORIG/lib/hpm2.c ipmitool-1.8.13-1/lib/hpm2.c --- ipmitool-1.8.13-1_ORIG/lib/hpm2.c 1969-12-31 19:00:00.000000000 -0500 +++ ipmitool-1.8.13-1/lib/hpm2.c 2015-09-17 05:13:53.417979600 -0400 @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2012 Pigeon Point Systems. 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 Pigeon Point Systems nor 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. + * PIGEON POINT SYSTEMS ("PPS") AND ITS LICENSORS SHALL NOT BE LIABLE + * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING + * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL + * PPS OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, + * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR + * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF + * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF PPS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include + +#if HAVE_PRAGMA_PACK +#pragma pack(push, 1) +#endif + +/* HPM.x Get Capabilities request */ +struct hpmx_cmd_get_capabilities_rq { + uint8_t picmg_id; + uint8_t hpmx_id; +} ATTRIBUTE_PACKING; + +/* HPM.2 Get Capabilities response */ +struct hpm2_cmd_get_capabilities_rp { + uint8_t picmg_id; + struct hpm2_lan_attach_capabilities caps; +} ATTRIBUTE_PACKING; + +#if HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif + +/* IPMI Get LAN Configuration Parameters command */ +#define IPMI_LAN_GET_CONFIG 0x02 + +int hpm2_get_capabilities(struct ipmi_intf * intf, + struct hpm2_lan_attach_capabilities * caps) +{ + struct ipmi_rq req; + struct ipmi_rs * rsp; + struct hpmx_cmd_get_capabilities_rq rq; + + /* reset result */ + memset(caps, 0, sizeof (struct hpm2_lan_attach_capabilities)); + + /* prepare request */ + rq.picmg_id = 0; + rq.hpmx_id = 2; + + /* prepare request */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_PICMG; + req.msg.cmd = HPM2_GET_LAN_ATTACH_CAPABILITIES; + req.msg.data = (uint8_t *) &rq; + req.msg.data_len = sizeof(rq); + + + /* send */ + rsp = intf->sendrecv(intf, &req); + + if (!rsp) { + lprintf(LOG_NOTICE,"Error sending request\n"); + return -1; + } + + if (rsp->ccode == 0xC1) { + lprintf(LOG_DEBUG,"IPM Controller is not HPM.2 compatible"); + return rsp->ccode; + } else if (rsp->ccode) { + lprintf(LOG_NOTICE,"Get HPM.x Capabilities request failed," + " compcode = %x\n", rsp->ccode); + return rsp->ccode; + } + + /* check response length */ + if (rsp->data_len < 2 || rsp->data_len > 10) { + lprintf(LOG_NOTICE,"Bad response length, len=%d\n", rsp->data_len); + return -1; + } + + /* check HPM.x identifier */ + if (rsp->data[1] != 2) { + lprintf(LOG_NOTICE,"Bad HPM.x ID, id=%d\n", rsp->data[1]); + return rsp->ccode; + } + + /* + * this hardly can happen, since completion code is already checked. + * but check for safety + */ + if (rsp->data_len < 4) { + lprintf(LOG_NOTICE,"Bad response length, len=%d\n", rsp->data_len); + return -1; + } + + /* copy HPM.2 capabilities */ + memcpy(caps, rsp->data + 2, rsp->data_len - 2); + +#if WORDS_BIGENDIAN + /* swap bytes to convert from little-endian format */ + caps->lan_channel_mask = BSWAP_16(caps->lan_channel_mask); +#endif + + /* check HPM.2 revision */ + if (caps->hpm2_revision_id != HPM2_REVISION) { + lprintf(LOG_NOTICE,"Bad HPM.2 revision, rev=%d\n", + caps->hpm2_revision_id); + return -1; + } + + if (!caps->lan_channel_mask) { + return -1; + } + + /* check response length */ + if (rsp->data_len < 8) { + lprintf(LOG_NOTICE,"Bad response length, len=%d\n", rsp->data_len); + return -1; + } + + /* check HPM.2 LAN parameters start */ + if (caps->hpm2_lan_params_start < 0xC0) { + lprintf(LOG_NOTICE,"Bad HPM.2 LAN params start, start=%x\n", + caps->hpm2_lan_params_start); + return -1; + } + + /* check HPM.2 LAN parameters revision */ + if (caps->hpm2_lan_params_rev != HPM2_LAN_PARAMS_REV) { + lprintf(LOG_NOTICE,"Bad HPM.2 LAN params revision, rev=%d\n", + caps->hpm2_lan_params_rev); + return -1; + } + + /* check for HPM.2 SOL extension */ + if (!(caps->hpm2_caps & HPM2_CAPS_SOL_EXTENSION)) { + /* no further checks */ + return 0; + } + + /* check response length */ + if (rsp->data_len < 10) { + lprintf(LOG_NOTICE,"Bad response length, len=%d\n", rsp->data_len); + return -1; + } + + /* check HPM.2 SOL parameters start */ + if (caps->hpm2_sol_params_start < 0xC0) { + lprintf(LOG_NOTICE,"Bad HPM.2 SOL params start, start=%x\n", + caps->hpm2_sol_params_start); + return -1; + } + + /* check HPM.2 SOL parameters revision */ + if (caps->hpm2_sol_params_rev != HPM2_SOL_PARAMS_REV) { + lprintf(LOG_NOTICE,"Bad HPM.2 SOL params revision, rev=%d\n", + caps->hpm2_sol_params_rev); + return -1; + } + + return 0; +} + +int hpm2_get_lan_channel_capabilities(struct ipmi_intf * intf, + uint8_t hpm2_lan_params_start, + struct hpm2_lan_channel_capabilities * caps) +{ + struct ipmi_rq req; + struct ipmi_rs * rsp; + uint8_t rq[4]; + + /* reset result */ + memset(caps, 0, sizeof (struct hpm2_lan_channel_capabilities)); + + /* prepare request */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_TRANSPORT; + req.msg.cmd = IPMI_LAN_GET_CONFIG; + req.msg.data = (uint8_t *) &rq; + req.msg.data_len = sizeof(rq); + + /* prepare request data */ + rq[0] = 0xE; /* sending channel */ + rq[1] = hpm2_lan_params_start; /* HPM.2 Channel Caps */ + rq[2] = rq[3] = 0; + + /* send */ + rsp = intf->sendrecv(intf, &req); + + if (rsp) { + lprintf(LOG_NOTICE,"Error sending request\n"); + return -1; + } + + if (rsp->ccode == 0x80) { + lprintf(LOG_DEBUG,"HPM.2 Channel Caps parameter is not supported\n"); + return rsp->ccode; + } else if (rsp->ccode) { + lprintf(LOG_NOTICE,"Get LAN Configuration Parameters request failed," + " compcode = %x\n", rsp->ccode); + return rsp->ccode; + } + + /* check response length */ + if (rsp->data_len != sizeof (struct hpm2_lan_channel_capabilities) + 1) { + lprintf(LOG_NOTICE,"Bad response length, len=%d\n", rsp->data_len); + return -1; + } + + /* check parameter revision */ + if (rsp->data[0] != HPM2_LAN_PARAMS_REV) { + lprintf(LOG_NOTICE,"Bad HPM.2 LAN parameter revision, rev=%d\n", + rsp->data[0]); + return -1; + } + + /* copy parameter data */ + memcpy(caps, &rsp->data[1], sizeof (struct hpm2_lan_channel_capabilities)); + +#if WORDS_BIGENDIAN + /* swap bytes to convert from little-endian format */ + caps->max_inbound_pld_size = BSWAP_16(caps->max_inbound_pld_size); + caps->max_outbound_pld_size = BSWAP_16(caps->max_outbound_pld_size); +#endif + + return 0; +} + +int hpm2_detect_max_payload_size(struct ipmi_intf * intf) +{ + struct hpm2_lan_attach_capabilities attach_caps; + struct hpm2_lan_channel_capabilities channel_caps; + int err; + + /* query HPM.2 support */ + err = hpm2_get_capabilities(intf, &attach_caps); + + /* check if HPM.2 is supported */ + if (err != 0 || !attach_caps.lan_channel_mask) { + return err; + } + + /* query channel capabilities */ + err = hpm2_get_lan_channel_capabilities(intf, + attach_caps.hpm2_lan_params_start, &channel_caps); + + /* check if succeeded */ + if (err != 0) { + return err; + } + + /* update request and response sizes */ + ipmi_intf_set_max_request_data_size(intf, + channel_caps.max_inbound_pld_size - 7); + ipmi_intf_set_max_response_data_size(intf, + channel_caps.max_outbound_pld_size - 8); + + /* print debug info */ + lprintf(LOG_DEBUG,"Set maximum request size to %d\n" + "Set maximum response size to %d\n", + intf->max_request_data_size, intf->max_response_data_size); + + return 0; +} diff -Naur ipmitool-1.8.13-1_ORIG/lib/ipmi_dcmi.c ipmitool-1.8.13-1/lib/ipmi_dcmi.c --- ipmitool-1.8.13-1_ORIG/lib/ipmi_dcmi.c 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/lib/ipmi_dcmi.c 2015-09-18 04:06:38.184438634 -0400 @@ -481,44 +481,14 @@ 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 -Naur ipmitool-1.8.13-1_ORIG/lib/ipmi_fru.c ipmitool-1.8.13-1/lib/ipmi_fru.c --- ipmitool-1.8.13-1_ORIG/lib/ipmi_fru.c 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/lib/ipmi_fru.c 2015-09-18 04:07:00.553850332 -0400 @@ -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_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 @@ 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 @@ * 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,335 @@ 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; + p_first = malloc(sizeof(struct ipmi_fru_bloc)); + if (!p_first) { + lprintf(LOG_ERR, "ipmitool: malloc failure"); + return NULL; + } - fru_data = malloc(fru->size + 1); - if (fru_data == NULL) { - lprintf(LOG_ERR, " Out of memory!"); - return NULL; + 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"); + + 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; + } + + p_new->next = NULL; + p_new->start = header.offsets[i] * 8; + p_new->size = fru->size - p_new->start; + + 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; + + p_bloc->next = p_new; + p_bloc->size = p_new->start - p_bloc->start; + p_bloc = p_new; } + } - memset(fru_data, 0, fru->size + 1); + // Multi + if (header.offset.multi) { + off = header.offset.multi * 8; 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; - - if (read_fru_area(intf, fru, id, last_off, len, fru_data) < 0) - break; + /* + * 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; + } - last_off += len; + if (read_fru_area(intf, fru, id, off, 5, + (uint8_t *) &rec_hdr) < 0) { + break; } - 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 = malloc(sizeof(struct ipmi_fru_bloc)); + if (!p_new) { + lprintf(LOG_ERR, "ipmitool: malloc failure"); + free_fru_bloc(p_first); + return NULL; + } + + 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); + + p_bloc->next = p_new; + p_bloc->size = p_new->start - p_bloc->start; + p_bloc = p_new; + + off += rec_hdr.len + sizeof(struct fru_multirec_header); + + /* 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)); - lprintf(LOG_DEBUG ,"Multi-Record area ends at: %i (%xh)",i,i); + lprintf(LOG_DEBUG,"Multi-Record area ends at: %i (%xh)", off, off); - if(fru->size > i) - { + if (fru->size > off) { // Bloc for remaining space - num_bloc ++; - } - } - else - { - /* Since there is no multi-rec area and no end delimiter, the remaining - space will be added to the last bloc */ - } - - + p_new = malloc(sizeof(struct ipmi_fru_bloc)); + if (!p_new) { + lprintf(LOG_ERR, "ipmitool: malloc failure"); + free_fru_bloc(p_first); + return NULL; + } - /****************************************** - 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"); + 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_data != NULL) { - free(fru_data); - fru_data = NULL; + p_bloc->next = p_new; + p_bloc->size = p_new->start - p_bloc->start; } - - return NULL; } - // Common header - bloc_count = 0; - - p_bloc[bloc_count].start= 0; - p_bloc[bloc_count].size = 8; - strcpy((char *)p_bloc[bloc_count].blocId, "Common Header Section"); - bloc_count ++; - - // 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 ++; + /* 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 ,""); } - // 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; - do { - h = (struct fru_multirec_header *) (fru_data + i); - - 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");*/ - - i += h->len + sizeof (struct fru_multirec_header); - - } while (!(h->format & 0x80) && ( bloc_count < num_bloc ) ); - - 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 */ - - 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 ++; - } - - } + return p_first; +} - if (fru_data != NULL) { - free(fru_data); - fru_data = NULL; - } +void +free_fru_bloc(t_ipmi_fru_bloc *bloc) +{ + t_ipmi_fru_bloc * del; - /* 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"); - } + while (bloc) { + del = bloc; + bloc = bloc->next; + free(del); + del = NULL; } - - (* ptr_number_bloc) = num_bloc; - - return p_bloc; } - +/* + * 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) { + uint16_t max_rq_size = ipmi_intf_get_max_request_data_size(intf); + + /* validate lower bound of the maximum request data size */ + if (max_rq_size <= 3) { + lprintf(LOG_ERROR, "Maximum request size is too small to send " + "a write request"); + return -1; + } - /* 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 */ + /* + * Write FRU Info command returns the number of written bytes in + * a single byte field. + */ + if (max_rq_size - 3 > 255) { + /* Limit the max write size with 255 bytes. */ + fru->max_write_size = 255; + } else { + /* subtract 1 byte for FRU ID an 2 bytes for offset */ + fru->max_write_size = max_rq_size - 3; + } + + /* 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); - return ((doffset+off) >= finish); + if (saved_fru_bloc) { + free_fru_bloc(saved_fru_bloc); + } + + return doffset >= finish; } -#endif /* read_fru_area - fill in frubuf[offset:length] from the FRU[offset:length] * @@ -749,7 +598,6 @@ 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,20 +623,32 @@ 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) { + uint16_t max_rs_size = ipmi_intf_get_max_response_data_size(intf) - 1; + /* validate lower bound of the maximum response data size */ + if (max_rs_size <= 1) { + lprintf(LOG_ERROR, "Maximum response size is too small to send " + "a read request"); + return -1; + } - /* 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 */ - } + /* + * Read FRU Info command may read up to 255 bytes of data. + */ + if (max_rs_size - 1 > 255) { + /* Limit the max read size with 255 bytes. */ + fru->max_read_size = 255; + } else { + /* subtract 1 byte for bytes count */ + fru->max_write_size = max_rs_size - 1; + } + /* check word access */ + if (fru->access) { + fru->max_read_size &= ~1; + } + } do { tmp = fru->access ? off >> 1 : off; @@ -796,8 +656,8 @@ 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 +667,43 @@ 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 +879,48 @@ 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 +941,7 @@ } /* 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 +952,10 @@ free(fru_area); fru_area = NULL; } - if (i == j) + + if (i == j) { break; + } } if (fru_area != NULL) { @@ -1096,39 +976,45 @@ 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 +1067,7 @@ } /* 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 +1099,44 @@ 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 +1202,7 @@ } /* 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 +1235,42 @@ 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 +1328,7 @@ 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 +1360,7 @@ 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 +1390,7 @@ 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 +1398,7 @@ 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 +1408,11 @@ } 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 +2194,7 @@ 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 +2871,7 @@ return -1; } + memset(&fru, 0, sizeof(fru)); fru.size = (rsp->data[1] << 8) | rsp->data[0]; fru.access = rsp->data[2] & 0x1; @@ -3088,7 +2974,8 @@ 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 +3018,7 @@ 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 +3026,7 @@ } /* 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 +3204,8 @@ 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 +3272,8 @@ 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 +3393,7 @@ return -1; } + memset(&fru, 0, sizeof(fru)); fru.size = (rsp->data[1] << 8) | rsp->data[0]; fru.access = rsp->data[2] & 0x1; @@ -3524,6 +3417,7 @@ 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 +3596,7 @@ return -1; } + memset(&fru, 0, sizeof(fru)); fru.size = (rsp->data[1] << 8) | rsp->data[0]; fru.access = rsp->data[2] & 0x1; @@ -4171,6 +4066,7 @@ return -1; } + memset(&fru, 0, sizeof(fru)); fru->size = (rsp->data[1] << 8) | rsp->data[0]; fru->access = rsp->data[2] & 0x1; @@ -4755,6 +4651,7 @@ 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 -Naur ipmitool-1.8.13-1_ORIG/lib/ipmi_hpmfwupg.c ipmitool-1.8.13-1/lib/ipmi_hpmfwupg.c --- ipmitool-1.8.13-1_ORIG/lib/ipmi_hpmfwupg.c 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/lib/ipmi_hpmfwupg.c 2015-09-18 04:07:08.926348713 -0400 @@ -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,2590 @@ #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]); - } -} - - -/**************************************************************************** -* -* 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"); - } - - 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) -{ - int rc = HPMFWUPG_SUCCESS; - struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) - pFwupgCtx->pImageData; - md5_state_t ctx; + pVersion->deferredMajor, + pVersion->deferredMinor, + pVersion->deferredAux[0], + pVersion->deferredAux[1], + pVersion->deferredAux[2], + pVersion->deferredAux[3]); + } + } +} + +/* 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; + gVersionInfo[componentId].deferredActivationSupported = getCompProp.resp.Response. + generalPropResp.GeneralCompProperties.bitfield.deferredActivation; + 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]; + } + 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; + } + if (gVersionInfo[componentId].deferredActivationSupported) { + 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]; + } + } else { + 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; +} + +/* 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; +} + +/* 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) +{ + 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; -} - -/**************************************************************************** -* -* 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)); - } - } - } - } + 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; +} + +/* 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; +} + +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])) { + 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) { + 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])) { + return (1); + } + /* Image and rollback target versions are the same too, skip it */ + return (0); +} - return rc; +/* HpmfwupgValidateActionRecordChecksum - validate checksum of the specified + * action record header. + */ +int +HpmfwupgValidateActionRecordChecksum(struct HpmfwupgActionRecord *pActionRecord) +{ + int rc = HPMFWUPG_SUCCESS; + /* Validate action record checksum */ + if (HpmfwupgCalculateChecksum((unsigned char*)pActionRecord, + 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; +} + +/* 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); + } + /* 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; + } + /* 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; + } + 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; + } + } + if (option & VIEW_MODE) { + HpmDisplayLine("-",74); + fflush(stdout); + lprintf(LOG_NOTICE, + "(*) Component requires Payload Cold Reset"); + lprintf(LOG_NOTICE, + "(^) Indicates component would be upgraded"); + } + return HPMFWUPG_SUCCESS; } -static 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])) - 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) - 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])) - return (1); - - /* Image and rollback target versions are the same too, skip it */ - return (0); +/* 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"); + return rc; } -/**************************************************************************** -* -* 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) -{ - 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; - - /* Validate action record checksum */ - if (HpmfwupgCalculateChecksum((unsigned char*)pActionRecord, - sizeof(struct HpmfwupgActionRecord)) != 0) { - lprintf(LOG_NOTICE," Invalid Action record."); +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; + uint16_t max_rq_size; + + /* 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; + + /* Find max buffer length according the connection parameters */ + max_rq_size = ipmi_intf_get_max_request_data_size(intf); + + /* validate lower bound of max request size */ + if (max_rq_size <= sizeof(struct HpmfwupgUploadFirmwareBlockReq)) { + lprintf(LOG_ERROR, "Maximum request size is too small to " + "send a upload request."); return HPMFWUPG_ERROR; } - switch( pActionRecord->actionType ) - { - case HPMFWUPG_ACTION_BACKUP_COMPONENTS: - { - pImagePtr += sizeof(struct HpmfwupgActionRecord); - } - break; + bufLength = max_rq_size - sizeof(struct HpmfwupgUploadFirmwareBlockReq); - 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; + /* 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; + } + 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); + } + skip = FALSE; + } + if (!skip) { + HpmDisplayUpgrade(0,0,1,0); + /* Initialize parameters */ + uploadCmd.req = malloc(max_rq_size); + 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, count); + 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++; } } - pImagePtr += sizeof(struct HpmfwupgActionRecord); + /* free buffer */ + free(uploadCmd.req); + uploadCmd.req = NULL; } - 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++; - } - 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"); + 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 = pData + firmwareLength; + *pImagePtr = pDataInitial + firmwareLength; } - break; - default: - lprintf(LOG_NOTICE, - " Invalid Action type. Cannot continue"); - return HPMFWUPG_ERROR; - break; + 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; +} - if (option & VIEW_MODE) { - HpmDisplayLine("-",74); +/* 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); - lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset"); - lprintf(LOG_NOTICE,"(^) Indicates component would be upgraded"); - } - return HPMFWUPG_SUCCESS; -} - - -/**************************************************************************** -* -* 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; -} - -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; - } - - 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); + /* 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."); + } } - skip = FALSE; } + /* 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; +} - 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; -} - -/**************************************************************************** -* -* 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; -} - -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 +HpmfwupgGetBufferFromFile(char *imageFilename, + struct HpmfwupgUpgradeCtx *pFwupgCtx) +{ + 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; -} - -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; + } + fclose(pImageFile); + return rc; } -int HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf, - struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx) +int +HpmfwupgGetDeviceId(struct ipmi_intf *intf, struct ipm_devid_rsp *pGetDevId) { - 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; - req.msg.data_len = sizeof(struct HpmfwupgGetTargetUpgCapabilitiesReq); + 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; +} - rsp = HpmfwupgSendCmd(intf, req, NULL); +int +HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf, + struct HpmfwupgGetTargetUpgCapabilitiesCtx *pCtx) +{ + 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 == 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; +} - 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; -} - - -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 +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; req.msg.data_len = sizeof(struct HpmfwupgGetComponentPropertiesReq); + 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; +} - 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; -} - -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 +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; req.msg.data_len = sizeof(struct HpmfwupgAbortUpgradeReq); + 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; +} - 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; -} - -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 +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; req.msg.data_len = sizeof(struct HpmfwupgInitiateUpgradeActionReq); + 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; +} - rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); +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 == 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; +} - 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; -} - -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 HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf, struct HpmfwupgFinishFirmwareUploadCtx* 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_FINISH_FIRMWARE_UPLOAD; - req.msg.data = (unsigned char*)&pCtx->req; +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; req.msg.data_len = sizeof(struct HpmfwupgFinishFirmwareUploadReq); + 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; +} - 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; -} - -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 HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf, - struct HpmfwupgGetUpgradeStatusCtx *pCtx, - struct HpmfwupgUpgradeCtx *pFwupgCtx, - int silent) +int +HpmfwupgActivateFirmware(struct ipmi_intf *intf, + struct HpmfwupgActivateFirmwareCtx *pCtx, + struct HpmfwupgUpgradeCtx *pFwupgCtx) { - 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_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 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, &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; +} - 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; -} - -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 +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; req.msg.data_len = sizeof(struct HpmfwupgQueryRollbackStatusReq); + /* 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; +} - /* - * 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; -} - -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 +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 = 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 == 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 + /* 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; +} - /* 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; -} - -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; - } - } - }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; -} - -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; -} - -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"); -} - -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(); - } +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; +} - return rc; +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 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 -Naur ipmitool-1.8.13-1_ORIG/lib/ipmi_kontronoem.c ipmitool-1.8.13-1/lib/ipmi_kontronoem.c --- ipmitool-1.8.13-1_ORIG/lib/ipmi_kontronoem.c 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/lib/ipmi_kontronoem.c 2015-09-18 04:07:19.045533592 -0400 @@ -350,6 +350,7 @@ 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 @@ return(-1); } + memset(&fru, 0, sizeof(fru)); fru.size = (rsp->data[1] << 8) | rsp->data[0]; fru.access = rsp->data[2] & 0x1; diff -Naur ipmitool-1.8.13-1_ORIG/lib/ipmi_main.c ipmitool-1.8.13-1/lib/ipmi_main.c --- ipmitool-1.8.13-1_ORIG/lib/ipmi_main.c 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/lib/ipmi_main.c 2015-09-18 04:07:30.710376681 -0400 @@ -361,7 +361,8 @@ uint8_t transit_addr = 0; uint8_t transit_channel = 0; uint8_t target_lun = 0; - uint8_t arg_addr = 0, addr; + uint8_t arg_addr = 0; + uint8_t addr = 0; uint16_t my_long_packet_size=0; uint8_t my_long_packet_set=0; uint8_t lookupbit = 0x10; /* use name-only lookup by default */ @@ -894,9 +895,11 @@ /* 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. @@ -923,24 +926,26 @@ } /* If bridging addresses are specified, handle them */ - if (transit_addr > 0 || target_addr > 0) { + if (target_addr > 0) { + ipmi_main_intf->target_addr = target_addr; + ipmi_main_intf->target_lun = target_lun ; + ipmi_main_intf->target_channel = target_channel ; + } + if (transit_addr > 0) { /* sanity check, transit makes no sense without a target */ if ((transit_addr != 0 || transit_channel != 0) && - target_addr == 0) { + ipmi_main_intf->target_addr == 0) { lprintf(LOG_ERR, "Transit address/channel %#x/%#x ignored. " "Target address must be specified!", transit_addr, transit_channel); goto out_free; } - ipmi_main_intf->target_addr = target_addr; - ipmi_main_intf->target_lun = target_lun ; - ipmi_main_intf->target_channel = target_channel ; ipmi_main_intf->transit_addr = transit_addr; ipmi_main_intf->transit_channel = transit_channel; - - + } + if (ipmi_main_intf->target_addr > 0) { /* must be admin level to do this over lan */ ipmi_intf_session_set_privlvl(ipmi_main_intf, IPMI_SESSION_PRIV_ADMIN); /* Get the ipmb address of the targeted entity */ @@ -977,13 +982,15 @@ } /* Enable Big Buffer when requested */ - ipmi_main_intf->channel_buf_size = 0; if ( my_long_packet_size != 0 ) { - printf("Setting large buffer to %i\n", my_long_packet_size); - if (ipmi_kontronoem_set_large_buffer( ipmi_main_intf, my_long_packet_size ) == 0) - { + /* Enable Big Buffer when requested */ + if (!ipmi_oem_active(ipmi_main_intf, "kontron") || + ipmi_kontronoem_set_large_buffer(ipmi_main_intf, + my_long_packet_size ) == 0) { + printf("Setting large buffer to %i\n", my_long_packet_size); my_long_packet_set = 1; - ipmi_main_intf->channel_buf_size = my_long_packet_size; + ipmi_intf_set_max_request_data_size(ipmi_main_intf, + my_long_packet_size); } } @@ -997,8 +1004,10 @@ rc = ipmi_cmd_run(ipmi_main_intf, NULL, 0, NULL); if (my_long_packet_set == 1) { - /* Restore defaults */ - ipmi_kontronoem_set_large_buffer( ipmi_main_intf, 0 ); + if (ipmi_oem_active(ipmi_main_intf, "kontron")) { + /* Restore defaults */ + ipmi_kontronoem_set_large_buffer( ipmi_main_intf, 0 ); + } } /* clean repository caches */ diff -Naur ipmitool-1.8.13-1_ORIG/lib/ipmi_oem.c ipmitool-1.8.13-1/lib/ipmi_oem.c --- ipmitool-1.8.13-1_ORIG/lib/ipmi_oem.c 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/lib/ipmi_oem.c 2015-09-18 04:07:38.471578903 -0400 @@ -67,6 +67,10 @@ name: "i82571spt", desc: "Intel 82571 MAC with integrated RMCP+ support in super pass-through mode", }, + { + name: "kontron", + desc: "Kontron OEM big buffer support" + }, { 0 } }; diff -Naur ipmitool-1.8.13-1_ORIG/lib/ipmi_sdr.c ipmitool-1.8.13-1/lib/ipmi_sdr.c --- ipmitool-1.8.13-1_ORIG/lib/ipmi_sdr.c 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/lib/ipmi_sdr.c 2015-09-18 04:07:46.136508153 -0400 @@ -59,7 +59,7 @@ extern int verbose; static int use_built_in; /* Uses DeviceSDRs instead of SDRR */ -static int sdr_max_read_len = GET_SDR_ENTIRE_RECORD; +static int sdr_max_read_len = 0; static int sdr_extended = 0; static long sdriana = 0; @@ -456,10 +456,12 @@ { 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ { 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 @@ 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 @@ { 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 @@ 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 @@ ("Power Redundancy | PS@%02xh | nr\n", oem->data[8]); } + break; case 9: /* SR2300, non-redundant, PSx present */ if (verbose) { printf("Power Redundancy : Yes\n"); @@ -3008,6 +3024,17 @@ req.msg.data = (uint8_t *) & sdr_rq; req.msg.data_len = sizeof (sdr_rq); + /* check if max length is null */ + if ( sdr_max_read_len == 0 ) { + /* get maximum response size */ + sdr_max_read_len = ipmi_intf_get_max_response_data_size(intf) - 2; + + /* cap the number of bytes to read */ + if (sdr_max_read_len > 0xFE) { + sdr_max_read_len = 0xFE; + } + } + /* read SDR record with partial reads * because a full read usually exceeds the maximum * transport buffer size. (completion code 0xca) diff -Naur ipmitool-1.8.13-1_ORIG/lib/ipmi_tsol.c ipmitool-1.8.13-1/lib/ipmi_tsol.c --- ipmitool-1.8.13-1_ORIG/lib/ipmi_tsol.c 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/lib/ipmi_tsol.c 2015-09-18 04:07:53.019149465 -0400 @@ -381,7 +381,7 @@ 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 @@ } 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 @@ (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 @@ } if (-1 == bind(fd_socket, (struct sockaddr *)&sin, sizeof(sin))) { lprintf(LOG_ERR, "Failed to bind socket."); + close(fd_socket); return -1; } diff -Naur ipmitool-1.8.13-1_ORIG/lib/Makefile.am ipmitool-1.8.13-1/lib/Makefile.am --- ipmitool-1.8.13-1_ORIG/lib/Makefile.am 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/lib/Makefile.am 2015-09-18 04:07:59.065245786 -0400 @@ -39,7 +39,7 @@ ipmi_oem.c ipmi_isol.c ipmi_sunoem.c ipmi_fwum.c ipmi_picmg.c \ ipmi_main.c ipmi_tsol.c ipmi_firewall.c ipmi_kontronoem.c \ ipmi_hpmfwupg.c ipmi_sdradd.c ipmi_ekanalyzer.c ipmi_gendev.c \ - ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c \ + ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c hpm2.c \ ../src/plugins/lan/md5.c ../src/plugins/lan/md5.h libipmitool_la_LDFLAGS = -export-dynamic diff -Naur ipmitool-1.8.13-1_ORIG/lib/Makefile.in ipmitool-1.8.13-1/lib/Makefile.in --- ipmitool-1.8.13-1_ORIG/lib/Makefile.in 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/lib/Makefile.in 2015-09-18 04:08:27.472519633 -0400 @@ -84,7 +84,8 @@ ipmi_sunoem.lo ipmi_fwum.lo ipmi_picmg.lo ipmi_main.lo \ ipmi_tsol.lo ipmi_firewall.lo ipmi_kontronoem.lo \ ipmi_hpmfwupg.lo ipmi_sdradd.lo ipmi_ekanalyzer.lo \ - ipmi_gendev.lo ipmi_ime.lo ipmi_delloem.lo ipmi_dcmi.lo md5.lo + ipmi_gendev.lo ipmi_ime.lo ipmi_delloem.lo ipmi_dcmi.lo \ + hpm2.lo md5.lo libipmitool_la_OBJECTS = $(am_libipmitool_la_OBJECTS) libipmitool_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -156,6 +157,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ @@ -260,7 +263,7 @@ ipmi_oem.c ipmi_isol.c ipmi_sunoem.c ipmi_fwum.c ipmi_picmg.c \ ipmi_main.c ipmi_tsol.c ipmi_firewall.c ipmi_kontronoem.c \ ipmi_hpmfwupg.c ipmi_sdradd.c ipmi_ekanalyzer.c ipmi_gendev.c \ - ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c \ + ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c hpm2.c \ ../src/plugins/lan/md5.c ../src/plugins/lan/md5.h libipmitool_la_LDFLAGS = -export-dynamic @@ -320,6 +323,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dimm_spd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hpm2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_chassis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_dcmi.Plo@am__quote@ diff -Naur ipmitool-1.8.13-1_ORIG/Makefile.in ipmitool-1.8.13-1/Makefile.in --- ipmitool-1.8.13-1_ORIG/Makefile.in 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/Makefile.in 2015-09-18 04:01:21.905361855 -0400 @@ -185,6 +185,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/src/Makefile.in ipmitool-1.8.13-1/src/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/Makefile.in 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/src/Makefile.in 2015-09-18 04:08:40.026115618 -0400 @@ -192,6 +192,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/bmc/Makefile.in ipmitool-1.8.13-1/src/plugins/bmc/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/plugins/bmc/Makefile.in 2015-09-18 03:59:15.224042771 -0400 +++ ipmitool-1.8.13-1/src/plugins/bmc/Makefile.in 2015-09-18 04:08:52.777843102 -0400 @@ -146,6 +146,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/free/Makefile.in ipmitool-1.8.13-1/src/plugins/free/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/plugins/free/Makefile.in 2015-09-18 03:59:15.228042780 -0400 +++ ipmitool-1.8.13-1/src/plugins/free/Makefile.in 2015-09-18 04:09:00.287761151 -0400 @@ -119,6 +119,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/imb/Makefile.in ipmitool-1.8.13-1/src/plugins/imb/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/plugins/imb/Makefile.in 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/src/plugins/imb/Makefile.in 2015-09-18 04:09:08.658584257 -0400 @@ -146,6 +146,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/ipmi_intf.c ipmitool-1.8.13-1/src/plugins/ipmi_intf.c --- ipmitool-1.8.13-1_ORIG/src/plugins/ipmi_intf.c 2015-09-18 03:59:15.228042780 -0400 +++ ipmitool-1.8.13-1/src/plugins/ipmi_intf.c 2015-09-18 04:10:37.229611633 -0400 @@ -36,11 +36,25 @@ #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 #include +#define IPMI_DEFAULT_PAYLOAD_SIZE 25 + #ifdef IPMI_INTF_OPEN extern struct ipmi_intf ipmi_open_intf; #endif @@ -66,6 +80,9 @@ extern struct ipmi_intf ipmi_serial_term_intf; extern struct ipmi_intf ipmi_serial_bm_intf; #endif +#ifdef IPMI_INTF_USB +extern struct ipmi_intf ipmi_usb_intf; +#endif struct ipmi_intf * ipmi_intf_table[] = { #ifdef IPMI_INTF_OPEN @@ -93,6 +110,9 @@ &ipmi_serial_term_intf, &ipmi_serial_bm_intf, #endif +#ifdef IPMI_INTF_USB + &ipmi_usb_intf, +#endif NULL }; @@ -315,3 +335,317 @@ { 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 + +uint16_t +ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf) +{ + int16_t size; + + size = intf->max_request_data_size; + + /* check if request size is not specified */ + if (!size) { + /* + * The IPMB standard overall message length for ‘non -bridging’ + * messages is specified as 32 bytes, maximum, including slave + * address. This sets the upper limit for typical IPMI messages. + * With the exception of messages used for bridging messages to + * other busses or interfaces (e.g. Master Write-Read and Send Message) + * IPMI messages should be designed to fit within this 32-byte maximum. + * In order to support bridging, the Master Write -Read and Send Message + * commands are allowed to exceed the 32-byte maximum transaction on IPMB + */ + + size = IPMI_DEFAULT_PAYLOAD_SIZE; + + /* check if message is forwarded */ + if (intf->target_addr && intf->target_addr != intf->my_addr) { + /* add Send Message request size */ + size += 8; + } + } + + /* check if message is forwarded */ + if (intf->target_addr && intf->target_addr != intf->my_addr) { + /* subtract send message request size */ + size -= 8; + + /* + * Check that forwarded request size is not greater + * than the default payload size. + */ + if (size > IPMI_DEFAULT_PAYLOAD_SIZE) { + size = IPMI_DEFAULT_PAYLOAD_SIZE; + } + + /* check for double bridging */ + if (intf->transit_addr && intf->transit_addr != intf->target_addr) { + /* subtract inner send message request size */ + size -= 8; + } + } + + /* check for underflow */ + if (size < 0) { + return 0; + } + + return size; +} + +uint16_t +ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf) +{ + int16_t size; + + size = intf->max_response_data_size; + + /* check if response size is not specified */ + if (!size) { + /* + * The IPMB standard overall message length for ‘non -bridging’ + * messages is specified as 32 bytes, maximum, including slave + * address. This sets the upper limit for typical IPMI messages. + * With the exception of messages used for bridging messages to + * other busses or interfaces (e.g. Master Write-Read and Send Message) + * IPMI messages should be designed to fit within this 32-byte maximum. + * In order to support bridging, the Master Write -Read and Send Message + * commands are allowed to exceed the 32-byte maximum transaction on IPMB + */ + + size = IPMI_DEFAULT_PAYLOAD_SIZE; /* response length with subtracted header and checksum byte */ + + /* check if message is forwarded */ + if (intf->target_addr && intf->target_addr != intf->my_addr) { + /* add Send Message header size */ + size += 7; + } + } + + /* check if message is forwarded */ + if (intf->target_addr && intf->target_addr != intf->my_addr) { + /* + * Some IPMI controllers like PICMG AMC Carriers embed responses + * to the forwarded messages into the Send Message response. + * In order to be sure that the response is not truncated, + * subtract the internal message header size. + */ + size -= 8; + + /* + * Check that forwarded response is not greater + * than the default payload size. + */ + if (size > IPMI_DEFAULT_PAYLOAD_SIZE) { + size = IPMI_DEFAULT_PAYLOAD_SIZE; + } + + /* check for double bridging */ + if (intf->transit_addr && intf->transit_addr != intf->target_addr) { + /* subtract inner send message header size */ + size -= 8; + } + } + + /* check for underflow */ + if (size < 0) { + return 0; + } + + return size; +} + +void +ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size) +{ + if (size < IPMI_DEFAULT_PAYLOAD_SIZE) { + lprintf(LOG_ERR, "Request size is too small (%d), leave default size", + size); + return; + } + + if (intf->set_max_request_data_size) { + intf->set_max_request_data_size(intf, size); + } else { + intf->max_request_data_size = size; + } +} + +void +ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size) +{ + if (size < IPMI_DEFAULT_PAYLOAD_SIZE - 1) { + lprintf(LOG_ERR, "Response size is too small (%d), leave default size", + size); + return; + } + + if (intf->set_max_response_data_size) { + intf->set_max_response_data_size(intf, size); + } else { + intf->max_response_data_size = size; + } +} diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/lan/lan.c ipmitool-1.8.13-1/src/plugins/lan/lan.c --- ipmitool-1.8.13-1_ORIG/src/plugins/lan/lan.c 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/src/plugins/lan/lan.c 2015-09-18 04:09:26.645114647 -0400 @@ -52,6 +52,7 @@ #include #include #include +#include #if HAVE_CONFIG_H # include @@ -67,6 +68,13 @@ #define IPMI_LAN_PORT 0x26f #define IPMI_LAN_CHANNEL_E 0x0e +/* + * LAN interface is required to support 45 byte request transactions and + * 42 byte response transactions. + */ +#define IPMI_LAN_MAX_REQUEST_SIZE 38 /* 45 - 7 */ +#define IPMI_LAN_MAX_RESPONSE_SIZE 34 /* 42 - 8 */ + extern const struct valstr ipmi_privlvl_vals[]; extern const struct valstr ipmi_authtype_session_vals[]; extern int verbose; @@ -88,6 +96,8 @@ static int ipmi_lan_open(struct ipmi_intf * intf); static void ipmi_lan_close(struct ipmi_intf * intf); static int ipmi_lan_ping(struct ipmi_intf * intf); +static void ipmi_lan_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size); +static void ipmi_lan_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size); struct ipmi_intf ipmi_lan_intf = { name: "lan", @@ -100,6 +110,8 @@ recv_sol: ipmi_lan_recv_sol, send_sol: ipmi_lan_send_sol, keepalive: ipmi_lan_keepalive, + set_max_request_data_size: ipmi_lan_set_max_rq_data_size, + set_max_response_data_size: ipmi_lan_set_max_rp_data_size, target_addr: IPMI_BMC_SLAVE_ADDR, }; @@ -2032,44 +2044,14 @@ 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; } @@ -2085,6 +2067,10 @@ } intf->manufacturer_id = ipmi_get_oem(intf); + + /* automatically detect interface request and response sizes */ + hpm2_detect_max_payload_size(intf); + return intf->fd; } @@ -2097,5 +2083,30 @@ return -1; } memset(intf->session, 0, sizeof(struct ipmi_session)); + + /* setup default LAN maximum request and response sizes */ + intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE; + intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE; + return 0; } + +static void +ipmi_lan_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size) +{ + if (size + 7 > 0xFF) { + size = 0xFF - 7; + } + + intf->max_request_data_size = size; +} + +static void +ipmi_lan_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size) +{ + if (size + 8 > 0xFF) { + size = 0xFF - 8; + } + + intf->max_response_data_size = size; +} diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/lan/Makefile.in ipmitool-1.8.13-1/src/plugins/lan/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/plugins/lan/Makefile.in 2015-09-18 03:59:15.260042758 -0400 +++ ipmitool-1.8.13-1/src/plugins/lan/Makefile.in 2015-09-18 04:09:17.178806850 -0400 @@ -146,6 +146,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/lanplus/lanplus.c ipmitool-1.8.13-1/src/plugins/lanplus/lanplus.c --- ipmitool-1.8.13-1_ORIG/src/plugins/lanplus/lanplus.c 2015-09-18 03:59:15.228042780 -0400 +++ ipmitool-1.8.13-1/src/plugins/lanplus/lanplus.c 2015-09-18 04:09:35.908412550 -0400 @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -65,6 +66,13 @@ #include "rmcp.h" #include "asf.h" +/* + * LAN interface is required to support 45 byte request transactions and + * 42 byte response transactions. + */ +#define IPMI_LAN_MAX_REQUEST_SIZE 38 /* 45 - 7 */ +#define IPMI_LAN_MAX_RESPONSE_SIZE 34 /* 42 - 8 */ + extern const struct valstr ipmi_rakp_return_codes[]; extern const struct valstr ipmi_priv_levels[]; extern const struct valstr ipmi_auth_algorithms[]; @@ -112,8 +120,10 @@ static void ack_sol_packet( struct ipmi_intf * intf, struct ipmi_rs * rsp); +static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size); +static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size); -static uint8_t bridgePossible = 0; +static uint8_t bridgePossible = 0; struct ipmi_intf ipmi_lanplus_intf = { name: "lanplus", @@ -125,6 +135,8 @@ recv_sol: ipmi_lanplus_recv_sol, send_sol: ipmi_lanplus_send_sol, keepalive: ipmi_lanplus_keepalive, + set_max_request_data_size: ipmi_lanp_set_max_rq_data_size, + set_max_response_data_size: ipmi_lanp_set_max_rp_data_size, target_addr: IPMI_BMC_SLAVE_ADDR, }; @@ -2099,6 +2111,7 @@ uint8_t * msg_data; int msg_length; struct ipmi_session * session = intf->session; + struct ipmi_rq_entry * entry = NULL; int try = 0; int xmit = 1; time_t ltime; @@ -2123,7 +2136,6 @@ /* * Build an IPMI v1.5 or v2 command */ - struct ipmi_rq_entry * entry; struct ipmi_rq * ipmi_request = payload->payload.ipmi_request.request; lprintf(LOG_DEBUG, ""); @@ -2174,7 +2186,8 @@ 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 */ @@ -2249,11 +2262,17 @@ { case IPMI_PAYLOAD_TYPE_RMCP_OPEN_REQUEST: session->v2_data.session_state = LANPLUS_STATE_OPEN_SESSION_SENT; + /* not retryable for timeouts, force no retry */ + try = session->retry; break; case IPMI_PAYLOAD_TYPE_RAKP_1: session->v2_data.session_state = LANPLUS_STATE_RAKP_1_SENT; + /* not retryable for timeouts, force no retry */ + try = session->retry; break; case IPMI_PAYLOAD_TYPE_RAKP_3: + /* not retryable for timeouts, force no retry */ + try = session->retry; session->v2_data.session_state = LANPLUS_STATE_RAKP_3_SENT; break; } @@ -2304,6 +2323,10 @@ if (rsp) break; + /* This payload type is retryable for timeouts. */ + if ((payload->payload_type == IPMI_PAYLOAD_TYPE_IPMI) && entry) { + ipmi_req_remove_entry( entry->rq_seq, entry->req.msg.cmd); + } } /* only timeout if time exceeds the timeout value */ @@ -2770,6 +2793,7 @@ struct ipmi_session * session = intf->session; uint8_t * msg; struct ipmi_rs * rsp; + /* 0 = success, 1 = error, 2 = timeout */ int rc = 0; @@ -2779,7 +2803,7 @@ msg = (uint8_t*)malloc(IPMI_OPEN_SESSION_REQUEST_SIZE); if (msg == NULL) { lprintf(LOG_ERR, "ipmitool: malloc failure"); - return -1; + return 1; } memset(msg, 0, IPMI_OPEN_SESSION_REQUEST_SIZE); @@ -2809,7 +2833,7 @@ session->cipher_suite_id); free(msg); msg = NULL; - return -1; + return 1; } @@ -2858,18 +2882,24 @@ free(msg); msg = NULL; - + if (!rsp) { + lprintf(LOG_WARNING, "Error sending open session message."); + return -1; + } if (verbose) lanplus_dump_open_session_response(rsp); - + if (rsp == NULL ) { + lprintf(LOG_DEBUG, "Timeout in open session response message."); + return 2; + } if (rsp->payload.open_session_response.rakp_return_code != IPMI_RAKP_STATUS_NO_ERRORS) { lprintf(LOG_WARNING, "Error in open session response message : %s\n", val2str(rsp->payload.open_session_response.rakp_return_code, ipmi_rakp_return_codes)); - return -1; + return 1; } else { @@ -2903,7 +2933,7 @@ "not what we requested 0x%02x\n", rsp->payload.open_session_response.auth_alg, session->v2_data.requested_auth_alg); - rc = -1; + rc = 1; } else if (rsp->payload.open_session_response.integrity_alg != session->v2_data.requested_integrity_alg) @@ -2912,7 +2942,7 @@ "not what we requested 0x%02x\n", rsp->payload.open_session_response.integrity_alg, session->v2_data.requested_integrity_alg); - rc = -1; + rc = 1; } else if (rsp->payload.open_session_response.crypt_alg != session->v2_data.requested_crypt_alg) @@ -2921,7 +2951,7 @@ "not what we requested 0x%02x\n", rsp->payload.open_session_response.crypt_alg, session->v2_data.requested_crypt_alg); - rc = -1; + rc = 1; } } @@ -2955,7 +2985,7 @@ struct ipmi_session * session = intf->session; uint8_t * msg; struct ipmi_rs * rsp; - int rc = 0; + int rc = 0; /* 0 = success, 1 = error, 2 = timeout */ /* * Build a RAKP 1 message @@ -3035,8 +3065,8 @@ if (rsp == NULL) { - lprintf(LOG_INFO, "> Error: no response from RAKP 1 message"); - return 1; + lprintf(LOG_WARNING, "> Error: no response from RAKP 1 message"); + return 2; } session->v2_data.session_state = LANPLUS_STATE_RAKP_2_RECEIVED; @@ -3208,8 +3238,8 @@ } else if (rsp == NULL) { - lprintf(LOG_INFO, "> Error: no response from RAKP 3 message"); - return 1; + lprintf(LOG_WARNING, "> Error: no response from RAKP 3 message"); + return 2; } @@ -3333,8 +3363,8 @@ ipmi_lanplus_open(struct ipmi_intf * intf) { int rc; + int retry; struct get_channel_auth_cap_rsp auth_cap; - struct sockaddr_in addr; struct ipmi_session *session; if (!intf || !intf->session) @@ -3360,7 +3390,6 @@ /* Setup our lanplus session state */ - session->v2_data.session_state = LANPLUS_STATE_PRESESSION; session->v2_data.auth_alg = IPMI_AUTH_RAKP_NONE; session->v2_data.crypt_alg = IPMI_CRYPT_NONE; session->v2_data.console_id = 0x00; @@ -3373,46 +3402,14 @@ /* 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; } @@ -3436,43 +3433,61 @@ goto fail; } - /* - * Open session + * If the open/rakp1/rakp3 sequence encounters a timeout, the whole sequence + * needs to restart. The individual messages are not individually retryable, + * as the session state is advancing. */ - if (ipmi_lanplus_open_session(intf)){ - intf->close(intf); - goto fail; - } - - /* - * RAKP 1 - */ - if (ipmi_lanplus_rakp1(intf)){ - intf->close(intf); - goto fail; - } - - - /* - * RAKP 3 - */ - if (ipmi_lanplus_rakp3(intf)){ - intf->close(intf); - goto fail; + for (retry = 0; retry < IPMI_LAN_RETRY; retry++) { + session->v2_data.session_state = LANPLUS_STATE_PRESESSION; + /* + * Open session + */ + if ((rc = ipmi_lanplus_open_session(intf)) == 1) { + intf->close(intf); + goto fail; + } + if (rc == 2) { + lprintf(LOG_DEBUG, "Retry lanplus open session, %d", retry); + continue; + } + /* + * RAKP 1 + */ + if ((rc = ipmi_lanplus_rakp1(intf)) == 1) { + intf->close(intf); + goto fail; + } + if (rc == 2) { + lprintf(LOG_DEBUG, "Retry lanplus rakp1, %d", retry); + continue; + } + /* + * RAKP 3 + */ + if ((rc = ipmi_lanplus_rakp3(intf)) == 1) { + intf->close(intf); + goto fail; + } + if (rc == 0) break; + lprintf(LOG_DEBUG,"Retry lanplus rakp3, %d", retry); } - lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n"); if (!ipmi_oem_active(intf, "i82571spt")) { rc = ipmi_set_session_privlvl_cmd(intf); - if (rc < 0) + if (rc < 0) { + intf->close(intf); goto fail; + } } intf->manufacturer_id = ipmi_get_oem(intf); bridgePossible = 1; + /* automatically detect interface request and response sizes */ + hpm2_detect_max_payload_size(intf); + return intf->fd; fail: @@ -3624,5 +3639,46 @@ return -1; } memset(intf->session, 0, sizeof(struct ipmi_session)); + + /* setup default LAN maximum request and response sizes */ + intf->max_request_data_size = IPMI_LAN_MAX_REQUEST_SIZE; + intf->max_response_data_size = IPMI_LAN_MAX_RESPONSE_SIZE; + return 0; } + +static void ipmi_lanp_set_max_rq_data_size(struct ipmi_intf * intf, uint16_t size) +{ + if (intf->session->cipher_suite_id == 3) { + /* + * encrypted payload can only be multiple of 16 bytes + */ + size &= ~15; + + /* + * decrement payload size on confidentiality header size + * plus minimal confidentiality trailer size + */ + size -= (16 + 1); + } + + intf->max_request_data_size = size; +} + +static void ipmi_lanp_set_max_rp_data_size(struct ipmi_intf * intf, uint16_t size) +{ + if (intf->session->cipher_suite_id == 3) { + /* + * encrypted payload can only be multiple of 16 bytes + */ + size &= ~15; + + /* + * decrement payload size on confidentiality header size + * plus minimal confidentiality trailer size + */ + size -= (16 + 1); + } + + intf->max_response_data_size = size; +} diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/lanplus/Makefile.in ipmitool-1.8.13-1/src/plugins/lanplus/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/plugins/lanplus/Makefile.in 2015-09-18 03:59:15.228042780 -0400 +++ ipmitool-1.8.13-1/src/plugins/lanplus/Makefile.in 2015-09-18 04:09:42.824098493 -0400 @@ -147,6 +147,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/lipmi/Makefile.in ipmitool-1.8.13-1/src/plugins/lipmi/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/plugins/lipmi/Makefile.in 2015-09-18 03:59:15.228042780 -0400 +++ ipmitool-1.8.13-1/src/plugins/lipmi/Makefile.in 2015-09-18 04:09:51.587801864 -0400 @@ -146,6 +146,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/Makefile.am ipmitool-1.8.13-1/src/plugins/Makefile.am --- ipmitool-1.8.13-1_ORIG/src/plugins/Makefile.am 2015-09-18 03:59:15.224042771 -0400 +++ ipmitool-1.8.13-1/src/plugins/Makefile.am 2015-09-18 04:11:33.297828847 -0400 @@ -32,8 +32,8 @@ 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_USB@ @INTF_SERIAL@ +DIST_SUBDIRS = lan lanplus open lipmi imb bmc free usb serial noinst_LTLIBRARIES = libintf.la libintf_la_SOURCES = ipmi_intf.c diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/Makefile.in ipmitool-1.8.13-1/src/plugins/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/plugins/Makefile.in 2015-09-18 03:59:15.228042780 -0400 +++ ipmitool-1.8.13-1/src/plugins/Makefile.in 2015-09-18 04:11:42.644564657 -0400 @@ -185,6 +185,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ @@ -281,8 +283,8 @@ top_srcdir = @top_srcdir@ 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_USB@ @INTF_SERIAL@ +DIST_SUBDIRS = lan lanplus open lipmi imb bmc free usb serial noinst_LTLIBRARIES = libintf.la libintf_la_SOURCES = ipmi_intf.c libintf_la_LDFLAGS = -export-dynamic diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/open/Makefile.in ipmitool-1.8.13-1/src/plugins/open/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/plugins/open/Makefile.in 2015-09-18 03:59:15.224042771 -0400 +++ ipmitool-1.8.13-1/src/plugins/open/Makefile.in 2015-09-18 04:10:01.394958274 -0400 @@ -146,6 +146,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/open/open.c ipmitool-1.8.13-1/src/plugins/open/open.c --- ipmitool-1.8.13-1_ORIG/src/plugins/open/open.c 2015-09-18 03:59:15.224042771 -0400 +++ ipmitool-1.8.13-1/src/plugins/open/open.c 2015-09-18 04:10:08.374248854 -0400 @@ -65,6 +65,22 @@ # include "open.h" #endif +/** + * Maximum input message size for KCS/SMIC is 40 with 2 utility bytes and + * 38 bytes of data. + * Maximum input message size for BT is 42 with 4 utility bytes and + * 38 bytes of data. + */ +#define IPMI_OPENIPMI_MAX_RQ_DATA_SIZE 38 + +/** + * Maximum output message size for KCS/SMIC is 38 with 2 utility bytes, a byte + * for completion code and 35 bytes of data. + * Maximum output message size for BT is 40 with 4 utility bytes, a byte + * for completion code and 35 bytes of data. + */ +#define IPMI_OPENIPMI_MAX_RS_DATA_SIZE 35 + extern int verbose; static int @@ -187,8 +203,9 @@ /* 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 +274,8 @@ _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); @@ -389,7 +406,7 @@ /* save response data for caller */ if (rsp.ccode == 0 && rsp.data_len > 0) { memmove(rsp.data, rsp.data + 1, rsp.data_len); - rsp.data[recv.msg.data_len] = 0; + rsp.data[rsp.data_len] = 0; } if (data != NULL) { @@ -400,9 +417,19 @@ return &rsp; } +int ipmi_openipmi_setup(struct ipmi_intf * intf) +{ + /* set default payload size */ + intf->max_request_data_size = IPMI_OPENIPMI_MAX_RQ_DATA_SIZE; + intf->max_response_data_size = IPMI_OPENIPMI_MAX_RS_DATA_SIZE; + + return 0; +} + struct ipmi_intf ipmi_open_intf = { name: "open", desc: "Linux OpenIPMI Interface", + setup: ipmi_openipmi_setup, open: ipmi_openipmi_open, close: ipmi_openipmi_close, sendrecv: ipmi_openipmi_send_cmd, diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/serial/Makefile.in ipmitool-1.8.13-1/src/plugins/serial/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/plugins/serial/Makefile.in 2015-09-18 03:59:15.228042780 -0400 +++ ipmitool-1.8.13-1/src/plugins/serial/Makefile.in 2015-09-18 04:10:16.766852694 -0400 @@ -146,6 +146,8 @@ INTF_OPEN_LIB = @INTF_OPEN_LIB@ INTF_SERIAL = @INTF_SERIAL@ INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ LD = @LD@ LDFLAGS = @LDFLAGS@ diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/serial/serial_basic.c ipmitool-1.8.13-1/src/plugins/serial/serial_basic.c --- ipmitool-1.8.13-1_ORIG/src/plugins/serial/serial_basic.c 2015-09-18 03:59:15.228042780 -0400 +++ ipmitool-1.8.13-1/src/plugins/serial/serial_basic.c 2015-09-18 04:10:22.900566057 -0400 @@ -189,6 +189,10 @@ return -1; } memset(intf->session, 0, sizeof(struct ipmi_session)); + + /* setup default LAN maximum request and response sizes */ + intf->max_request_data_size = SERIAL_BM_MAX_RQ_SIZE; + intf->max_response_data_size = SERIAL_BM_MAX_RS_SIZE; return 0; } @@ -266,8 +270,14 @@ /* 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 +333,13 @@ 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 -Naur ipmitool-1.8.13-1_ORIG/src/plugins/serial/serial_terminal.c ipmitool-1.8.13-1/src/plugins/serial/serial_terminal.c --- ipmitool-1.8.13-1_ORIG/src/plugins/serial/serial_terminal.c 2015-09-18 03:59:15.228042780 -0400 +++ ipmitool-1.8.13-1/src/plugins/serial/serial_terminal.c 2015-09-18 04:10:31.037047668 -0400 @@ -211,8 +211,13 @@ /* 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 @@ 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 + } /* @@ -882,6 +894,10 @@ } memset(intf->session, 0, sizeof(struct ipmi_session)); + + /* setup default LAN maximum request and response sizes */ + intf->max_request_data_size = IPMI_SERIAL_MAX_RQ_SIZE; + intf->max_response_data_size = IPMI_SERIAL_MAX_RS_SIZE; return 0; } diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/usb/Makefile.am ipmitool-1.8.13-1/src/plugins/usb/Makefile.am --- ipmitool-1.8.13-1_ORIG/src/plugins/usb/Makefile.am 1969-12-31 19:00:00.000000000 -0500 +++ ipmitool-1.8.13-1/src/plugins/usb/Makefile.am 2015-09-17 04:25:14.781906100 -0400 @@ -0,0 +1,39 @@ +# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# Redistribution of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# Redistribution in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Sun Microsystems, Inc. or the names of +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# This software is provided "AS IS," without a warranty of any kind. +# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, +# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. +# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE +# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING +# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL +# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, +# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR +# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF +# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, +# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = -I$(top_srcdir)/include + +EXTRA_LTLIBRARIES = libintf_usb.la +noinst_LTLIBRARIES = @INTF_USB_LIB@ +libintf_usb_la_LIBADD = $(top_builddir)/lib/libipmitool.la +libintf_usb_la_SOURCES = usb.c + diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/usb/Makefile.in ipmitool-1.8.13-1/src/plugins/usb/Makefile.in --- ipmitool-1.8.13-1_ORIG/src/plugins/usb/Makefile.in 1969-12-31 19:00:00.000000000 -0500 +++ ipmitool-1.8.13-1/src/plugins/usb/Makefile.in 2015-09-17 05:58:51.918047600 -0400 @@ -0,0 +1,538 @@ +# Makefile.in generated by automake 1.11.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# Redistribution of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# Redistribution in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# Neither the name of Sun Microsystems, Inc. or the names of +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# This software is provided "AS IS," without a warranty of any kind. +# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, +# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. +# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE +# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING +# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL +# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, +# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR +# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF +# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, +# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/plugins/usb +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libintf_usb_la_DEPENDENCIES = $(top_builddir)/lib/libipmitool.la +am_libintf_usb_la_OBJECTS = usb.lo +libintf_usb_la_OBJECTS = $(am_libintf_usb_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libintf_usb_la_SOURCES) +DIST_SOURCES = $(libintf_usb_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +ARCH = @ARCH@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASEDIR = @BASEDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTRO = @DISTRO@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTF_BMC = @INTF_BMC@ +INTF_BMC_LIB = @INTF_BMC_LIB@ +INTF_FREE = @INTF_FREE@ +INTF_FREE_LIB = @INTF_FREE_LIB@ +INTF_IMB = @INTF_IMB@ +INTF_IMB_LIB = @INTF_IMB_LIB@ +INTF_LAN = @INTF_LAN@ +INTF_LANPLUS = @INTF_LANPLUS@ +INTF_LANPLUS_LIB = @INTF_LANPLUS_LIB@ +INTF_LAN_LIB = @INTF_LAN_LIB@ +INTF_LIPMI = @INTF_LIPMI@ +INTF_LIPMI_LIB = @INTF_LIPMI_LIB@ +INTF_OPEN = @INTF_OPEN@ +INTF_OPEN_LIB = @INTF_OPEN_LIB@ +INTF_SERIAL = @INTF_SERIAL@ +INTF_SERIAL_LIB = @INTF_SERIAL_LIB@ +INTF_USB = @INTF_USB@ +INTF_USB_LIB = @INTF_USB_LIB@ +IPMITOOL_INTF_LIB = @IPMITOOL_INTF_LIB@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OS = @OS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POW_LIB = @POW_LIB@ +PSTAMP = @PSTAMP@ +RANLIB = @RANLIB@ +RPMBUILD = @RPMBUILD@ +RPM_RELEASE = @RPM_RELEASE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_configure_args = @ac_configure_args@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +MAINTAINERCLEANFILES = Makefile.in +INCLUDES = -I$(top_srcdir)/include +EXTRA_LTLIBRARIES = libintf_usb.la +noinst_LTLIBRARIES = @INTF_USB_LIB@ +libintf_usb_la_LIBADD = $(top_builddir)/lib/libipmitool.la +libintf_usb_la_SOURCES = usb.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/usb/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/usb/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libintf_usb.la: $(libintf_usb_la_OBJECTS) $(libintf_usb_la_DEPENDENCIES) $(EXTRA_libintf_usb_la_DEPENDENCIES) + $(LINK) $(libintf_usb_la_OBJECTS) $(libintf_usb_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usb.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -Naur ipmitool-1.8.13-1_ORIG/src/plugins/usb/usb.c ipmitool-1.8.13-1/src/plugins/usb/usb.c --- ipmitool-1.8.13-1_ORIG/src/plugins/usb/usb.c 1969-12-31 19:00:00.000000000 -0500 +++ ipmitool-1.8.13-1/src/plugins/usb/usb.c 2015-09-17 04:25:14.781906100 -0400 @@ -0,0 +1,626 @@ +/* + * Copyright (c) 2015 American Megatrends, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Fri Apr 4 00:30:12 2015 + * + * This code implements support for USB interface. (OEM) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PACKED __attribute__ ((packed)) +#define BEGIN_SIG "$G2-CONFIG-HOST$" +#define BEGIN_SIG_LEN 16 +#define MAX_REQUEST_SIZE 64 * 1024 +#define CMD_RESERVED 0x0000 +#define SCSI_AMICMD_CURI_WRITE 0xE2 +#define SCSI_AMICMD_CURI_READ 0xE3 +#define SCSI_AMIDEF_CMD_SECTOR 0x01 +#define SCSI_AMIDEF_DATA_SECTOR 0x02 +#define ERR_SUCCESS 0 /* Success */ +#define ERR_BIG_DATA 1 /* Too Much Data */ +#define ERR_NO_DATA 2 /* No/Less Data Available */ +#define ERR_UNSUPPORTED 3 /* Unsupported Command */ +#define IN_PROCESS 0x8000 /* Bit 15 of Status */ +#define SCSI_AMICMD_ID 0xEE + +/* SCSI Command Packets */ +typedef struct { + unsigned char OpCode; + unsigned char Lun; + unsigned int Lba; + union { + struct { + unsigned char Reserved6; + unsigned short Length; + unsigned char Reserved9[3]; + } PACKED Cmd10; + struct Len32 { + unsigned int Length32; + unsigned char Reserved10[2]; + } PACKED Cmd12; + } PACKED CmdLen; +}PACKED SCSI_COMMAND_PACKET; + +typedef struct { + uint8_t byNetFnLUN; + uint8_t byCmd; + uint8_t byData[MAX_REQUEST_SIZE]; +}PACKED IPMIUSBRequest_T; + +typedef struct { + uint8_t BeginSig[BEGIN_SIG_LEN]; + uint16_t Command; + uint16_t Status; + uint32_t DataInLen; + uint32_t DataOutLen; + uint32_t InternalUseDataIn; + uint32_t InternalUseDataOut; + } CONFIG_CMD; + +static int ipmi_usb_setup(struct ipmi_intf *intf); +static struct ipmi_rs *ipmi_usb_send_cmd(struct ipmi_intf *intf, + struct ipmi_rq *req); + +struct ipmi_intf ipmi_usb_intf = { + .name = "usb", + .desc = "IPMI USB Interface(OEM Interface for AMI Devices)", + .setup = ipmi_usb_setup, + .sendrecv =ipmi_usb_send_cmd, +}; + +int +scsiProbeNew(int* num_ami_devices, int* sg_nos) +{ + int inplen = *num_ami_devices; + int numdevfound = 0; + char linebuf[81]; + char vendor[81]; + int lineno = 0; + FILE* fp; + + fp = fopen("/proc/scsi/sg/device_strs","r"); + if(fp == NULL) { + /* Return 1 on error */ + return 1; + } + + while(1) { + /* Read line by line and search for "AMI" */ + if(fgets(linebuf, 80, fp) == NULL) { + if(fp != NULL) { + fclose(fp); + } + /* Return 1 on error */ + return 1; + } + + if(sscanf(linebuf, "%s", vendor) == 1) { + if(strncmp(vendor, "AMI", strlen("AMI")) == 0) + { + numdevfound++; + sg_nos[numdevfound-1] = lineno; + if(numdevfound == inplen) { + break; + } + } + lineno++; + } + } + + *num_ami_devices = numdevfound; + if(fp != NULL) { + fclose(fp); + } + + return 0; +} + +int +OpenCD(struct ipmi_intf *intf,char *CDName) +{ + intf->fd = open(CDName, O_RDWR); + if(intf->fd == -1) { + lprintf(LOG_ERR, "OpenCD:Unable to open device, %s", strerror(errno)); + return 1; + } + return 0; +} + +int +sendscsicmd_SGIO(int cd_desc, unsigned char* cdb_buf, unsigned char cdb_len, + void* data_buf, unsigned int* data_len, int direction, + void* sense_buf, unsigned char slen, unsigned int timeout) +{ + sg_io_hdr_t io_hdr; + + /* Prepare command */ + memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); + io_hdr.interface_id = 'S'; + io_hdr.cmd_len = cdb_len; + + /* Transfer direction and length */ + io_hdr.dxfer_direction = direction; + io_hdr.dxfer_len = *data_len; + + io_hdr.dxferp = data_buf; + + io_hdr.cmdp = cdb_buf; + + io_hdr.sbp = (unsigned char *)sense_buf; + io_hdr.mx_sb_len = slen; + + io_hdr.timeout = timeout; + + if(!timeout) { + io_hdr.timeout = 20000; + } + + if(ioctl(cd_desc,SG_IO,&io_hdr) < 0) { + lprintf(LOG_ERR,"sendscsicmd_SGIO: SG_IO ioctl error"); + return 1; + } else { + if(io_hdr.status != 0) { + return 1; + } + } + + if(!timeout) { + return 0; + } + + if((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) { + lprintf(LOG_DEBUG, "sendscsicmd_SGIO: SG_INFO_OK - Not OK"); + } else { + lprintf(LOG_DEBUG, "sendscsicmd_SGIO : SG_INFO_OK - OK"); + return 0; + } + + return 1; +} + +int +AMI_SPT_CMD_Identify(int cd_desc, char* szSignature) +{ + SCSI_COMMAND_PACKET IdPkt = {0}; + int ret; + unsigned int siglen = 10; + + IdPkt.OpCode = SCSI_AMICMD_ID; + ret = sendscsicmd_SGIO(cd_desc, (unsigned char*)&IdPkt, + 10, szSignature, &siglen, SG_DXFER_FROM_DEV, + NULL, 0, 5000); + + return ret; +} + +int +IsG2Drive(int cd_desc) +{ + char szSignature[15]; + int ret; + + memset(szSignature, 0, 15); + + flock(cd_desc, LOCK_EX); + ret = AMI_SPT_CMD_Identify(cd_desc, szSignature); + flock(cd_desc, LOCK_UN); + if( ret != 0 ) { + lprintf(LOG_DEBUG,"IsG2Drive:Unable to send ID command to the device"); + return 1; + } + + if(strncmp(szSignature, "$$$AMI$$$",strlen("$$$AMI$$$")) != 0 ) { + lprintf(LOG_ERR, "IsG2Drive:Signature mismatch when ID command sent"); + return 1; + } + + return 0; +} + +int +FindG2CDROM(struct ipmi_intf *intf) +{ + int err = 0; + char device[256]; + int devarray[8]; + int numdev = 8; + int iter; + err = scsiProbeNew(&numdev,devarray); + + if(err == 0 && numdev > 0) { + for(iter=0; iter < numdev; iter++) { + sprintf(device, "/dev/sg%d", devarray[iter]); + + if(!OpenCD(intf,device)) { + if(!IsG2Drive(intf->fd)) { + lprintf(LOG_DEBUG, "USB Device found"); + return 1; + } + close(intf->fd); + } + } + } else { + lprintf(LOG_DEBUG, "Unable to find Virtual CDROM Device"); + } + + return 0; +} + +static int +ipmi_usb_setup(struct ipmi_intf *intf) +{ + if(FindG2CDROM(intf) == 0) { + lprintf(LOG_ERR,"Error in USB session setup \n"); + return -1; + } + intf->opened = 1; + return 0; +} + +void +InitCmdHeader(CONFIG_CMD* pG2CDCmdHeader) +{ + memset(pG2CDCmdHeader, 0, sizeof(CONFIG_CMD)); + strncpy((char*)pG2CDCmdHeader->BeginSig,BEGIN_SIG,BEGIN_SIG_LEN); +} + +int +AMI_SPT_CMD_SendCmd(int cd_desc, char *Buffer, char type, uint16_t buflen, + unsigned int timeout) +{ + SCSI_COMMAND_PACKET Cmdpkt; + char sensebuff[32]; + int ret; + unsigned int pktLen; + int count = 3; + + memset(&Cmdpkt, 0, sizeof(SCSI_COMMAND_PACKET)); + + Cmdpkt.OpCode = SCSI_AMICMD_CURI_WRITE; + Cmdpkt.Lba = htonl(type); + Cmdpkt.CmdLen.Cmd10.Length = htons(1); + + pktLen = buflen; + while(count > 0) { + ret = sendscsicmd_SGIO(cd_desc, (unsigned char*)&Cmdpkt, 10, Buffer, + &pktLen, SG_DXFER_TO_DEV, sensebuff, 32, timeout); + count--; + if(ret == 0) { + break; + } else { + ret = -1; + } + } + + return ret; +} + +int +AMI_SPT_CMD_RecvCmd(int cd_desc, char *Buffer, char type, uint16_t buflen) +{ + SCSI_COMMAND_PACKET Cmdpkt; + char sensebuff[32]; + int ret; + unsigned int pktLen; + int count = 3; + + memset(&Cmdpkt, 0, sizeof(SCSI_COMMAND_PACKET)); + + Cmdpkt.OpCode = SCSI_AMICMD_CURI_READ; + Cmdpkt.Lba = htonl(type); + Cmdpkt.CmdLen.Cmd10.Length = htons(1); + + pktLen = buflen; + while(count > 0) { + ret = sendscsicmd_SGIO(cd_desc, (unsigned char*)&Cmdpkt, 10, Buffer, + &pktLen, SG_DXFER_FROM_DEV, sensebuff, 32, 5000); + count--; + if(0 == ret) { + break; + } else { + ret = -1; + } + } + + return ret; +} + +int +ReadCD(int cd_desc, char CmdData, char *Buffer, uint32_t DataLen) +{ + int ret; + + ret = AMI_SPT_CMD_RecvCmd(cd_desc, Buffer, CmdData, DataLen); + + if(ret != 0) { + lprintf(LOG_ERR, "Error while reading CD-Drive"); + return -1; + } + + return 0; +} + +int +WriteCD(int cd_desc, char CmdData, char *Buffer, unsigned int timeout, + uint32_t DataLen) +{ + int ret; + + ret = AMI_SPT_CMD_SendCmd(cd_desc, Buffer, CmdData, DataLen, timeout); + if ( ret != 0 ) { + lprintf(LOG_ERR, "Error while writing to CD-Drive"); + return -1; + } + + return 0; +} + +int +WriteSplitData(struct ipmi_intf *intf, char* Buffer, char Sector, + uint32_t NumBytes, uint32_t timeout) +{ + uint32_t BytesWritten = 0; + int retVal; + + if(NumBytes == 0) { + return 0; + } + + while(BytesWritten < NumBytes) { + if((retVal = WriteCD(intf->fd, Sector, (Buffer+BytesWritten), timeout, + NumBytes)) != 0) + { + return retVal; + } + + BytesWritten += NumBytes; + } + + return 0; +} + +int +ReadSplitData(struct ipmi_intf *intf, char* Buffer, char Sector, + uint32_t NumBytes) +{ + uint32_t BytesRead = 0; + + if(NumBytes == 0) { + return 0; + } + + while(BytesRead < NumBytes) { + if(ReadCD(intf->fd, Sector, (Buffer+BytesRead), NumBytes) == -1) { + return 1; + } + BytesRead += NumBytes; + } + + return 0; +} + + +int +WaitForCommandCompletion(struct ipmi_intf *intf, CONFIG_CMD* pG2CDCmdHeader, + uint32_t timeout, uint32_t DataLen) +{ + uint32_t TimeCounter = 0; + + do { + if(ReadCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR,(char*)(pG2CDCmdHeader), + DataLen) == -1) + { + lprintf(LOG_ERR,"ReadCD returned ERROR"); + return 1; + } + + if(pG2CDCmdHeader->Status & IN_PROCESS) { + usleep(1000); + if(timeout > 0) { + TimeCounter++; + if(TimeCounter == (timeout+1)) { + return 2; + } + } + } else { + lprintf(LOG_DEBUG,"Command completed"); + break; + } + } while(1); + + return 0; +} + +int +SendDataToUSBDriver(struct ipmi_intf *intf, char *ReqBuffer, + unsigned int ReqBuffLen, unsigned char *ResBuffer, + int *ResBuffLen, unsigned int timeout) +{ + char CmdHeaderBuffer[sizeof(CONFIG_CMD)]; + int retVal; + int waitretval = 0; + unsigned int to = 0; + uint32_t DataLen = 0; + + CONFIG_CMD* pG2CDCmdHeader = (CONFIG_CMD*)CmdHeaderBuffer; + + /*FillHeader*/ + InitCmdHeader(pG2CDCmdHeader); + + /*Set command number*/ + pG2CDCmdHeader->Command = CMD_RESERVED; + + /*Fill Lengths*/ + pG2CDCmdHeader->DataOutLen = *ResBuffLen; + pG2CDCmdHeader->DataInLen = ReqBuffLen; + + if(!timeout) { + to = 3000; + } + + DataLen = sizeof(CONFIG_CMD); + + if(WriteCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR, (char*)(pG2CDCmdHeader), to, + DataLen) == -1) + { + lprintf(LOG_ERR,"Error in Write CD of SCSI_AMIDEF_CMD_SECTOR"); + return -1; + } + + /* Write the data to hard disk */ + if((retVal = WriteSplitData(intf, ReqBuffer, SCSI_AMIDEF_DATA_SECTOR, + ReqBuffLen, timeout)) != 0) + { + lprintf(LOG_ERR, "Error in WriteSplitData of SCSI_AMIDEF_DATA_SECTOR"); + return -1; + } + + if(!timeout) { + return 0; + } + + /*Read Status now*/ + waitretval = WaitForCommandCompletion(intf, pG2CDCmdHeader, timeout, + DataLen); + if(waitretval != 0) { + lprintf(LOG_ERR, "WaitForCommandComplete failed"); + return (0-waitretval); + } else { + lprintf(LOG_DEBUG, "WaitForCommandCompletion SUCCESS"); + } + + switch(pG2CDCmdHeader->Status) { + case ERR_SUCCESS: + *ResBuffLen = pG2CDCmdHeader->DataOutLen; + lprintf(LOG_DEBUG, "Before ReadSplitData %x", *ResBuffLen); + if(ReadSplitData(intf, (char *)ResBuffer, SCSI_AMIDEF_DATA_SECTOR, + pG2CDCmdHeader->DataOutLen) != 0) + { + lprintf(LOG_ERR,"Err ReadSplitData SCSI_AMIDEF_DATA_SCTR"); + return -1; + } + + /* Additional read to see verify there was not problem with the + * previous read */ + DataLen = sizeof(CONFIG_CMD); + ReadCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR, (char*)(pG2CDCmdHeader), + DataLen); + break; + + case ERR_BIG_DATA: + lprintf(LOG_ERR,"Too much data"); + break; + + case ERR_NO_DATA: + lprintf(LOG_ERR,"Too little data"); + break; + + case ERR_UNSUPPORTED: + lprintf(LOG_ERR,"Unsupported command"); + break; + + default: + lprintf(LOG_ERR,"Unknown status"); + } + + return pG2CDCmdHeader->Status; +} + + + +static struct ipmi_rs * +ipmi_usb_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req) +{ + static struct ipmi_rs rsp; + long timeout = 20000; + uint8_t byRet = 0; + char ReqBuff[MAX_REQUEST_SIZE] = {0}; + IPMIUSBRequest_T* pReqPkt = (IPMIUSBRequest_T*)ReqBuff; + int retries = 0; + + /********** FORM IPMI PACKET *****************/ + pReqPkt->byNetFnLUN = req->msg.netfn << 2; + pReqPkt->byNetFnLUN += req->msg.lun; + pReqPkt->byCmd = req->msg.cmd; + if(req->msg.data_len) { + memcpy(pReqPkt->byData, req->msg.data, req->msg.data_len); + } + + /********** SEND DATA TO USB ******************/ + while(retries < 3) { + retries++; + byRet = SendDataToUSBDriver(intf, ReqBuff, 2 + req->msg.data_len, + rsp.data, &rsp.data_len,timeout); + + if (byRet == 0) { + break; + } + } + + if(retries == 3) { + lprintf(LOG_ERR,"Error while sending command using", + "SendDataToUSBDriver"); + rsp.ccode = byRet; + return &rsp; + } + + rsp.ccode = rsp.data[0]; + + /* Save response data for caller */ + if((rsp.ccode == 0) && (rsp.data_len > 0)) { + memmove(rsp.data, rsp.data + 1, rsp.data_len-1); + rsp.data[rsp.data_len] = 0; + rsp.data_len -= 1; + } + + return &rsp; +} +