summaryrefslogtreecommitdiff
path: root/util/ihpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/ihpm.c')
-rw-r--r--util/ihpm.c4003
1 files changed, 4003 insertions, 0 deletions
diff --git a/util/ihpm.c b/util/ihpm.c
new file mode 100644
index 0000000..740ab74
--- /dev/null
+++ b/util/ihpm.c
@@ -0,0 +1,4003 @@
+/*
+ * ihpm.c
+ * Hardware Platform Management, IPM Controller Firmware Upgrade Procedure
+ *
+ * Change history:
+ * 08/25/2010 ARCress - ported from ipmitool/lib/ipmi_hpmfwupg.c
+ * 08/24/2011 ARcress - updated to Kontron 1.08 (K17) version,
+ * added hpm_decode_cc(), etc.
+ *
+ *---------------------------------------------------------------------
+ */
+/*
+ * Copyright (c) 2006 Kontron Canada, Inc. All Rights Reserved.
+ * 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.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#include <winsock.h>
+#include <stdlib.h>
+#define uint8_t unsigned char
+#define uint16_t unsigned short
+#define uint32_t unsigned int
+typedef uint32_t socklen_t;
+#include "getopt.h"
+#else
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <ctype.h> /*for toupper*/
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#else
+#include <getopt.h>
+#endif
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include "ipmicmd.h"
+#include "ihpm.h"
+
+/****************************************************************************
+*
+* 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 9
+static char * progname = "ihpm";
+static char * progver = "1.09"; /* HPMFWUPG_VERSION */
+extern char fdebug; /*from ipmicmd.c*/
+static uchar g_bus = PUBLIC_BUS;
+static uchar g_sa = BMC_SA;
+static uchar g_lun = BMC_LUN;
+static uchar g_addrtype = ADDR_SMI;
+static int g_channel_buf_size = 0;
+
+/*
+ * 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
+#define HPMFWUPG_NOT_SUPPORTED_NOW 0xd5
+
+/*
+ * This error code is used as a temporary PATCH to
+ * the latest Open ipmi driver. This PATCH
+ * will be removed once a new Open IPMI driver is released.
+ * (Buggy version = 39)
+ */
+#define ENABLE_OPENIPMI_V39_PATCH
+
+#ifdef ENABLE_OPENIPMI_V39_PATCH
+
+#define RETRY_COUNT_MAX 3
+
+static int errorCount;
+
+#define HPMFWUPG_IS_RETRYABLE(error) \
+((((error==0x83)||(error==0x82)||(error==0x80)) && (errorCount++<RETRY_COUNT_MAX))?TRUE:FALSE)
+#else
+#define HPMFWUPG_IS_RETRYABLE(error) FALSE
+#endif
+
+/*
+ * HPM FIRMWARE UPGRADE GENERAL DEFINITIONS
+ */
+
+#define HPMFWUPG_PICMG_IDENTIFIER 0
+#define HPMFWUPG_VERSION_SIZE 6
+#define HPMFWUPG_DESC_STRING_LENGTH 12
+#define HPMFWUPG_DEFAULT_INACCESS_TIMEOUT 60 /* sec */
+#define HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT 60 /* sec */
+#define HPMFWUPG_MD5_SIGNATURE_LENGTH 16
+
+/* Component IDs */
+typedef enum eHpmfwupgComponentId
+{
+ HPMFWUPG_COMPONENT_ID_0 = 0,
+ HPMFWUPG_COMPONENT_ID_1,
+ HPMFWUPG_COMPONENT_ID_2,
+ HPMFWUPG_COMPONENT_ID_3,
+ HPMFWUPG_COMPONENT_ID_4,
+ HPMFWUPG_COMPONENT_ID_5,
+ HPMFWUPG_COMPONENT_ID_6,
+ HPMFWUPG_COMPONENT_ID_7,
+ HPMFWUPG_COMPONENT_ID_MAX
+} tHpmfwupgComponentId;
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgComponentBitMask
+{
+ union
+ {
+ unsigned char byte;
+ struct
+ {
+ #ifdef WORDS_BIGENDIAN
+ unsigned char component7 : 1;
+ unsigned char component6 : 1;
+ unsigned char component5 : 1;
+ unsigned char component4 : 1;
+ unsigned char component3 : 1;
+ unsigned char component2 : 1;
+ unsigned char component1 : 1;
+ unsigned char component0 : 1;
+ #else
+ unsigned char component0 : 1;
+ unsigned char component1 : 1;
+ unsigned char component2 : 1;
+ unsigned char component3 : 1;
+ unsigned char component4 : 1;
+ unsigned char component5 : 1;
+ unsigned char component6 : 1;
+ unsigned char component7 : 1;
+ #endif
+ }ATTRIBUTE_PACKING bitField;
+ }ATTRIBUTE_PACKING ComponentBits;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+static const int HPMFWUPG_SUCCESS = 0;
+static const int HPMFWUPG_ERROR = -1;
+/* Upload firmware specific error codes */
+static const int HPMFWUPG_UPLOAD_BLOCK_LENGTH = 1;
+static const int HPMFWUPG_UPLOAD_RETRY = 2;
+
+
+/*
+ * TARGET UPGRADE CAPABILITIES DEFINITIONS
+ */
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetTargetUpgCapabilitiesReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetTargetUpgCapabilitiesResp
+{
+ unsigned char picmgId;
+ unsigned char hpmVersion;
+ union
+ {
+ unsigned char byte;
+ struct
+ {
+ #if WORDS_BIGENDIAN
+ unsigned char fwUpgUndesirable : 1;
+ unsigned char autRollbackOverride : 1;
+ unsigned char ipmcDegradedDurinUpg: 1;
+ unsigned char deferActivation : 1;
+ unsigned char servAffectDuringUpg : 1;
+ unsigned char manualRollback : 1;
+ unsigned char autRollback : 1;
+ unsigned char ipmcSelftestCap : 1;
+ #else
+ unsigned char ipmcSelftestCap : 1;
+ unsigned char autRollback : 1;
+ unsigned char manualRollback : 1;
+ unsigned char servAffectDuringUpg : 1;
+ unsigned char deferActivation : 1;
+ unsigned char ipmcDegradedDurinUpg: 1;
+ unsigned char autRollbackOverride : 1;
+ unsigned char fwUpgUndesirable : 1;
+ #endif
+ }ATTRIBUTE_PACKING bitField;
+ }ATTRIBUTE_PACKING GlobalCapabilities;
+ unsigned char upgradeTimeout;
+ unsigned char selftestTimeout;
+ unsigned char rollbackTimeout;
+ unsigned char inaccessTimeout;
+ struct HpmfwupgComponentBitMask componentsPresent;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetTargetUpgCapabilitiesCtx
+{
+ struct HpmfwupgGetTargetUpgCapabilitiesReq req;
+ struct HpmfwupgGetTargetUpgCapabilitiesResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * COMPONENT PROPERTIES DEFINITIONS
+ */
+
+typedef enum eHpmfwupgCompPropertiesSelect
+{
+ HPMFWUPG_COMP_GEN_PROPERTIES = 0,
+ HPMFWUPG_COMP_CURRENT_VERSION,
+ HPMFWUPG_COMP_DESCRIPTION_STRING,
+ HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION,
+ HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION,
+ HPMFWUPG_COMP_RESERVED,
+ HPMFWUPG_COMP_OEM_PROPERTIES = 192
+} tHpmfwupgCompPropertiesSelect;
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetComponentPropertiesReq
+{
+ unsigned char picmgId;
+ unsigned char componentId;
+ unsigned char selector;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetGeneralPropResp
+{
+ unsigned char picmgId;
+ union
+ {
+ unsigned char byte;
+ struct
+ {
+ #if WORDS_BIGENDIAN
+ unsigned char reserved : 2;
+ unsigned char payloadColdReset : 1;
+ unsigned char deferredActivation : 1;
+ unsigned char comparisonSupport : 1;
+ unsigned char preparationSupport : 1;
+ unsigned char rollbackBackup : 2;
+ #else
+ unsigned char rollbackBackup : 2;
+ unsigned char preparationSupport : 1;
+ unsigned char comparisonSupport : 1;
+ unsigned char deferredActivation : 1;
+ unsigned char payloadColdReset : 1;
+ unsigned char reserved : 2;
+ #endif
+ }ATTRIBUTE_PACKING bitfield;
+ }ATTRIBUTE_PACKING GeneralCompProperties;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetCurrentVersionResp
+{
+ unsigned char picmgId;
+ unsigned char currentVersion[HPMFWUPG_VERSION_SIZE];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetDescStringResp
+{
+ unsigned char picmgId;
+ char descString[HPMFWUPG_DESC_STRING_LENGTH];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetRollbackFwVersionResp
+{
+ unsigned char picmgId;
+ unsigned char rollbackFwVersion[HPMFWUPG_VERSION_SIZE];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetDeferredFwVersionResp
+{
+ unsigned char picmgId;
+ unsigned char deferredFwVersion[HPMFWUPG_VERSION_SIZE];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * GetComponentProperties - OEM properties (192)
+ */
+#define HPMFWUPG_OEM_LENGTH 4
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetOemProperties
+{
+ unsigned char picmgId;
+ unsigned char oemRspData[HPMFWUPG_OEM_LENGTH];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetComponentPropertiesResp
+{
+ union
+ {
+ struct HpmfwupgGetGeneralPropResp generalPropResp;
+ struct HpmfwupgGetCurrentVersionResp currentVersionResp;
+ struct HpmfwupgGetDescStringResp descStringResp;
+ struct HpmfwupgGetRollbackFwVersionResp rollbackFwVersionResp;
+ struct HpmfwupgGetDeferredFwVersionResp deferredFwVersionResp;
+ struct HpmfwupgGetOemProperties oemProperties;
+ }ATTRIBUTE_PACKING Response;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetComponentPropertiesCtx
+{
+ struct HpmfwupgGetComponentPropertiesReq req;
+ struct HpmfwupgGetComponentPropertiesResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+/*
+ * ABORT UPGRADE DEFINITIONS
+ */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgAbortUpgradeReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgAbortUpgradeResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgAbortUpgradeCtx
+{
+ struct HpmfwupgAbortUpgradeReq req;
+ struct HpmfwupgAbortUpgradeResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * UPGRADE ACTIONS DEFINITIONS
+ */
+typedef enum eHpmfwupgUpgradeAction
+{
+ HPMFWUPG_UPGRADE_ACTION_BACKUP = 0,
+ HPMFWUPG_UPGRADE_ACTION_PREPARE,
+ HPMFWUPG_UPGRADE_ACTION_UPGRADE,
+ HPMFWUPG_UPGRADE_ACTION_COMPARE,
+ HPMFWUPG_UPGRADE_ACTION_INVALID = 0xff
+} tHpmfwupgUpgradeAction;
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgInitiateUpgradeActionReq
+{
+ unsigned char picmgId;
+ struct HpmfwupgComponentBitMask componentsMask;
+ unsigned char upgradeAction;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgInitiateUpgradeActionResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgInitiateUpgradeActionCtx
+{
+ struct HpmfwupgInitiateUpgradeActionReq req;
+ struct HpmfwupgInitiateUpgradeActionResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * UPLOAD FIRMWARE BLOCK DEFINITIONS
+ */
+
+#define HPMFWUPG_SEND_DATA_COUNT_MAX 256
+#define HPMFWUPG_SEND_DATA_COUNT_KCS 30
+#define HPMFWUPG_SEND_DATA_COUNT_LAN 25
+#define HPMFWUPG_SEND_DATA_COUNT_IPMB 26
+#define HPMFWUPG_SEND_DATA_COUNT_IPMBL 26
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgUploadFirmwareBlockReq
+{
+ unsigned char picmgId;
+ unsigned char blockNumber;
+ unsigned char data[HPMFWUPG_SEND_DATA_COUNT_MAX];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgUploadFirmwareBlockResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgUploadFirmwareBlockCtx
+{
+ struct HpmfwupgUploadFirmwareBlockReq req;
+ struct HpmfwupgUploadFirmwareBlockResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+/*
+ * FINISH FIRMWARE UPLOAD DEFINITIONS
+ */
+
+#define HPMFWUPG_IMAGE_SIZE_BYTE_COUNT 4
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgFinishFirmwareUploadReq
+{
+ unsigned char picmgId;
+ unsigned char componentId;
+ unsigned char imageLength[HPMFWUPG_IMAGE_SIZE_BYTE_COUNT];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgFinishFirmwareUploadResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgFinishFirmwareUploadCtx
+{
+ struct HpmfwupgFinishFirmwareUploadReq req;
+ struct HpmfwupgFinishFirmwareUploadResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * ACTIVATE FW DEFINITIONS
+ */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgActivateFirmwareReq
+{
+ unsigned char picmgId;
+ unsigned char rollback_override;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgActivateFirmwareResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgActivateFirmwareCtx
+{
+ struct HpmfwupgActivateFirmwareReq req;
+ struct HpmfwupgActivateFirmwareResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+/*
+ * GET UPGRADE STATUS DEFINITIONS
+ */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetUpgradeStatusReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetUpgradeStatusResp
+{
+ unsigned char picmgId;
+ unsigned char cmdInProcess;
+ unsigned char lastCmdCompCode;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgGetUpgradeStatusCtx
+{
+ struct HpmfwupgGetUpgradeStatusReq req;
+ struct HpmfwupgGetUpgradeStatusResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * MANUAL FW ROLLBACK DEFINITIONS
+ */
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgManualFirmwareRollbackReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgManualFirmwareRollbackResp
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+struct HpmfwupgManualFirmwareRollbackCtx
+{
+ struct HpmfwupgManualFirmwareRollbackReq req;
+ struct HpmfwupgManualFirmwareRollbackResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * QUERY ROLLBACK STATUS DEFINITIONS
+ */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQueryRollbackStatusReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQueryRollbackStatusResp
+{
+ unsigned char picmgId;
+ struct HpmfwupgComponentBitMask rollbackComp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQueryRollbackStatusCtx
+{
+ struct HpmfwupgQueryRollbackStatusReq req;
+ struct HpmfwupgQueryRollbackStatusResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+/*
+ * QUERY SELF TEST RESULT DEFINITIONS
+ */
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQuerySelftestResultReq
+{
+ unsigned char picmgId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQuerySelftestResultResp
+{
+ unsigned char picmgId;
+ unsigned char result1;
+ unsigned char result2;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgQuerySelftestResultCtx
+{
+ struct HpmfwupgQuerySelftestResultReq req;
+ struct HpmfwupgQuerySelftestResultResp resp;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+/*
+ * HPM.1 IMAGE DEFINITIONS
+ */
+
+#define HPMFWUPG_HEADER_SIGNATURE_LENGTH 8
+#define HPMFWUPG_MANUFATURER_ID_LENGTH 3
+#define HPMFWUPG_PRODUCT_ID_LENGTH 2
+#define HPMFWUPG_TIME_LENGTH 4
+#define HPMFWUPG_TIMEOUT_LENGTH 1
+#define HPMFWUPG_COMP_REVISION_LENGTH 2
+#define HPMFWUPG_FIRM_REVISION_LENGTH 6
+#define HPMFWUPG_IMAGE_HEADER_VERSION 0
+#define HPMFWUPG_IMAGE_SIGNATURE "PICMGFWU"
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgImageHeader
+{
+ char signature[HPMFWUPG_HEADER_SIGNATURE_LENGTH];
+ unsigned char formatVersion;
+ unsigned char deviceId;
+ unsigned char manId[HPMFWUPG_MANUFATURER_ID_LENGTH];
+ unsigned char prodId[HPMFWUPG_PRODUCT_ID_LENGTH];
+ unsigned char time[HPMFWUPG_TIME_LENGTH];
+ union
+ {
+ struct
+ {
+ #if WORDS_BIGENDIAN
+ unsigned char imageSelfTest : 1;
+ unsigned char autRollback : 1;
+ unsigned char manRollback : 1;
+ unsigned char servAffected : 1;
+ unsigned char reserved : 4;
+ #else
+ unsigned char reserved : 4;
+ unsigned char servAffected : 1;
+ unsigned char manRollback : 1;
+ unsigned char autRollback : 1;
+ unsigned char imageSelfTest : 1;
+ #endif
+ } ATTRIBUTE_PACKING bitField;
+ unsigned char byte;
+ }ATTRIBUTE_PACKING imageCapabilities;
+ struct HpmfwupgComponentBitMask components;
+ unsigned char selfTestTimeout;
+ unsigned char rollbackTimeout;
+ unsigned char inaccessTimeout;
+ unsigned char compRevision[HPMFWUPG_COMP_REVISION_LENGTH];
+ unsigned char firmRevision[HPMFWUPG_FIRM_REVISION_LENGTH];
+ unsigned short oemDataLength;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+
+#define HPMFWUPG_DESCRIPTION_LENGTH 21
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgActionRecord
+{
+ unsigned char actionType;
+ struct HpmfwupgComponentBitMask components;
+ unsigned char checksum;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#define HPMFWUPG_FIRMWARE_SIZE_LENGTH 4
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgFirmwareImage
+{
+ unsigned char version[HPMFWUPG_FIRM_REVISION_LENGTH];
+ char desc[HPMFWUPG_DESCRIPTION_LENGTH];
+ unsigned char length[HPMFWUPG_FIRMWARE_SIZE_LENGTH];
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(1)
+#endif
+struct HpmfwupgUpgradeCtx
+{
+ struct HpmfwupgComponentBitMask compUpdateMask;
+ unsigned int imageSize;
+ unsigned char* pImageData;
+ unsigned char componentId;
+ struct HpmfwupgGetTargetUpgCapabilitiesResp targetCap;
+ struct HpmfwupgGetGeneralPropResp genCompProp[HPMFWUPG_COMPONENT_ID_MAX];
+ struct ipm_devid_rsp devId;
+} ATTRIBUTE_PACKING;
+#ifdef HAVE_PRAGMA_PACK
+#pragma pack(0)
+#endif
+
+typedef enum eHpmfwupgActionType
+{
+ HPMFWUPG_ACTION_BACKUP_COMPONENTS = 0,
+ HPMFWUPG_ACTION_PREPARE_COMPONENTS,
+ HPMFWUPG_ACTION_UPLOAD_FIRMWARE,
+ HPMFWUPG_ACTION_RESERVED = 0xFF
+} tHpmfwupgActionType;
+
+/*
+ * FUNCTIONS PROTOTYPES
+ */
+#define HPMFWUPG_MAJORMINOR_VERSION_SIZE 2
+
+
+#define DEFAULT_COMPONENT_UPLOAD 0x0F
+
+/*
+ * Options added for user to check the version and to view both the FILE and TARGET Version
+ */
+#define VERSIONCHECK_MODE 0x01
+#define VIEW_MODE 0x02
+#define DEBUG_MODE 0x04
+#define FORCE_MODE_ALL 0x08
+#define FORCE_MODE_COMPONENT 0x10
+#define FORCE_MODE (FORCE_MODE_ALL|FORCE_MODE_COMPONENT)
+
+typedef struct _VERSIONINFO
+{
+ unsigned char componentId;
+ unsigned char targetMajor;
+ unsigned char targetMinor;
+ unsigned char targetAux[4];
+ unsigned char rollbackMajor;
+ unsigned char rollbackMinor;
+ unsigned char rollbackAux[4];
+ unsigned char imageMajor;
+ unsigned char imageMinor;
+ unsigned char imageAux[4];
+ unsigned char coldResetRequired;
+ unsigned char rollbackSupported;
+ unsigned char skipUpgrade;
+ char descString[15];
+}VERSIONINFO, *PVERSIONINFO;
+
+VERSIONINFO gVersionInfo[HPMFWUPG_COMPONENT_ID_MAX];
+
+#define TARGET_VER (0x01)
+#define ROLLBACK_VER (0x02)
+#define IMAGE_VER (0x04)
+
+
+
+
+static int HpmfwupgPreUpgradeCheck(void *intf,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx,int componentToUpload,int option);
+static int HpmfwupgUpgrade(void *intf, char* imageFilename, int activate, int,int);
+static int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgPreparationStage( void *intf,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx, int option);
+static int HpmfwupgUpgradeStage ( void *intf,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx, int compToUpload ,int option);
+static int HpmfwupgActivationStage(void *intf,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgGetTargetUpgCapabilities(void *intf,
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx);
+static int HpmfwupgGetComponentProperties(void *intf,
+ struct HpmfwupgGetComponentPropertiesCtx* pCtx);
+static int HpmfwupgQuerySelftestResult(void *intf,
+ struct HpmfwupgQuerySelftestResultCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgQueryRollbackStatus(void *intf,
+ struct HpmfwupgQueryRollbackStatusCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgAbortUpgrade(void *intf,
+ struct HpmfwupgAbortUpgradeCtx* pCtx);
+static int HpmfwupgInitiateUpgradeAction(void *intf,
+ struct HpmfwupgInitiateUpgradeActionCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgUploadFirmwareBlock(void *intf,
+ struct HpmfwupgUploadFirmwareBlockCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx, int count ,
+ unsigned int *pOffset, unsigned int *blockLen);
+static int HpmfwupgFinishFirmwareUpload(void *intf,
+ struct HpmfwupgFinishFirmwareUploadCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgActivateFirmware(void *intf,
+ struct HpmfwupgActivateFirmwareCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgGetUpgradeStatus(void *intf,
+ struct HpmfwupgGetUpgradeStatusCtx* pCtxstruct,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgManualFirmwareRollback(void *intf,
+ struct HpmfwupgManualFirmwareRollbackCtx* pCtx,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static void HpmfwupgPrintUsage(void);
+static unsigned char HpmfwupgCalculateChecksum(unsigned char* pData, unsigned int length);
+static int HpmfwupgGetDeviceId(void *intf, struct ipm_devid_rsp* pGetDevId);
+static int HpmfwupgGetBufferFromFile(char* imageFilename, struct HpmfwupgUpgradeCtx* pFwupgCtx);
+static int HpmfwupgWaitLongDurationCmd(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx);
+
+static struct ipmi_rs * HpmfwupgSendCmd(void *intf, struct ipmi_rq req,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx);
+
+
+static int HpmFwupgActionUploadFirmware
+(
+ struct HpmfwupgComponentBitMask components,
+ struct HpmfwupgUpgradeCtx* pFwupgCtx,
+ unsigned char** pImagePtr,
+ int componentToUpload,
+ void *intf,
+ int option,
+ int* pFlagColdReset
+);
+
+static char * hpm_decode_cc( uchar cmd, uchar cc )
+{
+ char *pstr;
+ switch(cc) {
+ case 0x80: pstr = "Command in progress"; break;
+ case 0x81: pstr = "HPM not supported"; break;
+ case 0x82: pstr = "Checksum error"; break;
+ case 0x83: pstr = "Firmware mismatch"; break;
+ default: pstr = decode_cc(cmd,cc);
+ }
+ return(pstr);
+}
+
+/****************************************************************************
+*
+* Function Name: HpmGetuserInput
+*
+* Description: This function gets input from user and returns TRUE if its Yes
+* or FALSE if its No
+*
+*****************************************************************************/
+int HpmGetUserInput(char *str)
+{
+ char userInput[2];
+ printf("%s",str);
+ scanf("%s",userInput);
+ if (toupper(userInput[0]) == 'Y')
+ {
+ return 1;
+ }
+ return 0;
+}
+/****************************************************************************
+*
+* Function Name: HpmDisplayLine
+*
+* Description: This is to display the line with the given character.
+*
+*****************************************************************************/
+void HpmDisplayLine(char *s, int n)
+{
+ while (n--) printf ("%c",*s);
+ printf("\n");
+}
+
+/****************************************************************************
+*
+* Function Name: HpmDisplayUpgradeHeader
+*
+* Description: This function the displays the Upgrade header information
+*
+*****************************************************************************/
+void HpmDisplayUpgradeHeader(int option)
+{
+ printf("\n");
+ HpmDisplayLine("-",78 );
+ printf("|ID | Name | Versions | %% |\n");
+ printf("| | | Active | Backup | File | |\n");
+ printf("|---|-----------|-----------------|-----------------|-----------------|------|\n");
+}
+
+/****************************************************************************
+*
+* Function Name: HpmDisplayUpgrade
+*
+* Description: This function displays the progress of the upgrade it prints the "."
+* every 5% of its completion.
+*
+*****************************************************************************/
+void HpmDisplayUpgrade( int skip, unsigned int totalSent,
+ unsigned int displayFWLength,time_t timeElapsed)
+{
+ int percent;
+ static int old_percent=1;
+ if (skip)
+ {
+ printf(" Skip |\n");
+ return;
+ }
+ fflush(stdout);
+
+ percent = (int)((totalSent * 100)/displayFWLength);
+ if (percent != old_percent)
+ {
+ if ( percent == 0 ) printf(" 0 %% |");
+ else if (percent == 100) printf("\b\b\b\b\b\b\b100 %% |\n");
+ else printf("\b\b\b\b\b\b\b%3d %% |", percent);
+ old_percent = percent;
+ }
+
+ if (totalSent== displayFWLength)
+ {
+ /* Display the time taken to complete the upgrade */
+ printf("| | Upload Time: %02d.%02d | Image Size: %05x |\n",
+ timeElapsed/60,timeElapsed%60,totalSent);
+ }
+}
+
+/****************************************************************************
+*
+* Function Name: HpmDisplayVersionHeader
+*
+* Description: This function displays the information about version header
+*
+*****************************************************************************/
+int HpmDisplayVersionHeader(int mode)
+{
+ if ( mode & IMAGE_VER)
+ {
+ HpmDisplayLine("-",71 );
+ printf("|ID | Name | Versions |\n");
+ printf("| | | Active | Backup | File |\n");
+ HpmDisplayLine("-",71 );
+ }
+ else
+ {
+ HpmDisplayLine("-",53 );
+ printf("|ID | Name | Versions |\n");
+ printf("| | | Active | Backup |\n");
+ HpmDisplayLine("-",53 );
+ }
+ return 0;
+}
+
+/****************************************************************************
+*
+* Function Name: HpmDisplayVersion
+*
+* Description: This function displays the version of the image and target
+*
+*****************************************************************************/
+int HpmDisplayVersion(int mode,VERSIONINFO *pVersion)
+{
+ char descString[12];
+ memset(&descString,0x00,12);
+ /*
+ * Added this to ensure that even if the description string
+ * is more than required it does not give problem in displaying it
+ */
+ strncpy(descString,pVersion->descString,11);
+ /*
+ * 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%-2d|%-11s|",pVersion->coldResetRequired?'*':' ',pVersion->componentId,descString);
+
+ if (mode & TARGET_VER)
+ {
+ if (pVersion->targetMajor == 0xFF && pVersion->targetMinor == 0xFF)
+ printf(" ---.-- -------- |");
+ 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->rollbackMinor == 0xFF)
+ printf(" ---.-- -------- |");
+ else
+ printf(" %3d.%02x %02X%02X%02X%02X |",
+ pVersion->rollbackMajor,
+ pVersion->rollbackMinor,
+ pVersion->rollbackAux[0],
+ pVersion->rollbackAux[1],
+ pVersion->rollbackAux[2],
+ pVersion->rollbackAux[3]);
+ }
+ else
+ {
+ printf(" ---.-- -------- |");
+ }
+ }
+
+ if (mode & IMAGE_VER)
+ {
+ if (pVersion->imageMajor == 0xFF && pVersion->imageMinor == 0xFF)
+ printf(" ---.-- |");
+ else
+ printf(" %3d.%02x %02X%02X%02X%02X |",
+ pVersion->imageMajor,
+ pVersion->imageMinor,
+ pVersion->imageAux[0],
+ pVersion->imageAux[1],
+ pVersion->imageAux[2],
+ pVersion->imageAux[3]);
+ }
+ return 0;
+}
+
+
+/****************************************************************************
+*
+* Function Name: HpmfwupgTargerCheck
+*
+* Description: This function gets the target information and displays it on the
+* screen
+*
+*****************************************************************************/
+int HpmfwupgTargetCheck(void * 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 rc;
+ }
+
+ 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),
+ get_mfg_str(devIdrsp.manufacturer_id,NULL));
+ 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];
+ }
+ mode |= ROLLBACK_VER;
+ }
+
+ 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]);
+ printf("\n");
+ }
+ }
+ }
+
+ if (option & VIEW_MODE)
+ {
+ HpmDisplayLine("-",53 );
+ if (flagColdReset)
+ {
+ 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(void *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);
+ }
+ }
+
+ /*
+ * 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);
+ }
+ }
+
+ /*
+ * 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 )
+ {
+ if (verbose) printf("HPM Upgrade error %d\n",rc);
+ free(fwupgCtx.pImageData);
+ }
+ }
+
+ /*
+ * ACTIVATION STAGE
+ */
+ if ( rc == HPMFWUPG_SUCCESS && activate )
+ {
+ lprintf(LOG_NOTICE,"Performing activation stage: ");
+ rc = HpmfwupgActivationStage(intf, &fwupgCtx);
+ if ( rc != HPMFWUPG_SUCCESS )
+ {
+ if (verbose) printf("HPM Activation error %d\n",rc);
+ free(fwupgCtx.pImageData);
+ }
+ }
+
+ 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);
+ }
+ 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;
+ 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(void *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
+ {
+ /*
+ * If you use all option its kind of FORCE command where we need to upgrade all the components
+ */
+ printf("\n\n Use \"all\" option for uploading all the components\n");
+ }
+ }
+ }
+
+ /* Validate earliest compatible revision */
+ if ( rc == HPMFWUPG_SUCCESS )
+ {
+ /* Validate major & minor revision */
+ if ( pImageHeader->compRevision[0] < pFwupgCtx->devId.fw_rev1 )
+ {
+ /* Do nothing, upgrade accepted */
+ }
+ else if ( pImageHeader->compRevision[0] == pFwupgCtx->devId.fw_rev1 )
+ {
+ /* Must validate minor revision */
+ if ( pImageHeader->compRevision[1] > pFwupgCtx->devId.fw_rev2 )
+ {
+ /* Version not compatible for upgrade */
+ lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]);
+ lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]);
+ lprintf(LOG_NOTICE," Not compatible with ");
+ lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1);
+ lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ /* Version not compatible for upgrade */
+ lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]);
+ lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]);
+ lprintf(LOG_NOTICE," Not compatible with ");
+ lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1);
+ lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2);
+ rc = HPMFWUPG_ERROR;
+ }
+
+ if (rc != HPMFWUPG_SUCCESS)
+ {
+ /* Confirming it once again */
+ if ( (option & FORCE_MODE) || (option & VIEW_MODE) )
+ {
+ if( HpmGetUserInput("\n Continue IGNORING Earliest compatibility (Y/N) :"))
+ rc = HPMFWUPG_SUCCESS;
+ }
+ }
+ }
+
+ /* Get target upgrade capabilities */
+ if ( rc == HPMFWUPG_SUCCESS )
+ {
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
+
+ rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd);
+
+ if ( rc == HPMFWUPG_SUCCESS )
+ {
+ /* Copy response to context */
+ memcpy(&pFwupgCtx->targetCap,
+ &targetCapCmd.resp,
+ sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp));
+
+ if (option & VIEW_MODE)
+ {
+ return rc;
+ }
+ else
+ {
+ /* Make sure all component IDs defined in the upgrade
+ image are supported by the IPMC */
+ if ( (pImageHeader->components.ComponentBits.byte &
+ pFwupgCtx->targetCap.componentsPresent.ComponentBits.byte ) !=
+ pImageHeader->components.ComponentBits.byte )
+ {
+ lprintf(LOG_NOTICE,"\n Some components present in the image file are not supported by the IPMC");
+ rc = HPMFWUPG_ERROR;
+ }
+
+ /* Make sure the upgrade is desirable rigth now */
+ if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.fwUpgUndesirable == 1 )
+ {
+ lprintf(LOG_NOTICE,"\n Upgrade undesirable at this moment");
+ rc = HPMFWUPG_ERROR;
+ }
+
+ /* Get confimation from the user if he wants to continue when service
+ affected during upgrade */
+ if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.servAffectDuringUpg == 1 ||
+ pImageHeader->imageCapabilities.bitField.servAffected == 1 )
+ {
+ if (HpmGetUserInput("\nServices may be affected during upgrade. Do you wish to continue? y/n "))
+ {
+ rc = HPMFWUPG_SUCCESS;
+ }
+ else
+ {
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ }
+ }
+ }
+
+ /* Get the general properties of each component present in image */
+ if ( rc == HPMFWUPG_SUCCESS )
+ {
+ int componentId;
+
+ for ( componentId = HPMFWUPG_COMPONENT_ID_0;
+ componentId < HPMFWUPG_COMPONENT_ID_MAX;
+ componentId++ )
+ {
+ /* Reset component properties */
+ memset(&pFwupgCtx->genCompProp[componentId], 0, sizeof (struct HpmfwupgGetGeneralPropResp));
+
+ if ( (1 << componentId & pImageHeader->components.ComponentBits.byte) )
+ {
+ struct HpmfwupgGetComponentPropertiesCtx getCompPropCmd;
+
+ /* Get general component properties */
+ getCompPropCmd.req.componentId = componentId;
+ getCompPropCmd.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES;
+
+ rc = HpmfwupgGetComponentProperties(intf, &getCompPropCmd);
+
+ if ( rc == HPMFWUPG_SUCCESS )
+ {
+ /* Copy response to context */
+ memcpy(&pFwupgCtx->genCompProp[componentId],
+ &getCompPropCmd.resp,
+ sizeof(struct HpmfwupgGetGeneralPropResp));
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+/****************************************************************************
+*
+* 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(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx,
+ int componentToUpload,int option)
+{
+ int rc = HPMFWUPG_SUCCESS;
+ unsigned char* pImagePtr;
+ struct HpmfwupgActionRecord* pActionRecord;
+ unsigned int actionsSize;
+ int flagColdReset = FALSE;
+ struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
+ pFwupgCtx->pImageData;
+
+ /* 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)
+ {
+ HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER|IMAGE_VER);
+ }
+
+ /* 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:
+ {
+ pImagePtr += sizeof(struct HpmfwupgActionRecord);
+ }
+ break;
+
+ case HPMFWUPG_ACTION_PREPARE_COMPONENTS:
+ {
+ if (componentToUpload != DEFAULT_COMPONENT_UPLOAD)
+ {
+ if (!(1<<componentToUpload & pActionRecord->components.ComponentBits.byte))
+ {
+ lprintf(LOG_NOTICE,"\nComponent Id given is not supported\n");
+ return HPMFWUPG_ERROR;
+ }
+ }
+ pImagePtr += sizeof(struct HpmfwupgActionRecord);
+ }
+ break;
+
+ case HPMFWUPG_ACTION_UPLOAD_FIRMWARE:
+ /* Upload all firmware blocks */
+ {
+ struct HpmfwupgFirmwareImage* pFwImage;
+ unsigned char* pData;
+ unsigned int firmwareLength = 0;
+ unsigned char mode = 0;
+ unsigned char componentId = 0x00;
+ unsigned char componentIdByte = 0x00;
+ VERSIONINFO *pVersionInfo;
+ // struct HpmfwupgGetComponentPropertiesCtx getCompProp;
+
+ /* Save component ID on which the upload is done */
+ componentIdByte = pActionRecord->components.ComponentBits.byte;
+
+ 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;
+ }
+ pVersionInfo->skipUpgrade = FALSE;
+
+ if (option & FORCE_MODE_ALL)
+ {
+ /* user has given all to upload all the components on the command line */
+ if(verbose) {
+ lprintf(LOG_NOTICE,"Forcing ALL components");
+ }
+ }
+ else if( option & FORCE_MODE_COMPONENT )
+ {
+ if( componentToUpload != componentId )
+ {
+ if(verbose) {
+ lprintf(LOG_NOTICE,"Forcing component %d skip", componentId);
+ }
+ /* user has given the component Id to upload on the command line */
+ pVersionInfo->skipUpgrade = TRUE;
+ }
+ else if(verbose)
+ {
+ lprintf(LOG_NOTICE,"Forcing component %d update", componentId);
+ /* user has given the component Id to upload on the command line */
+ }
+ }
+ else
+ {
+ if
+ (
+ (pVersionInfo->imageMajor == pVersionInfo->targetMajor)
+ &&
+ (pVersionInfo->imageMinor == pVersionInfo->targetMinor))
+ {
+ if (pVersionInfo->rollbackSupported)
+ {
+ /*If the Image Versions are same as Target Versions then check for the
+ * rollback version*/
+ if
+ (
+ (pVersionInfo->imageMajor == pVersionInfo->rollbackMajor)
+ &&
+ (pVersionInfo->imageMinor == pVersionInfo->rollbackMinor)
+ )
+ {
+ /* This indicates that the Rollback version is also same as
+ * Image version -- So now we must skip it */
+ pVersionInfo->skipUpgrade = TRUE;
+ }
+ mode |= ROLLBACK_VER;
+ }
+ else
+ {
+ pVersionInfo->skipUpgrade = TRUE;
+ }
+ }
+ if ( verbose ) {
+ lprintf(LOG_NOTICE,"Component %d: %s", componentId , (pVersionInfo->skipUpgrade?"skipped":"to update"));
+ }
+ }
+ if( pVersionInfo->skipUpgrade == FALSE )
+ {
+ pFwupgCtx->compUpdateMask.ComponentBits.byte |= 1<<componentId;
+ }
+ if (option & VIEW_MODE)
+ {
+ HpmDisplayVersion(mode,pVersionInfo);
+ printf("\n");
+ }
+ pImagePtr = pData + firmwareLength;
+ }
+ break;
+ default:
+ lprintf(LOG_NOTICE," Invalid Action type. Cannot continue");
+ rc = HPMFWUPG_ERROR;
+ break;
+ }
+ }
+ }
+ if (option & VIEW_MODE)
+ {
+ HpmDisplayLine("-",71);
+ if (flagColdReset)
+ {
+ fflush(stdout);
+ lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset");
+ }
+ }
+ return rc;
+}
+
+
+/****************************************************************************
+*
+* Function Name: HpmfwupgUpgradeStage
+*
+* Description: This function the upgrade stage of a firmware upgrade
+* procedure as defined in section 3.3 of the IPM Controller
+* Firmware Upgrade Specification version 1.0
+*
+*****************************************************************************/
+int HpmfwupgUpgradeStage(void *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(0);
+ }
+
+ /* 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("-",78);
+
+ if (flagColdReset)
+ {
+ 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,
+ void *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);
+ }
+
+ if( (1 << componentId) & pFwupgCtx->compUpdateMask.ComponentBits.byte)
+ {
+ if( verbose ) {
+ lprintf(LOG_NOTICE,"Do not skip %d" , componentId);
+ }
+ skip = FALSE;
+ }
+
+ if(!skip)
+ {
+ /* Initialize parameters */
+ uploadCmd.req.blockNumber = 0;
+
+ /* Check if we receive size in parameters */
+ if(g_channel_buf_size != 0)
+ {
+ if (g_sa == BMC_SA)
+ {
+ bufLength = g_channel_buf_size - 9; /* Plan for overhead */
+ }
+ else
+ {
+ bufLength = g_channel_buf_size - 11; /* Plan for overhead */
+ }
+ }
+ else
+ {
+ /* Find max buffer length according the connection parameters */
+ if ( is_remote() ) /*IPMI LAN*/
+ {
+ bufLength = HPMFWUPG_SEND_DATA_COUNT_LAN - 2;
+ if (g_sa != BMC_SA)
+ bufLength -= 8;
+ }
+ else
+ {
+ int i;
+ i = get_driver_type();
+ if ((i == DRV_MV || i == DRV_KCS) && /*open driver*/
+ (g_sa == BMC_SA) )
+ {
+ bufLength = HPMFWUPG_SEND_DATA_COUNT_KCS - 2;
+ }
+ else
+ {
+ if ( g_bus == 7 )
+ {
+ bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMBL;
+ }
+ else
+ {
+ bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMB;
+ }
+ }
+ }
+ }
+ if (verbose)
+ printf("Upgrade buffer size = %d (%d)\n",bufLength,g_channel_buf_size);
+
+ /* 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 ( is_remote() ) // 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 \r\n",
+ uploadCmd.req.blockNumber,totalSent);
+ if (imageOffset || blockLength)
+ {
+ printf("\r--> ImgOff : %x BlkLen : %x\n",imageOffset,blockLength);
+ }
+ if (displayFWLength == totalSent)
+ {
+ printf(" Time Taken %02d:%02d\n",(end-start)/60, (end-start)%60);
+ printf("\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);
+ if ( option & DEBUG_MODE)
+ printf("HpmfwupgFinishFirmwareUpload rc = %d sent = %d\n",rc,totalSent);
+ *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(void *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;
+ 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 )
+ {
+ fread(pFwupgCtx->pImageData, sizeof(unsigned char), pFwupgCtx->imageSize, pImageFile);
+ }
+ else
+ {
+ rc = HPMFWUPG_ERROR;
+ }
+
+ fclose(pImageFile);
+ }
+
+ return rc;
+}
+
+int HpmfwupgGetDeviceId(void *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, compcode = %x\n", rsp->ccode);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error getting device ID\n");
+ rc = HPMFWUPG_ERROR;
+ }
+ return rc;
+}
+
+int HpmfwupgGetTargetUpgCapabilities(void *intf,
+ struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx)
+{
+ int rc = HPMFWUPG_SUCCESS;
+ struct ipmi_rs * rsp;
+ struct ipmi_rq req;
+
+ pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
+
+ memset(&req, 0, sizeof(req));
+ req.msg.netfn = IPMI_NETFN_PICMG;
+ req.msg.cmd = HPMFWUPG_GET_TARGET_UPG_CAPABILITIES;
+ req.msg.data = (unsigned char*)&pCtx->req;
+ req.msg.data_len = sizeof(struct HpmfwupgGetTargetUpgCapabilitiesReq);
+
+ rsp = HpmfwupgSendCmd(intf, req, NULL);
+
+ if ( rsp )
+ {
+ if ( rsp->ccode == 0x00 )
+ {
+ memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp));
+ if ( verbose )
+ {
+ lprintf(LOG_NOTICE,"TARGET UPGRADE CAPABILITIES");
+ lprintf(LOG_NOTICE,"-------------------------------");
+ lprintf(LOG_NOTICE,"HPM.1 version............%d ", pCtx->resp.hpmVersion);
+ lprintf(LOG_NOTICE,"Component 0 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
+ bitField.component0 ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Component 1 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
+ bitField.component1 ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Component 2 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
+ bitField.component2 ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Component 3 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
+ bitField.component3 ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Component 4 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
+ bitField.component4 ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Component 5 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
+ bitField.component5 ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Component 6 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
+ bitField.component6 ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Component 7 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits.
+ bitField.component7 ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Upgrade undesirable.....[%c] ", pCtx->resp.GlobalCapabilities.
+ bitField.fwUpgUndesirable ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Aut rollback override...[%c] ", pCtx->resp.GlobalCapabilities.
+ bitField.autRollbackOverride ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"IPMC degraded...........[%c] ", pCtx->resp.GlobalCapabilities.
+ bitField.ipmcDegradedDurinUpg ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Defered activation......[%c] ", pCtx->resp.GlobalCapabilities.
+ bitField.deferActivation ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Service affected........[%c] ", pCtx->resp.GlobalCapabilities.
+ bitField.servAffectDuringUpg ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Manual rollback.........[%c] ", pCtx->resp.GlobalCapabilities.
+ bitField.manualRollback ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Automatic rollback......[%c] ", pCtx->resp.GlobalCapabilities.
+ bitField.autRollback ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Self test...............[%c] ", pCtx->resp.GlobalCapabilities.
+ bitField.ipmcSelftestCap ? 'y' : 'n');
+ lprintf(LOG_NOTICE,"Upgrade timeout.........[%d sec] ", pCtx->resp.upgradeTimeout*5);
+ lprintf(LOG_NOTICE,"Self test timeout.......[%d sec] ", pCtx->resp.selftestTimeout*5);
+ lprintf(LOG_NOTICE,"Rollback timeout........[%d sec] ", pCtx->resp.rollbackTimeout*5);
+ lprintf(LOG_NOTICE,"Inaccessibility timeout.[%d sec] \n", pCtx->resp.inaccessTimeout*5);
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error getting target upgrade capabilities\n", rsp->ccode);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error getting target upgrade capabilities\n");
+ rc = HPMFWUPG_ERROR;
+ }
+
+
+
+ return rc;
+}
+
+
+int HpmfwupgGetComponentProperties(void *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 )
+ {
+ 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, compcode = %x\n", rsp->ccode);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error getting component properties\n");
+ rc = HPMFWUPG_ERROR;
+ }
+
+
+ return rc;
+}
+
+int HpmfwupgAbortUpgrade(void *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 )
+ {
+ if ( rsp->ccode != 0x00 )
+ {
+ lprintf(LOG_NOTICE,"Error aborting upgrade, compcode = %x\n", rsp->ccode);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error aborting upgrade\n");
+ rc = HPMFWUPG_ERROR;
+ }
+ return rc;
+}
+
+int HpmfwupgInitiateUpgradeAction(void *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 )
+ {
+ /* 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, compcode = %x %s\n",
+ rsp->ccode, hpm_decode_cc(req.msg.cmd,rsp->ccode));
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error initiating upgrade action\n");
+ rc = HPMFWUPG_ERROR;
+ }
+
+ return rc;
+}
+
+int HpmfwupgUploadFirmwareBlock(void *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, compcode = %x\n", rsp->ccode);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error uploading firmware block\n");
+ rc = HPMFWUPG_ERROR;
+ }
+
+ return rc;
+}
+
+int HpmfwupgFinishFirmwareUpload(void *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;
+ req.msg.data_len = sizeof(struct HpmfwupgFinishFirmwareUploadReq);
+
+ rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
+
+ if ( rsp )
+ {
+ /* Long duration command handling */
+ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS)
+ {
+ rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
+ }
+ else if ( rsp->ccode != IPMI_CC_OK )
+ {
+ lprintf(LOG_NOTICE,"Error finishing firmware upload, compcode = %x %s\n",
+ rsp->ccode, hpm_decode_cc(req.msg.cmd,rsp->ccode));
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error finishing firmware upload\n");
+ rc = HPMFWUPG_ERROR;
+ }
+
+ return rc;
+}
+
+int HpmfwupgActivateFirmware(void *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 == HPMFWUPG_NOT_SUPPORTED_NOW) /*0xd5*/
+ {
+ printf("Activation already completed.\n");
+ rc = HPMFWUPG_SUCCESS;
+ }
+ else if ( rsp->ccode != IPMI_CC_OK )
+ {
+ lprintf(LOG_NOTICE,"Error activating firmware, compcode = %x\n",
+ rsp->ccode);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error activating firmware\n");
+ rc = HPMFWUPG_ERROR;
+ }
+
+ return rc;
+}
+
+int HpmfwupgGetUpgradeStatus(void *intf, struct HpmfwupgGetUpgradeStatusCtx* 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_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->ccode == 0x00 )
+ {
+ memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetUpgradeStatusResp));
+ if ( verbose > 1 )
+ {
+ 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);
+ }
+ }
+ /*
+ * 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)
+ */
+ else if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) )
+ {
+ lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected");
+
+ pCtx->resp.lastCmdCompCode = HPMFWUPG_COMMAND_IN_PROGRESS;
+ }
+ else
+ {
+ if ( verbose )
+ {
+ lprintf(LOG_NOTICE,"Error getting upgrade status, compcode = %x\n", rsp->ccode);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ }
+ else
+ {
+ if ( verbose )
+ {
+ lprintf(LOG_NOTICE,"Error getting upgrade status");
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+
+ return rc;
+}
+
+int HpmfwupgManualFirmwareRollback(void *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;
+ req.msg.data_len = sizeof(struct HpmfwupgManualFirmwareRollbackReq);
+
+ rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
+
+ if ( rsp )
+ {
+ /* Long duration command handling */
+ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
+ {
+ struct HpmfwupgQueryRollbackStatusCtx resCmd;
+ printf("Waiting firmware rollback...");
+ fflush(stdout);
+ rc = HpmfwupgQueryRollbackStatus(intf, &resCmd, pFwupgCtx);
+ }
+ else if ( rsp->ccode != 0x00 )
+ {
+ lprintf(LOG_NOTICE,"Error sending manual rollback, compcode = %x\n", rsp->ccode);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error sending manual rollback\n");
+ rc = HPMFWUPG_ERROR;
+ }
+ return rc;
+}
+
+int HpmfwupgQueryRollbackStatus(void *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 )
+ {
+ 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 = (uint32_t)time(NULL);
+ timeoutSec2 = (uint32_t)time(NULL);
+ do
+ {
+ /* Must wait at least 100 ms between status requests */
+ os_usleep(0,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 = (uint32_t)time(NULL);
+
+ }while( rsp &&
+ (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) &&
+ (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, compcode = %x", rsp->ccode);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error getting upgrade status\n");
+ rc = HPMFWUPG_ERROR;
+ }
+
+ return rc;
+}
+
+int HpmfwupgQuerySelftestResult(void *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;
+ req.msg.data_len = sizeof(struct HpmfwupgQuerySelftestResultReq);
+
+
+ /* Poll rollback status until completion or timeout */
+ timeoutSec1 = (uint32_t)time(NULL);
+ timeoutSec2 = (uint32_t)time(NULL);
+ do
+ {
+ /* Must wait at least 100 ms between status requests */
+ os_usleep(0,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 = (uint32_t)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, compcode = %x\n", rsp->ccode);
+ rc = HPMFWUPG_ERROR;
+ }
+ }
+ else
+ {
+ lprintf(LOG_NOTICE,"Error getting upgrade status\n");
+ rc = HPMFWUPG_ERROR;
+ }
+
+ return rc;
+}
+
+struct ipmi_rs * HpmfwupgSendCmd(void *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;
+ static struct ipmi_rs fakeRsp;
+ int rv, rsp_len;
+
+ /*
+ * 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 = (uint32_t)time(NULL);
+
+ do
+ {
+ static unsigned char isValidSize = FALSE;
+ rv = ipmi_sendrecv(&req, fakeRsp.data, &rsp_len);
+ if( rv < 0)
+ {
+ #define HPM_LAN_PACKET_RESIZE_LIMIT 6
+
+ if(is_remote()) /* also covers lanplus */
+ {
+ static int errorCount=0;
+
+ 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;
+ rv = fakeRsp.ccode;
+ 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;
+ rv = fakeRsp.ccode;
+ 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 */
+ ipmi_close_();
+ os_usleep(inaccessTimeout,0);
+
+ /* Fake timeout to retry command */
+ fakeRsp.ccode = 0xc3;
+ rv = fakeRsp.ccode;
+ rsp = &fakeRsp;
+ }
+ }
+ }
+ }
+
+ /* Handle inaccessibility timeout (rsp = NULL if IOL) */
+ if ( rv < 0 || rv == 0xff || rv == 0xc3 || rv == 0xd3 )
+ {
+ if ( inaccessTimeoutCounter < inaccessTimeout )
+ {
+ timeoutSec2 = (uint32_t)time(NULL);
+ if ( timeoutSec2 > timeoutSec1 )
+ {
+ inaccessTimeoutCounter += timeoutSec2 - timeoutSec1;
+ timeoutSec1 = (uint32_t)time(NULL);
+ }
+ os_usleep(0,100000);
+ retry = 1;
+ }
+ else
+ {
+ retry = 0;
+ }
+ }
+ /* Handle node busy timeout */
+ else if ( rv == 0xc0 )
+ {
+ if ( upgradeTimeoutCounter < upgradeTimeout )
+ {
+ timeoutSec2 = (uint32_t)time(NULL);
+ if ( timeoutSec2 > timeoutSec1 )
+ {
+ timeoutSec1 = (uint32_t)time(NULL);
+ // upgradeTimeoutCounter += timeoutSec2 - timeoutSec1;
+ upgradeTimeoutCounter += 1;
+ }
+ os_usleep(0,100000);
+ retry = 1;
+ }
+ else
+ {
+ retry = 0;
+ }
+ }
+ else
+ {
+ #ifdef ENABLE_OPENIPMI_V39_PATCH
+ if( rv == 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 );
+
+ if (rv < 0) rsp = NULL;
+ else {
+ rsp = &fakeRsp; /*has data already*/
+ rsp->ccode = (uchar)rv;
+ rsp->session.payloadtype = 0; /*IPMI_PAYLOAD_TYPE_IPMI*/
+ rsp->data_len = rsp_len;
+ }
+ return rsp;
+}
+
+int HpmfwupgWaitLongDurationCmd(void *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 = 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 = (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 = (uint32_t)time(NULL);
+ timeoutSec2 = (uint32_t)time(NULL);
+ rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx);
+ }
+
+ while(
+ (upgStatusCmd.resp.lastCmdCompCode == HPMFWUPG_COMMAND_IN_PROGRESS ) &&
+ (timeoutSec2 - timeoutSec1 < upgradeTimeout ) &&
+ (rc == HPMFWUPG_SUCCESS)
+ )
+ {
+ /* Must wait at least 1000 ms between status requests */
+ os_usleep(0,1000000);
+ rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx);
+ //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,
+ hpm_decode_cc(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 < (int)length; dataIdx++ )
+ {
+ checksum += pData[dataIdx];
+ }
+ return checksum;
+}
+
+static void HpmfwupgPrintUsage(void)
+{
+ lprintf(LOG_NOTICE,"help - This help menu");
+ lprintf(LOG_NOTICE,"check - Check the target information");
+ lprintf(LOG_NOTICE,"check <file> - If the user is unsure of what update is going to be ");
+ lprintf(LOG_NOTICE," This will display the existing target version and image ");
+ lprintf(LOG_NOTICE," version on the screen");
+ lprintf(LOG_NOTICE,"upgrade <file> - Upgrade the firmware using a valid HPM.1 image <file>");
+ lprintf(LOG_NOTICE," This checks the version from the file and image and ");
+ lprintf(LOG_NOTICE," if it differs then only updates else skips");
+ lprintf(LOG_NOTICE,"upgrade <file> all - Updates all the components present in the file on the target board");
+ lprintf(LOG_NOTICE," without skipping (use this only after using \"check\" command");
+ lprintf(LOG_NOTICE,"upgrade <file> component x - Upgrade only component <x> from the given <file>");
+ lprintf(LOG_NOTICE," component 0 - BOOT");
+ lprintf(LOG_NOTICE," component 1 - RTK");
+ lprintf(LOG_NOTICE,"upgrade <file> activate - Upgrade the firmware using a valid HPM.1 image <file>");
+ lprintf(LOG_NOTICE," If activate is specified, activate new firmware rigth");
+ lprintf(LOG_NOTICE," away");
+ lprintf(LOG_NOTICE,"activate [norollback] - Activate the newly uploaded firmware");
+ lprintf(LOG_NOTICE,"targetcap - Get the target upgrade capabilities");
+ lprintf(LOG_NOTICE,"compprop <id> <select> - Get the specified component properties");
+ lprintf(LOG_NOTICE," Valid component <ID> 0-7 ");
+ lprintf(LOG_NOTICE," Properties <select> 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,"abort - Abort the on-going firmware upgrade");
+ lprintf(LOG_NOTICE,"upgstatus - Returns the status of the last long duration command");
+ 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,"selftestresult - Query the self test results\n");
+}
+
+int ipmi_hpmfwupg_main(void * 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 ERR_USAGE;
+ }
+ if ( (strcmp(argv[0], "check") == 0) )
+ {
+ /* hpm check */
+ if (argv[1] == NULL)
+ {
+ rc = HpmfwupgTargetCheck(intf,VIEW_MODE);
+ }
+ else
+ {
+ /* hpm check <filename> */
+ rc = HpmfwupgTargetCheck(intf,0);
+ if (rc == HPMFWUPG_SUCCESS)
+ {
+ rc = HpmfwupgUpgrade(intf, argv[1],0,DEFAULT_COMPONENT_UPLOAD,VIEW_MODE);
+ }
+ }
+ }
+
+ else if ( strcmp(argv[0], "upgrade") == 0)
+ {
+ int i =0;
+ if (fdebug) option |= DEBUG_MODE;
+ if (g_channel_buf_size > 0)
+ printf("Large buffer size %d specified\n", g_channel_buf_size );
+ for (i=1; i< argc ; i++)
+ {
+ if (strcmp(argv[i],"activate") == 0)
+ {
+ activateFlag = 1;
+ }
+ /* hpm upgrade <filename> all */
+ if (strcmp(argv[i],"all") == 0)
+ {
+ option &= ~(VERSIONCHECK_MODE);
+ option &= ~(VIEW_MODE);
+ option |= FORCE_MODE_ALL;
+ }
+ /* hpm upgrade <filename> component <comp Id> */
+ if (strcmp(argv[i],"component") == 0)
+ {
+ if (i+1 < argc)
+ {
+ componentId = atoi(argv[i+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;
+ cmdCtx.req.componentId = atob(argv[1]);
+ cmdCtx.req.selector = atob(argv[2]);
+ 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);
+ }
+ else if ( (argc == 1) && (strcmp(argv[0], "rollback") == 0) )
+ {
+ struct HpmfwupgManualFirmwareRollbackCtx cmdCtx;
+ verbose++;
+ rc = HpmfwupgManualFirmwareRollback(intf, &cmdCtx, NULL);
+ }
+ else if ( (argc == 1) && (strcmp(argv[0], "rollbackstatus") == 0) )
+ {
+ struct HpmfwupgQueryRollbackStatusCtx cmdCtx;
+ verbose++;
+ rc = HpmfwupgQueryRollbackStatus(intf, &cmdCtx, NULL);
+ }
+ else if ( (argc == 1) && (strcmp(argv[0], "selftestresult") == 0) )
+ {
+ struct HpmfwupgQuerySelftestResultCtx cmdCtx;
+ verbose++;
+ rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL);
+ }
+ else
+ {
+ HpmfwupgPrintUsage();
+ }
+
+ return rc;
+}
+
+#ifdef METACOMMAND
+int i_hpm(int argc, char **argv)
+#else
+#ifdef WIN32
+int __cdecl
+#else
+int
+#endif
+main(int argc, char **argv)
+#endif
+{
+ void *intf = NULL;
+ int rc = 0;
+ int c, i;
+ char *s1;
+
+ printf("%s ver %s\n", progname,progver);
+ set_loglevel(LOG_NOTICE);
+
+ while ( (c = getopt( argc, argv,"m:z:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF )
+ switch (c) {
+ case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */
+ g_bus = htoi(&optarg[0]); /*bus/channel*/
+ g_sa = htoi(&optarg[2]); /*device slave address*/
+ g_lun = htoi(&optarg[4]); /*LUN*/
+ g_addrtype = ADDR_IPMB;
+ if (optarg[6] == 's') {
+ g_addrtype = ADDR_SMI; s1 = "SMI";
+ } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; }
+ ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype);
+ printf("Use MC at %s bus=%x sa=%x lun=%x\n",
+ s1,g_bus,g_sa,g_lun);
+ break;
+ case 'z':
+ g_channel_buf_size = atoi(optarg);
+ if (g_channel_buf_size < HPMFWUPG_SEND_DATA_COUNT_LAN)
+ rc = ERR_BAD_LENGTH;
+ else if (g_channel_buf_size > IPMI_REQBUF_SIZE)
+ rc = LAN_ERR_BADLENGTH;
+ if (rc != 0) {
+ printf("Invalid buffer size %d\n",g_channel_buf_size);
+ return rc;
+ }
+ break;
+ case 'x': fdebug = 1; verbose = 1;
+ set_loglevel(LOG_DEBUG);
+ break; /* debug messages */
+ case 'N': /* nodename */
+ case 'U': /* remote username */
+ case 'P': /* remote password */
+ case 'R': /* remote password */
+ case 'E': /* get password from IPMI_PASSWORD environment var */
+ case 'F': /* force driver type */
+ case 'T': /* auth type */
+ case 'J': /* cipher suite */
+ case 'V': /* priv level */
+ case 'Y': /* prompt for remote password */
+ case 'Z': /* set local MC address */
+ parse_lan_options(c,optarg,fdebug);
+ break;
+ case '?':
+ HpmfwupgPrintUsage();
+ return ERR_USAGE;
+ break;
+ }
+ for (i = 0; i < optind; i++) { argv++; argc--; }
+
+ rc = ipmi_hpmfwupg_main(intf, argc, argv);
+
+ ipmi_close_();
+ // show_outcome(progname,rc);
+ return rc;
+}
+/* end ihpm.c */
+