mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 10:37:22 +00:00
3968 lines
128 KiB
C
3968 lines
128 KiB
C
/*
|
|
* 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.
|
|
*/
|
|
|
|
#include <ipmitool/ipmi_intf.h>
|
|
#include <ipmitool/ipmi_mc.h>
|
|
#include <ipmitool/ipmi_hpmfwupg.h>
|
|
#include <ipmitool/helper.h>
|
|
#include <ipmitool/ipmi_strings.h>
|
|
#include <ipmitool/log.h>
|
|
#include "../src/plugins/lan/md5.h"
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
|
|
#if HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Copyright (c) 2006 Kontron Canada, Inc. All Rights Reserved.
|
|
*
|
|
* HPM.1
|
|
* Hardware Platform Management
|
|
* IPM Controller Firmware Upgrade Procedure
|
|
*
|
|
* This module implements an Upgrade Agent for the IPM Controller
|
|
* Firmware Upgrade Procedure (HPM.1) specification version 1.0.
|
|
*
|
|
* author:
|
|
* Frederic.Lelievre@ca.kontron.com
|
|
* Francois.Isabelle@ca.kontron.com
|
|
* Jean-Michel.Audet@ca.kontron.com
|
|
* MarieJosee.Blais@ca.kontron.com
|
|
*
|
|
*****************************************************************************
|
|
*
|
|
* HISTORY
|
|
* ===========================================================================
|
|
* 2007-01-11
|
|
*
|
|
* - Incremented to version 0.2
|
|
* - Added lan packet size reduction mechanism to workaround fact
|
|
* that lan iface will not return C7 on excessive length
|
|
* - Fixed some typos
|
|
* - now uses lprintf()
|
|
*
|
|
* - Incremented to version 0.3
|
|
* - added patch for openipmi si driver V39 (send message in driver does not
|
|
* retry on 82/83 completion code and return 82/83 as response from target
|
|
* [conditionnaly built with ENABLE_OPENIPMI_V39_PATCH]
|
|
*
|
|
* see: ipmi-fix-send-msg-retry.pacth in openipmi-developer mailing list
|
|
*
|
|
* 2007-01-16
|
|
*
|
|
* - Incremented to version 0.4
|
|
* - Fixed lan iface inaccesiblity timeout handling. Waiting for firmware
|
|
* activation completion (fixed sleep) before re-opening a session and
|
|
* get the final firmware upgrade status.
|
|
* - Fixed some user interface stuff.
|
|
*
|
|
* 2007-05-09
|
|
*
|
|
* - Incremented to version 1.0
|
|
* - Modifications for compliancy with HPM.1 specification version 1.0
|
|
*
|
|
* 2007-06-05
|
|
*
|
|
* - Modified the display of upgrade of Firmware version.
|
|
* - Added new options like "check" and "component" and "all" to hpm commands.
|
|
* - By default we skip the upgrade if we have the same firmware version
|
|
* as compared to the Image file (*.hpm).This will ensure that user does
|
|
* not update the target incase its already been updated
|
|
*
|
|
* 2008-01-25
|
|
* - Reduce buffer length more aggressively when no response from iol.
|
|
* - Incremented version to 1.02
|
|
*
|
|
* 2009-02-11
|
|
* - With multi-component HPM file, if one component need to be skipped because
|
|
* the component is already up-to-date, ipmitool sends "Initiate upgrade
|
|
* action / Upload for upgrade" anyway.
|
|
*
|
|
* If the component needs to be skipped, ipmitool will not send "Initiate
|
|
* upgrade action / Upload for upgrade"
|
|
*
|
|
* - Incremented version to 1.03
|
|
*
|
|
* 2009-02-11
|
|
* - Fixed side effect introduced by last version, "forced" update didn't
|
|
* work anymore
|
|
* - Incremented version to 1.04
|
|
*
|
|
* 2009-03-25
|
|
* - Fix the case where ipmitool loses the iol connection during the upload
|
|
* block process. Once IPMITool was successfully sent the first byte,
|
|
* IPMITool will not resize the block size.
|
|
*
|
|
* 2009-03-26
|
|
* - Fix the problem when we try to upgrade specific component and the component
|
|
* is already updated, IPMITool sends a "prepare action" but IPMITool skips
|
|
* the upload firmware block process.
|
|
* So, if we specify a specific component, we want to force to upload this
|
|
* specific component.
|
|
* - Incremented version to 1.05
|
|
*
|
|
* 2009-04-20
|
|
* - Reworked previous update, when 'component' is specified, the other
|
|
* components are now skipped.
|
|
* - Incremented version to 1.06
|
|
*
|
|
* ===========================================================================
|
|
* TODO
|
|
* ===========================================================================
|
|
* 2007-01-11
|
|
* - Add interpretation of GetSelftestResults
|
|
* - Add interpretation of component ID string
|
|
*
|
|
*****************************************************************************/
|
|
|
|
extern int verbose;
|
|
|
|
/*
|
|
* Agent version
|
|
*/
|
|
#define HPMFWUPG_VERSION_MAJOR 1
|
|
#define HPMFWUPG_VERSION_MINOR 0
|
|
#define HPMFWUPG_VERSION_SUBMINOR 8
|
|
|
|
/*
|
|
* HPM.1 FIRMWARE UPGRADE COMMANDS (part of PICMG)
|
|
*/
|
|
|
|
#define HPMFWUPG_GET_TARGET_UPG_CAPABILITIES 0x2E
|
|
#define HPMFWUPG_GET_COMPONENT_PROPERTIES 0x2F
|
|
#define HPMFWUPG_ABORT_UPGRADE 0x30
|
|
#define HPMFWUPG_INITIATE_UPGRADE_ACTION 0x31
|
|
#define HPMFWUPG_UPLOAD_FIRMWARE_BLOCK 0x32
|
|
#define HPMFWUPG_FINISH_FIRMWARE_UPLOAD 0x33
|
|
#define HPMFWUPG_GET_UPGRADE_STATUS 0x34
|
|
#define HPMFWUPG_ACTIVATE_FIRMWARE 0x35
|
|
#define HPMFWUPG_QUERY_SELFTEST_RESULT 0x36
|
|
#define HPMFWUPG_QUERY_ROLLBACK_STATUS 0x37
|
|
#define HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK 0x38
|
|
|
|
/*
|
|
* HPM.1 SPECIFIC COMPLETION CODES
|
|
*/
|
|
#define HPMFWUPG_ROLLBACK_COMPLETED 0x00
|
|
#define HPMFWUPG_COMMAND_IN_PROGRESS 0x80
|
|
#define HPMFWUPG_NOT_SUPPORTED 0x81
|
|
#define HPMFWUPG_SIZE_MISMATCH 0x81
|
|
#define HPMFWUPG_ROLLBACK_FAILURE 0x81
|
|
#define HPMFWUPG_INV_COMP_MASK 0x81
|
|
#define HPMFWUPG__ABORT_FAILURE 0x81
|
|
#define HPMFWUPG_INV_COMP_ID 0x82
|
|
#define HPMFWUPG_INT_CHECKSUM_ERROR 0x82
|
|
#define HPMFWUPG_INV_UPLOAD_MODE 0x82
|
|
#define HPMFWUPG_ROLLBACK_OVERRIDE 0x82
|
|
#define HPMFWUPG_INV_COMP_PROP 0x83
|
|
#define HPMFWUPG_FW_MISMATCH 0x83
|
|
#define HPMFWUPG_ROLLBACK_DENIED 0x83
|
|
|
|
/*
|
|
* This error code is used as a temporary PATCH to
|
|
* the latest Open ipmi driver. This PATCH
|
|
* will be removed once a new Open IPMI driver is released.
|
|
* (Buggy version = 39)
|
|
*/
|
|
#define ENABLE_OPENIPMI_V39_PATCH
|
|
|
|
#ifdef ENABLE_OPENIPMI_V39_PATCH
|
|
|
|
#define RETRY_COUNT_MAX 3
|
|
|
|
static int errorCount;
|
|
|
|
#define HPMFWUPG_IS_RETRYABLE(error) \
|
|
((((error==0x83)||(error==0x82)||(error==0x80)) && (errorCount++<RETRY_COUNT_MAX))?TRUE:FALSE)
|
|
#else
|
|
#define HPMFWUPG_IS_RETRYABLE(error) FALSE
|
|
#endif
|
|
|
|
/*
|
|
* HPM FIRMWARE UPGRADE GENERAL DEFINITIONS
|
|
*/
|
|
|
|
#define HPMFWUPG_PICMG_IDENTIFIER 0
|
|
#define HPMFWUPG_VERSION_SIZE 6
|
|
#define HPMFWUPG_DESC_STRING_LENGTH 12
|
|
#define HPMFWUPG_DEFAULT_INACCESS_TIMEOUT 60 /* sec */
|
|
#define HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT 60 /* sec */
|
|
#define HPMFWUPG_MD5_SIGNATURE_LENGTH 16
|
|
|
|
/* Component IDs */
|
|
typedef enum eHpmfwupgComponentId
|
|
{
|
|
HPMFWUPG_COMPONENT_ID_0 = 0,
|
|
HPMFWUPG_COMPONENT_ID_1,
|
|
HPMFWUPG_COMPONENT_ID_2,
|
|
HPMFWUPG_COMPONENT_ID_3,
|
|
HPMFWUPG_COMPONENT_ID_4,
|
|
HPMFWUPG_COMPONENT_ID_5,
|
|
HPMFWUPG_COMPONENT_ID_6,
|
|
HPMFWUPG_COMPONENT_ID_7,
|
|
HPMFWUPG_COMPONENT_ID_MAX
|
|
} tHpmfwupgComponentId;
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgComponentBitMask
|
|
{
|
|
union
|
|
{
|
|
unsigned char byte;
|
|
struct
|
|
{
|
|
#ifdef WORDS_BIGENDIAN
|
|
unsigned char component7 : 1;
|
|
unsigned char component6 : 1;
|
|
unsigned char component5 : 1;
|
|
unsigned char component4 : 1;
|
|
unsigned char component3 : 1;
|
|
unsigned char component2 : 1;
|
|
unsigned char component1 : 1;
|
|
unsigned char component0 : 1;
|
|
#else
|
|
unsigned char component0 : 1;
|
|
unsigned char component1 : 1;
|
|
unsigned char component2 : 1;
|
|
unsigned char component3 : 1;
|
|
unsigned char component4 : 1;
|
|
unsigned char component5 : 1;
|
|
unsigned char component6 : 1;
|
|
unsigned char component7 : 1;
|
|
#endif
|
|
}ATTRIBUTE_PACKING bitField;
|
|
}ATTRIBUTE_PACKING ComponentBits;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
|
|
static const int HPMFWUPG_SUCCESS = 0;
|
|
static const int HPMFWUPG_ERROR = -1;
|
|
/* Upload firmware specific error codes */
|
|
static const int HPMFWUPG_UPLOAD_BLOCK_LENGTH = 1;
|
|
static const int HPMFWUPG_UPLOAD_RETRY = 2;
|
|
|
|
|
|
/*
|
|
* TARGET UPGRADE CAPABILITIES DEFINITIONS
|
|
*/
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetTargetUpgCapabilitiesReq
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetTargetUpgCapabilitiesResp
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char hpmVersion;
|
|
union
|
|
{
|
|
unsigned char byte;
|
|
struct
|
|
{
|
|
#if WORDS_BIGENDIAN
|
|
unsigned char fwUpgUndesirable : 1;
|
|
unsigned char autRollbackOverride : 1;
|
|
unsigned char ipmcDegradedDurinUpg: 1;
|
|
unsigned char deferActivation : 1;
|
|
unsigned char servAffectDuringUpg : 1;
|
|
unsigned char manualRollback : 1;
|
|
unsigned char autRollback : 1;
|
|
unsigned char ipmcSelftestCap : 1;
|
|
#else
|
|
unsigned char ipmcSelftestCap : 1;
|
|
unsigned char autRollback : 1;
|
|
unsigned char manualRollback : 1;
|
|
unsigned char servAffectDuringUpg : 1;
|
|
unsigned char deferActivation : 1;
|
|
unsigned char ipmcDegradedDurinUpg: 1;
|
|
unsigned char autRollbackOverride : 1;
|
|
unsigned char fwUpgUndesirable : 1;
|
|
#endif
|
|
}ATTRIBUTE_PACKING bitField;
|
|
}ATTRIBUTE_PACKING GlobalCapabilities;
|
|
unsigned char upgradeTimeout;
|
|
unsigned char selftestTimeout;
|
|
unsigned char rollbackTimeout;
|
|
unsigned char inaccessTimeout;
|
|
struct HpmfwupgComponentBitMask componentsPresent;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetTargetUpgCapabilitiesCtx
|
|
{
|
|
struct HpmfwupgGetTargetUpgCapabilitiesReq req;
|
|
struct HpmfwupgGetTargetUpgCapabilitiesResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
/*
|
|
* COMPONENT PROPERTIES DEFINITIONS
|
|
*/
|
|
|
|
typedef enum eHpmfwupgCompPropertiesSelect
|
|
{
|
|
HPMFWUPG_COMP_GEN_PROPERTIES = 0,
|
|
HPMFWUPG_COMP_CURRENT_VERSION,
|
|
HPMFWUPG_COMP_DESCRIPTION_STRING,
|
|
HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION,
|
|
HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION,
|
|
HPMFWUPG_COMP_RESERVED,
|
|
HPMFWUPG_COMP_OEM_PROPERTIES = 192
|
|
} tHpmfwupgCompPropertiesSelect;
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetComponentPropertiesReq
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char componentId;
|
|
unsigned char selector;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetGeneralPropResp
|
|
{
|
|
unsigned char picmgId;
|
|
union
|
|
{
|
|
unsigned char byte;
|
|
struct
|
|
{
|
|
#if WORDS_BIGENDIAN
|
|
unsigned char reserved : 2;
|
|
unsigned char payloadColdReset : 1;
|
|
unsigned char deferredActivation : 1;
|
|
unsigned char comparisonSupport : 1;
|
|
unsigned char preparationSupport : 1;
|
|
unsigned char rollbackBackup : 2;
|
|
#else
|
|
unsigned char rollbackBackup : 2;
|
|
unsigned char preparationSupport : 1;
|
|
unsigned char comparisonSupport : 1;
|
|
unsigned char deferredActivation : 1;
|
|
unsigned char payloadColdReset : 1;
|
|
unsigned char reserved : 2;
|
|
#endif
|
|
}ATTRIBUTE_PACKING bitfield;
|
|
}ATTRIBUTE_PACKING GeneralCompProperties;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetCurrentVersionResp
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char currentVersion[HPMFWUPG_VERSION_SIZE];
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetDescStringResp
|
|
{
|
|
unsigned char picmgId;
|
|
char descString[HPMFWUPG_DESC_STRING_LENGTH];
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetRollbackFwVersionResp
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char rollbackFwVersion[HPMFWUPG_VERSION_SIZE];
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetDeferredFwVersionResp
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char deferredFwVersion[HPMFWUPG_VERSION_SIZE];
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
/*
|
|
* GetComponentProperties - OEM properties (192)
|
|
*/
|
|
#define HPMFWUPG_OEM_LENGTH 4
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetOemProperties
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char oemRspData[HPMFWUPG_OEM_LENGTH];
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetComponentPropertiesResp
|
|
{
|
|
union
|
|
{
|
|
struct HpmfwupgGetGeneralPropResp generalPropResp;
|
|
struct HpmfwupgGetCurrentVersionResp currentVersionResp;
|
|
struct HpmfwupgGetDescStringResp descStringResp;
|
|
struct HpmfwupgGetRollbackFwVersionResp rollbackFwVersionResp;
|
|
struct HpmfwupgGetDeferredFwVersionResp deferredFwVersionResp;
|
|
struct HpmfwupgGetOemProperties oemProperties;
|
|
}ATTRIBUTE_PACKING Response;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetComponentPropertiesCtx
|
|
{
|
|
struct HpmfwupgGetComponentPropertiesReq req;
|
|
struct HpmfwupgGetComponentPropertiesResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
|
|
/*
|
|
* ABORT UPGRADE DEFINITIONS
|
|
*/
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgAbortUpgradeReq
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgAbortUpgradeResp
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgAbortUpgradeCtx
|
|
{
|
|
struct HpmfwupgAbortUpgradeReq req;
|
|
struct HpmfwupgAbortUpgradeResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
/*
|
|
* UPGRADE ACTIONS DEFINITIONS
|
|
*/
|
|
typedef enum eHpmfwupgUpgradeAction
|
|
{
|
|
HPMFWUPG_UPGRADE_ACTION_BACKUP = 0,
|
|
HPMFWUPG_UPGRADE_ACTION_PREPARE,
|
|
HPMFWUPG_UPGRADE_ACTION_UPGRADE,
|
|
HPMFWUPG_UPGRADE_ACTION_COMPARE,
|
|
HPMFWUPG_UPGRADE_ACTION_INVALID = 0xff
|
|
} tHpmfwupgUpgradeAction;
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgInitiateUpgradeActionReq
|
|
{
|
|
unsigned char picmgId;
|
|
struct HpmfwupgComponentBitMask componentsMask;
|
|
unsigned char upgradeAction;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgInitiateUpgradeActionResp
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgInitiateUpgradeActionCtx
|
|
{
|
|
struct HpmfwupgInitiateUpgradeActionReq req;
|
|
struct HpmfwupgInitiateUpgradeActionResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
/*
|
|
* UPLOAD FIRMWARE BLOCK DEFINITIONS
|
|
*/
|
|
|
|
#define HPMFWUPG_SEND_DATA_COUNT_MAX 256
|
|
#define HPMFWUPG_SEND_DATA_COUNT_KCS 30
|
|
#define HPMFWUPG_SEND_DATA_COUNT_LAN 25
|
|
#define HPMFWUPG_SEND_DATA_COUNT_IPMB 26
|
|
#define HPMFWUPG_SEND_DATA_COUNT_IPMBL 26
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgUploadFirmwareBlockReq
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char blockNumber;
|
|
unsigned char data[HPMFWUPG_SEND_DATA_COUNT_MAX];
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgUploadFirmwareBlockResp
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgUploadFirmwareBlockCtx
|
|
{
|
|
struct HpmfwupgUploadFirmwareBlockReq req;
|
|
struct HpmfwupgUploadFirmwareBlockResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
|
|
/*
|
|
* FINISH FIRMWARE UPLOAD DEFINITIONS
|
|
*/
|
|
|
|
#define HPMFWUPG_IMAGE_SIZE_BYTE_COUNT 4
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgFinishFirmwareUploadReq
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char componentId;
|
|
unsigned char imageLength[HPMFWUPG_IMAGE_SIZE_BYTE_COUNT];
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgFinishFirmwareUploadResp
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgFinishFirmwareUploadCtx
|
|
{
|
|
struct HpmfwupgFinishFirmwareUploadReq req;
|
|
struct HpmfwupgFinishFirmwareUploadResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
/*
|
|
* ACTIVATE FW DEFINITIONS
|
|
*/
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgActivateFirmwareReq
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char rollback_override;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgActivateFirmwareResp
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgActivateFirmwareCtx
|
|
{
|
|
struct HpmfwupgActivateFirmwareReq req;
|
|
struct HpmfwupgActivateFirmwareResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
|
|
/*
|
|
* GET UPGRADE STATUS DEFINITIONS
|
|
*/
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetUpgradeStatusReq
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetUpgradeStatusResp
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char cmdInProcess;
|
|
unsigned char lastCmdCompCode;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgGetUpgradeStatusCtx
|
|
{
|
|
struct HpmfwupgGetUpgradeStatusReq req;
|
|
struct HpmfwupgGetUpgradeStatusResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
/*
|
|
* MANUAL FW ROLLBACK DEFINITIONS
|
|
*/
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgManualFirmwareRollbackReq
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgManualFirmwareRollbackResp
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
struct HpmfwupgManualFirmwareRollbackCtx
|
|
{
|
|
struct HpmfwupgManualFirmwareRollbackReq req;
|
|
struct HpmfwupgManualFirmwareRollbackResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
/*
|
|
* QUERY ROLLBACK STATUS DEFINITIONS
|
|
*/
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgQueryRollbackStatusReq
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgQueryRollbackStatusResp
|
|
{
|
|
unsigned char picmgId;
|
|
struct HpmfwupgComponentBitMask rollbackComp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgQueryRollbackStatusCtx
|
|
{
|
|
struct HpmfwupgQueryRollbackStatusReq req;
|
|
struct HpmfwupgQueryRollbackStatusResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
/*
|
|
* QUERY SELF TEST RESULT DEFINITIONS
|
|
*/
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgQuerySelftestResultReq
|
|
{
|
|
unsigned char picmgId;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgQuerySelftestResultResp
|
|
{
|
|
unsigned char picmgId;
|
|
unsigned char result1;
|
|
unsigned char result2;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(1)
|
|
#endif
|
|
struct HpmfwupgQuerySelftestResultCtx
|
|
{
|
|
struct HpmfwupgQuerySelftestResultReq req;
|
|
struct HpmfwupgQuerySelftestResultResp resp;
|
|
} ATTRIBUTE_PACKING;
|
|
#ifdef HAVE_PRAGMA_PACK
|
|
#pragma pack(0)
|
|
#endif
|
|
/*
|
|
* HPM.1 IMAGE DEFINITIONS
|
|
*/
|
|
|
|
#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 deferredMajor;
|
|
unsigned char deferredMinor;
|
|
unsigned char deferredAux[4];
|
|
unsigned char imageMajor;
|
|
unsigned char imageMinor;
|
|
unsigned char imageAux[4];
|
|
unsigned char coldResetRequired;
|
|
unsigned char rollbackSupported;
|
|
char descString[15];
|
|
}VERSIONINFO, *PVERSIONINFO;
|
|
|
|
VERSIONINFO gVersionInfo[HPMFWUPG_COMPONENT_ID_MAX];
|
|
|
|
#define TARGET_VER (0x01)
|
|
#define ROLLBACK_VER (0x02)
|
|
#define IMAGE_VER (0x04)
|
|
|
|
|
|
|
|
|
|
static int HpmfwupgUpgrade(struct ipmi_intf *intf, char* imageFilename, int activate, int,int);
|
|
static int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
static int HpmfwupgPreparationStage( struct ipmi_intf *intf,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx, int option);
|
|
static int HpmfwupgUpgradeStage ( struct ipmi_intf *intf,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx, int compToUpload ,int option);
|
|
static int HpmfwupgActivationStage(struct ipmi_intf *intf,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
static int HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf,
|
|
struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx);
|
|
static int HpmfwupgGetComponentProperties(struct ipmi_intf *intf,
|
|
struct HpmfwupgGetComponentPropertiesCtx* pCtx);
|
|
static int HpmfwupgQuerySelftestResult(struct ipmi_intf *intf,
|
|
struct HpmfwupgQuerySelftestResultCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
static int HpmfwupgQueryRollbackStatus(struct ipmi_intf *intf,
|
|
struct HpmfwupgQueryRollbackStatusCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
static int HpmfwupgAbortUpgrade(struct ipmi_intf *intf,
|
|
struct HpmfwupgAbortUpgradeCtx* pCtx);
|
|
static int HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf,
|
|
struct HpmfwupgInitiateUpgradeActionCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
static int HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf,
|
|
struct HpmfwupgUploadFirmwareBlockCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx, int count ,
|
|
unsigned int *pOffset, unsigned int *blockLen);
|
|
static int HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf,
|
|
struct HpmfwupgFinishFirmwareUploadCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
static int HpmfwupgActivateFirmware(struct ipmi_intf *intf,
|
|
struct HpmfwupgActivateFirmwareCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
static int HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf, struct HpmfwupgGetUpgradeStatusCtx* pCtxstruct, struct HpmfwupgUpgradeCtx* pFwupgCtx, int silent);
|
|
static int HpmfwupgManualFirmwareRollback(struct ipmi_intf *intf,
|
|
struct HpmfwupgManualFirmwareRollbackCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
static void HpmfwupgPrintUsage(void);
|
|
static unsigned char HpmfwupgCalculateChecksum(unsigned char* pData, unsigned int length);
|
|
static int HpmfwupgGetDeviceId(struct ipmi_intf *intf, struct ipm_devid_rsp* pGetDevId);
|
|
static int HpmfwupgGetBufferFromFile(char* imageFilename, struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
static int HpmfwupgWaitLongDurationCmd(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
|
|
static struct ipmi_rs * HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx);
|
|
|
|
|
|
static int HpmFwupgActionUploadFirmware
|
|
(
|
|
struct HpmfwupgComponentBitMask components,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx,
|
|
unsigned char** pImagePtr,
|
|
int componentToUpload,
|
|
struct ipmi_intf *intf,
|
|
int option,
|
|
int* pFlagColdReset
|
|
);
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function Name: HpmGetuserInput
|
|
*
|
|
* Description: This function gets input from user and returns TRUE if its Yes
|
|
* or FALSE if its No
|
|
*
|
|
*****************************************************************************/
|
|
int HpmGetUserInput(char *str)
|
|
{
|
|
char userInput[2];
|
|
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(void)
|
|
{
|
|
printf("\n");
|
|
HpmDisplayLine("-",79 );
|
|
printf(
|
|
"|ID | Name | Versions | %% |\n");
|
|
printf(
|
|
"| | | Active | Backup | File | |\n");
|
|
printf(
|
|
"|----|-------------|-----------------|-----------------|-----------------|----|\n");
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function Name: HpmDisplayUpgrade
|
|
*
|
|
* Description: This function displays the progress of the upgrade it prints the "."
|
|
* every 5% of its completion.
|
|
*
|
|
*****************************************************************************/
|
|
void HpmDisplayUpgrade( int skip, unsigned int totalSent,
|
|
unsigned int displayFWLength,time_t timeElapsed)
|
|
{
|
|
int percent;
|
|
static int old_percent=1;
|
|
if (skip)
|
|
{
|
|
printf("Skip|\n");
|
|
return;
|
|
}
|
|
fflush(stdout);
|
|
|
|
percent = ((float)totalSent/displayFWLength)*100;
|
|
if (percent != old_percent)
|
|
{
|
|
if ( percent == 0 ) printf(" 0%%|");
|
|
else if (percent == 100) printf("\b\b\b\b\b100%%|\n");
|
|
else printf("\b\b\b\b\b%3d%%|", percent);
|
|
old_percent = percent;
|
|
}
|
|
|
|
if (totalSent== displayFWLength)
|
|
{
|
|
/* Display the time taken to complete the upgrade */
|
|
printf(
|
|
"| |Upload Time: %02ld:%02ld | Image Size: %7d bytes |\n",
|
|
timeElapsed/60,timeElapsed%60,totalSent);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function Name: HpmDisplayVersionHeader
|
|
*
|
|
* Description: This function displays the information about version header
|
|
*
|
|
*****************************************************************************/
|
|
void HpmDisplayVersionHeader(int mode)
|
|
{
|
|
if ( mode & IMAGE_VER)
|
|
{
|
|
HpmDisplayLine("-",74 );
|
|
printf(
|
|
"|ID | Name | Versions |\n");
|
|
printf(
|
|
"| | | Active | Backup | File |\n");
|
|
HpmDisplayLine("-",74 );
|
|
}
|
|
else
|
|
{
|
|
HpmDisplayLine("-",74 );
|
|
printf(
|
|
"|ID | Name | Versions |\n");
|
|
printf(
|
|
"| | | Active | Backup | Deferred |\n");
|
|
HpmDisplayLine("-",74 );
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function Name: HpmDisplayVersion
|
|
*
|
|
* Description: This function displays the version of the image and target
|
|
*
|
|
*****************************************************************************/
|
|
void HpmDisplayVersion(int mode, VERSIONINFO *pVersion, int upgradable)
|
|
{
|
|
char descString[16];
|
|
|
|
memset(&descString,0x00,sizeof(descString));
|
|
/*
|
|
* Added this to ensure that even if the description string
|
|
* is more than required it does not give problem in displaying it
|
|
*/
|
|
strncpy(descString,pVersion->descString,13);
|
|
|
|
/*
|
|
* If the cold reset is required then we can display * on it
|
|
* so that user is aware that he needs to do payload power
|
|
* cycle after upgrade
|
|
*/
|
|
printf("|%c%c%2d|%-13s|",
|
|
pVersion->coldResetRequired?'*':' ',
|
|
upgradable ? '^': ' ',
|
|
pVersion->componentId,descString);
|
|
|
|
if (mode & TARGET_VER)
|
|
{
|
|
if ((pVersion->targetMajor == 0xFF ||
|
|
(pVersion->targetMajor == 0x7F)) &&
|
|
pVersion->targetMinor == 0xFF)
|
|
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->rollbackMajor == 0x7F)) &&
|
|
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->imageMajor == 0x7F)) &&
|
|
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]);
|
|
}
|
|
else
|
|
{
|
|
if ((pVersion->deferredMajor == 0xFF ||
|
|
(pVersion->deferredMajor == 0x7F)) &&
|
|
pVersion->deferredMinor == 0xFF)
|
|
printf(" ---.-- -------- |");
|
|
else
|
|
printf(" %3d.%02x %02X%02X%02X%02X |",
|
|
pVersion->deferredMajor,
|
|
pVersion->deferredMinor,
|
|
pVersion->deferredAux[0],
|
|
pVersion->deferredAux[1],
|
|
pVersion->deferredAux[2],
|
|
pVersion->deferredAux[3]);
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function Name: HpmfwupgTargerCheck
|
|
*
|
|
* Description: This function gets the target information and displays it on the
|
|
* screen
|
|
*
|
|
*****************************************************************************/
|
|
int HpmfwupgTargetCheck(struct ipmi_intf * intf, int option)
|
|
{
|
|
struct HpmfwupgUpgradeCtx fwupgCtx;
|
|
struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
int componentId = 0;
|
|
int flagColdReset = FALSE;
|
|
struct ipm_devid_rsp devIdrsp;
|
|
struct HpmfwupgGetComponentPropertiesCtx getCompProp;
|
|
int mode = 0;
|
|
|
|
|
|
rc = HpmfwupgGetDeviceId(intf, &devIdrsp);
|
|
|
|
if (rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
lprintf(LOG_NOTICE,"Verify whether the Target board is present \n");
|
|
return HPMFWUPG_ERROR;
|
|
}
|
|
|
|
rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd);
|
|
if (rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
/*
|
|
* That indicates the target is not responding to the command
|
|
* May be that there is no HPM support
|
|
*/
|
|
lprintf(LOG_NOTICE,"Board might not be supporting the HPM.1 Standards\n");
|
|
return rc;
|
|
}
|
|
if (option & VIEW_MODE)
|
|
{
|
|
lprintf(LOG_NOTICE,"-------Target Information-------");
|
|
lprintf(LOG_NOTICE,"Device Id : 0x%x", devIdrsp.device_id);
|
|
lprintf(LOG_NOTICE,"Device Revision : 0x%x", devIdrsp.device_revision);
|
|
lprintf(LOG_NOTICE,"Product Id : 0x%04x", buf2short(devIdrsp.product_id));
|
|
lprintf(LOG_NOTICE,"Manufacturer Id : 0x%04x (%s)\n\n", buf2short(devIdrsp.manufacturer_id),
|
|
val2str(buf2short(devIdrsp.manufacturer_id),ipmi_oem_info));
|
|
HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER);
|
|
}
|
|
|
|
for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX;
|
|
componentId++ )
|
|
{
|
|
/* If the component is supported */
|
|
if ( ((1 << componentId) & targetCapCmd.resp.componentsPresent.ComponentBits.byte) )
|
|
{
|
|
memset((PVERSIONINFO)&gVersionInfo[componentId],0x00,sizeof(VERSIONINFO));
|
|
|
|
getCompProp.req.componentId = componentId;
|
|
getCompProp.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES;
|
|
rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
if (rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
lprintf(LOG_NOTICE,"Get CompGenProp Failed for component Id %d\n",componentId);
|
|
return rc;
|
|
}
|
|
|
|
gVersionInfo[componentId].rollbackSupported = getCompProp.resp.Response.
|
|
generalPropResp.GeneralCompProperties.bitfield.rollbackBackup;
|
|
gVersionInfo[componentId].coldResetRequired = getCompProp.resp.Response.
|
|
generalPropResp.GeneralCompProperties.bitfield.payloadColdReset;
|
|
|
|
getCompProp.req.selector = HPMFWUPG_COMP_DESCRIPTION_STRING;
|
|
rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
if (rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
lprintf(LOG_NOTICE,"Get CompDescString Failed for component Id %d\n",componentId);
|
|
return rc;
|
|
}
|
|
strcpy((char *)&gVersionInfo[componentId].descString,
|
|
getCompProp.resp.Response.descStringResp.descString);
|
|
|
|
getCompProp.req.selector = HPMFWUPG_COMP_CURRENT_VERSION;
|
|
rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
if (rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
lprintf(LOG_NOTICE,"Get CompCurrentVersion Failed for component Id %d\n",componentId);
|
|
return rc;
|
|
}
|
|
|
|
gVersionInfo[componentId].componentId = componentId;
|
|
gVersionInfo[componentId].targetMajor = getCompProp.resp.Response.
|
|
currentVersionResp.currentVersion[0];
|
|
gVersionInfo[componentId].targetMinor = getCompProp.resp.Response.
|
|
currentVersionResp.currentVersion[1];
|
|
gVersionInfo[componentId].targetAux[0] = getCompProp.resp.Response.
|
|
currentVersionResp.currentVersion[2];
|
|
gVersionInfo[componentId].targetAux[1] = getCompProp.resp.Response.
|
|
currentVersionResp.currentVersion[3];
|
|
gVersionInfo[componentId].targetAux[2] = getCompProp.resp.Response.
|
|
currentVersionResp.currentVersion[4];
|
|
gVersionInfo[componentId].targetAux[3] = getCompProp.resp.Response.
|
|
currentVersionResp.currentVersion[5];
|
|
mode = TARGET_VER;
|
|
|
|
if (gVersionInfo[componentId].rollbackSupported)
|
|
{
|
|
getCompProp.req.selector = HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION;
|
|
rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
if (rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
lprintf(LOG_NOTICE,"Get CompRollbackVersion Failed for component Id %d\n",componentId);
|
|
} else {
|
|
gVersionInfo[componentId].rollbackMajor = getCompProp.resp
|
|
.Response.rollbackFwVersionResp.rollbackFwVersion[0];
|
|
gVersionInfo[componentId].rollbackMinor = getCompProp.resp
|
|
.Response.rollbackFwVersionResp.rollbackFwVersion[1];
|
|
gVersionInfo[componentId].rollbackAux[0] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[2];
|
|
gVersionInfo[componentId].rollbackAux[1] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[3];
|
|
gVersionInfo[componentId].rollbackAux[2] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[4];
|
|
gVersionInfo[componentId].rollbackAux[3] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[5];
|
|
}
|
|
|
|
getCompProp.req.selector = HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION;
|
|
rc = HpmfwupgGetComponentProperties(intf, &getCompProp);
|
|
if (rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
lprintf(LOG_NOTICE,"Get CompRollbackVersion Failed for component Id %d\n",componentId);
|
|
} else {
|
|
gVersionInfo[componentId].deferredMajor = getCompProp.resp
|
|
.Response.deferredFwVersionResp.deferredFwVersion[0];
|
|
gVersionInfo[componentId].deferredMinor = getCompProp.resp
|
|
.Response.deferredFwVersionResp.deferredFwVersion[1];
|
|
gVersionInfo[componentId].deferredAux[0] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[2];
|
|
gVersionInfo[componentId].deferredAux[1] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[3];
|
|
gVersionInfo[componentId].deferredAux[2] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[4];
|
|
gVersionInfo[componentId].deferredAux[3] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[5];
|
|
}
|
|
mode |= ROLLBACK_VER;
|
|
}
|
|
else
|
|
{
|
|
gVersionInfo[componentId].rollbackMajor = 0xff;
|
|
gVersionInfo[componentId].rollbackMinor = 0xff;
|
|
gVersionInfo[componentId].rollbackAux[0] = 0xff;
|
|
gVersionInfo[componentId].rollbackAux[1] = 0xff;
|
|
gVersionInfo[componentId].rollbackAux[2] = 0xff;
|
|
gVersionInfo[componentId].rollbackAux[3] = 0xff;
|
|
|
|
gVersionInfo[componentId].deferredMajor = 0xff;
|
|
gVersionInfo[componentId].deferredMinor = 0xff;
|
|
gVersionInfo[componentId].deferredAux[0] = 0xff;
|
|
gVersionInfo[componentId].deferredAux[1] = 0xff;
|
|
gVersionInfo[componentId].deferredAux[2] = 0xff;
|
|
gVersionInfo[componentId].deferredAux[3] = 0xff;
|
|
}
|
|
|
|
if (gVersionInfo[componentId].coldResetRequired)
|
|
{
|
|
/*
|
|
* If any of the component indicates that the Payload Cold reset is required
|
|
* then set the flag
|
|
*/
|
|
flagColdReset = TRUE;
|
|
}
|
|
if (option & VIEW_MODE)
|
|
{
|
|
HpmDisplayVersion(mode,&gVersionInfo[componentId], 0);
|
|
printf("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (option & VIEW_MODE)
|
|
{
|
|
HpmDisplayLine("-",74 );
|
|
fflush(stdout);
|
|
lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset");
|
|
printf("\n\n");
|
|
}
|
|
return HPMFWUPG_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Function Name: HpmfwupgUpgrade
|
|
*
|
|
* Description: This function performs the HPM.1 firmware upgrade procedure as
|
|
* defined the IPM Controller Firmware Upgrade Specification
|
|
* version 1.0
|
|
*
|
|
*****************************************************************************/
|
|
int HpmfwupgUpgrade(struct ipmi_intf *intf, char* imageFilename,
|
|
int activate,int componentToUpload, int option)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct HpmfwupgImageHeader imageHeader;
|
|
struct HpmfwupgUpgradeCtx fwupgCtx;
|
|
|
|
/*
|
|
* GET IMAGE BUFFER FROM FILE
|
|
*/
|
|
|
|
rc = HpmfwupgGetBufferFromFile(imageFilename, &fwupgCtx);
|
|
|
|
/*
|
|
* VALIDATE IMAGE INTEGRITY
|
|
*/
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
printf("Validating firmware image integrity...");
|
|
fflush(stdout);
|
|
rc = HpmfwupgValidateImageIntegrity(&fwupgCtx);
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
printf("OK\n");
|
|
fflush(stdout);
|
|
}
|
|
else
|
|
{
|
|
free(fwupgCtx.pImageData);
|
|
fwupgCtx.pImageData = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* PREPARATION STAGE
|
|
*/
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
printf("Performing preparation stage...");
|
|
fflush(stdout);
|
|
rc = HpmfwupgPreparationStage(intf, &fwupgCtx, option);
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
printf("OK\n");
|
|
fflush(stdout);
|
|
}
|
|
else
|
|
{
|
|
free(fwupgCtx.pImageData);
|
|
fwupgCtx.pImageData = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* UPGRADE STAGE
|
|
*/
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
if (option & VIEW_MODE)
|
|
{
|
|
lprintf(LOG_NOTICE,"\nComparing Target & Image File version");
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"\nPerforming upgrade stage:");
|
|
}
|
|
if (option & VIEW_MODE)
|
|
{
|
|
rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,componentToUpload,VIEW_MODE);
|
|
}
|
|
else
|
|
{
|
|
rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,componentToUpload,option);
|
|
if (rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
if( verbose ) {
|
|
printf("Component update mask : 0x%02x\n", fwupgCtx.compUpdateMask.ComponentBits.byte);
|
|
}
|
|
rc = HpmfwupgUpgradeStage(intf, &fwupgCtx,componentToUpload,option);
|
|
}
|
|
}
|
|
|
|
if ( rc != HPMFWUPG_SUCCESS )
|
|
{
|
|
free(fwupgCtx.pImageData);
|
|
fwupgCtx.pImageData = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ACTIVATION STAGE
|
|
*/
|
|
if ( rc == HPMFWUPG_SUCCESS && activate )
|
|
{
|
|
lprintf(LOG_NOTICE,"Performing activation stage: ");
|
|
rc = HpmfwupgActivationStage(intf, &fwupgCtx);
|
|
if ( rc != HPMFWUPG_SUCCESS )
|
|
{
|
|
free(fwupgCtx.pImageData);
|
|
fwupgCtx.pImageData = NULL;
|
|
}
|
|
}
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
if (option & VIEW_MODE)
|
|
{
|
|
// Dont display anything here in case we are just viewing it
|
|
lprintf(LOG_NOTICE," ");
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"\nFirmware upgrade procedure successful\n");
|
|
}
|
|
free(fwupgCtx.pImageData);
|
|
fwupgCtx.pImageData = NULL;
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Firmware upgrade procedure failed\n");
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function Name: HpmfwupgValidateImageIntegrity
|
|
*
|
|
* Description: This function validates a HPM.1 firmware image file as defined
|
|
* in section 4 of the IPM Controller Firmware Upgrade
|
|
* Specification version 1.0
|
|
*
|
|
*****************************************************************************/
|
|
int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
|
|
pFwupgCtx->pImageData;
|
|
md5_state_t ctx;
|
|
static unsigned char md[HPMFWUPG_MD5_SIGNATURE_LENGTH];
|
|
unsigned char* pMd5Sig = pFwupgCtx->pImageData +
|
|
(pFwupgCtx->imageSize -
|
|
HPMFWUPG_MD5_SIGNATURE_LENGTH);
|
|
|
|
/* Validate MD5 checksum */
|
|
memset(md, 0, HPMFWUPG_MD5_SIGNATURE_LENGTH);
|
|
memset(&ctx, 0, sizeof(md5_state_t));
|
|
md5_init(&ctx);
|
|
md5_append(&ctx, pFwupgCtx->pImageData, pFwupgCtx->imageSize -
|
|
HPMFWUPG_MD5_SIGNATURE_LENGTH);
|
|
md5_finish(&ctx, md);
|
|
if ( memcmp(md, pMd5Sig,HPMFWUPG_MD5_SIGNATURE_LENGTH) != 0 )
|
|
{
|
|
lprintf(LOG_NOTICE,"\n Invalid MD5 signature");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
/* Validate Header signature */
|
|
if( strncmp(pImageHeader->signature, HPMFWUPG_IMAGE_SIGNATURE, HPMFWUPG_HEADER_SIGNATURE_LENGTH) == 0 )
|
|
{
|
|
/* Validate Header image format version */
|
|
if ( pImageHeader->formatVersion == HPMFWUPG_IMAGE_HEADER_VERSION )
|
|
{
|
|
/* Validate header checksum */
|
|
if ( HpmfwupgCalculateChecksum((unsigned char*)pImageHeader,
|
|
sizeof(struct HpmfwupgImageHeader) +
|
|
pImageHeader->oemDataLength +
|
|
sizeof(unsigned char)/*checksum*/) != 0 )
|
|
{
|
|
lprintf(LOG_NOTICE,"\n Invalid header checksum");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"\n Unrecognized image version");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"\n Invalid image signature");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function Name: HpmfwupgPreparationStage
|
|
*
|
|
* Description: This function the preperation stage of a firmware upgrade
|
|
* procedure as defined in section 3.2 of the IPM Controller
|
|
* Firmware Upgrade Specification version 1.0
|
|
*
|
|
*****************************************************************************/
|
|
int HpmfwupgPreparationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx, int option)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
|
|
pFwupgCtx->pImageData;
|
|
|
|
/* Get device ID */
|
|
rc = HpmfwupgGetDeviceId(intf, &pFwupgCtx->devId);
|
|
|
|
/* Match current IPMC IDs with upgrade image */
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
/* Validate device ID */
|
|
if ( pImageHeader->deviceId == pFwupgCtx->devId.device_id )
|
|
{
|
|
/* Validate product ID */
|
|
if ( memcmp(pImageHeader->prodId, pFwupgCtx->devId.product_id, HPMFWUPG_PRODUCT_ID_LENGTH ) == 0 )
|
|
{
|
|
/* Validate man ID */
|
|
if ( memcmp(pImageHeader->manId, pFwupgCtx->devId.manufacturer_id,
|
|
HPMFWUPG_MANUFATURER_ID_LENGTH ) != 0 )
|
|
{
|
|
lprintf(LOG_NOTICE,"\n Invalid image file for manufacturer %u",
|
|
buf2short(pFwupgCtx->devId.manufacturer_id));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"\n Invalid image file for product %u",
|
|
buf2short(pFwupgCtx->devId.product_id));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"\n Invalid device ID %x", pFwupgCtx->devId.device_id);
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
if (rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
/*
|
|
* Giving one more chance to user to check whether its OK to continue even if the
|
|
* product ID does not match. This is helpful as sometimes we just want to update
|
|
* and dont care whether we have a different product Id. If the user says NO then
|
|
* we need to just bail out from here
|
|
*/
|
|
if ( (option & FORCE_MODE) || (option & VIEW_MODE) )
|
|
{
|
|
printf("\n Image Information");
|
|
printf("\n Device Id : 0x%x",pImageHeader->deviceId);
|
|
printf("\n Prod Id : 0x%02x%02x",pImageHeader->prodId[1], pImageHeader->prodId[0]);
|
|
printf("\n Manuf Id : 0x%02x%02x%02x",pImageHeader->manId[2],
|
|
pImageHeader->manId[1],pImageHeader->manId[0]);
|
|
printf("\n Board Information");
|
|
printf("\n Device Id : 0x%x", pFwupgCtx->devId.device_id);
|
|
printf("\n Prod Id : 0x%02x%02x",pFwupgCtx->devId.product_id[1], pFwupgCtx->devId.product_id[0]);
|
|
printf("\n Manuf Id : 0x%02x%02x%02x",pFwupgCtx->devId.manufacturer_id[2],
|
|
pFwupgCtx->devId.manufacturer_id[1],pFwupgCtx->devId.manufacturer_id[0]);
|
|
if (HpmGetUserInput("\n Continue ignoring DeviceID/ProductID/ManufacturingID (Y/N) :"))
|
|
rc = HPMFWUPG_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
printf("\n\n Use \"force\" option for copying all the components\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Validate earliest compatible revision */
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
/* Validate major & minor revision */
|
|
if ( pImageHeader->compRevision[0] < pFwupgCtx->devId.fw_rev1 )
|
|
{
|
|
/* Do nothing, upgrade accepted */
|
|
}
|
|
else if ( pImageHeader->compRevision[0] == pFwupgCtx->devId.fw_rev1 )
|
|
{
|
|
/* Must validate minor revision */
|
|
if ( pImageHeader->compRevision[1] > pFwupgCtx->devId.fw_rev2 )
|
|
{
|
|
/* Version not compatible for upgrade */
|
|
lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]);
|
|
lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]);
|
|
lprintf(LOG_NOTICE," Not compatible with ");
|
|
lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1);
|
|
lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2);
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Version not compatible for upgrade */
|
|
lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]);
|
|
lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]);
|
|
lprintf(LOG_NOTICE," Not compatible with ");
|
|
lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1);
|
|
lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2);
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
if (rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
/* Confirming it once again */
|
|
if ( (option & FORCE_MODE) || (option & VIEW_MODE) )
|
|
{
|
|
if( HpmGetUserInput("\n Continue IGNORING Earliest compatibility (Y/N) :"))
|
|
rc = HPMFWUPG_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Get target upgrade capabilities */
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
|
|
rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd);
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
/* Copy response to context */
|
|
memcpy(&pFwupgCtx->targetCap,
|
|
&targetCapCmd.resp,
|
|
sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp));
|
|
|
|
if (option & VIEW_MODE)
|
|
{
|
|
return rc;
|
|
}
|
|
else
|
|
{
|
|
/* Make sure all component IDs defined in the upgrade
|
|
image are supported by the IPMC */
|
|
if ( (pImageHeader->components.ComponentBits.byte &
|
|
pFwupgCtx->targetCap.componentsPresent.ComponentBits.byte ) !=
|
|
pImageHeader->components.ComponentBits.byte )
|
|
{
|
|
lprintf(LOG_NOTICE,"\n Some components present in the image file are not supported by the IPMC");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
/* Make sure the upgrade is desirable rigth now */
|
|
if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.fwUpgUndesirable == 1 )
|
|
{
|
|
lprintf(LOG_NOTICE,"\n Upgrade undesirable at this moment");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
/* Get confimation from the user if he wants to continue when service
|
|
affected during upgrade */
|
|
if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.servAffectDuringUpg == 1 ||
|
|
pImageHeader->imageCapabilities.bitField.servAffected == 1 )
|
|
{
|
|
if (HpmGetUserInput("\nServices may be affected during upgrade. Do you wish to continue? y/n "))
|
|
{
|
|
rc = HPMFWUPG_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Get the general properties of each component present in image */
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
int componentId;
|
|
|
|
for ( componentId = HPMFWUPG_COMPONENT_ID_0;
|
|
componentId < HPMFWUPG_COMPONENT_ID_MAX;
|
|
componentId++ )
|
|
{
|
|
/* Reset component properties */
|
|
memset(&pFwupgCtx->genCompProp[componentId], 0, sizeof (struct HpmfwupgGetGeneralPropResp));
|
|
|
|
if ( (1 << componentId & pImageHeader->components.ComponentBits.byte) )
|
|
{
|
|
struct HpmfwupgGetComponentPropertiesCtx getCompPropCmd;
|
|
|
|
/* Get general component properties */
|
|
getCompPropCmd.req.componentId = componentId;
|
|
getCompPropCmd.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES;
|
|
|
|
rc = HpmfwupgGetComponentProperties(intf, &getCompPropCmd);
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
/* Copy response to context */
|
|
memcpy(&pFwupgCtx->genCompProp[componentId],
|
|
&getCompPropCmd.resp,
|
|
sizeof(struct HpmfwupgGetGeneralPropResp));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int image_version_upgradable(VERSIONINFO *pVersionInfo)
|
|
{
|
|
/* If the image and active target versions are different, then
|
|
* upgrade */
|
|
if ((pVersionInfo->imageMajor != pVersionInfo->targetMajor) ||
|
|
(pVersionInfo->imageMinor != pVersionInfo->targetMinor) ||
|
|
(pVersionInfo->imageAux[0] != pVersionInfo->targetAux[0]) ||
|
|
(pVersionInfo->imageAux[1] != pVersionInfo->targetAux[1]) ||
|
|
(pVersionInfo->imageAux[2] != pVersionInfo->targetAux[2]) ||
|
|
(pVersionInfo->imageAux[3] != pVersionInfo->targetAux[3]))
|
|
return (1);
|
|
|
|
/* If the image and active target versions are the same and rollback
|
|
* is not supported, then there's nothing to do, skip the upgrade */
|
|
if (!pVersionInfo->rollbackSupported)
|
|
return (0);
|
|
|
|
/* If the image and rollback target versions are different, then
|
|
* go ahead and upgrade */
|
|
if ((pVersionInfo->imageMajor != pVersionInfo->rollbackMajor) ||
|
|
(pVersionInfo->imageMinor != pVersionInfo->rollbackMinor) ||
|
|
(pVersionInfo->imageAux[0] != pVersionInfo->rollbackAux[0]) ||
|
|
(pVersionInfo->imageAux[1] != pVersionInfo->rollbackAux[1]) ||
|
|
(pVersionInfo->imageAux[2] != pVersionInfo->rollbackAux[2]) ||
|
|
(pVersionInfo->imageAux[3] != pVersionInfo->rollbackAux[3]))
|
|
return (1);
|
|
|
|
/* Image and rollback target versions are the same too, skip it */
|
|
return (0);
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function Name: HpmfwupgPreUpgradeCheck
|
|
*
|
|
* Description: This function the pre Upgrade check, this mainly helps in checking
|
|
* which all version upgrade is skippable because the image version
|
|
* is same as target version.
|
|
*
|
|
*****************************************************************************/
|
|
int HpmfwupgPreUpgradeCheck(struct ipmi_intf *intf,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx,
|
|
int componentToUpload, int option)
|
|
{
|
|
unsigned char* pImagePtr;
|
|
struct HpmfwupgActionRecord *pActionRecord;
|
|
int flagColdReset = FALSE;
|
|
struct HpmfwupgImageHeader *pImageHeader;
|
|
|
|
pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData;
|
|
|
|
/* Put pointer after image header */
|
|
pImagePtr = (unsigned char*)
|
|
(pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) +
|
|
pImageHeader->oemDataLength + sizeof(unsigned char)/*chksum*/);
|
|
|
|
if (option & VIEW_MODE) {
|
|
HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER|IMAGE_VER);
|
|
}
|
|
|
|
/* Perform actions defined in the image */
|
|
while (pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize -
|
|
HPMFWUPG_MD5_SIGNATURE_LENGTH)) {
|
|
/* Get action record */
|
|
pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr;
|
|
|
|
/* Validate action record checksum */
|
|
if (HpmfwupgCalculateChecksum((unsigned char*)pActionRecord,
|
|
sizeof(struct HpmfwupgActionRecord)) != 0) {
|
|
lprintf(LOG_NOTICE," Invalid Action record.");
|
|
return HPMFWUPG_ERROR;
|
|
}
|
|
|
|
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;
|
|
unsigned char mode;
|
|
unsigned char componentId;
|
|
unsigned char componentIdByte;
|
|
unsigned int upgrade_comp;
|
|
VERSIONINFO *pVersionInfo;
|
|
struct HpmfwupgGetComponentPropertiesCtx getCompProp;
|
|
|
|
/* Save component ID on which the upload is done */
|
|
componentIdByte = pActionRecord->components.ComponentBits.byte;
|
|
|
|
componentId = 0;
|
|
while ((componentIdByte >>= 1) !=0) {
|
|
componentId++;
|
|
}
|
|
pFwupgCtx->componentId = componentId;
|
|
|
|
pFwImage = (struct HpmfwupgFirmwareImage*)(pImagePtr +
|
|
sizeof(struct HpmfwupgActionRecord));
|
|
|
|
pData = ((unsigned char*)pFwImage +
|
|
sizeof(struct HpmfwupgFirmwareImage));
|
|
|
|
/* Get firmware length */
|
|
firmwareLength = pFwImage->length[0];
|
|
firmwareLength |= (pFwImage->length[1] << 8) & 0xff00;
|
|
firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000;
|
|
firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000;
|
|
|
|
pVersionInfo = &gVersionInfo[componentId];
|
|
|
|
pVersionInfo->imageMajor = pFwImage->version[0];
|
|
pVersionInfo->imageMinor = pFwImage->version[1];
|
|
pVersionInfo->imageAux[0] = pFwImage->version[2];
|
|
pVersionInfo->imageAux[1] = pFwImage->version[3];
|
|
pVersionInfo->imageAux[2] = pFwImage->version[4];
|
|
pVersionInfo->imageAux[3] = pFwImage->version[5];
|
|
|
|
mode = TARGET_VER | IMAGE_VER;
|
|
|
|
if (pVersionInfo->coldResetRequired)
|
|
flagColdReset = TRUE;
|
|
|
|
upgrade_comp = 0;
|
|
if (option & FORCE_MODE_ALL) {
|
|
upgrade_comp = 1;
|
|
}
|
|
else if ((option & FORCE_MODE_COMPONENT) &&
|
|
(componentToUpload == componentId)) {
|
|
upgrade_comp = 1;
|
|
}
|
|
else if (image_version_upgradable(pVersionInfo)) {
|
|
upgrade_comp = 1;
|
|
}
|
|
|
|
if (verbose)
|
|
lprintf(LOG_NOTICE,"%s component %d",
|
|
(upgrade_comp ? "Updating" : "Skipping"),
|
|
componentId);
|
|
|
|
if (upgrade_comp)
|
|
pFwupgCtx->compUpdateMask.ComponentBits.byte |=
|
|
1 << componentId;
|
|
|
|
if (option & VIEW_MODE) {
|
|
if (pVersionInfo->rollbackSupported)
|
|
mode |= ROLLBACK_VER;
|
|
HpmDisplayVersion(mode,pVersionInfo, upgrade_comp);
|
|
printf("\n");
|
|
}
|
|
pImagePtr = pData + firmwareLength;
|
|
}
|
|
break;
|
|
default:
|
|
lprintf(LOG_NOTICE,
|
|
" Invalid Action type. Cannot continue");
|
|
return HPMFWUPG_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (option & VIEW_MODE) {
|
|
HpmDisplayLine("-",74);
|
|
fflush(stdout);
|
|
lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset");
|
|
lprintf(LOG_NOTICE,"(^) Indicates component would be upgraded");
|
|
}
|
|
return HPMFWUPG_SUCCESS;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function Name: HpmfwupgUpgradeStage
|
|
*
|
|
* Description: This function the upgrade stage of a firmware upgrade
|
|
* procedure as defined in section 3.3 of the IPM Controller
|
|
* Firmware Upgrade Specification version 1.0
|
|
*
|
|
*****************************************************************************/
|
|
int HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx,
|
|
int componentToUpload, int option)
|
|
{
|
|
struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
|
|
pFwupgCtx->pImageData;
|
|
struct HpmfwupgActionRecord* pActionRecord;
|
|
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
unsigned char* pImagePtr;
|
|
unsigned int actionsSize;
|
|
int flagColdReset = FALSE;
|
|
time_t start,end;
|
|
|
|
/* Put pointer after image header */
|
|
pImagePtr = (unsigned char*)
|
|
(pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) +
|
|
pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/);
|
|
|
|
/* Deternime actions size */
|
|
actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader);
|
|
|
|
if (option & VERSIONCHECK_MODE || option & FORCE_MODE)
|
|
{
|
|
HpmDisplayUpgradeHeader();
|
|
}
|
|
|
|
/* Perform actions defined in the image */
|
|
while( ( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize -
|
|
HPMFWUPG_MD5_SIGNATURE_LENGTH)) &&
|
|
( rc == HPMFWUPG_SUCCESS) )
|
|
{
|
|
/* Get action record */
|
|
pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr;
|
|
|
|
/* Validate action record checksum */
|
|
if ( HpmfwupgCalculateChecksum((unsigned char*)pActionRecord,
|
|
sizeof(struct HpmfwupgActionRecord)) != 0 )
|
|
{
|
|
lprintf(LOG_NOTICE," Invalid Action record.");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
switch( pActionRecord->actionType )
|
|
{
|
|
case HPMFWUPG_ACTION_BACKUP_COMPONENTS:
|
|
{
|
|
/* Send prepare components command */
|
|
struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd;
|
|
|
|
initUpgActionCmd.req.componentsMask = pFwupgCtx->compUpdateMask;
|
|
/* Action is prepare components */
|
|
initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_BACKUP;
|
|
rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx);
|
|
pImagePtr += sizeof(struct HpmfwupgActionRecord);
|
|
|
|
}
|
|
break;
|
|
case HPMFWUPG_ACTION_PREPARE_COMPONENTS:
|
|
{
|
|
int componentId;
|
|
/* Make sure every components specified by this action
|
|
supports the prepare components */
|
|
|
|
/* Component 'filtering' is done in PreUpdateCheck() and pFwupgCtx is set accordiongly */
|
|
|
|
for ( componentId = HPMFWUPG_COMPONENT_ID_0;
|
|
componentId < HPMFWUPG_COMPONENT_ID_MAX;
|
|
componentId++ )
|
|
{
|
|
if ( (1 << componentId & pFwupgCtx->compUpdateMask.ComponentBits.byte) )
|
|
{
|
|
if ( pFwupgCtx->genCompProp[componentId].GeneralCompProperties.bitfield.preparationSupport == 0 )
|
|
{
|
|
lprintf(LOG_NOTICE," Prepare component not supported by component ID %d", componentId);
|
|
rc = HPMFWUPG_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
if ( pFwupgCtx->compUpdateMask.ComponentBits.byte != 0x00 )
|
|
{
|
|
/* Send prepare components command */
|
|
struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd;
|
|
initUpgActionCmd.req.componentsMask = pFwupgCtx->compUpdateMask;
|
|
/* Action is prepare components */
|
|
initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_PREPARE;
|
|
rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx);
|
|
|
|
}
|
|
pImagePtr += sizeof(struct HpmfwupgActionRecord);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case HPMFWUPG_ACTION_UPLOAD_FIRMWARE:
|
|
/* Upload all firmware blocks */
|
|
rc = HpmFwupgActionUploadFirmware
|
|
(
|
|
pActionRecord->components,
|
|
pFwupgCtx,
|
|
&pImagePtr,
|
|
componentToUpload,
|
|
intf,
|
|
option,
|
|
&flagColdReset
|
|
);
|
|
|
|
break;
|
|
default:
|
|
lprintf(LOG_NOTICE," Invalid Action type. Cannot continue");
|
|
rc = HPMFWUPG_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
HpmDisplayLine("-",79);
|
|
|
|
fflush(stdout);
|
|
lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset");
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int HpmFwupgActionUploadFirmware
|
|
(
|
|
struct HpmfwupgComponentBitMask components,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx,
|
|
unsigned char** pImagePtr,
|
|
int componentToUpload,
|
|
struct ipmi_intf *intf,
|
|
int option,
|
|
int *pFlagColdReset
|
|
)
|
|
{
|
|
struct HpmfwupgFirmwareImage* pFwImage;
|
|
struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd;
|
|
struct HpmfwupgUploadFirmwareBlockCtx uploadCmd;
|
|
struct HpmfwupgFinishFirmwareUploadCtx finishCmd;
|
|
struct HpmfwupgGetComponentPropertiesCtx getCompProp;
|
|
VERSIONINFO *pVersionInfo;
|
|
time_t start,end;
|
|
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
int skip = TRUE;
|
|
unsigned char* pData, *pDataInitial;
|
|
unsigned char count;
|
|
unsigned int totalSent = 0;
|
|
unsigned char bufLength = 0;
|
|
unsigned int firmwareLength = 0;
|
|
|
|
unsigned int displayFWLength = 0;
|
|
unsigned char *pDataTemp;
|
|
unsigned int imageOffset = 0x00;
|
|
unsigned int blockLength = 0x00;
|
|
unsigned int lengthOfBlock = 0x00;
|
|
unsigned int numTxPkts = 0;
|
|
unsigned int numRxPkts = 0;
|
|
unsigned char mode = 0;
|
|
unsigned char componentId = 0x00;
|
|
unsigned char componentIdByte = 0x00;
|
|
|
|
/* Save component ID on which the upload is done */
|
|
componentIdByte = components.ComponentBits.byte;
|
|
while ((componentIdByte>>=1)!=0)
|
|
{
|
|
componentId++;
|
|
}
|
|
pFwupgCtx->componentId = componentId;
|
|
|
|
pVersionInfo = (VERSIONINFO*) &gVersionInfo[componentId];
|
|
|
|
pFwImage = (struct HpmfwupgFirmwareImage*)((*pImagePtr) +
|
|
sizeof(struct HpmfwupgActionRecord));
|
|
|
|
pDataInitial = ((unsigned char*)pFwImage + sizeof(struct HpmfwupgFirmwareImage));
|
|
pData = pDataInitial;
|
|
|
|
/* Get firmware length */
|
|
firmwareLength = pFwImage->length[0];
|
|
firmwareLength |= (pFwImage->length[1] << 8) & 0xff00;
|
|
firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000;
|
|
firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000;
|
|
|
|
mode = TARGET_VER | IMAGE_VER;
|
|
|
|
if (pVersionInfo->rollbackSupported)
|
|
{
|
|
mode |= ROLLBACK_VER;
|
|
}
|
|
|
|
if ((option & DEBUG_MODE))
|
|
{
|
|
printf("\n\n Comp ID : %d [%-20s]\n",pVersionInfo->componentId,pFwImage->desc);
|
|
}
|
|
else
|
|
{
|
|
HpmDisplayVersion(mode,pVersionInfo, 0);
|
|
}
|
|
|
|
if( (1 << componentId) & pFwupgCtx->compUpdateMask.ComponentBits.byte)
|
|
{
|
|
if( verbose ) {
|
|
lprintf(LOG_NOTICE,"Do not skip %d" , componentId);
|
|
}
|
|
skip = FALSE;
|
|
}
|
|
|
|
if(!skip)
|
|
{
|
|
HpmDisplayUpgrade(0,0,1,0);
|
|
/* Initialize parameters */
|
|
uploadCmd.req.blockNumber = 0;
|
|
|
|
/* Check if we receive size in parameters */
|
|
if(intf->channel_buf_size != 0)
|
|
{
|
|
if (intf->target_addr == intf->my_addr)
|
|
{
|
|
bufLength = intf->channel_buf_size - 9; /* Plan for overhead */
|
|
}
|
|
else
|
|
{
|
|
bufLength = intf->channel_buf_size - 11; /* Plan for overhead */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Find max buffer length according the connection parameters */
|
|
if ( strstr(intf->name,"lan") != NULL )
|
|
{
|
|
bufLength = HPMFWUPG_SEND_DATA_COUNT_LAN - 2;
|
|
if ( intf->transit_addr != intf->my_addr && intf->transit_addr != 0 )
|
|
bufLength -= 8;
|
|
}
|
|
else
|
|
{
|
|
if
|
|
(
|
|
strstr(intf->name,"open") != NULL
|
|
&&
|
|
(
|
|
intf->target_addr == intf->my_addr
|
|
)
|
|
)
|
|
{
|
|
bufLength = HPMFWUPG_SEND_DATA_COUNT_KCS - 2;
|
|
}
|
|
else
|
|
{
|
|
if ( intf->target_channel == 7 )
|
|
{
|
|
bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMBL;
|
|
}
|
|
else
|
|
{
|
|
bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMB;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Send Initiate Upgrade Action */
|
|
initUpgActionCmd.req.componentsMask = components;
|
|
/* Action is upgrade */
|
|
initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_UPGRADE;
|
|
rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx);
|
|
|
|
if (rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
skip = TRUE;
|
|
}
|
|
|
|
if ( (pVersionInfo->coldResetRequired) && (!skip))
|
|
{
|
|
*pFlagColdReset = TRUE;
|
|
}
|
|
/* pDataInitial is the starting pointer of the image data */
|
|
/* pDataTemp is one which we will move across */
|
|
pData = pDataInitial;
|
|
pDataTemp = pDataInitial;
|
|
lengthOfBlock = firmwareLength;
|
|
totalSent = 0x00;
|
|
displayFWLength= firmwareLength;
|
|
time(&start);
|
|
|
|
|
|
while ( (pData < (pDataTemp+lengthOfBlock)) && (rc == HPMFWUPG_SUCCESS) )
|
|
{
|
|
if ( (pData+bufLength) <= (pDataTemp+lengthOfBlock) )
|
|
{
|
|
count = bufLength;
|
|
}
|
|
else
|
|
{
|
|
count = (unsigned char)((pDataTemp+lengthOfBlock) - pData);
|
|
}
|
|
memcpy(&uploadCmd.req.data, pData, bufLength);
|
|
|
|
imageOffset = 0x00;
|
|
blockLength = 0x00;
|
|
numTxPkts++;
|
|
rc = HpmfwupgUploadFirmwareBlock(intf, &uploadCmd, pFwupgCtx, count,
|
|
&imageOffset,&blockLength);
|
|
numRxPkts++;
|
|
|
|
if ( rc != HPMFWUPG_SUCCESS)
|
|
{
|
|
if ( rc == HPMFWUPG_UPLOAD_BLOCK_LENGTH )
|
|
{
|
|
/* Retry with a smaller buffer length */
|
|
if ( strstr(intf->name,"lan") != NULL )
|
|
{
|
|
bufLength -= (unsigned char)8;
|
|
lprintf(LOG_INFO,"Trying reduced buffer length: %d", bufLength);
|
|
}
|
|
else
|
|
{
|
|
bufLength -= (unsigned char)1;
|
|
lprintf(LOG_INFO,"Trying reduced buffer length: %d", bufLength);
|
|
}
|
|
rc = HPMFWUPG_SUCCESS;
|
|
}
|
|
else if ( rc == HPMFWUPG_UPLOAD_RETRY )
|
|
{
|
|
rc = HPMFWUPG_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
fflush(stdout);
|
|
lprintf(LOG_NOTICE,"\n Error in Upload FIRMWARE command [rc=%d]\n",rc);
|
|
lprintf(LOG_NOTICE,"\n TotalSent:0x%x ",totalSent);
|
|
/* Exiting from the function */
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (blockLength > firmwareLength)
|
|
{
|
|
/*
|
|
* blockLength is the remaining length of the firmware to upload so
|
|
* if its greater than the firmware length then its kind of error
|
|
*/
|
|
lprintf(LOG_NOTICE,"\n Error in Upload FIRMWARE command [rc=%d]\n",rc);
|
|
lprintf(LOG_NOTICE,"\n TotalSent:0x%x Img offset:0x%x Blk length:0x%x Fwlen:0x%x\n",
|
|
totalSent,imageOffset,blockLength,firmwareLength);
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
totalSent += count;
|
|
if (imageOffset != 0x00)
|
|
{
|
|
/* block Length is valid */
|
|
lengthOfBlock = blockLength;
|
|
pDataTemp = pDataInitial + imageOffset;
|
|
pData = pDataTemp;
|
|
if ( displayFWLength == firmwareLength)
|
|
{
|
|
/* This is basically used only to make sure that we display uptil 100% */
|
|
displayFWLength = blockLength + totalSent;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pData += count;
|
|
}
|
|
time(&end);
|
|
/*
|
|
* Just added debug mode in case we need to see exactly how many bytes have
|
|
* gone through - Its a hidden option used mainly should be used for debugging
|
|
*/
|
|
if ( option & DEBUG_MODE)
|
|
{
|
|
fflush(stdout);
|
|
printf(" Blk Num : %02x Bytes : %05x ",
|
|
uploadCmd.req.blockNumber,totalSent);
|
|
if (imageOffset || blockLength)
|
|
{
|
|
printf("\n--> ImgOff : %x BlkLen : %x\n",imageOffset,blockLength);
|
|
}
|
|
if (displayFWLength == totalSent)
|
|
{
|
|
printf("\n Time Taken %02ld:%02ld",(end-start)/60, (end-start)%60);
|
|
printf("\n\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HpmDisplayUpgrade(0,totalSent,displayFWLength,(end-start));
|
|
}
|
|
uploadCmd.req.blockNumber++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (skip)
|
|
{
|
|
|
|
HpmDisplayUpgrade(1,0,0,0);
|
|
*pImagePtr = pDataInitial + firmwareLength;
|
|
}
|
|
|
|
if
|
|
(
|
|
(rc == HPMFWUPG_SUCCESS)
|
|
&&
|
|
(!skip)
|
|
)
|
|
{
|
|
/* Send finish component */
|
|
/* Set image length */
|
|
finishCmd.req.componentId = componentId;
|
|
/* We need to send the actual data that is sent
|
|
* not the comlete firmware image length
|
|
*/
|
|
finishCmd.req.imageLength[0] = totalSent & 0xFF;
|
|
finishCmd.req.imageLength[1] = (totalSent >> 8) & 0xFF;
|
|
finishCmd.req.imageLength[2] = (totalSent >> 16) & 0xFF;
|
|
finishCmd.req.imageLength[3] = (totalSent >> 24) & 0xFF;
|
|
rc = HpmfwupgFinishFirmwareUpload(intf, &finishCmd, pFwupgCtx);
|
|
*pImagePtr = pDataInitial + firmwareLength;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Function Name: HpmfwupgActivationStage
|
|
*
|
|
* Description: This function the validation stage of a firmware upgrade
|
|
* procedure as defined in section 3.4 of the IPM Controller
|
|
* Firmware Upgrade Specification version 1.0
|
|
*
|
|
*****************************************************************************/
|
|
static int HpmfwupgActivationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct HpmfwupgActivateFirmwareCtx activateCmd;
|
|
struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
|
|
pFwupgCtx->pImageData;
|
|
|
|
/* Print out stuf...*/
|
|
printf(" ");
|
|
fflush(stdout);
|
|
/* Activate new firmware */
|
|
rc = HpmfwupgActivateFirmware(intf, &activateCmd, pFwupgCtx);
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
/* Query self test result if supported by target and new image */
|
|
if ( (pFwupgCtx->targetCap.GlobalCapabilities.bitField.ipmcSelftestCap == 1) ||
|
|
(pImageHeader->imageCapabilities.bitField.imageSelfTest == 1) )
|
|
{
|
|
struct HpmfwupgQuerySelftestResultCtx selfTestCmd;
|
|
rc = HpmfwupgQuerySelftestResult(intf, &selfTestCmd, pFwupgCtx);
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
/* Get the self test result */
|
|
if ( selfTestCmd.resp.result1 != 0x55 )
|
|
{
|
|
/* Perform manual rollback if necessary */
|
|
/* BACKUP/ MANUAL ROLLBACK not supported by this UA */
|
|
lprintf(LOG_NOTICE," Self test failed:");
|
|
lprintf(LOG_NOTICE," Result1 = %x", selfTestCmd.resp.result1);
|
|
lprintf(LOG_NOTICE," Result2 = %x", selfTestCmd.resp.result2);
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Perform manual rollback if necessary */
|
|
/* BACKUP / MANUAL ROLLBACK not supported by this UA */
|
|
lprintf(LOG_NOTICE," Self test failed.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If activation / self test failed, query rollback status if automatic rollback supported */
|
|
if ( rc == HPMFWUPG_ERROR )
|
|
{
|
|
if ( (pFwupgCtx->targetCap.GlobalCapabilities.bitField.autRollback == 1) &&
|
|
(pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.rollbackBackup != 0x00) )
|
|
{
|
|
struct HpmfwupgQueryRollbackStatusCtx rollCmd;
|
|
lprintf(LOG_NOTICE," Getting rollback status...");
|
|
fflush(stdout);
|
|
rc = HpmfwupgQueryRollbackStatus(intf, &rollCmd, pFwupgCtx);
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgGetBufferFromFile(char* imageFilename, struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
int ret = 0;
|
|
FILE* pImageFile = fopen(imageFilename, "rb");
|
|
|
|
if ( pImageFile == NULL )
|
|
{
|
|
lprintf(LOG_NOTICE,"Cannot open image file %s", imageFilename);
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
/* Get the raw data in file */
|
|
fseek(pImageFile, 0, SEEK_END);
|
|
pFwupgCtx->imageSize = ftell(pImageFile);
|
|
pFwupgCtx->pImageData = malloc(sizeof(unsigned char)*pFwupgCtx->imageSize);
|
|
pFwupgCtx->compUpdateMask.ComponentBits.byte = 0;
|
|
rewind(pImageFile);
|
|
if ( pFwupgCtx->pImageData != NULL )
|
|
{
|
|
ret = fread(pFwupgCtx->pImageData, sizeof(unsigned char),
|
|
pFwupgCtx->imageSize, pImageFile);
|
|
if (ret != pFwupgCtx->imageSize) {
|
|
lprintf(LOG_ERROR,"Failed to read file %s size %d",
|
|
imageFilename, pFwupgCtx->imageSize);
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
fclose(pImageFile);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgGetDeviceId(struct ipmi_intf *intf, struct ipm_devid_rsp* pGetDevId)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_APP;
|
|
req.msg.cmd = BMC_GET_DEVICE_ID;
|
|
req.msg.data_len = 0;
|
|
|
|
rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
|
|
if ( rsp )
|
|
{
|
|
if ( rsp->ccode == 0x00 )
|
|
{
|
|
memcpy(pGetDevId, rsp->data, sizeof(struct ipm_devid_rsp));
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error getting device ID");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error getting device ID\n");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf,
|
|
struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
req.msg.cmd = HPMFWUPG_GET_TARGET_UPG_CAPABILITIES;
|
|
req.msg.data = (unsigned char*)&pCtx->req;
|
|
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(struct ipmi_intf *intf, struct HpmfwupgGetComponentPropertiesCtx* pCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
req.msg.cmd = HPMFWUPG_GET_COMPONENT_PROPERTIES;
|
|
req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgGetComponentPropertiesReq);
|
|
|
|
rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
|
|
if ( rsp )
|
|
{
|
|
if ( rsp->ccode == 0x00 )
|
|
{
|
|
switch ( pCtx->req.selector )
|
|
{
|
|
case HPMFWUPG_COMP_GEN_PROPERTIES:
|
|
memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetGeneralPropResp));
|
|
if ( verbose )
|
|
{
|
|
lprintf(LOG_NOTICE,"GENERAL PROPERTIES");
|
|
lprintf(LOG_NOTICE,"-------------------------------");
|
|
lprintf(LOG_NOTICE,"Payload cold reset req....[%c] ", pCtx->resp.Response.generalPropResp.
|
|
GeneralCompProperties.bitfield.payloadColdReset ? 'y' : 'n');
|
|
lprintf(LOG_NOTICE,"Def. activation supported.[%c] ", pCtx->resp.Response.generalPropResp.
|
|
GeneralCompProperties.bitfield.deferredActivation ? 'y' : 'n');
|
|
lprintf(LOG_NOTICE,"Comparison supported......[%c] ", pCtx->resp.Response.generalPropResp.
|
|
GeneralCompProperties.bitfield.comparisonSupport ? 'y' : 'n');
|
|
lprintf(LOG_NOTICE,"Preparation supported.....[%c] ", pCtx->resp.Response.generalPropResp.
|
|
GeneralCompProperties.bitfield.preparationSupport ? 'y' : 'n');
|
|
lprintf(LOG_NOTICE,"Rollback supported........[%c] \n", pCtx->resp.Response.generalPropResp.
|
|
GeneralCompProperties.bitfield.rollbackBackup ? 'y' : 'n');
|
|
}
|
|
break;
|
|
case HPMFWUPG_COMP_CURRENT_VERSION:
|
|
memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetCurrentVersionResp));
|
|
if ( verbose )
|
|
{
|
|
lprintf(LOG_NOTICE,"Current Version: ");
|
|
lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.currentVersionResp.currentVersion[0]);
|
|
lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.currentVersionResp.currentVersion[1]);
|
|
lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.currentVersionResp.currentVersion[2],
|
|
pCtx->resp.Response.currentVersionResp.currentVersion[3],
|
|
pCtx->resp.Response.currentVersionResp.currentVersion[4],
|
|
pCtx->resp.Response.currentVersionResp.currentVersion[5]);
|
|
}
|
|
break;
|
|
case HPMFWUPG_COMP_DESCRIPTION_STRING:
|
|
memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDescStringResp));
|
|
if ( verbose )
|
|
{
|
|
lprintf(LOG_NOTICE,"Description string: %s\n", pCtx->resp.Response.descStringResp.descString);
|
|
}
|
|
break;
|
|
case HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION:
|
|
memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetRollbackFwVersionResp));
|
|
if ( verbose )
|
|
{
|
|
lprintf(LOG_NOTICE,"Rollback FW Version: ");
|
|
lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[0]);
|
|
lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[1]);
|
|
lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[2],
|
|
pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[3],
|
|
pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[4],
|
|
pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[5]);
|
|
}
|
|
break;
|
|
case HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION:
|
|
memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDeferredFwVersionResp));
|
|
if ( verbose )
|
|
{
|
|
lprintf(LOG_NOTICE,"Deferred FW Version: ");
|
|
lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[0]);
|
|
lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[1]);
|
|
lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[2],
|
|
pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[3],
|
|
pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[4],
|
|
pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[5]);
|
|
}
|
|
break;
|
|
// OEM Properties command
|
|
case HPMFWUPG_COMP_OEM_PROPERTIES:
|
|
memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetOemProperties));
|
|
if ( verbose )
|
|
{
|
|
unsigned char i = 0;
|
|
lprintf(LOG_NOTICE,"OEM Properties: ");
|
|
for (i=0; i < HPMFWUPG_OEM_LENGTH; i++)
|
|
{
|
|
lprintf(LOG_NOTICE," 0x%x ", pCtx->resp.Response.oemProperties.oemRspData[i]);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
lprintf(LOG_NOTICE,"Unsupported component selector");
|
|
rc = HPMFWUPG_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error getting component properties");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error getting component properties\n");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgAbortUpgrade(struct ipmi_intf *intf, struct HpmfwupgAbortUpgradeCtx* pCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
req.msg.cmd = HPMFWUPG_ABORT_UPGRADE;
|
|
req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgAbortUpgradeReq);
|
|
|
|
rsp = HpmfwupgSendCmd(intf, req, NULL);
|
|
|
|
if ( rsp )
|
|
{
|
|
if ( rsp->ccode != 0x00 )
|
|
{
|
|
lprintf(LOG_NOTICE,"Error aborting upgrade");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error aborting upgrade\n");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf, struct HpmfwupgInitiateUpgradeActionCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
req.msg.cmd = HPMFWUPG_INITIATE_UPGRADE_ACTION;
|
|
req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgInitiateUpgradeActionReq);
|
|
|
|
rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
|
|
if ( rsp )
|
|
{
|
|
/* Long duration command handling */
|
|
if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
|
|
{
|
|
rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
}
|
|
else if ( rsp->ccode != 0x00 )
|
|
{
|
|
lprintf(LOG_NOTICE,"Error initiating upgrade action");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error initiating upgrade action\n");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf, struct HpmfwupgUploadFirmwareBlockCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx, int count
|
|
,unsigned int *imageOffset, unsigned int *blockLength )
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
req.msg.cmd = HPMFWUPG_UPLOAD_FIRMWARE_BLOCK;
|
|
req.msg.data = (unsigned char*)&pCtx->req;
|
|
/* 2 is the size of the upload struct - data */
|
|
req.msg.data_len = 2 + count;
|
|
|
|
rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
|
|
if ( rsp )
|
|
{
|
|
if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ||
|
|
rsp->ccode == 0x00 )
|
|
{
|
|
/*
|
|
* We need to check if the response also contains the next upload firmware offset
|
|
* and the firmware length in its response - These are optional but very vital
|
|
*/
|
|
if ( rsp->data_len > 1 )
|
|
{
|
|
/*
|
|
* If the response data length is greater than 1 it should contain both the
|
|
* the Section offset and section length. Because we cannot just have
|
|
* Section offset without section length so the length should be 9
|
|
*/
|
|
if ( rsp->data_len == 9 )
|
|
{
|
|
/* rsp->data[1] - LSB rsp->data[2] - rsp->data[3] = MSB */
|
|
*imageOffset = (rsp->data[4] << 24) + (rsp->data[3] << 16) + (rsp->data[2] << 8) + rsp->data[1];
|
|
*blockLength = (rsp->data[8] << 24) + (rsp->data[7] << 16) + (rsp->data[6] << 8) + rsp->data[5];
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The Spec does not say much for this kind of errors where the
|
|
* firmware returned only offset and length so currently returning it
|
|
* as 0x82 - Internal CheckSum Error
|
|
*/
|
|
lprintf(LOG_NOTICE,"Error wrong rsp->datalen %d for Upload Firmware block command\n",rsp->data_len);
|
|
rsp->ccode = HPMFWUPG_INT_CHECKSUM_ERROR;
|
|
}
|
|
}
|
|
}
|
|
/* Long duration command handling */
|
|
if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
|
|
{
|
|
rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
}
|
|
else if (rsp->ccode != 0x00)
|
|
{
|
|
/*
|
|
* PATCH --> This validation is to handle retryables errors codes on IPMB bus.
|
|
* This will be fixed in the next release of open ipmi and this
|
|
* check will have to be removed. (Buggy version = 39)
|
|
*/
|
|
if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) )
|
|
{
|
|
lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected");
|
|
rc = HPMFWUPG_UPLOAD_RETRY;
|
|
}
|
|
/*
|
|
* If completion code = 0xc7, we will retry with a reduced buffer length.
|
|
* Do not print error.
|
|
*/
|
|
else if ( rsp->ccode == IPMI_CC_REQ_DATA_INV_LENGTH )
|
|
{
|
|
rc = HPMFWUPG_UPLOAD_BLOCK_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error uploading firmware block");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error uploading firmware block\n");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf, struct HpmfwupgFinishFirmwareUploadCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
req.msg.cmd = HPMFWUPG_FINISH_FIRMWARE_UPLOAD;
|
|
req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgFinishFirmwareUploadReq);
|
|
|
|
rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
|
|
if ( rsp )
|
|
{
|
|
/* Long duration command handling */
|
|
if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
|
|
{
|
|
rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
}
|
|
else if ( rsp->ccode != IPMI_CC_OK )
|
|
{
|
|
lprintf(LOG_NOTICE,"Error finishing firmware upload");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error fininshing firmware upload\n");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgActivateFirmware(struct ipmi_intf *intf, struct HpmfwupgActivateFirmwareCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
req.msg.cmd = HPMFWUPG_ACTIVATE_FIRMWARE;
|
|
req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgActivateFirmwareReq) -
|
|
(!pCtx->req.rollback_override ? 1 : 0);
|
|
|
|
rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
|
|
if ( rsp )
|
|
{
|
|
/* Long duration command handling */
|
|
if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
|
|
{
|
|
printf("Waiting firmware activation...");
|
|
fflush(stdout);
|
|
|
|
rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx);
|
|
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
lprintf(LOG_NOTICE,"OK");
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Failed");
|
|
}
|
|
}
|
|
else if ( rsp->ccode != IPMI_CC_OK )
|
|
{
|
|
lprintf(LOG_NOTICE,"Error activating firmware");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error activating firmware\n");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf,
|
|
struct HpmfwupgGetUpgradeStatusCtx *pCtx,
|
|
struct HpmfwupgUpgradeCtx *pFwupgCtx,
|
|
int silent)
|
|
{
|
|
int 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){
|
|
lprintf(LOG_NOTICE,
|
|
"Error getting upgrade status. Failed to get response.");
|
|
return HPMFWUPG_ERROR;
|
|
}
|
|
|
|
if ( rsp->ccode == 0x00 ) {
|
|
memcpy(&pCtx->resp, rsp->data,
|
|
sizeof(struct HpmfwupgGetUpgradeStatusResp));
|
|
if (!silent)
|
|
{
|
|
lprintf(LOG_NOTICE,"Upgrade status:");
|
|
lprintf(LOG_NOTICE," Command in progress: %x",
|
|
pCtx->resp.cmdInProcess);
|
|
lprintf(LOG_NOTICE," Last command completion code: %x",
|
|
pCtx->resp.lastCmdCompCode);
|
|
}
|
|
} else if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) {
|
|
/*
|
|
* PATCH --> This validation is to handle retryable errors
|
|
* codes on the IPMB bus.
|
|
* This will be fixed in the next release of
|
|
* open ipmi and this check can be removed.
|
|
* (Buggy version = 39)
|
|
*/
|
|
if (!silent)
|
|
{
|
|
lprintf(LOG_DEBUG,"HPM: Retryable error detected");
|
|
}
|
|
pCtx->resp.lastCmdCompCode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
} else {
|
|
lprintf(LOG_NOTICE,"Error getting upgrade status");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
return HPMFWUPG_ERROR;
|
|
}
|
|
|
|
return HPMFWUPG_SUCCESS;
|
|
}
|
|
|
|
int HpmfwupgManualFirmwareRollback(struct ipmi_intf *intf, struct HpmfwupgManualFirmwareRollbackCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
req.msg.cmd = HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK;
|
|
req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgManualFirmwareRollbackReq);
|
|
|
|
rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
|
|
if ( rsp )
|
|
{
|
|
/* Long duration command handling */
|
|
if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS )
|
|
{
|
|
struct HpmfwupgQueryRollbackStatusCtx resCmd;
|
|
printf("Waiting firmware rollback...");
|
|
fflush(stdout);
|
|
rc = HpmfwupgQueryRollbackStatus(intf, &resCmd, pFwupgCtx);
|
|
}
|
|
else if ( rsp->ccode != 0x00 )
|
|
{
|
|
lprintf(LOG_NOTICE,"Error sending manual rollback");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error sending manual rollback\n");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgQueryRollbackStatus(struct ipmi_intf *intf, struct HpmfwupgQueryRollbackStatusCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
unsigned int rollbackTimeout = 0;
|
|
unsigned int timeoutSec1, timeoutSec2;
|
|
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
req.msg.cmd = HPMFWUPG_QUERY_ROLLBACK_STATUS;
|
|
req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgQueryRollbackStatusReq);
|
|
|
|
/*
|
|
* If we are not in upgrade context, we use default timeout values
|
|
*/
|
|
if ( pFwupgCtx != NULL )
|
|
{
|
|
rollbackTimeout = pFwupgCtx->targetCap.rollbackTimeout*5;
|
|
}
|
|
else
|
|
{
|
|
struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
verbose--;
|
|
rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd);
|
|
verbose++;
|
|
if ( rc == HPMFWUPG_SUCCESS )
|
|
{
|
|
rollbackTimeout = targetCapCmd.resp.rollbackTimeout *5;
|
|
}
|
|
else
|
|
{
|
|
rollbackTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
}
|
|
}
|
|
|
|
/* Poll rollback status until completion or timeout */
|
|
timeoutSec1 = time(NULL);
|
|
timeoutSec2 = time(NULL);
|
|
do
|
|
{
|
|
/* Must wait at least 100 ms between status requests */
|
|
usleep(100000);
|
|
rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
/*
|
|
* PATCH --> This validation is to handle retryables errors codes on IPMB bus.
|
|
* This will be fixed in the next release of open ipmi and this
|
|
* check will have to be removed. (Buggy version = 39)
|
|
*/
|
|
if ( rsp )
|
|
{
|
|
if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) )
|
|
{
|
|
lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected");
|
|
rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
}
|
|
}
|
|
timeoutSec2 = time(NULL);
|
|
|
|
}while( rsp &&
|
|
((rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) ||
|
|
(rsp->ccode == IPMI_CC_TIMEOUT)) &&
|
|
(timeoutSec2 - timeoutSec1 < rollbackTimeout ) );
|
|
|
|
if ( rsp )
|
|
{
|
|
if ( rsp->ccode == 0x00 )
|
|
{
|
|
memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgQueryRollbackStatusResp));
|
|
if ( pCtx->resp.rollbackComp.ComponentBits.byte != 0 )
|
|
{
|
|
/* Rollback occured */
|
|
lprintf(LOG_NOTICE,"Rollback occured on component mask: 0x%02x",
|
|
pCtx->resp.rollbackComp.ComponentBits.byte);
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"No Firmware rollback occured");
|
|
}
|
|
}
|
|
else if ( rsp->ccode == 0x81 )
|
|
{
|
|
lprintf(LOG_NOTICE,"Rollback failed on component mask: 0x%02x",
|
|
pCtx->resp.rollbackComp.ComponentBits.byte);
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error getting rollback status");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error getting upgrade status\n");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int HpmfwupgQuerySelftestResult(struct ipmi_intf *intf, struct HpmfwupgQuerySelftestResultCtx* pCtx,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
struct ipmi_rs * rsp;
|
|
struct ipmi_rq req;
|
|
unsigned char selfTestTimeout = 0;
|
|
unsigned int timeoutSec1, timeoutSec2;
|
|
|
|
pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER;
|
|
|
|
/*
|
|
* If we are not in upgrade context, we use default timeout values
|
|
*/
|
|
if ( pFwupgCtx != NULL )
|
|
{
|
|
/* Getting selftest timeout from new image */
|
|
struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*)
|
|
pFwupgCtx->pImageData;
|
|
selfTestTimeout = pImageHeader->selfTestTimeout;
|
|
}
|
|
else
|
|
{
|
|
selfTestTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
}
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
req.msg.cmd = HPMFWUPG_QUERY_SELFTEST_RESULT;
|
|
req.msg.data = (unsigned char*)&pCtx->req;
|
|
req.msg.data_len = sizeof(struct HpmfwupgQuerySelftestResultReq);
|
|
|
|
|
|
/* Poll rollback status until completion or timeout */
|
|
timeoutSec1 = time(NULL);
|
|
timeoutSec2 = time(NULL);
|
|
do
|
|
{
|
|
/* Must wait at least 100 ms between status requests */
|
|
usleep(100000);
|
|
rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx);
|
|
/*
|
|
* PATCH --> This validation is to handle retryables errors codes on IPMB bus.
|
|
* This will be fixed in the next release of open ipmi and this
|
|
* check will have to be removed. (Buggy version = 39)
|
|
*/
|
|
if ( rsp )
|
|
{
|
|
if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) )
|
|
{
|
|
lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected");
|
|
rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
}
|
|
}
|
|
timeoutSec2 = time(NULL);
|
|
|
|
}while( rsp &&
|
|
(rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) &&
|
|
(timeoutSec2 - timeoutSec1 < selfTestTimeout ) );
|
|
|
|
if ( rsp )
|
|
{
|
|
if ( rsp->ccode == 0x00 )
|
|
{
|
|
memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgQuerySelftestResultResp));
|
|
if ( verbose )
|
|
{
|
|
lprintf(LOG_NOTICE,"Self test results:");
|
|
lprintf(LOG_NOTICE,"Result1 = %x", pCtx->resp.result1);
|
|
lprintf(LOG_NOTICE,"Result2 = %x", pCtx->resp.result2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error getting self test results");
|
|
lprintf(LOG_NOTICE,"compcode=0x%x: %s",
|
|
rsp->ccode,
|
|
val2str(rsp->ccode, completion_code_vals));
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lprintf(LOG_NOTICE,"Error getting upgrade status\n");
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
struct ipmi_rs * HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req,
|
|
struct HpmfwupgUpgradeCtx* pFwupgCtx )
|
|
{
|
|
struct ipmi_rs * rsp;
|
|
unsigned int inaccessTimeout = 0, inaccessTimeoutCounter = 0;
|
|
unsigned int upgradeTimeout = 0, upgradeTimeoutCounter = 0;
|
|
unsigned int timeoutSec1, timeoutSec2;
|
|
unsigned char retry = 0;
|
|
|
|
/*
|
|
* If we are not in upgrade context, we use default timeout values
|
|
*/
|
|
if ( pFwupgCtx != NULL )
|
|
{
|
|
inaccessTimeout = pFwupgCtx->targetCap.inaccessTimeout*5;
|
|
upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5;
|
|
}
|
|
else
|
|
{
|
|
/* keeping the inaccessTimeout to 60 seconds results in almost 2900 retries
|
|
* So if the target is not available it will be retrying the command for 2900
|
|
* times which is not effecient -So reducing the Timout to 5 seconds which is
|
|
* almost 200 retries if it continuously recieves 0xC3 as completion code.
|
|
*/
|
|
inaccessTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
}
|
|
|
|
timeoutSec1 = time(NULL);
|
|
|
|
do
|
|
{
|
|
static unsigned char isValidSize = FALSE;
|
|
rsp = intf->sendrecv(intf, &req);
|
|
|
|
if( ( rsp == NULL ) )
|
|
{
|
|
#define HPM_LAN_PACKET_RESIZE_LIMIT 6
|
|
|
|
if(strstr(intf->name,"lan")!= NULL) /* also covers lanplus */
|
|
{
|
|
static int errorCount=0;
|
|
static struct ipmi_rs fakeRsp;
|
|
|
|
lprintf(LOG_DEBUG,"HPM: no response available");
|
|
lprintf(LOG_DEBUG,"HPM: the command may be rejected for " \
|
|
"security reasons");
|
|
|
|
if
|
|
(
|
|
req.msg.netfn == IPMI_NETFN_PICMG
|
|
&&
|
|
req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK
|
|
&&
|
|
errorCount < HPM_LAN_PACKET_RESIZE_LIMIT
|
|
&&
|
|
(!isValidSize)
|
|
)
|
|
{
|
|
lprintf(LOG_DEBUG,"HPM: upload firmware block API called");
|
|
lprintf(LOG_DEBUG,"HPM: returning length error to force resize");
|
|
|
|
fakeRsp.ccode = IPMI_CC_REQ_DATA_INV_LENGTH;
|
|
rsp = &fakeRsp;
|
|
errorCount++;
|
|
}
|
|
else if
|
|
(
|
|
req.msg.netfn == IPMI_NETFN_PICMG
|
|
&&
|
|
( req.msg.cmd == HPMFWUPG_ACTIVATE_FIRMWARE ||
|
|
req.msg.cmd == HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK )
|
|
)
|
|
{
|
|
/*
|
|
* rsp == NULL and command activate firmware or manual firmware
|
|
* rollback most likely occurs when we have sent a firmware activation
|
|
* request. Fake a command in progress response.
|
|
*/
|
|
lprintf(LOG_DEBUG,"HPM: activate/rollback firmware API called");
|
|
lprintf(LOG_DEBUG,"HPM: returning in progress to handle IOL session lost");
|
|
|
|
fakeRsp.ccode = HPMFWUPG_COMMAND_IN_PROGRESS;
|
|
rsp = &fakeRsp;
|
|
}
|
|
else if
|
|
(
|
|
req.msg.netfn == IPMI_NETFN_PICMG
|
|
&&
|
|
( req.msg.cmd == HPMFWUPG_QUERY_ROLLBACK_STATUS ||
|
|
req.msg.cmd == HPMFWUPG_GET_UPGRADE_STATUS )
|
|
)
|
|
{
|
|
/*
|
|
* rsp == NULL and command get upgrade status or query rollback
|
|
* status most likely occurs when we are waiting for firmware
|
|
* activation. Try to re-open the IOL session (re-open will work
|
|
* once the IPMC recovers from firmware activation.
|
|
*/
|
|
|
|
lprintf(LOG_DEBUG,"HPM: upg/rollback status firmware API called");
|
|
lprintf(LOG_DEBUG,"HPM: try to re-open IOL session");
|
|
|
|
{
|
|
/* force session re-open */
|
|
intf->opened = 0;
|
|
intf->session->authtype = IPMI_SESSION_AUTHTYPE_NONE;
|
|
intf->session->session_id = 0;
|
|
intf->session->in_seq = 0;
|
|
intf->session->out_seq = 0;
|
|
intf->session->active = 0;
|
|
intf->session->retry = 10;
|
|
|
|
while
|
|
(
|
|
intf->open(intf) == HPMFWUPG_ERROR
|
|
&&
|
|
inaccessTimeoutCounter < inaccessTimeout
|
|
)
|
|
{
|
|
inaccessTimeoutCounter += (time(NULL) - timeoutSec1);
|
|
timeoutSec1 = time(NULL);
|
|
}
|
|
/* Fake timeout to retry command */
|
|
fakeRsp.ccode = 0xc3;
|
|
rsp = &fakeRsp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Handle inaccessibility timeout (rsp = NULL if IOL) */
|
|
if ( rsp == NULL || rsp->ccode == 0xff || rsp->ccode == 0xc3 || rsp->ccode == 0xd3 )
|
|
{
|
|
if ( inaccessTimeoutCounter < inaccessTimeout )
|
|
{
|
|
timeoutSec2 = time(NULL);
|
|
if ( timeoutSec2 > timeoutSec1 )
|
|
{
|
|
inaccessTimeoutCounter += timeoutSec2 - timeoutSec1;
|
|
timeoutSec1 = time(NULL);
|
|
}
|
|
usleep(100000);
|
|
retry = 1;
|
|
}
|
|
else
|
|
{
|
|
retry = 0;
|
|
}
|
|
}
|
|
/* Handle node busy timeout */
|
|
else if ( rsp->ccode == 0xc0 )
|
|
{
|
|
if ( upgradeTimeoutCounter < upgradeTimeout )
|
|
{
|
|
timeoutSec2 = time(NULL);
|
|
if ( timeoutSec2 > timeoutSec1 )
|
|
{
|
|
timeoutSec1 = time(NULL);
|
|
upgradeTimeoutCounter += timeoutSec2 - timeoutSec1;
|
|
}
|
|
usleep(100000);
|
|
retry = 1;
|
|
}
|
|
else
|
|
{
|
|
retry = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef ENABLE_OPENIPMI_V39_PATCH
|
|
if( rsp->ccode == IPMI_CC_OK )
|
|
{
|
|
errorCount = 0 ;
|
|
}
|
|
#endif
|
|
retry = 0;
|
|
|
|
if
|
|
(
|
|
req.msg.netfn == IPMI_NETFN_PICMG
|
|
&&
|
|
req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK
|
|
&&
|
|
(!isValidSize)
|
|
)
|
|
{
|
|
lprintf(LOG_INFO,"Buffer length is now considered valid" );
|
|
|
|
isValidSize = TRUE;
|
|
}
|
|
}
|
|
}while( retry );
|
|
return rsp;
|
|
}
|
|
|
|
int HpmfwupgWaitLongDurationCmd(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
unsigned int upgradeTimeout = 0;
|
|
unsigned int timeoutSec1, timeoutSec2;
|
|
struct HpmfwupgGetUpgradeStatusCtx upgStatusCmd;
|
|
|
|
/*
|
|
* If we are not in upgrade context, we use default timeout values
|
|
*/
|
|
if ( pFwupgCtx != NULL )
|
|
{
|
|
upgradeTimeout = (unsigned int)(pFwupgCtx->targetCap.upgradeTimeout*5);
|
|
if ( verbose )
|
|
printf("Use File Upgrade Capabilities: %i seconds\n", upgradeTimeout);
|
|
}
|
|
else
|
|
{
|
|
/* Try to retreive from Caps */
|
|
struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
|
|
|
|
if(HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd) != HPMFWUPG_SUCCESS)
|
|
{
|
|
upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
|
|
|
|
if ( verbose )
|
|
printf("Use default timeout: %i seconds\n", upgradeTimeout);
|
|
}
|
|
else
|
|
{
|
|
upgradeTimeout = (unsigned int)(targetCapCmd.resp.upgradeTimeout * 5);
|
|
if ( verbose )
|
|
printf("Use Command Upgrade Capabilities Timeout: %i seconds\n", upgradeTimeout);
|
|
}
|
|
}
|
|
|
|
if(rc == HPMFWUPG_SUCCESS)
|
|
{
|
|
/* Poll upgrade status until completion or timeout*/
|
|
timeoutSec1 = time(NULL);
|
|
timeoutSec2 = time(NULL);
|
|
rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx, 1);
|
|
}
|
|
|
|
while(
|
|
//With KCS: Cover the case where we sometime receive d5 (on the first get status) from the ipmi driver.
|
|
(upgStatusCmd.resp.lastCmdCompCode != 0x00 ) &&
|
|
((timeoutSec2 - timeoutSec1) < upgradeTimeout ) &&
|
|
(rc == HPMFWUPG_SUCCESS)
|
|
)
|
|
{
|
|
/* Must wait at least 1000 ms between status requests */
|
|
usleep(1000000);
|
|
timeoutSec2 = time(NULL);
|
|
rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx, 1);
|
|
//printf("Get Status: %x - %x = %x _ %x [%x]\n", timeoutSec2, timeoutSec1,(timeoutSec2 - timeoutSec1),upgradeTimeout, rc);
|
|
}
|
|
|
|
if ( upgStatusCmd.resp.lastCmdCompCode != 0x00 )
|
|
{
|
|
if ( verbose )
|
|
{
|
|
lprintf(LOG_NOTICE,"Error waiting for command %x, compcode = %x",
|
|
upgStatusCmd.resp.cmdInProcess,
|
|
upgStatusCmd.resp.lastCmdCompCode);
|
|
}
|
|
rc = HPMFWUPG_ERROR;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
unsigned char HpmfwupgCalculateChecksum(unsigned char* pData, unsigned int length)
|
|
{
|
|
unsigned char checksum = 0;
|
|
int dataIdx = 0;
|
|
|
|
for ( dataIdx = 0; dataIdx < length; dataIdx++ )
|
|
{
|
|
checksum += pData[dataIdx];
|
|
}
|
|
return checksum;
|
|
}
|
|
|
|
static void HpmfwupgPrintUsage(void)
|
|
{
|
|
lprintf(LOG_NOTICE,"help - This help menu.");
|
|
lprintf(LOG_NOTICE,"");
|
|
lprintf(LOG_NOTICE,"check - Check the target information.");
|
|
lprintf(LOG_NOTICE,"check <file> - If the user is unsure of what update is going to be ");
|
|
lprintf(LOG_NOTICE," This will display the existing target version and");
|
|
lprintf(LOG_NOTICE," image version on the screen");
|
|
lprintf(LOG_NOTICE,"");
|
|
lprintf(LOG_NOTICE,"upgrade <file> - Copies all the components from a valid HPM.1");
|
|
lprintf(LOG_NOTICE," image <file> to the target.");
|
|
lprintf(LOG_NOTICE," This compares the versions from both the target");
|
|
lprintf(LOG_NOTICE," and image and will only perform the copy");
|
|
lprintf(LOG_NOTICE," if the versions differ.");
|
|
lprintf(LOG_NOTICE,"upgrade <file> activate - Copy and activate the firmware using a valid HPM.1");
|
|
lprintf(LOG_NOTICE," image <file>.");
|
|
lprintf(LOG_NOTICE," This compares the versions from both the target");
|
|
lprintf(LOG_NOTICE," and image and will only perform the copy and");
|
|
lprintf(LOG_NOTICE," activation if the versions differ.");
|
|
lprintf(LOG_NOTICE,"upgrade <file> force - Copies all the components present in <file>");
|
|
lprintf(LOG_NOTICE," to the target board without checking the versions.");
|
|
lprintf(LOG_NOTICE," Make sure to check the versions first using the");
|
|
lprintf(LOG_NOTICE," \"check <file>\" command.");
|
|
lprintf(LOG_NOTICE,"upgrade <file> component x - Copy only component <x> from the given <file>");
|
|
lprintf(LOG_NOTICE," without checking if the versions differ.");
|
|
lprintf(LOG_NOTICE," For example:");
|
|
lprintf(LOG_NOTICE," component 0 = Bootloader");
|
|
lprintf(LOG_NOTICE," component 1 = Firmware");
|
|
lprintf(LOG_NOTICE," Make sure to check the versions first using the");
|
|
lprintf(LOG_NOTICE," \"check <file>\" command.");
|
|
lprintf(LOG_NOTICE,"upgstatus - Returns the status of the last long duration command.");
|
|
lprintf(LOG_NOTICE,"");
|
|
lprintf(LOG_NOTICE,"activate - Activate the newly uploaded firmware.");
|
|
lprintf(LOG_NOTICE,"activate norollback - Activate the newly uploaded firmware but inform");
|
|
lprintf(LOG_NOTICE," the target to not automatically rollback if ");
|
|
lprintf(LOG_NOTICE," the upgrade fails.");
|
|
lprintf(LOG_NOTICE,"");
|
|
lprintf(LOG_NOTICE,"targetcap - Get the target upgrade capabilities.");
|
|
lprintf(LOG_NOTICE,"");
|
|
lprintf(LOG_NOTICE,"compprop <id> <prop> - Get specified component properties from the target.");
|
|
lprintf(LOG_NOTICE," Valid component <id>: 0-7 ");
|
|
lprintf(LOG_NOTICE," Properties <prop> can be one of the following: ");
|
|
lprintf(LOG_NOTICE," 0- General properties");
|
|
lprintf(LOG_NOTICE," 1- Current firmware version");
|
|
lprintf(LOG_NOTICE," 2- Description string");
|
|
lprintf(LOG_NOTICE," 3- Rollback firmware version");
|
|
lprintf(LOG_NOTICE," 4- Deferred firmware version");
|
|
lprintf(LOG_NOTICE,"");
|
|
lprintf(LOG_NOTICE,"abort - Abort the on-going firmware upgrade.");
|
|
lprintf(LOG_NOTICE,"");
|
|
lprintf(LOG_NOTICE,"rollback - Performs a manual rollback on the IPM Controller.");
|
|
lprintf(LOG_NOTICE," firmware");
|
|
lprintf(LOG_NOTICE,"rollbackstatus - Query the rollback status.");
|
|
lprintf(LOG_NOTICE,"");
|
|
lprintf(LOG_NOTICE,"selftestresult - Query the self test results.\n");
|
|
}
|
|
|
|
int ipmi_hpmfwupg_main(struct ipmi_intf * intf, int argc, char ** argv)
|
|
{
|
|
int rc = HPMFWUPG_SUCCESS;
|
|
int activateFlag = 0x00;
|
|
int componentId = DEFAULT_COMPONENT_UPLOAD;
|
|
int option = VERSIONCHECK_MODE;
|
|
|
|
lprintf(LOG_DEBUG,"ipmi_hpmfwupg_main()");
|
|
|
|
|
|
lprintf(LOG_NOTICE,"\nPICMG HPM.1 Upgrade Agent %d.%d.%d: \n",
|
|
HPMFWUPG_VERSION_MAJOR, HPMFWUPG_VERSION_MINOR, HPMFWUPG_VERSION_SUBMINOR);
|
|
|
|
if ( (argc == 0) || (strcmp(argv[0], "help") == 0) )
|
|
{
|
|
HpmfwupgPrintUsage();
|
|
return HPMFWUPG_ERROR;
|
|
}
|
|
if ( (strcmp(argv[0], "check") == 0) )
|
|
{
|
|
/* hpm check */
|
|
if (argv[1] == NULL)
|
|
{
|
|
rc = HpmfwupgTargetCheck(intf,VIEW_MODE);
|
|
}
|
|
else
|
|
{
|
|
/* hpm check <filename> */
|
|
rc = HpmfwupgTargetCheck(intf,0);
|
|
if (rc == HPMFWUPG_SUCCESS)
|
|
{
|
|
rc = HpmfwupgUpgrade(intf, argv[1],0,DEFAULT_COMPONENT_UPLOAD,VIEW_MODE);
|
|
}
|
|
}
|
|
}
|
|
|
|
else if ( strcmp(argv[0], "upgrade") == 0)
|
|
{
|
|
int i =0;
|
|
for (i=1; i< argc ; i++)
|
|
{
|
|
if (strcmp(argv[i],"activate") == 0)
|
|
{
|
|
activateFlag = 1;
|
|
}
|
|
/* hpm upgrade <filename> force */
|
|
if (strcmp(argv[i],"force") == 0)
|
|
{
|
|
option &= ~(VERSIONCHECK_MODE);
|
|
option &= ~(VIEW_MODE);
|
|
option |= FORCE_MODE_ALL;
|
|
}
|
|
/* hpm upgrade <filename> component <comp Id> */
|
|
if (strcmp(argv[i],"component") == 0)
|
|
{
|
|
if (i+1 < argc)
|
|
{
|
|
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;
|
|
if (str2uchar(argv[1], &(cmdCtx.req.componentId)) != 0
|
|
|| cmdCtx.req.componentId > 7) {
|
|
lprintf(LOG_ERR, "Given Component ID '%s' is invalid.", argv[1]);
|
|
lprintf(LOG_ERR, "Valid Compoment ID is: <0..7>");
|
|
return (-1);
|
|
}
|
|
if (str2uchar(argv[2], &(cmdCtx.req.selector)) != 0
|
|
|| cmdCtx.req.selector > 4) {
|
|
lprintf(LOG_ERR, "Given Properties selector '%s' is invalid.",
|
|
argv[2]);
|
|
lprintf(LOG_ERR, "Valid Properties selector is: <0..4>");
|
|
return (-1);
|
|
}
|
|
verbose++;
|
|
rc = HpmfwupgGetComponentProperties(intf, &cmdCtx);
|
|
}
|
|
else if ( (argc == 1) && (strcmp(argv[0], "abort") == 0) )
|
|
{
|
|
struct HpmfwupgAbortUpgradeCtx cmdCtx;
|
|
verbose++;
|
|
rc = HpmfwupgAbortUpgrade(intf, &cmdCtx);
|
|
}
|
|
else if ( (argc == 1) && (strcmp(argv[0], "upgstatus") == 0) )
|
|
{
|
|
struct HpmfwupgGetUpgradeStatusCtx cmdCtx;
|
|
verbose++;
|
|
rc = HpmfwupgGetUpgradeStatus(intf, &cmdCtx, NULL, 0);
|
|
}
|
|
else if ( (argc == 1) && (strcmp(argv[0], "rollback") == 0) )
|
|
{
|
|
struct HpmfwupgManualFirmwareRollbackCtx cmdCtx;
|
|
verbose++;
|
|
rc = HpmfwupgManualFirmwareRollback(intf, &cmdCtx, NULL);
|
|
}
|
|
else if ( (argc == 1) && (strcmp(argv[0], "rollbackstatus") == 0) )
|
|
{
|
|
struct HpmfwupgQueryRollbackStatusCtx cmdCtx;
|
|
verbose++;
|
|
rc = HpmfwupgQueryRollbackStatus(intf, &cmdCtx, NULL);
|
|
}
|
|
else if ( (argc == 1) && (strcmp(argv[0], "selftestresult") == 0) )
|
|
{
|
|
struct HpmfwupgQuerySelftestResultCtx cmdCtx;
|
|
verbose++;
|
|
rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL);
|
|
}
|
|
else
|
|
{
|
|
HpmfwupgPrintUsage();
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|