/* * ihpm.c * Hardware Platform Management, IPM Controller Firmware Upgrade Procedure * * Change history: * 08/25/2010 ARCress - ported from ipmitool/lib/ipmi_hpmfwupg.c * 08/24/2011 ARcress - updated to Kontron 1.08 (K17) version, * added hpm_decode_cc(), etc. * *--------------------------------------------------------------------- */ /* * Copyright (c) 2006 Kontron Canada, Inc. All Rights Reserved. * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifdef WIN32 #include #include #include #define uint8_t unsigned char #define uint16_t unsigned short #define uint32_t unsigned int typedef uint32_t socklen_t; #include "getopt.h" #else #include #include #include #include #include /*for toupper*/ #if defined(HPUX) /* getopt is defined in stdio.h */ #elif defined(MACOS) /* getopt is defined in unistd.h */ #include #else #include #endif #endif #include #include #include #include #include "ipmicmd.h" #include "ihpm.h" /**************************************************************************** * * Copyright (c) 2006 Kontron Canada, Inc. All Rights Reserved. * * HPM.1 * Hardware Platform Management * IPM Controller Firmware Upgrade Procedure * * This module implements an Upgrade Agent for the IPM Controller * Firmware Upgrade Procedure (HPM.1) specification version 1.0. * * author: * Frederic.Lelievre@ca.kontron.com * Francois.Isabelle@ca.kontron.com * Jean-Michel.Audet@ca.kontron.com * MarieJosee.Blais@ca.kontron.com * ***************************************************************************** * * HISTORY * =========================================================================== * 2007-01-11 * * - Incremented to version 0.2 * - Added lan packet size reduction mechanism to workaround fact * that lan iface will not return C7 on excessive length * - Fixed some typos * - now uses lprintf() * * - Incremented to version 0.3 * - added patch for openipmi si driver V39 (send message in driver does not * retry on 82/83 completion code and return 82/83 as response from target * [conditionnaly built with ENABLE_OPENIPMI_V39_PATCH] * * see: ipmi-fix-send-msg-retry.pacth in openipmi-developer mailing list * * 2007-01-16 * * - Incremented to version 0.4 * - Fixed lan iface inaccesiblity timeout handling. Waiting for firmware * activation completion (fixed sleep) before re-opening a session and * get the final firmware upgrade status. * - Fixed some user interface stuff. * * 2007-05-09 * * - Incremented to version 1.0 * - Modifications for compliancy with HPM.1 specification version 1.0 * * 2007-06-05 * * - Modified the display of upgrade of Firmware version. * - Added new options like "check" and "component" and "all" to hpm commands. * - By default we skip the upgrade if we have the same firmware version * as compared to the Image file (*.hpm).This will ensure that user does * not update the target incase its already been updated * * 2008-01-25 * - Reduce buffer length more aggressively when no response from iol. * - Incremented version to 1.02 * * 2009-02-11 * - With multi-component HPM file, if one component need to be skipped because * the component is already up-to-date, ipmitool sends "Initiate upgrade * action / Upload for upgrade" anyway. * * If the component needs to be skipped, ipmitool will not send "Initiate * upgrade action / Upload for upgrade" * * - Incremented version to 1.03 * * 2009-02-11 * - Fixed side effect introduced by last version, "forced" update didn't * work anymore * - Incremented version to 1.04 * * 2009-03-25 * - Fix the case where ipmitool loses the iol connection during the upload * block process. Once IPMITool was successfully sent the first byte, * IPMITool will not resize the block size. * * 2009-03-26 * - Fix the problem when we try to upgrade specific component and the component * is already updated, IPMITool sends a "prepare action" but IPMITool skips * the upload firmware block process. * So, if we specify a specific component, we want to force to upload this * specific component. * - Incremented version to 1.05 * * 2009-04-20 * - Reworked previous update, when 'component' is specified, the other * components are now skipped. * - Incremented version to 1.06 * * =========================================================================== * TODO * =========================================================================== * 2007-01-11 * - Add interpretation of GetSelftestResults * - Add interpretation of component ID string * *****************************************************************************/ extern int verbose; /* * Agent version */ #define HPMFWUPG_VERSION_MAJOR 1 #define HPMFWUPG_VERSION_MINOR 0 #define HPMFWUPG_VERSION_SUBMINOR 9 static char * progname = "ihpm"; static char * progver = "1.09"; /* HPMFWUPG_VERSION */ extern char fdebug; /*from ipmicmd.c*/ static uchar g_bus = PUBLIC_BUS; static uchar g_sa = BMC_SA; static uchar g_lun = BMC_LUN; static uchar g_addrtype = ADDR_SMI; static int g_channel_buf_size = 0; /* * HPM.1 FIRMWARE UPGRADE COMMANDS (part of PICMG) */ #define HPMFWUPG_GET_TARGET_UPG_CAPABILITIES 0x2E #define HPMFWUPG_GET_COMPONENT_PROPERTIES 0x2F #define HPMFWUPG_ABORT_UPGRADE 0x30 #define HPMFWUPG_INITIATE_UPGRADE_ACTION 0x31 #define HPMFWUPG_UPLOAD_FIRMWARE_BLOCK 0x32 #define HPMFWUPG_FINISH_FIRMWARE_UPLOAD 0x33 #define HPMFWUPG_GET_UPGRADE_STATUS 0x34 #define HPMFWUPG_ACTIVATE_FIRMWARE 0x35 #define HPMFWUPG_QUERY_SELFTEST_RESULT 0x36 #define HPMFWUPG_QUERY_ROLLBACK_STATUS 0x37 #define HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK 0x38 /* * HPM.1 SPECIFIC COMPLETION CODES */ #define HPMFWUPG_ROLLBACK_COMPLETED 0x00 #define HPMFWUPG_COMMAND_IN_PROGRESS 0x80 #define HPMFWUPG_NOT_SUPPORTED 0x81 #define HPMFWUPG_SIZE_MISMATCH 0x81 #define HPMFWUPG_ROLLBACK_FAILURE 0x81 #define HPMFWUPG_INV_COMP_MASK 0x81 #define HPMFWUPG__ABORT_FAILURE 0x81 #define HPMFWUPG_INV_COMP_ID 0x82 #define HPMFWUPG_INT_CHECKSUM_ERROR 0x82 #define HPMFWUPG_INV_UPLOAD_MODE 0x82 #define HPMFWUPG_ROLLBACK_OVERRIDE 0x82 #define HPMFWUPG_INV_COMP_PROP 0x83 #define HPMFWUPG_FW_MISMATCH 0x83 #define HPMFWUPG_ROLLBACK_DENIED 0x83 #define HPMFWUPG_NOT_SUPPORTED_NOW 0xd5 /* * This error code is used as a temporary PATCH to * the latest Open ipmi driver. This PATCH * will be removed once a new Open IPMI driver is released. * (Buggy version = 39) */ #define ENABLE_OPENIPMI_V39_PATCH #ifdef ENABLE_OPENIPMI_V39_PATCH #define RETRY_COUNT_MAX 3 static int errorCount; #define HPMFWUPG_IS_RETRYABLE(error) \ ((((error==0x83)||(error==0x82)||(error==0x80)) && (errorCount++descString,11); /* * If the cold reset is required then we can display * on it * so that user is aware that he needs to do payload power * cycle after upgrade */ printf("|%c%-2d|%-11s|",pVersion->coldResetRequired?'*':' ',pVersion->componentId,descString); if (mode & TARGET_VER) { if (pVersion->targetMajor == 0xFF && pVersion->targetMinor == 0xFF) printf(" ---.-- -------- |"); else printf(" %3d.%02x %02X%02X%02X%02X |", pVersion->targetMajor, pVersion->targetMinor, pVersion->targetAux[0], pVersion->targetAux[1], pVersion->targetAux[2], pVersion->targetAux[3] ); if (mode & ROLLBACK_VER) { if (pVersion->rollbackMajor == 0xFF && pVersion->rollbackMinor == 0xFF) printf(" ---.-- -------- |"); else printf(" %3d.%02x %02X%02X%02X%02X |", pVersion->rollbackMajor, pVersion->rollbackMinor, pVersion->rollbackAux[0], pVersion->rollbackAux[1], pVersion->rollbackAux[2], pVersion->rollbackAux[3]); } else { printf(" ---.-- -------- |"); } } if (mode & IMAGE_VER) { if (pVersion->imageMajor == 0xFF && pVersion->imageMinor == 0xFF) printf(" ---.-- |"); else printf(" %3d.%02x %02X%02X%02X%02X |", pVersion->imageMajor, pVersion->imageMinor, pVersion->imageAux[0], pVersion->imageAux[1], pVersion->imageAux[2], pVersion->imageAux[3]); } return 0; } /**************************************************************************** * * Function Name: HpmfwupgTargerCheck * * Description: This function gets the target information and displays it on the * screen * *****************************************************************************/ int HpmfwupgTargetCheck(void * intf, int option) { // struct HpmfwupgUpgradeCtx fwupgCtx; struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; int rc = HPMFWUPG_SUCCESS; int componentId = 0; int flagColdReset = FALSE; struct ipm_devid_rsp devIdrsp; struct HpmfwupgGetComponentPropertiesCtx getCompProp; int mode = 0; rc = HpmfwupgGetDeviceId(intf, &devIdrsp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Verify whether the Target board is present \n"); return rc; } rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); if (rc != HPMFWUPG_SUCCESS) { /* * That indicates the target is not responding to the command * May be that there is no HPM support */ lprintf(LOG_NOTICE,"Board might not be supporting the HPM.1 Standards\n"); return rc; } if (option & VIEW_MODE) { lprintf(LOG_NOTICE,"-------Target Information-------"); lprintf(LOG_NOTICE,"Device Id : 0x%x", devIdrsp.device_id); lprintf(LOG_NOTICE,"Device Revision : 0x%x", devIdrsp.device_revision); lprintf(LOG_NOTICE,"Product Id : 0x%04x", buf2short(devIdrsp.product_id)); lprintf(LOG_NOTICE,"Manufacturer Id : 0x%04x (%s)\n\n", buf2short(devIdrsp.manufacturer_id), get_mfg_str(devIdrsp.manufacturer_id,NULL)); HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER); } for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX; componentId++ ) { /* If the component is supported */ if ( ((1 << componentId) & targetCapCmd.resp.componentsPresent.ComponentBits.byte) ) { memset((PVERSIONINFO)&gVersionInfo[componentId],0x00,sizeof(VERSIONINFO)); getCompProp.req.componentId = componentId; getCompProp.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompGenProp Failed for component Id %d\n",componentId); return rc; } gVersionInfo[componentId].rollbackSupported = getCompProp.resp.Response. generalPropResp.GeneralCompProperties.bitfield.rollbackBackup; gVersionInfo[componentId].coldResetRequired = getCompProp.resp.Response. generalPropResp.GeneralCompProperties.bitfield.payloadColdReset; getCompProp.req.selector = HPMFWUPG_COMP_DESCRIPTION_STRING; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompDescString Failed for component Id %d\n",componentId); return rc; } strcpy((char *)&gVersionInfo[componentId].descString, getCompProp.resp.Response.descStringResp.descString); getCompProp.req.selector = HPMFWUPG_COMP_CURRENT_VERSION; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompCurrentVersion Failed for component Id %d\n",componentId); return rc; } gVersionInfo[componentId].componentId = componentId; gVersionInfo[componentId].targetMajor = getCompProp.resp.Response. currentVersionResp.currentVersion[0]; gVersionInfo[componentId].targetMinor = getCompProp.resp.Response. currentVersionResp.currentVersion[1]; gVersionInfo[componentId].targetAux[0] = getCompProp.resp.Response. currentVersionResp.currentVersion[2]; gVersionInfo[componentId].targetAux[1] = getCompProp.resp.Response. currentVersionResp.currentVersion[3]; gVersionInfo[componentId].targetAux[2] = getCompProp.resp.Response. currentVersionResp.currentVersion[4]; gVersionInfo[componentId].targetAux[3] = getCompProp.resp.Response. currentVersionResp.currentVersion[5]; mode = TARGET_VER; if (gVersionInfo[componentId].rollbackSupported) { getCompProp.req.selector = HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION; rc = HpmfwupgGetComponentProperties(intf, &getCompProp); if (rc != HPMFWUPG_SUCCESS) { lprintf(LOG_NOTICE,"Get CompRollbackVersion Failed for component Id %d\n",componentId); } else { gVersionInfo[componentId].rollbackMajor = getCompProp.resp .Response.rollbackFwVersionResp.rollbackFwVersion[0]; gVersionInfo[componentId].rollbackMinor = getCompProp.resp .Response.rollbackFwVersionResp.rollbackFwVersion[1]; gVersionInfo[componentId].rollbackAux[0] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[2]; gVersionInfo[componentId].rollbackAux[1] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[3]; gVersionInfo[componentId].rollbackAux[2] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[4]; gVersionInfo[componentId].rollbackAux[3] = getCompProp.resp.Response. rollbackFwVersionResp.rollbackFwVersion[5]; } mode |= ROLLBACK_VER; } if (gVersionInfo[componentId].coldResetRequired) { /* * If any of the component indicates that the Payload Cold reset is required * then set the flag */ flagColdReset = TRUE; } if (option & VIEW_MODE) { HpmDisplayVersion(mode,&gVersionInfo[componentId]); printf("\n"); } } } if (option & VIEW_MODE) { HpmDisplayLine("-",53 ); if (flagColdReset) { fflush(stdout); lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset"); } printf("\n\n"); } return HPMFWUPG_SUCCESS; } /***************************************************************************** * Function Name: HpmfwupgUpgrade * * Description: This function performs the HPM.1 firmware upgrade procedure as * defined the IPM Controller Firmware Upgrade Specification * version 1.0 * *****************************************************************************/ int HpmfwupgUpgrade(void *intf, char* imageFilename, int activate,int componentToUpload, int option) { int rc = HPMFWUPG_SUCCESS; // struct HpmfwupgImageHeader imageHeader; struct HpmfwupgUpgradeCtx fwupgCtx; /* * GET IMAGE BUFFER FROM FILE */ rc = HpmfwupgGetBufferFromFile(imageFilename, &fwupgCtx); /* * VALIDATE IMAGE INTEGRITY */ if ( rc == HPMFWUPG_SUCCESS ) { printf("Validating firmware image integrity..."); fflush(stdout); rc = HpmfwupgValidateImageIntegrity(&fwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { printf("OK\n"); fflush(stdout); } else { free(fwupgCtx.pImageData); } } /* * PREPARATION STAGE */ if ( rc == HPMFWUPG_SUCCESS ) { printf("Performing preparation stage..."); fflush(stdout); rc = HpmfwupgPreparationStage(intf, &fwupgCtx, option); if ( rc == HPMFWUPG_SUCCESS ) { printf("OK\n"); fflush(stdout); } else { free(fwupgCtx.pImageData); } } /* * UPGRADE STAGE */ if ( rc == HPMFWUPG_SUCCESS ) { if (option & VIEW_MODE) { lprintf(LOG_NOTICE,"\nComparing Target & Image File version"); } else { lprintf(LOG_NOTICE,"\nPerforming upgrade stage:"); } if (option & VIEW_MODE) { rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,componentToUpload,VIEW_MODE); } else { rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx,componentToUpload,option); if (rc == HPMFWUPG_SUCCESS ) { if( verbose ) { printf("Component update mask : 0x%02x\n", fwupgCtx.compUpdateMask.ComponentBits.byte); } rc = HpmfwupgUpgradeStage(intf, &fwupgCtx,componentToUpload,option); } } if ( rc != HPMFWUPG_SUCCESS ) { if (verbose) printf("HPM Upgrade error %d\n",rc); free(fwupgCtx.pImageData); } } /* * ACTIVATION STAGE */ if ( rc == HPMFWUPG_SUCCESS && activate ) { lprintf(LOG_NOTICE,"Performing activation stage: "); rc = HpmfwupgActivationStage(intf, &fwupgCtx); if ( rc != HPMFWUPG_SUCCESS ) { if (verbose) printf("HPM Activation error %d\n",rc); free(fwupgCtx.pImageData); } } if ( rc == HPMFWUPG_SUCCESS ) { if (option & VIEW_MODE) { // Dont display anything here in case we are just viewing it lprintf(LOG_NOTICE," "); } else { lprintf(LOG_NOTICE,"\nFirmware upgrade procedure successful\n"); } free(fwupgCtx.pImageData); } else { lprintf(LOG_NOTICE,"Firmware upgrade procedure failed\n"); } return rc; } /**************************************************************************** * * Function Name: HpmfwupgValidateImageIntegrity * * Description: This function validates a HPM.1 firmware image file as defined * in section 4 of the IPM Controller Firmware Upgrade * Specification version 1.0 * *****************************************************************************/ int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; md5_state_t ctx; static unsigned char md[HPMFWUPG_MD5_SIGNATURE_LENGTH]; unsigned char* pMd5Sig = pFwupgCtx->pImageData + (pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH); /* Validate MD5 checksum */ memset(md, 0, HPMFWUPG_MD5_SIGNATURE_LENGTH); memset(&ctx, 0, sizeof(md5_state_t)); md5_init(&ctx); md5_append(&ctx, pFwupgCtx->pImageData, pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH); md5_finish(&ctx, md); if ( memcmp(md, pMd5Sig,HPMFWUPG_MD5_SIGNATURE_LENGTH) != 0 ) { lprintf(LOG_NOTICE,"\n Invalid MD5 signature"); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { /* Validate Header signature */ if( strncmp(pImageHeader->signature, HPMFWUPG_IMAGE_SIGNATURE, HPMFWUPG_HEADER_SIGNATURE_LENGTH) == 0 ) { /* Validate Header image format version */ if ( pImageHeader->formatVersion == HPMFWUPG_IMAGE_HEADER_VERSION ) { /* Validate header checksum */ if ( HpmfwupgCalculateChecksum((unsigned char*)pImageHeader, sizeof(struct HpmfwupgImageHeader) + pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/) != 0 ) { lprintf(LOG_NOTICE,"\n Invalid header checksum"); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Unrecognized image version"); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Invalid image signature"); rc = HPMFWUPG_ERROR; } } return rc; } /**************************************************************************** * * Function Name: HpmfwupgPreparationStage * * Description: This function the preperation stage of a firmware upgrade * procedure as defined in section 3.2 of the IPM Controller * Firmware Upgrade Specification version 1.0 * *****************************************************************************/ int HpmfwupgPreparationStage(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx, int option) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; /* Get device ID */ rc = HpmfwupgGetDeviceId(intf, &pFwupgCtx->devId); /* Match current IPMC IDs with upgrade image */ if ( rc == HPMFWUPG_SUCCESS ) { /* Validate device ID */ if ( pImageHeader->deviceId == pFwupgCtx->devId.device_id ) { /* Validate product ID */ if ( memcmp(pImageHeader->prodId, pFwupgCtx->devId.product_id, HPMFWUPG_PRODUCT_ID_LENGTH ) == 0 ) { /* Validate man ID */ if ( memcmp(pImageHeader->manId, pFwupgCtx->devId.manufacturer_id, HPMFWUPG_MANUFATURER_ID_LENGTH ) != 0 ) { lprintf(LOG_NOTICE,"\n Invalid image file for manufacturer %u", buf2short(pFwupgCtx->devId.manufacturer_id)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Invalid image file for product %u", buf2short(pFwupgCtx->devId.product_id)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"\n Invalid device ID %x", pFwupgCtx->devId.device_id); rc = HPMFWUPG_ERROR; } if (rc != HPMFWUPG_SUCCESS) { /* * Giving one more chance to user to check whether its OK to continue even if the * product ID does not match. This is helpful as sometimes we just want to update * and dont care whether we have a different product Id. If the user says NO then * we need to just bail out from here */ if ( (option & FORCE_MODE) || (option & VIEW_MODE) ) { printf("\n Image Information"); printf("\n Device Id : 0x%x",pImageHeader->deviceId); printf("\n Prod Id : 0x%02x%02x",pImageHeader->prodId[1], pImageHeader->prodId[0]); printf("\n Manuf Id : 0x%02x%02x%02x",pImageHeader->manId[2], pImageHeader->manId[1],pImageHeader->manId[0]); printf("\n Board Information"); printf("\n Device Id : 0x%x", pFwupgCtx->devId.device_id); printf("\n Prod Id : 0x%02x%02x",pFwupgCtx->devId.product_id[1], pFwupgCtx->devId.product_id[0]); printf("\n Manuf Id : 0x%02x%02x%02x",pFwupgCtx->devId.manufacturer_id[2], pFwupgCtx->devId.manufacturer_id[1],pFwupgCtx->devId.manufacturer_id[0]); if (HpmGetUserInput("\n Continue ignoring DeviceID/ProductID/ManufacturingID (Y/N) :")) rc = HPMFWUPG_SUCCESS; } else { /* * If you use all option its kind of FORCE command where we need to upgrade all the components */ printf("\n\n Use \"all\" option for uploading all the components\n"); } } } /* Validate earliest compatible revision */ if ( rc == HPMFWUPG_SUCCESS ) { /* Validate major & minor revision */ if ( pImageHeader->compRevision[0] < pFwupgCtx->devId.fw_rev1 ) { /* Do nothing, upgrade accepted */ } else if ( pImageHeader->compRevision[0] == pFwupgCtx->devId.fw_rev1 ) { /* Must validate minor revision */ if ( pImageHeader->compRevision[1] > pFwupgCtx->devId.fw_rev2 ) { /* Version not compatible for upgrade */ lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]); lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]); lprintf(LOG_NOTICE," Not compatible with "); lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1); lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2); rc = HPMFWUPG_ERROR; } } else { /* Version not compatible for upgrade */ lprintf(LOG_NOTICE,"\n Version: Major: %d", pImageHeader->compRevision[0]); lprintf(LOG_NOTICE," Minor: %x", pImageHeader->compRevision[1]); lprintf(LOG_NOTICE," Not compatible with "); lprintf(LOG_NOTICE," Version: Major: %d", pFwupgCtx->devId.fw_rev1); lprintf(LOG_NOTICE," Minor: %x", pFwupgCtx->devId.fw_rev2); rc = HPMFWUPG_ERROR; } if (rc != HPMFWUPG_SUCCESS) { /* Confirming it once again */ if ( (option & FORCE_MODE) || (option & VIEW_MODE) ) { if( HpmGetUserInput("\n Continue IGNORING Earliest compatibility (Y/N) :")) rc = HPMFWUPG_SUCCESS; } } } /* Get target upgrade capabilities */ if ( rc == HPMFWUPG_SUCCESS ) { struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); if ( rc == HPMFWUPG_SUCCESS ) { /* Copy response to context */ memcpy(&pFwupgCtx->targetCap, &targetCapCmd.resp, sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp)); if (option & VIEW_MODE) { return rc; } else { /* Make sure all component IDs defined in the upgrade image are supported by the IPMC */ if ( (pImageHeader->components.ComponentBits.byte & pFwupgCtx->targetCap.componentsPresent.ComponentBits.byte ) != pImageHeader->components.ComponentBits.byte ) { lprintf(LOG_NOTICE,"\n Some components present in the image file are not supported by the IPMC"); rc = HPMFWUPG_ERROR; } /* Make sure the upgrade is desirable rigth now */ if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.fwUpgUndesirable == 1 ) { lprintf(LOG_NOTICE,"\n Upgrade undesirable at this moment"); rc = HPMFWUPG_ERROR; } /* Get confimation from the user if he wants to continue when service affected during upgrade */ if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.servAffectDuringUpg == 1 || pImageHeader->imageCapabilities.bitField.servAffected == 1 ) { if (HpmGetUserInput("\nServices may be affected during upgrade. Do you wish to continue? y/n ")) { rc = HPMFWUPG_SUCCESS; } else { rc = HPMFWUPG_ERROR; } } } } } /* Get the general properties of each component present in image */ if ( rc == HPMFWUPG_SUCCESS ) { int componentId; for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX; componentId++ ) { /* Reset component properties */ memset(&pFwupgCtx->genCompProp[componentId], 0, sizeof (struct HpmfwupgGetGeneralPropResp)); if ( (1 << componentId & pImageHeader->components.ComponentBits.byte) ) { struct HpmfwupgGetComponentPropertiesCtx getCompPropCmd; /* Get general component properties */ getCompPropCmd.req.componentId = componentId; getCompPropCmd.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES; rc = HpmfwupgGetComponentProperties(intf, &getCompPropCmd); if ( rc == HPMFWUPG_SUCCESS ) { /* Copy response to context */ memcpy(&pFwupgCtx->genCompProp[componentId], &getCompPropCmd.resp, sizeof(struct HpmfwupgGetGeneralPropResp)); } } } } return rc; } /**************************************************************************** * * Function Name: HpmfwupgPreUpgradeCheck * * Description: This function the pre Upgrade check, this mainly helps in checking * which all version upgrade is skippable because the image version * is same as target version. * *****************************************************************************/ int HpmfwupgPreUpgradeCheck(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx, int componentToUpload,int option) { int rc = HPMFWUPG_SUCCESS; unsigned char* pImagePtr; struct HpmfwupgActionRecord* pActionRecord; unsigned int actionsSize; int flagColdReset = FALSE; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; /* Put pointer after image header */ pImagePtr = (unsigned char*) (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) + pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/); /* Deternime actions size */ actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader); if (option & VIEW_MODE) { HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER|IMAGE_VER); } /* Perform actions defined in the image */ while( ( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH)) && ( rc == HPMFWUPG_SUCCESS) ) { /* Get action record */ pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr; /* Validate action record checksum */ if ( HpmfwupgCalculateChecksum((unsigned char*)pActionRecord, sizeof(struct HpmfwupgActionRecord)) != 0 ) { lprintf(LOG_NOTICE," Invalid Action record."); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { switch( pActionRecord->actionType ) { case HPMFWUPG_ACTION_BACKUP_COMPONENTS: { pImagePtr += sizeof(struct HpmfwupgActionRecord); } break; case HPMFWUPG_ACTION_PREPARE_COMPONENTS: { if (componentToUpload != DEFAULT_COMPONENT_UPLOAD) { if (!(1<components.ComponentBits.byte)) { lprintf(LOG_NOTICE,"\nComponent Id given is not supported\n"); return HPMFWUPG_ERROR; } } pImagePtr += sizeof(struct HpmfwupgActionRecord); } break; case HPMFWUPG_ACTION_UPLOAD_FIRMWARE: /* Upload all firmware blocks */ { struct HpmfwupgFirmwareImage* pFwImage; unsigned char* pData; unsigned int firmwareLength = 0; unsigned char mode = 0; unsigned char componentId = 0x00; unsigned char componentIdByte = 0x00; VERSIONINFO *pVersionInfo; // struct HpmfwupgGetComponentPropertiesCtx getCompProp; /* Save component ID on which the upload is done */ componentIdByte = pActionRecord->components.ComponentBits.byte; while ((componentIdByte>>=1)!=0) { componentId++; } pFwupgCtx->componentId = componentId; pFwImage = (struct HpmfwupgFirmwareImage*)(pImagePtr + sizeof(struct HpmfwupgActionRecord)); pData = ((unsigned char*)pFwImage + sizeof(struct HpmfwupgFirmwareImage)); /* Get firmware length */ firmwareLength = pFwImage->length[0]; firmwareLength |= (pFwImage->length[1] << 8) & 0xff00; firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000; firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000; pVersionInfo = &gVersionInfo[componentId]; pVersionInfo->imageMajor = pFwImage->version[0]; pVersionInfo->imageMinor = pFwImage->version[1]; pVersionInfo->imageAux[0] = pFwImage->version[2]; pVersionInfo->imageAux[1] = pFwImage->version[3]; pVersionInfo->imageAux[2] = pFwImage->version[4]; pVersionInfo->imageAux[3] = pFwImage->version[5]; mode = TARGET_VER | IMAGE_VER; if (pVersionInfo->coldResetRequired) { flagColdReset = TRUE; } pVersionInfo->skipUpgrade = FALSE; if (option & FORCE_MODE_ALL) { /* user has given all to upload all the components on the command line */ if(verbose) { lprintf(LOG_NOTICE,"Forcing ALL components"); } } else if( option & FORCE_MODE_COMPONENT ) { if( componentToUpload != componentId ) { if(verbose) { lprintf(LOG_NOTICE,"Forcing component %d skip", componentId); } /* user has given the component Id to upload on the command line */ pVersionInfo->skipUpgrade = TRUE; } else if(verbose) { lprintf(LOG_NOTICE,"Forcing component %d update", componentId); /* user has given the component Id to upload on the command line */ } } else { if ( (pVersionInfo->imageMajor == pVersionInfo->targetMajor) && (pVersionInfo->imageMinor == pVersionInfo->targetMinor)) { if (pVersionInfo->rollbackSupported) { /*If the Image Versions are same as Target Versions then check for the * rollback version*/ if ( (pVersionInfo->imageMajor == pVersionInfo->rollbackMajor) && (pVersionInfo->imageMinor == pVersionInfo->rollbackMinor) ) { /* This indicates that the Rollback version is also same as * Image version -- So now we must skip it */ pVersionInfo->skipUpgrade = TRUE; } mode |= ROLLBACK_VER; } else { pVersionInfo->skipUpgrade = TRUE; } } if ( verbose ) { lprintf(LOG_NOTICE,"Component %d: %s", componentId , (pVersionInfo->skipUpgrade?"skipped":"to update")); } } if( pVersionInfo->skipUpgrade == FALSE ) { pFwupgCtx->compUpdateMask.ComponentBits.byte |= 1<pImageData; struct HpmfwupgActionRecord* pActionRecord; int rc = HPMFWUPG_SUCCESS; unsigned char* pImagePtr; unsigned int actionsSize; int flagColdReset = FALSE; // time_t start,end; /* Put pointer after image header */ pImagePtr = (unsigned char*) (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) + pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/); /* Deternime actions size */ actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader); if (option & VERSIONCHECK_MODE || option & FORCE_MODE) { HpmDisplayUpgradeHeader(0); } /* Perform actions defined in the image */ while( ( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH)) && ( rc == HPMFWUPG_SUCCESS) ) { /* Get action record */ pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr; /* Validate action record checksum */ if ( HpmfwupgCalculateChecksum((unsigned char*)pActionRecord, sizeof(struct HpmfwupgActionRecord)) != 0 ) { lprintf(LOG_NOTICE," Invalid Action record."); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { switch( pActionRecord->actionType ) { case HPMFWUPG_ACTION_BACKUP_COMPONENTS: { /* Send prepare components command */ struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; initUpgActionCmd.req.componentsMask = pFwupgCtx->compUpdateMask; /* Action is prepare components */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_BACKUP; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); pImagePtr += sizeof(struct HpmfwupgActionRecord); } break; case HPMFWUPG_ACTION_PREPARE_COMPONENTS: { int componentId; /* Make sure every components specified by this action supports the prepare components */ /* Component 'filtering' is done in PreUpdateCheck() and pFwupgCtx is set accordiongly */ for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX; componentId++ ) { if ( (1 << componentId & pFwupgCtx->compUpdateMask.ComponentBits.byte) ) { if ( pFwupgCtx->genCompProp[componentId].GeneralCompProperties.bitfield.preparationSupport == 0 ) { lprintf(LOG_NOTICE," Prepare component not supported by component ID %d", componentId); rc = HPMFWUPG_ERROR; break; } } } if ( rc == HPMFWUPG_SUCCESS ) { if ( pFwupgCtx->compUpdateMask.ComponentBits.byte != 0x00 ) { /* Send prepare components command */ struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; initUpgActionCmd.req.componentsMask = pFwupgCtx->compUpdateMask; /* Action is prepare components */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_PREPARE; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); } pImagePtr += sizeof(struct HpmfwupgActionRecord); } } break; case HPMFWUPG_ACTION_UPLOAD_FIRMWARE: /* Upload all firmware blocks */ rc = HpmFwupgActionUploadFirmware ( pActionRecord->components, pFwupgCtx, &pImagePtr, componentToUpload, intf, option, &flagColdReset ); break; default: lprintf(LOG_NOTICE," Invalid Action type. Cannot continue"); rc = HPMFWUPG_ERROR; break; } } } HpmDisplayLine("-",78); if (flagColdReset) { fflush(stdout); lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset"); } return rc; } static int HpmFwupgActionUploadFirmware ( struct HpmfwupgComponentBitMask components, struct HpmfwupgUpgradeCtx* pFwupgCtx, unsigned char** pImagePtr, int componentToUpload, void *intf, int option, int *pFlagColdReset ) { struct HpmfwupgFirmwareImage* pFwImage; struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; struct HpmfwupgUploadFirmwareBlockCtx uploadCmd; struct HpmfwupgFinishFirmwareUploadCtx finishCmd; // struct HpmfwupgGetComponentPropertiesCtx getCompProp; VERSIONINFO *pVersionInfo; time_t start,end; int rc = HPMFWUPG_SUCCESS; int skip = TRUE; unsigned char* pData, *pDataInitial; unsigned char count; unsigned int totalSent = 0; unsigned char bufLength = 0; unsigned int firmwareLength = 0; unsigned int displayFWLength = 0; unsigned char *pDataTemp; unsigned int imageOffset = 0x00; unsigned int blockLength = 0x00; unsigned int lengthOfBlock = 0x00; unsigned int numTxPkts = 0; unsigned int numRxPkts = 0; unsigned char mode = 0; unsigned char componentId = 0x00; unsigned char componentIdByte = 0x00; /* Save component ID on which the upload is done */ componentIdByte = components.ComponentBits.byte; while ((componentIdByte>>=1)!=0) { componentId++; } pFwupgCtx->componentId = componentId; pVersionInfo = (VERSIONINFO*) &gVersionInfo[componentId]; pFwImage = (struct HpmfwupgFirmwareImage*)((*pImagePtr) + sizeof(struct HpmfwupgActionRecord)); pDataInitial = ((unsigned char*)pFwImage + sizeof(struct HpmfwupgFirmwareImage)); pData = pDataInitial; /* Get firmware length */ firmwareLength = pFwImage->length[0]; firmwareLength |= (pFwImage->length[1] << 8) & 0xff00; firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000; firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000; mode = TARGET_VER | IMAGE_VER; if (pVersionInfo->rollbackSupported) { mode |= ROLLBACK_VER; } if ((option & DEBUG_MODE)) { printf("\n\n Comp ID : %d [%-20s]\n",pVersionInfo->componentId,pFwImage->desc); } else { HpmDisplayVersion(mode,pVersionInfo); } if( (1 << componentId) & pFwupgCtx->compUpdateMask.ComponentBits.byte) { if( verbose ) { lprintf(LOG_NOTICE,"Do not skip %d" , componentId); } skip = FALSE; } if(!skip) { /* Initialize parameters */ uploadCmd.req.blockNumber = 0; /* Check if we receive size in parameters */ if(g_channel_buf_size != 0) { if (g_sa == BMC_SA) { bufLength = g_channel_buf_size - 9; /* Plan for overhead */ } else { bufLength = g_channel_buf_size - 11; /* Plan for overhead */ } } else { /* Find max buffer length according the connection parameters */ if ( is_remote() ) /*IPMI LAN*/ { bufLength = HPMFWUPG_SEND_DATA_COUNT_LAN - 2; if (g_sa != BMC_SA) bufLength -= 8; } else { int i; i = get_driver_type(); if ((i == DRV_MV || i == DRV_KCS) && /*open driver*/ (g_sa == BMC_SA) ) { bufLength = HPMFWUPG_SEND_DATA_COUNT_KCS - 2; } else { if ( g_bus == 7 ) { bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMBL; } else { bufLength = HPMFWUPG_SEND_DATA_COUNT_IPMB; } } } } if (verbose) printf("Upgrade buffer size = %d (%d)\n",bufLength,g_channel_buf_size); /* Send Initiate Upgrade Action */ initUpgActionCmd.req.componentsMask = components; /* Action is upgrade */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_UPGRADE; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); if (rc != HPMFWUPG_SUCCESS) { skip = TRUE; } if ( (pVersionInfo->coldResetRequired) && (!skip)) { *pFlagColdReset = TRUE; } /* pDataInitial is the starting pointer of the image data */ /* pDataTemp is one which we will move across */ pData = pDataInitial; pDataTemp = pDataInitial; lengthOfBlock = firmwareLength; totalSent = 0x00; displayFWLength= firmwareLength; time(&start); while ( (pData < (pDataTemp+lengthOfBlock)) && (rc == HPMFWUPG_SUCCESS) ) { if ( (pData+bufLength) <= (pDataTemp+lengthOfBlock) ) { count = bufLength; } else { count = (unsigned char)((pDataTemp+lengthOfBlock) - pData); } memcpy(&uploadCmd.req.data, pData, bufLength); imageOffset = 0x00; blockLength = 0x00; numTxPkts++; rc = HpmfwupgUploadFirmwareBlock(intf, &uploadCmd, pFwupgCtx, count, &imageOffset,&blockLength); numRxPkts++; if ( rc != HPMFWUPG_SUCCESS) { if ( rc == HPMFWUPG_UPLOAD_BLOCK_LENGTH ) { /* Retry with a smaller buffer length */ if ( is_remote() ) // strstr(intf->name,"lan") != NULL { bufLength -= (unsigned char)8; lprintf(LOG_INFO,"Trying reduced buffer length: %d", bufLength); } else { bufLength -= (unsigned char)1; lprintf(LOG_INFO,"Trying reduced buffer length: %d", bufLength); } rc = HPMFWUPG_SUCCESS; } else if ( rc == HPMFWUPG_UPLOAD_RETRY ) { rc = HPMFWUPG_SUCCESS; } else { fflush(stdout); lprintf(LOG_NOTICE,"\n Error in Upload FIRMWARE command [rc=%d]\n",rc); lprintf(LOG_NOTICE,"\n TotalSent:0x%x ",totalSent); /* Exiting from the function */ rc = HPMFWUPG_ERROR; } } else { if (blockLength > firmwareLength) { /* * blockLength is the remaining length of the firmware to upload so * if its greater than the firmware length then its kind of error */ lprintf(LOG_NOTICE,"\n Error in Upload FIRMWARE command [rc=%d]\n",rc); lprintf(LOG_NOTICE,"\n TotalSent:0x%x Img offset:0x%x Blk length:0x%x Fwlen:0x%x\n", totalSent,imageOffset,blockLength,firmwareLength); rc = HPMFWUPG_ERROR; } totalSent += count; if (imageOffset != 0x00) { /* block Length is valid */ lengthOfBlock = blockLength; pDataTemp = pDataInitial + imageOffset; pData = pDataTemp; if ( displayFWLength == firmwareLength) { /* This is basically used only to make sure that we display uptil 100% */ displayFWLength = blockLength + totalSent; } } else { pData += count; } time(&end); /* * Just added debug mode in case we need to see exactly how many bytes have * gone through - Its a hidden option used mainly should be used for debugging */ if ( option & DEBUG_MODE) { fflush(stdout); printf(" Blk Num : %02x Bytes : %05x \r\n", uploadCmd.req.blockNumber,totalSent); if (imageOffset || blockLength) { printf("\r--> ImgOff : %x BlkLen : %x\n",imageOffset,blockLength); } if (displayFWLength == totalSent) { printf(" Time Taken %02d:%02d\n",(end-start)/60, (end-start)%60); printf("\n"); } } else { HpmDisplayUpgrade(0,totalSent,displayFWLength,(end-start)); } uploadCmd.req.blockNumber++; } } } if (skip) { HpmDisplayUpgrade(1,0,0,0); *pImagePtr = pDataInitial + firmwareLength; } if ( (rc == HPMFWUPG_SUCCESS) && (!skip) ) { /* Send finish component */ /* Set image length */ finishCmd.req.componentId = componentId; /* We need to send the actual data that is sent * not the comlete firmware image length */ finishCmd.req.imageLength[0] = totalSent & 0xFF; finishCmd.req.imageLength[1] = (totalSent >> 8) & 0xFF; finishCmd.req.imageLength[2] = (totalSent >> 16) & 0xFF; finishCmd.req.imageLength[3] = (totalSent >> 24) & 0xFF; rc = HpmfwupgFinishFirmwareUpload(intf, &finishCmd, pFwupgCtx); if ( option & DEBUG_MODE) printf("HpmfwupgFinishFirmwareUpload rc = %d sent = %d\n",rc,totalSent); *pImagePtr = pDataInitial + firmwareLength; } return rc; } /**************************************************************************** * * Function Name: HpmfwupgActivationStage * * Description: This function the validation stage of a firmware upgrade * procedure as defined in section 3.4 of the IPM Controller * Firmware Upgrade Specification version 1.0 * *****************************************************************************/ static int HpmfwupgActivationStage(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgActivateFirmwareCtx activateCmd; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; /* Print out stuf...*/ printf(" "); fflush(stdout); /* Activate new firmware */ rc = HpmfwupgActivateFirmware(intf, &activateCmd, pFwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { /* Query self test result if supported by target and new image */ if ( (pFwupgCtx->targetCap.GlobalCapabilities.bitField.ipmcSelftestCap == 1) || (pImageHeader->imageCapabilities.bitField.imageSelfTest == 1) ) { struct HpmfwupgQuerySelftestResultCtx selfTestCmd; rc = HpmfwupgQuerySelftestResult(intf, &selfTestCmd, pFwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { /* Get the self test result */ if ( selfTestCmd.resp.result1 != 0x55 ) { /* Perform manual rollback if necessary */ /* BACKUP/ MANUAL ROLLBACK not supported by this UA */ lprintf(LOG_NOTICE," Self test failed:"); lprintf(LOG_NOTICE," Result1 = %x", selfTestCmd.resp.result1); lprintf(LOG_NOTICE," Result2 = %x", selfTestCmd.resp.result2); rc = HPMFWUPG_ERROR; } } else { /* Perform manual rollback if necessary */ /* BACKUP / MANUAL ROLLBACK not supported by this UA */ lprintf(LOG_NOTICE," Self test failed."); } } } /* If activation / self test failed, query rollback status if automatic rollback supported */ if ( rc == HPMFWUPG_ERROR ) { if ( (pFwupgCtx->targetCap.GlobalCapabilities.bitField.autRollback == 1) && (pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.rollbackBackup != 0x00) ) { struct HpmfwupgQueryRollbackStatusCtx rollCmd; lprintf(LOG_NOTICE," Getting rollback status..."); fflush(stdout); rc = HpmfwupgQueryRollbackStatus(intf, &rollCmd, pFwupgCtx); } } return rc; } int HpmfwupgGetBufferFromFile(char* imageFilename, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; FILE* pImageFile = fopen(imageFilename, "rb"); if ( pImageFile == NULL ) { lprintf(LOG_NOTICE,"Cannot open image file %s", imageFilename); rc = HPMFWUPG_ERROR; } if ( rc == HPMFWUPG_SUCCESS ) { /* Get the raw data in file */ fseek(pImageFile, 0, SEEK_END); pFwupgCtx->imageSize = ftell(pImageFile); pFwupgCtx->pImageData = malloc(sizeof(unsigned char)*pFwupgCtx->imageSize); pFwupgCtx->compUpdateMask.ComponentBits.byte = 0; rewind(pImageFile); if ( pFwupgCtx->pImageData != NULL ) { fread(pFwupgCtx->pImageData, sizeof(unsigned char), pFwupgCtx->imageSize, pImageFile); } else { rc = HPMFWUPG_ERROR; } fclose(pImageFile); } return rc; } int HpmfwupgGetDeviceId(void *intf, struct ipm_devid_rsp* pGetDevId) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_APP; req.msg.cmd = BMC_GET_DEVICE_ID; req.msg.data_len = 0; rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(pGetDevId, rsp->data, sizeof(struct ipm_devid_rsp)); } else { lprintf(LOG_NOTICE,"Error getting device ID, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting device ID\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgGetTargetUpgCapabilities(void *intf, struct HpmfwupgGetTargetUpgCapabilitiesCtx* pCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_GET_TARGET_UPG_CAPABILITIES; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgGetTargetUpgCapabilitiesReq); rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp)); if ( verbose ) { lprintf(LOG_NOTICE,"TARGET UPGRADE CAPABILITIES"); lprintf(LOG_NOTICE,"-------------------------------"); lprintf(LOG_NOTICE,"HPM.1 version............%d ", pCtx->resp.hpmVersion); lprintf(LOG_NOTICE,"Component 0 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component0 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 1 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component1 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 2 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component2 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 3 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component3 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 4 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component4 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 5 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component5 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 6 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component6 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Component 7 presence....[%c] ", pCtx->resp.componentsPresent.ComponentBits. bitField.component7 ? 'y' : 'n'); lprintf(LOG_NOTICE,"Upgrade undesirable.....[%c] ", pCtx->resp.GlobalCapabilities. bitField.fwUpgUndesirable ? 'y' : 'n'); lprintf(LOG_NOTICE,"Aut rollback override...[%c] ", pCtx->resp.GlobalCapabilities. bitField.autRollbackOverride ? 'y' : 'n'); lprintf(LOG_NOTICE,"IPMC degraded...........[%c] ", pCtx->resp.GlobalCapabilities. bitField.ipmcDegradedDurinUpg ? 'y' : 'n'); lprintf(LOG_NOTICE,"Defered activation......[%c] ", pCtx->resp.GlobalCapabilities. bitField.deferActivation ? 'y' : 'n'); lprintf(LOG_NOTICE,"Service affected........[%c] ", pCtx->resp.GlobalCapabilities. bitField.servAffectDuringUpg ? 'y' : 'n'); lprintf(LOG_NOTICE,"Manual rollback.........[%c] ", pCtx->resp.GlobalCapabilities. bitField.manualRollback ? 'y' : 'n'); lprintf(LOG_NOTICE,"Automatic rollback......[%c] ", pCtx->resp.GlobalCapabilities. bitField.autRollback ? 'y' : 'n'); lprintf(LOG_NOTICE,"Self test...............[%c] ", pCtx->resp.GlobalCapabilities. bitField.ipmcSelftestCap ? 'y' : 'n'); lprintf(LOG_NOTICE,"Upgrade timeout.........[%d sec] ", pCtx->resp.upgradeTimeout*5); lprintf(LOG_NOTICE,"Self test timeout.......[%d sec] ", pCtx->resp.selftestTimeout*5); lprintf(LOG_NOTICE,"Rollback timeout........[%d sec] ", pCtx->resp.rollbackTimeout*5); lprintf(LOG_NOTICE,"Inaccessibility timeout.[%d sec] \n", pCtx->resp.inaccessTimeout*5); } } else { lprintf(LOG_NOTICE,"Error getting target upgrade capabilities\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting target upgrade capabilities\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgGetComponentProperties(void *intf, struct HpmfwupgGetComponentPropertiesCtx* pCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_GET_COMPONENT_PROPERTIES; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgGetComponentPropertiesReq); rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode == 0x00 ) { switch ( pCtx->req.selector ) { case HPMFWUPG_COMP_GEN_PROPERTIES: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetGeneralPropResp)); if ( verbose ) { lprintf(LOG_NOTICE,"GENERAL PROPERTIES"); lprintf(LOG_NOTICE,"-------------------------------"); lprintf(LOG_NOTICE,"Payload cold reset req....[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.payloadColdReset ? 'y' : 'n'); lprintf(LOG_NOTICE,"Def. activation supported.[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.deferredActivation ? 'y' : 'n'); lprintf(LOG_NOTICE,"Comparison supported......[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.comparisonSupport ? 'y' : 'n'); lprintf(LOG_NOTICE,"Preparation supported.....[%c] ", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.preparationSupport ? 'y' : 'n'); lprintf(LOG_NOTICE,"Rollback supported........[%c] \n", pCtx->resp.Response.generalPropResp. GeneralCompProperties.bitfield.rollbackBackup ? 'y' : 'n'); } break; case HPMFWUPG_COMP_CURRENT_VERSION: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetCurrentVersionResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Current Version: "); lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.currentVersionResp.currentVersion[0]); lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.currentVersionResp.currentVersion[1]); lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.currentVersionResp.currentVersion[2], pCtx->resp.Response.currentVersionResp.currentVersion[3], pCtx->resp.Response.currentVersionResp.currentVersion[4], pCtx->resp.Response.currentVersionResp.currentVersion[5]); } break; case HPMFWUPG_COMP_DESCRIPTION_STRING: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDescStringResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Description string: %s\n", pCtx->resp.Response.descStringResp.descString); } break; case HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetRollbackFwVersionResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Rollback FW Version: "); lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[0]); lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[1]); lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[2], pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[3], pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[4], pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[5]); } break; case HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDeferredFwVersionResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Deferred FW Version: "); lprintf(LOG_NOTICE," Major: %d", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[0]); lprintf(LOG_NOTICE," Minor: %x", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[1]); lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d\n", pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[2], pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[3], pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[4], pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[5]); } break; // OEM Properties command case HPMFWUPG_COMP_OEM_PROPERTIES: memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetOemProperties)); if ( verbose ) { unsigned char i = 0; lprintf(LOG_NOTICE,"OEM Properties: "); for (i=0; i < HPMFWUPG_OEM_LENGTH; i++) { lprintf(LOG_NOTICE," 0x%x ", pCtx->resp.Response.oemProperties.oemRspData[i]); } } break; default: lprintf(LOG_NOTICE,"Unsupported component selector"); rc = HPMFWUPG_ERROR; break; } } else { lprintf(LOG_NOTICE,"Error getting component properties, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting component properties\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgAbortUpgrade(void *intf, struct HpmfwupgAbortUpgradeCtx* pCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_ABORT_UPGRADE; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgAbortUpgradeReq); rsp = HpmfwupgSendCmd(intf, req, NULL); if ( rsp ) { if ( rsp->ccode != 0x00 ) { lprintf(LOG_NOTICE,"Error aborting upgrade, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error aborting upgrade\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgInitiateUpgradeAction(void *intf, struct HpmfwupgInitiateUpgradeActionCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_INITIATE_UPGRADE_ACTION; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgInitiateUpgradeActionReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ) { rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); } else if ( rsp->ccode != 0x00 ) { lprintf(LOG_NOTICE,"Error initiating upgrade action, compcode = %x %s\n", rsp->ccode, hpm_decode_cc(req.msg.cmd,rsp->ccode)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error initiating upgrade action\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgUploadFirmwareBlock(void *intf, struct HpmfwupgUploadFirmwareBlockCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx, int count ,unsigned int *imageOffset, unsigned int *blockLength ) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_UPLOAD_FIRMWARE_BLOCK; req.msg.data = (unsigned char*)&pCtx->req; /* 2 is the size of the upload struct - data */ req.msg.data_len = 2 + count; rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS || rsp->ccode == 0x00 ) { /* * We need to check if the response also contains the next upload firmware offset * and the firmware length in its response - These are optional but very vital */ if ( rsp->data_len > 1 ) { /* * If the response data length is greater than 1 it should contain both the * the Section offset and section length. Because we cannot just have * Section offset without section length so the length should be 9 */ if ( rsp->data_len == 9 ) { /* rsp->data[1] - LSB rsp->data[2] - rsp->data[3] = MSB */ *imageOffset = (rsp->data[4] << 24) + (rsp->data[3] << 16) + (rsp->data[2] << 8) + rsp->data[1]; *blockLength = (rsp->data[8] << 24) + (rsp->data[7] << 16) + (rsp->data[6] << 8) + rsp->data[5]; } else { /* * The Spec does not say much for this kind of errors where the * firmware returned only offset and length so currently returning it * as 0x82 - Internal CheckSum Error */ lprintf(LOG_NOTICE,"Error wrong rsp->datalen %d for Upload Firmware block command\n",rsp->data_len); rsp->ccode = HPMFWUPG_INT_CHECKSUM_ERROR; } } } /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ) { rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); } else if (rsp->ccode != 0x00) { /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); rc = HPMFWUPG_UPLOAD_RETRY; } /* * If completion code = 0xc7, we will retry with a reduced buffer length. * Do not print error. */ else if ( rsp->ccode == IPMI_CC_REQ_DATA_INV_LENGTH ) { rc = HPMFWUPG_UPLOAD_BLOCK_LENGTH; } else { lprintf(LOG_NOTICE,"Error uploading firmware block, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } } else { lprintf(LOG_NOTICE,"Error uploading firmware block\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgFinishFirmwareUpload(void *intf, struct HpmfwupgFinishFirmwareUploadCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_FINISH_FIRMWARE_UPLOAD; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgFinishFirmwareUploadReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); } else if ( rsp->ccode != IPMI_CC_OK ) { lprintf(LOG_NOTICE,"Error finishing firmware upload, compcode = %x %s\n", rsp->ccode, hpm_decode_cc(req.msg.cmd,rsp->ccode)); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error finishing firmware upload\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgActivateFirmware(void *intf, struct HpmfwupgActivateFirmwareCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_ACTIVATE_FIRMWARE; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgActivateFirmwareReq) - (!pCtx->req.rollback_override ? 1 : 0); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { printf("Waiting firmware activation..."); fflush(stdout); rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); if ( rc == HPMFWUPG_SUCCESS ) { lprintf(LOG_NOTICE,"OK"); } else { lprintf(LOG_NOTICE,"Failed"); } } else if (rsp->ccode == HPMFWUPG_NOT_SUPPORTED_NOW) /*0xd5*/ { printf("Activation already completed.\n"); rc = HPMFWUPG_SUCCESS; } else if ( rsp->ccode != IPMI_CC_OK ) { lprintf(LOG_NOTICE,"Error activating firmware, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error activating firmware\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgGetUpgradeStatus(void *intf, struct HpmfwupgGetUpgradeStatusCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_GET_UPGRADE_STATUS; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgGetUpgradeStatusReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetUpgradeStatusResp)); if ( verbose > 1 ) { lprintf(LOG_NOTICE,"Upgrade status:"); lprintf(LOG_NOTICE," Command in progress: %x", pCtx->resp.cmdInProcess); lprintf(LOG_NOTICE," Last command completion code: %x", pCtx->resp.lastCmdCompCode); } } /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ else if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); pCtx->resp.lastCmdCompCode = HPMFWUPG_COMMAND_IN_PROGRESS; } else { if ( verbose ) { lprintf(LOG_NOTICE,"Error getting upgrade status, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } } else { if ( verbose ) { lprintf(LOG_NOTICE,"Error getting upgrade status"); rc = HPMFWUPG_ERROR; } } return rc; } int HpmfwupgManualFirmwareRollback(void *intf, struct HpmfwupgManualFirmwareRollbackCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgManualFirmwareRollbackReq); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); if ( rsp ) { /* Long duration command handling */ if ( rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS ) { struct HpmfwupgQueryRollbackStatusCtx resCmd; printf("Waiting firmware rollback..."); fflush(stdout); rc = HpmfwupgQueryRollbackStatus(intf, &resCmd, pFwupgCtx); } else if ( rsp->ccode != 0x00 ) { lprintf(LOG_NOTICE,"Error sending manual rollback, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error sending manual rollback\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgQueryRollbackStatus(void *intf, struct HpmfwupgQueryRollbackStatusCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; unsigned int rollbackTimeout = 0; unsigned int timeoutSec1, timeoutSec2; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_QUERY_ROLLBACK_STATUS; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgQueryRollbackStatusReq); /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { rollbackTimeout = pFwupgCtx->targetCap.rollbackTimeout*5; } else { struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; verbose--; rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); verbose++; if ( rc == HPMFWUPG_SUCCESS ) { rollbackTimeout = targetCapCmd.resp.rollbackTimeout *5; } else { rollbackTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; } } /* Poll rollback status until completion or timeout */ timeoutSec1 = (uint32_t)time(NULL); timeoutSec2 = (uint32_t)time(NULL); do { /* Must wait at least 100 ms between status requests */ os_usleep(0,100000); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ if ( rsp ) { if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS; } } timeoutSec2 = (uint32_t)time(NULL); }while( rsp && (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) && (timeoutSec2 - timeoutSec1 < rollbackTimeout ) ); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgQueryRollbackStatusResp)); if ( pCtx->resp.rollbackComp.ComponentBits.byte != 0 ) { /* Rollback occured */ lprintf(LOG_NOTICE,"Rollback occured on component mask: 0x%02x", pCtx->resp.rollbackComp.ComponentBits.byte); } else { lprintf(LOG_NOTICE,"No Firmware rollback occured"); } } else if ( rsp->ccode == 0x81 ) { lprintf(LOG_NOTICE,"Rollback failed on component mask: 0x%02x", pCtx->resp.rollbackComp.ComponentBits.byte); rc = HPMFWUPG_ERROR; } else { lprintf(LOG_NOTICE,"Error getting rollback status, compcode = %x", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting upgrade status\n"); rc = HPMFWUPG_ERROR; } return rc; } int HpmfwupgQuerySelftestResult(void *intf, struct HpmfwupgQuerySelftestResultCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; struct ipmi_rs * rsp; struct ipmi_rq req; unsigned char selfTestTimeout = 0; unsigned int timeoutSec1, timeoutSec2; pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { /* Getting selftest timeout from new image */ struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) pFwupgCtx->pImageData; selfTestTimeout = pImageHeader->selfTestTimeout; } else { selfTestTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; } memset(&req, 0, sizeof(req)); req.msg.netfn = IPMI_NETFN_PICMG; req.msg.cmd = HPMFWUPG_QUERY_SELFTEST_RESULT; req.msg.data = (unsigned char*)&pCtx->req; req.msg.data_len = sizeof(struct HpmfwupgQuerySelftestResultReq); /* Poll rollback status until completion or timeout */ timeoutSec1 = (uint32_t)time(NULL); timeoutSec2 = (uint32_t)time(NULL); do { /* Must wait at least 100 ms between status requests */ os_usleep(0,100000); rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); /* * PATCH --> This validation is to handle retryables errors codes on IPMB bus. * This will be fixed in the next release of open ipmi and this * check will have to be removed. (Buggy version = 39) */ if ( rsp ) { if ( HPMFWUPG_IS_RETRYABLE(rsp->ccode) ) { lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS; } } timeoutSec2 = (uint32_t)time(NULL); }while( rsp && (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) && (timeoutSec2 - timeoutSec1 < selfTestTimeout ) ); if ( rsp ) { if ( rsp->ccode == 0x00 ) { memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgQuerySelftestResultResp)); if ( verbose ) { lprintf(LOG_NOTICE,"Self test results:"); lprintf(LOG_NOTICE,"Result1 = %x", pCtx->resp.result1); lprintf(LOG_NOTICE,"Result2 = %x", pCtx->resp.result2); } } else { lprintf(LOG_NOTICE,"Error getting self test results, compcode = %x\n", rsp->ccode); rc = HPMFWUPG_ERROR; } } else { lprintf(LOG_NOTICE,"Error getting upgrade status\n"); rc = HPMFWUPG_ERROR; } return rc; } struct ipmi_rs * HpmfwupgSendCmd(void *intf, struct ipmi_rq req, struct HpmfwupgUpgradeCtx* pFwupgCtx ) { struct ipmi_rs * rsp; unsigned int inaccessTimeout = 0, inaccessTimeoutCounter = 0; unsigned int upgradeTimeout = 0, upgradeTimeoutCounter = 0; unsigned int timeoutSec1, timeoutSec2; unsigned char retry = 0; static struct ipmi_rs fakeRsp; int rv, rsp_len; /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { inaccessTimeout = pFwupgCtx->targetCap.inaccessTimeout*5; upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5; } else { /* keeping the inaccessTimeout to 60 seconds results in almost 2900 retries * So if the target is not available it will be retrying the command for 2900 * times which is not effecient -So reducing the Timout to 5 seconds which is * almost 200 retries if it continuously recieves 0xC3 as completion code. */ inaccessTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; } timeoutSec1 = (uint32_t)time(NULL); do { static unsigned char isValidSize = FALSE; rv = ipmi_sendrecv(&req, fakeRsp.data, &rsp_len); if( rv < 0) { #define HPM_LAN_PACKET_RESIZE_LIMIT 6 if(is_remote()) /* also covers lanplus */ { static int errorCount=0; lprintf(LOG_DEBUG,"HPM: no response available"); lprintf(LOG_DEBUG,"HPM: the command may be rejected for " \ "security reasons"); if ( req.msg.netfn == IPMI_NETFN_PICMG && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK && errorCount < HPM_LAN_PACKET_RESIZE_LIMIT && (!isValidSize) ) { lprintf(LOG_DEBUG,"HPM: upload firmware block API called"); lprintf(LOG_DEBUG,"HPM: returning length error to force resize"); fakeRsp.ccode = IPMI_CC_REQ_DATA_INV_LENGTH; rv = fakeRsp.ccode; rsp = &fakeRsp; errorCount++; } else if ( req.msg.netfn == IPMI_NETFN_PICMG && ( req.msg.cmd == HPMFWUPG_ACTIVATE_FIRMWARE || req.msg.cmd == HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK ) ) { /* * rsp == NULL and command activate firmware or manual firmware * rollback most likely occurs when we have sent a firmware activation * request. Fake a command in progress response. */ lprintf(LOG_DEBUG,"HPM: activate/rollback firmware API called"); lprintf(LOG_DEBUG,"HPM: returning in progress to handle IOL session lost"); fakeRsp.ccode = HPMFWUPG_COMMAND_IN_PROGRESS; rv = fakeRsp.ccode; rsp = &fakeRsp; } else if ( req.msg.netfn == IPMI_NETFN_PICMG && ( req.msg.cmd == HPMFWUPG_QUERY_ROLLBACK_STATUS || req.msg.cmd == HPMFWUPG_GET_UPGRADE_STATUS ) ) { /* * rsp == NULL and command get upgrade status or query rollback * status most likely occurs when we are waiting for firmware * activation. Try to re-open the IOL session (re-open will work * once the IPMC recovers from firmware activation. */ lprintf(LOG_DEBUG,"HPM: upg/rollback status firmware API called"); lprintf(LOG_DEBUG,"HPM: try to re-open IOL session"); { /* force session re-open */ ipmi_close_(); os_usleep(inaccessTimeout,0); /* Fake timeout to retry command */ fakeRsp.ccode = 0xc3; rv = fakeRsp.ccode; rsp = &fakeRsp; } } } } /* Handle inaccessibility timeout (rsp = NULL if IOL) */ if ( rv < 0 || rv == 0xff || rv == 0xc3 || rv == 0xd3 ) { if ( inaccessTimeoutCounter < inaccessTimeout ) { timeoutSec2 = (uint32_t)time(NULL); if ( timeoutSec2 > timeoutSec1 ) { inaccessTimeoutCounter += timeoutSec2 - timeoutSec1; timeoutSec1 = (uint32_t)time(NULL); } os_usleep(0,100000); retry = 1; } else { retry = 0; } } /* Handle node busy timeout */ else if ( rv == 0xc0 ) { if ( upgradeTimeoutCounter < upgradeTimeout ) { timeoutSec2 = (uint32_t)time(NULL); if ( timeoutSec2 > timeoutSec1 ) { timeoutSec1 = (uint32_t)time(NULL); // upgradeTimeoutCounter += timeoutSec2 - timeoutSec1; upgradeTimeoutCounter += 1; } os_usleep(0,100000); retry = 1; } else { retry = 0; } } else { #ifdef ENABLE_OPENIPMI_V39_PATCH if( rv == IPMI_CC_OK ) { errorCount = 0 ; } #endif retry = 0; if ( req.msg.netfn == IPMI_NETFN_PICMG && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK && (!isValidSize) ) { lprintf(LOG_INFO,"Buffer length is now considered valid" ); isValidSize = TRUE; } } }while( retry ); if (rv < 0) rsp = NULL; else { rsp = &fakeRsp; /*has data already*/ rsp->ccode = (uchar)rv; rsp->session.payloadtype = 0; /*IPMI_PAYLOAD_TYPE_IPMI*/ rsp->data_len = rsp_len; } return rsp; } int HpmfwupgWaitLongDurationCmd(void *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx) { int rc = HPMFWUPG_SUCCESS; unsigned int upgradeTimeout = 0; unsigned int timeoutSec1, timeoutSec2; struct HpmfwupgGetUpgradeStatusCtx upgStatusCmd; /* * If we are not in upgrade context, we use default timeout values */ if ( pFwupgCtx != NULL ) { upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5; if ( verbose ) printf("Use File Upgrade Capabilities: %i seconds\n", upgradeTimeout); } else { /* Try to retreive from Caps */ struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; if(HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd) != HPMFWUPG_SUCCESS) { upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; if ( verbose ) printf("Use default timeout: %i seconds\n", upgradeTimeout); } else { upgradeTimeout = (targetCapCmd.resp.upgradeTimeout * 5); if ( verbose ) printf("Use Command Upgrade Capabilities Timeout: %i seconds\n", upgradeTimeout); } } if(rc == HPMFWUPG_SUCCESS) { /* Poll upgrade status until completion or timeout*/ timeoutSec1 = (uint32_t)time(NULL); timeoutSec2 = (uint32_t)time(NULL); rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx); } while( (upgStatusCmd.resp.lastCmdCompCode == HPMFWUPG_COMMAND_IN_PROGRESS ) && (timeoutSec2 - timeoutSec1 < upgradeTimeout ) && (rc == HPMFWUPG_SUCCESS) ) { /* Must wait at least 1000 ms between status requests */ os_usleep(0,1000000); rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx); //printf("Get Status: %x - %x = %x _ %x [%x]\n", timeoutSec2, timeoutSec1,(timeoutSec2 - timeoutSec1),upgradeTimeout, rc); } if ( upgStatusCmd.resp.lastCmdCompCode != 0x00 ) { if ( verbose ) { lprintf(LOG_NOTICE,"Error waiting for command %x, compcode = %x", upgStatusCmd.resp.cmdInProcess, upgStatusCmd.resp.lastCmdCompCode, hpm_decode_cc(upgStatusCmd.resp.cmdInProcess, upgStatusCmd.resp.lastCmdCompCode)); } rc = HPMFWUPG_ERROR; } return rc; } unsigned char HpmfwupgCalculateChecksum(unsigned char* pData, unsigned int length) { unsigned char checksum = 0; int dataIdx = 0; for ( dataIdx = 0; dataIdx < (int)length; dataIdx++ ) { checksum += pData[dataIdx]; } return checksum; } static void HpmfwupgPrintUsage(void) { lprintf(LOG_NOTICE,"help - This help menu"); lprintf(LOG_NOTICE,"check - Check the target information"); lprintf(LOG_NOTICE,"check - If the user is unsure of what update is going to be "); lprintf(LOG_NOTICE," This will display the existing target version and image "); lprintf(LOG_NOTICE," version on the screen"); lprintf(LOG_NOTICE,"upgrade - Upgrade the firmware using a valid HPM.1 image "); lprintf(LOG_NOTICE," This checks the version from the file and image and "); lprintf(LOG_NOTICE," if it differs then only updates else skips"); lprintf(LOG_NOTICE,"upgrade all - Updates all the components present in the file on the target board"); lprintf(LOG_NOTICE," without skipping (use this only after using \"check\" command"); lprintf(LOG_NOTICE,"upgrade component x - Upgrade only component from the given "); lprintf(LOG_NOTICE," component 0 - BOOT"); lprintf(LOG_NOTICE," component 1 - RTK"); lprintf(LOG_NOTICE,"upgrade activate - Upgrade the firmware using a valid HPM.1 image "); lprintf(LOG_NOTICE," If activate is specified, activate new firmware rigth"); lprintf(LOG_NOTICE," away"); lprintf(LOG_NOTICE,"activate [norollback] - Activate the newly uploaded firmware"); lprintf(LOG_NOTICE,"targetcap - Get the target upgrade capabilities"); lprintf(LOG_NOTICE,"compprop can be one of the following: "); lprintf(LOG_NOTICE," 0- General properties"); lprintf(LOG_NOTICE," 1- Current firmware version"); lprintf(LOG_NOTICE," 2- Description string"); lprintf(LOG_NOTICE," 3- Rollback firmware version"); lprintf(LOG_NOTICE," 4- Deferred firmware version"); lprintf(LOG_NOTICE,"abort - Abort the on-going firmware upgrade"); lprintf(LOG_NOTICE,"upgstatus - Returns the status of the last long duration command"); lprintf(LOG_NOTICE,"rollback - Performs a manual rollback on the IPM Controller"); lprintf(LOG_NOTICE," firmware"); lprintf(LOG_NOTICE,"rollbackstatus - Query the rollback status"); lprintf(LOG_NOTICE,"selftestresult - Query the self test results\n"); } int ipmi_hpmfwupg_main(void * intf, int argc, char ** argv) { int rc = HPMFWUPG_SUCCESS; int activateFlag = 0x00; int componentId = DEFAULT_COMPONENT_UPLOAD; int option = VERSIONCHECK_MODE; lprintf(LOG_DEBUG,"ipmi_hpmfwupg_main()"); lprintf(LOG_NOTICE,"\nPICMG HPM.1 Upgrade Agent %d.%d.%d: \n", HPMFWUPG_VERSION_MAJOR, HPMFWUPG_VERSION_MINOR, HPMFWUPG_VERSION_SUBMINOR); if ( (argc == 0) || (strcmp(argv[0], "help") == 0) ) { HpmfwupgPrintUsage(); return ERR_USAGE; } if ( (strcmp(argv[0], "check") == 0) ) { /* hpm check */ if (argv[1] == NULL) { rc = HpmfwupgTargetCheck(intf,VIEW_MODE); } else { /* hpm check */ rc = HpmfwupgTargetCheck(intf,0); if (rc == HPMFWUPG_SUCCESS) { rc = HpmfwupgUpgrade(intf, argv[1],0,DEFAULT_COMPONENT_UPLOAD,VIEW_MODE); } } } else if ( strcmp(argv[0], "upgrade") == 0) { int i =0; if (fdebug) option |= DEBUG_MODE; if (g_channel_buf_size > 0) printf("Large buffer size %d specified\n", g_channel_buf_size ); for (i=1; i< argc ; i++) { if (strcmp(argv[i],"activate") == 0) { activateFlag = 1; } /* hpm upgrade all */ if (strcmp(argv[i],"all") == 0) { option &= ~(VERSIONCHECK_MODE); option &= ~(VIEW_MODE); option |= FORCE_MODE_ALL; } /* hpm upgrade component */ if (strcmp(argv[i],"component") == 0) { if (i+1 < argc) { componentId = atoi(argv[i+1]); option &= ~(VERSIONCHECK_MODE); option &= ~(VIEW_MODE); option |= FORCE_MODE_COMPONENT; if( verbose ) { lprintf(LOG_NOTICE,"Component Id %d provided",componentId ); } /* Error Checking */ if (componentId >= HPMFWUPG_COMPONENT_ID_MAX) { lprintf(LOG_NOTICE,"Given component ID %d exceeds Max Comp ID %d\n", componentId, HPMFWUPG_COMPONENT_ID_MAX-1); return HPMFWUPG_ERROR; } } if (componentId == DEFAULT_COMPONENT_UPLOAD) { /* That indicates the user has given component on console but not * given any ID */ lprintf(LOG_NOTICE,"No component Id provided\n"); return HPMFWUPG_ERROR; } } if (strcmp(argv[i],"debug") == 0) { option |= DEBUG_MODE; } } rc = HpmfwupgTargetCheck(intf,0); if (rc == HPMFWUPG_SUCCESS) { /* Call the Upgrade function to start the upgrade */ rc = HpmfwupgUpgrade(intf, argv[1],activateFlag,componentId,option); } } else if ( (argc >= 1) && (strcmp(argv[0], "activate") == 0) ) { struct HpmfwupgActivateFirmwareCtx cmdCtx; if ( (argc == 2) && (strcmp(argv[1], "norollback") == 0) ) cmdCtx.req.rollback_override = 1; else cmdCtx.req.rollback_override = 0; rc = HpmfwupgActivateFirmware(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "targetcap") == 0) ) { struct HpmfwupgGetTargetUpgCapabilitiesCtx cmdCtx; verbose++; rc = HpmfwupgGetTargetUpgCapabilities(intf, &cmdCtx); } else if ( (argc == 3) && (strcmp(argv[0], "compprop") == 0) ) { struct HpmfwupgGetComponentPropertiesCtx cmdCtx; cmdCtx.req.componentId = atob(argv[1]); cmdCtx.req.selector = atob(argv[2]); verbose++; rc = HpmfwupgGetComponentProperties(intf, &cmdCtx); } else if ( (argc == 1) && (strcmp(argv[0], "abort") == 0) ) { struct HpmfwupgAbortUpgradeCtx cmdCtx; verbose++; rc = HpmfwupgAbortUpgrade(intf, &cmdCtx); } else if ( (argc == 1) && (strcmp(argv[0], "upgstatus") == 0) ) { struct HpmfwupgGetUpgradeStatusCtx cmdCtx; verbose++; rc = HpmfwupgGetUpgradeStatus(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "rollback") == 0) ) { struct HpmfwupgManualFirmwareRollbackCtx cmdCtx; verbose++; rc = HpmfwupgManualFirmwareRollback(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "rollbackstatus") == 0) ) { struct HpmfwupgQueryRollbackStatusCtx cmdCtx; verbose++; rc = HpmfwupgQueryRollbackStatus(intf, &cmdCtx, NULL); } else if ( (argc == 1) && (strcmp(argv[0], "selftestresult") == 0) ) { struct HpmfwupgQuerySelftestResultCtx cmdCtx; verbose++; rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL); } else { HpmfwupgPrintUsage(); } return rc; } #ifdef METACOMMAND int i_hpm(int argc, char **argv) #else #ifdef WIN32 int __cdecl #else int #endif main(int argc, char **argv) #endif { void *intf = NULL; int rc = 0; int c, i; char *s1; printf("%s ver %s\n", progname,progver); set_loglevel(LOG_NOTICE); while ( (c = getopt( argc, argv,"m:z:T:V:J:EYF:P:N:R:U:Z:x?")) != EOF ) switch (c) { case 'm': /* specific IPMB MC, 3-byte address, e.g. "409600" */ g_bus = htoi(&optarg[0]); /*bus/channel*/ g_sa = htoi(&optarg[2]); /*device slave address*/ g_lun = htoi(&optarg[4]); /*LUN*/ g_addrtype = ADDR_IPMB; if (optarg[6] == 's') { g_addrtype = ADDR_SMI; s1 = "SMI"; } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; } ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype); printf("Use MC at %s bus=%x sa=%x lun=%x\n", s1,g_bus,g_sa,g_lun); break; case 'z': g_channel_buf_size = atoi(optarg); if (g_channel_buf_size < HPMFWUPG_SEND_DATA_COUNT_LAN) rc = ERR_BAD_LENGTH; else if (g_channel_buf_size > IPMI_REQBUF_SIZE) rc = LAN_ERR_BADLENGTH; if (rc != 0) { printf("Invalid buffer size %d\n",g_channel_buf_size); return rc; } break; case 'x': fdebug = 1; verbose = 1; set_loglevel(LOG_DEBUG); break; /* debug messages */ case 'N': /* nodename */ case 'U': /* remote username */ case 'P': /* remote password */ case 'R': /* remote password */ case 'E': /* get password from IPMI_PASSWORD environment var */ case 'F': /* force driver type */ case 'T': /* auth type */ case 'J': /* cipher suite */ case 'V': /* priv level */ case 'Y': /* prompt for remote password */ case 'Z': /* set local MC address */ parse_lan_options(c,optarg,fdebug); break; case '?': HpmfwupgPrintUsage(); return ERR_USAGE; break; } for (i = 0; i < optind; i++) { argv++; argc--; } rc = ipmi_hpmfwupg_main(intf, argc, argv); ipmi_close_(); // show_outcome(progname,rc); return rc; } /* end ihpm.c */