diff --git a/ipmitool/lib/ipmi_hpmfwupg.c b/ipmitool/lib/ipmi_hpmfwupg.c index 0a26bc8..08b929e 100644 --- a/ipmitool/lib/ipmi_hpmfwupg.c +++ b/ipmitool/lib/ipmi_hpmfwupg.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "../src/plugins/lan/md5.h" #include @@ -58,6 +59,7 @@ * author: * Frederic.Lelievre@ca.kontron.com * Francois.Isabelle@ca.kontron.com +* Jean-Michel.Audet@ca.kontron.com * ***************************************************************************** * @@ -91,6 +93,14 @@ * - 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 +* * TODO * =========================================================================== * 2007-01-11 @@ -290,7 +300,7 @@ typedef enum eHpmfwupgCompPropertiesSelect HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION, HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION, HPMFWUPG_COMP_RESERVED, - HPMFWUPG_COMP_OEM = 0x192 + HPMFWUPG_COMP_OEM_PROPERTIES = 192 } tHpmfwupgCompPropertiesSelect; struct HpmfwupgGetComponentPropertiesReq @@ -351,6 +361,16 @@ struct HpmfwupgGetDeferredFwVersionResp unsigned char deferredFwVersion[HPMFWUPG_VERSION_SIZE]; }__attribute__ ((packed)); +/* + * GetComponentProperties - OEM properties (192) + */ +#define HPMFWUPG_OEM_LENGTH 4 +struct HpmfwupgGetOemProperties +{ + unsigned char picmgId; + unsigned char oemRspData[HPMFWUPG_OEM_LENGTH]; +}__attribute__ ((packed)); + struct HpmfwupgGetComponentPropertiesResp { union @@ -360,6 +380,7 @@ struct HpmfwupgGetComponentPropertiesResp struct HpmfwupgGetDescStringResp descStringResp; struct HpmfwupgGetRollbackFwVersionResp rollbackFwVersionResp; struct HpmfwupgGetDeferredFwVersionResp deferredFwVersionResp; + struct HpmfwupgGetOemProperties oemProperties; }Response; }__attribute__ ((packed)); @@ -662,20 +683,58 @@ typedef enum eHpmfwupgActionType { HPMFWUPG_ACTION_BACKUP_COMPONENTS = 0, HPMFWUPG_ACTION_PREPARE_COMPONENTS, - HPMFWUPG_ACTION_UPLOAD_FIRMWARE, + HPMFWUPG_ACTION_UPLOAD_FIRMWARE, HPMFWUPG_ACTION_RESERVED = 0xFF } tHpmfwupgActionType; /* * FUNCTIONS PROTOTYPES */ +#define HPMFWUPG_MAJORMINOR_VERSION_SIZE 2 -static int HpmfwupgUpgrade(struct ipmi_intf *intf, char* imageFilename, int activate); + +#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 +{ + int componentId; + int targetMajor; + int targetMinor; + int rollbackMajor; + int rollbackMinor; + int imageMajor; + int imageMinor; + int coldResetRequired; + int rollbackSupported; + int skipUpgrade; + char descString[15]; +}VERSIONINFO, *PVERSIONINFO; + +VERSIONINFO gVersionInfo[HPMFWUPG_COMPONENT_ID_MAX]; + +#define TARGET_VER (0x01) +#define ROLLBACK_VER (0x02) +#define IMAGE_VER (0x04) + + + + +static int 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); -static int HpmfwupgUpgradeStage(struct ipmi_intf *intf, - 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, @@ -695,7 +754,8 @@ static int HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx); static int HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf, struct HpmfwupgUploadFirmwareBlockCtx* pCtx, - struct HpmfwupgUpgradeCtx* pFwupgCtx, int count); + struct HpmfwupgUpgradeCtx* pFwupgCtx, int count , + unsigned int *pOffset, unsigned int *blockLen); static int HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf, struct HpmfwupgFinishFirmwareUploadCtx* pCtx, struct HpmfwupgUpgradeCtx* pFwupgCtx); @@ -719,6 +779,312 @@ static struct ipmi_rs * HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq /**************************************************************************** * +* 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(str); + scanf("%s",userInput); + if (toupper(userInput[0]) == 'Y') + { + return 1; + } + return 0; +} +/**************************************************************************** +* +* Function Name: HpmDisplayLine +* +* Description: This is to display the line with the given character. +* +*****************************************************************************/ +void HpmDisplayLine(char *s, int n) +{ + while (n--) printf ("%c",*s); + printf("\n"); +} + +/**************************************************************************** +* +* Function Name: HpmDisplayUpgradeHeader +* +* Description: This function the displays the Upgrade header information +* +*****************************************************************************/ +void HpmDisplayUpgradeHeader(int option) +{ + printf("\n"); + HpmDisplayLine("-",79 ); + printf("|ID | Name | Versions | Upload Progress | Upload| Image |\n"); + printf("| | | Active| Backup| File |0%% 50%% 100%%| Time | Size |\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 % 5) == 0)) + { + if (percent != old_percent) + { + if ( percent == 0 ) printf("|"); + else if (percent == 100) printf("|"); + else printf("."); + old_percent = percent; + } + } + + if (totalSent== displayFWLength) + { + /* Display the time taken to complete the upgrade */ + printf("| %02d.%02d | %05x |\n",timeElapsed/60,timeElapsed%60,totalSent); + } +} + +/**************************************************************************** +* +* Function Name: HpmDisplayVersionHeader +* +* Description: This function displays the information about version header +* +*****************************************************************************/ +int HpmDisplayVersionHeader(int mode) +{ + + if ( mode & IMAGE_VER) + { + HpmDisplayLine("-",41 ); + printf("|ID | Name | Versions |\n"); + printf("| | | Active| Backup| File |\n"); + HpmDisplayLine("-",41 ); + } + else + { + HpmDisplayLine("-",33 ); + printf("|ID | Name | Versions |\n"); + printf("| | | Active| Backup|\n"); + HpmDisplayLine("-",33 ); + } +} + +/**************************************************************************** +* +* Function Name: HpmDisplayVersion +* +* Description: This function displays the version of the image and target +* +*****************************************************************************/ +int HpmDisplayVersion(int mode,VERSIONINFO *pVersion) +{ + char descString[12]; + memset(&descString,0x00,12); + /* + * Added this to ensure that even if the description string + * is more than required it does not give problem in displaying it + */ + strncpy(descString,pVersion->descString,11); + /* + * If the cold reset is required then we can display * on it + * so that user is aware that he needs to do payload power + * cycle after upgrade + */ + printf("|%c%-2d|%-11s|",pVersion->coldResetRequired?'*':' ',pVersion->componentId,descString); + + if (mode & TARGET_VER) + { + if (pVersion->targetMajor == 0xFF && pVersion->targetMinor == 0xFF) + printf(" --.-- |"); + else + printf("%3d.%02x |",pVersion->targetMajor,pVersion->targetMinor); + + if (mode & ROLLBACK_VER) + { + if (pVersion->rollbackMajor == 0xFF && pVersion->rollbackMinor == 0xFF) + printf(" --.-- |"); + else + printf("%3d.%02x |",pVersion->rollbackMajor,pVersion->rollbackMinor); + } + else + { + printf(" --.-- |"); + } + } + + if (mode & IMAGE_VER) + { + if (pVersion->imageMajor == 0xFF && pVersion->imageMinor == 0xFF) + printf(" --.-- |"); + else + printf("%3d.%02x |",pVersion->imageMajor,pVersion->imageMinor); + } +} + + +/**************************************************************************** +* +* 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; + } + + 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]; + 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); + return rc; + } + gVersionInfo[componentId].rollbackMajor = getCompProp.resp + .Response.rollbackFwVersionResp.rollbackFwVersion[0]; + gVersionInfo[componentId].rollbackMinor = getCompProp.resp + .Response.rollbackFwVersionResp.rollbackFwVersion[1]; + 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("-",33 ); + 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 @@ -726,7 +1092,8 @@ static struct ipmi_rs * HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq * version 1.0 * *****************************************************************************/ -int HpmfwupgUpgrade(struct ipmi_intf *intf, char* imageFilename, int activate) +int HpmfwupgUpgrade(struct ipmi_intf *intf, char* imageFilename, + int activate,int componentToUpload, int option) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgImageHeader imageHeader; @@ -766,14 +1133,11 @@ int HpmfwupgUpgrade(struct ipmi_intf *intf, char* imageFilename, int activate) { printf("Performing preparation stage..."); fflush(stdout); - rc = HpmfwupgPreparationStage(intf, &fwupgCtx); + rc = HpmfwupgPreparationStage(intf, &fwupgCtx, option); if ( rc == HPMFWUPG_SUCCESS ) { printf("OK\n"); fflush(stdout); - /* Print useful information to user */ - lprintf(LOG_NOTICE," Target Product ID : %u", buf2short(fwupgCtx.devId.product_id)); - lprintf(LOG_NOTICE," Target Manufacturer ID: %u", buf2short(fwupgCtx.devId.manufacturer_id)); } else { @@ -787,8 +1151,27 @@ int HpmfwupgUpgrade(struct ipmi_intf *intf, char* imageFilename, int activate) if ( rc == HPMFWUPG_SUCCESS ) { - lprintf(LOG_NOTICE,"Performing upgrade stage:"); - rc = HpmfwupgUpgradeStage(intf, &fwupgCtx); + 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,0); + if (rc == HPMFWUPG_SUCCESS ) + { + rc = HpmfwupgUpgradeStage(intf, &fwupgCtx,componentToUpload,option); + } + } + if ( rc != HPMFWUPG_SUCCESS ) { free(fwupgCtx.pImageData); @@ -810,12 +1193,20 @@ int HpmfwupgUpgrade(struct ipmi_intf *intf, char* imageFilename, int activate) if ( rc == HPMFWUPG_SUCCESS ) { - lprintf(LOG_NOTICE,"\nFirmware upgrade procedure successful\n"); + 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,"\nFirmware upgrade procedure failed\n"); + lprintf(LOG_NOTICE,"Firmware upgrade procedure failed\n"); } return rc; @@ -843,11 +1234,11 @@ int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx) /* Validate MD5 checksum */ memset(md, 0, HPMFWUPG_MD5_SIGNATURE_LENGTH); - memset(&ctx, 0, sizeof(md5_state_t)); + memset(&ctx, 0, sizeof(md5_state_t)); md5_init(&ctx); - md5_append(&ctx, pFwupgCtx->pImageData, pFwupgCtx->imageSize - + md5_append(&ctx, pFwupgCtx->pImageData, pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH); - md5_finish(&ctx, md); + md5_finish(&ctx, md); if ( memcmp(md, pMd5Sig,HPMFWUPG_MD5_SIGNATURE_LENGTH) != 0 ) { lprintf(LOG_NOTICE,"\n Invalid MD5 signature"); @@ -896,7 +1287,7 @@ int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx* pFwupgCtx) * Firmware Upgrade Specification version 1.0 * *****************************************************************************/ -int HpmfwupgPreparationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx) +int HpmfwupgPreparationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx, int option) { int rc = HPMFWUPG_SUCCESS; struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) @@ -936,6 +1327,38 @@ int HpmfwupgPreparationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* 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 */ @@ -970,6 +1393,16 @@ int HpmfwupgPreparationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* 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 */ @@ -985,39 +1418,45 @@ int HpmfwupgPreparationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* memcpy(&pFwupgCtx->targetCap, &targetCapCmd.resp, sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp)); - - /* 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 ) + + if (option & VIEW_MODE) { - lprintf(LOG_NOTICE,"\n Some components present in the image file are not supported by the IPMC"); - rc = HPMFWUPG_ERROR; + return rc; } - - /* Make sure the upgrade is desirable rigth now */ - if ( pFwupgCtx->targetCap.GlobalCapabilities.bitField.fwUpgUndesirable == 1 ) + else { - lprintf(LOG_NOTICE,"\n Upgrade undesirable at this moment"); - rc = HPMFWUPG_ERROR; + /* 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 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 ) - { - char answer; - printf("\n Services may be affected during upgrade. Do you wish to continue? y/n "); - fflush(stdout); - answer = getchar(); - if ( answer == 'n' ) - { - rc = HPMFWUPG_ERROR; - } - } - } } @@ -1031,7 +1470,7 @@ int HpmfwupgPreparationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* componentId++ ) { /* Reset component properties */ - memset(&pFwupgCtx->genCompProp[0], 0, sizeof (struct HpmfwupgGetGeneralPropResp)); + memset(&pFwupgCtx->genCompProp[componentId], 0, sizeof (struct HpmfwupgGetGeneralPropResp)); if ( (1 << componentId & pImageHeader->components.ComponentBits.byte) ) { @@ -1059,19 +1498,21 @@ int HpmfwupgPreparationStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* /**************************************************************************** * -* Function Name: HpmfwupgUpgradeStage +* Function Name: HpmfwupgPreUpgradeCheck * -* 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 +* 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 HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx) +int HpmfwupgPreUpgradeCheck(struct ipmi_intf *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; @@ -1083,6 +1524,181 @@ int HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwu /* 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]; + + mode = TARGET_VER | IMAGE_VER; + + if (pVersionInfo->coldResetRequired) + { + flagColdReset = TRUE; + } + pVersionInfo->skipUpgrade = FALSE; + + 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 (option & VIEW_MODE) + { + HpmDisplayVersion(mode,pVersionInfo); + printf("\n"); + } + pImagePtr = pData + firmwareLength; + } + break; + default: + lprintf(LOG_NOTICE," Invalid Action type. Cannot continue"); + rc = HPMFWUPG_ERROR; + break; + } + } + } + if (option & VIEW_MODE) + { + HpmDisplayLine("-",41); + if (flagColdReset) + { + fflush(stdout); + lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset"); + } + } + return rc; +} + + +/**************************************************************************** +* +* Function Name: HpmfwupgUpgradeStage +* +* Description: This function the upgrade stage of a firmware upgrade +* procedure as defined in section 3.3 of the IPM Controller +* Firmware Upgrade Specification version 1.0 +* +*****************************************************************************/ +int HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwupgCtx, + int componentToUpload, int option) +{ + struct HpmfwupgImageHeader* pImageHeader = (struct HpmfwupgImageHeader*) + pFwupgCtx->pImageData; + struct HpmfwupgComponentBitMask componentToUploadMsk; + 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)) && @@ -1112,7 +1728,7 @@ int HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwu /* Action is prepare components */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_BACKUP; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); - pImagePtr += sizeof(struct HpmfwupgActionRecord); + pImagePtr += sizeof(struct HpmfwupgActionRecord); } break; @@ -1121,6 +1737,7 @@ int HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwu int componentId; /* Make sure every components specified by this action supports the prepare components */ + componentToUploadMsk.ComponentBits.byte = 0x00; for ( componentId = HPMFWUPG_COMPONENT_ID_0; componentId < HPMFWUPG_COMPONENT_ID_MAX; componentId++ ) @@ -1133,22 +1750,43 @@ int HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwu rc = HPMFWUPG_ERROR; break; } + if (!gVersionInfo[componentId].skipUpgrade) + { + /* If the component needs not to be skipped then you need to + * add it in componentToUploadMsk */ + componentToUploadMsk.ComponentBits.byte |= 1<components.ComponentBits.byte; + } + if ( rc == HPMFWUPG_SUCCESS ) { - /* Send prepare components command */ - struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; - - initUpgActionCmd.req.componentsMask = pActionRecord->components; - /* Action is prepare components */ - initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_PREPARE; - rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); + if ( componentToUploadMsk.ComponentBits.byte != 0x00 ) + { + /* Send prepare components command */ + struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; + initUpgActionCmd.req.componentsMask = componentToUploadMsk; + /* 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 */ { @@ -1156,41 +1794,63 @@ int HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwu struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; struct HpmfwupgUploadFirmwareBlockCtx uploadCmd; struct HpmfwupgFinishFirmwareUploadCtx finishCmd; + struct HpmfwupgGetComponentPropertiesCtx getCompProp; + VERSIONINFO *pVersionInfo; + 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; + + /* Send initiate command */ initUpgActionCmd.req.componentsMask = pActionRecord->components; - - /* Action is upgrade */ + /* Action is upgrade */ initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_UPGRADE; rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); - if ( rc == HPMFWUPG_SUCCESS ) + if (rc != HPMFWUPG_SUCCESS) + { + break; + } + /* Save component ID on which the upload is done */ + componentIdByte = pActionRecord->components.ComponentBits.byte; + while ((componentIdByte>>=1)!=0) { - /* Save component ID on which the upload is done */ - pFwupgCtx->componentId = (1 << pActionRecord->components.ComponentBits.byte); - - /* Initialize parameters */ - uploadCmd.req.blockNumber = 0; - pFwImage = (struct HpmfwupgFirmwareImage*)(pImagePtr + + componentId++; + } + pFwupgCtx->componentId = componentId; + + /* Initialize parameters */ + uploadCmd.req.blockNumber = 0; + pFwImage = (struct HpmfwupgFirmwareImage*)(pImagePtr + sizeof(struct HpmfwupgActionRecord)); - lprintf(LOG_NOTICE," Upgrading %s", pFwImage->desc); - lprintf(LOG_NOTICE," with Version: Major: %d", pFwImage->version[0]); - lprintf(LOG_NOTICE," Minor: %x", pFwImage->version[1]); - lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d", pFwImage->version[2], - pFwImage->version[3], - pFwImage->version[4], - pFwImage->version[5]); - + +/* + * lprintf(LOG_NOTICE," Upgrading %s", pFwImage->desc); + * lprintf(LOG_NOTICE," with Version: Major: %d", pFwImage->version[0]); + * lprintf(LOG_NOTICE," Minor: %x", pFwImage->version[1]); + * lprintf(LOG_NOTICE," Aux : %03d %03d %03d %03d", pFwImage->version[2], + * pFwImage->version[3], + * pFwImage->version[4], + * pFwImage->version[5]); + */ pDataInitial = ((unsigned char*)pFwImage + sizeof(struct HpmfwupgFirmwareImage)); pData = pDataInitial; - /* Find max buffer length according the connection - parameters */ + /* Find max buffer length according the connection parameters */ if ( strstr(intf->name,"lan") != NULL ) { bufLength = HPMFWUPG_SEND_DATA_COUNT_LAN; @@ -1227,69 +1887,185 @@ int HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwu firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000; firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000; - while ( (pData < (pDataInitial + firmwareLength)) && - (rc == HPMFWUPG_SUCCESS) ) + if ( (!(1<components.ComponentBits.byte)) + && (componentToUpload != DEFAULT_COMPONENT_UPLOAD)) { - if ( pData + bufLength - <= (pDataInitial + firmwareLength) ) + /* We will skip if the user has given some components in command line "component 2" */ + pImagePtr = pDataInitial + firmwareLength; + break; + } + + pVersionInfo = (VERSIONINFO*) &gVersionInfo[componentId]; + + mode = TARGET_VER | IMAGE_VER; + if (pVersionInfo->rollbackSupported) + { + mode |= ROLLBACK_VER; + } + if ( pVersionInfo->coldResetRequired) + { + flagColdReset = TRUE; + } + if( (option & VERSIONCHECK_MODE) && pVersionInfo->skipUpgrade) + { + + HpmDisplayVersion(mode,pVersionInfo); + HpmDisplayUpgrade(1,0,0,0); + pImagePtr = pDataInitial + firmwareLength; + break; + } + + if ((option & DEBUG_MODE)) + { + printf("\n\n Comp ID : %d [%-20s]\n",pVersionInfo->componentId,pFwImage->desc); + } + else + { + HpmDisplayVersion(mode,pVersionInfo); + } + + /* 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)((pDataInitial + firmwareLength) - pData); + count = (unsigned char)((pDataTemp+lengthOfBlock) - pData); } - totalSent += count; memcpy(&uploadCmd.req.data, pData, bufLength); - - rc = HpmfwupgUploadFirmwareBlock(intf, &uploadCmd, pFwupgCtx, count); - - if ( rc == HPMFWUPG_SUCCESS ) + + imageOffset = 0x00; + blockLength = 0x00; + numTxPkts++; + rc = HpmfwupgUploadFirmwareBlock(intf, &uploadCmd, pFwupgCtx, count, + &imageOffset,&blockLength); + numRxPkts++; + + if ( rc != HPMFWUPG_SUCCESS) { - uploadCmd.req.blockNumber++; - pData += count; - /* avoid lprintf to control \n generation */ - printf(" Writing firmware: %.0f %c completed\r", - (float)totalSent/firmwareLength*100, '%'); - fflush(stdout); + if ( rc == HPMFWUPG_UPLOAD_BLOCK_LENGTH ) + { + /* Retry with a smaller buffer length */ + bufLength -= (unsigned char)1; + 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; + break; + } } - else if ( rc == HPMFWUPG_UPLOAD_BLOCK_LENGTH ) + else { - /* Retry with a smaller buffer length */ - bufLength -= (unsigned char)1; - rc = HPMFWUPG_SUCCESS; + if (blockLength > firmwareLength) + { + /* + * blockLength is the remaining length of the firnware 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; + break; + } + 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", + uploadCmd.req.blockNumber,totalSent); + if (imageOffset || blockLength) + { + printf("\n\r--> ImgOff : %x BlkLen : %x\n",imageOffset,blockLength); + } + if (displayFWLength == totalSent) + { + printf("\n Time Taken %02d:%02d",(end-start)/60, (end-start)%60); + printf("\n\n"); + } + } + else + { + HpmDisplayUpgrade(0,totalSent,displayFWLength,(end-start)); + } + uploadCmd.req.blockNumber++; } - else if ( rc == HPMFWUPG_UPLOAD_RETRY ) - { - rc = HPMFWUPG_SUCCESS; - } - } - lprintf(LOG_NOTICE,""); - - if ( rc == HPMFWUPG_SUCCESS ) - { + } + + if (rc == HPMFWUPG_SUCCESS) + { /* Send finish component */ /* Set image length */ finishCmd.req.componentsMask = pActionRecord->components; - finishCmd.req.imageLength[0] = pFwImage->length[0]; - finishCmd.req.imageLength[1] = pFwImage->length[1]; - finishCmd.req.imageLength[2] = pFwImage->length[2]; - finishCmd.req.imageLength[3] = pFwImage->length[3]; + /* 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; + } } - } - } break; default: lprintf(LOG_NOTICE," Invalid Action type. Cannot continue"); rc = HPMFWUPG_ERROR; break; - } + } } } + + HpmDisplayLine("-",79); + + if (flagColdReset) + { + fflush(stdout); + lprintf(LOG_NOTICE,"(*) Component requires Payload Cold Reset"); + } return rc; -} +} /**************************************************************************** * @@ -1299,7 +2075,7 @@ int HpmfwupgUpgradeStage(struct ipmi_intf *intf, struct HpmfwupgUpgradeCtx* pFwu * 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; @@ -1595,6 +2371,19 @@ int HpmfwupgGetComponentProperties(struct ipmi_intf *intf, struct HpmfwupgGetCom 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; @@ -1689,25 +2478,58 @@ int HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf, struct HpmfwupgInitiat } int HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf, struct HpmfwupgUploadFirmwareBlockCtx* pCtx, - struct HpmfwupgUpgradeCtx* pFwupgCtx, int count) + struct HpmfwupgUpgradeCtx* pFwupgCtx, int count + ,unsigned int *imageOffset, unsigned int *blockLength ) { int rc = HPMFWUPG_SUCCESS; - struct ipmi_rs * rsp; + 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; + 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 ) { @@ -2145,7 +2967,12 @@ struct ipmi_rs * HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req, } else { - inaccessTimeout = HPMFWUPG_DEFAULT_INACCESS_TIMEOUT; + /* 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 = 5; upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; } @@ -2245,6 +3072,7 @@ struct ipmi_rs * HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req, inaccessTimeoutCounter += timeoutSec2 - timeoutSec1; timeoutSec1 = time(NULL); } + retry = 1; } else @@ -2347,6 +3175,18 @@ unsigned char HpmfwupgCalculateChecksum(unsigned char* pData, unsigned int lengt 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"); @@ -2371,6 +3211,9 @@ static void HpmfwupgPrintUsage(void) 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()"); @@ -2381,22 +3224,80 @@ int ipmi_hpmfwupg_main(struct ipmi_intf * intf, int argc, char ** argv) if ( (argc == 0) || (strcmp(argv[0], "help") == 0) ) { HpmfwupgPrintUsage(); - } - else if ( (argc == 2) && (strcmp(argv[0], "upgrade") == 0) ) + return; + } + if ( (strcmp(argv[0], "check") == 0) ) { - rc = HpmfwupgUpgrade(intf, argv[1], 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 ( (argc == 3) && (strcmp(argv[0], "upgrade") == 0) ) + + else if ( strcmp(argv[0], "upgrade") == 0) { - if ( strcmp(argv[2], "activate") == 0 ) + int i =0; + 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; + /* 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) { - rc = HpmfwupgUpgrade(intf, argv[1], 1); - } - else - { - HpmfwupgPrintUsage(); + /* 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; @@ -2447,10 +3348,10 @@ int ipmi_hpmfwupg_main(struct ipmi_intf * intf, int argc, char ** argv) rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL); } else - { + { HpmfwupgPrintUsage(); } return rc; } - +