1 /* 2 * Copyright (c) 2006 Kontron Canada, Inc. All Rights Reserved. 3 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * Redistribution of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * Redistribution in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * Neither the name of Sun Microsystems, Inc. or the names of 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * This software is provided "AS IS," without a warranty of any kind. 21 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 22 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 23 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 24 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE 25 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING 26 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL 27 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, 28 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR 29 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 30 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 31 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 32 */ 33 34 #include <ipmitool/ipmi_intf.h> 35 #include <ipmitool/ipmi_mc.h> 36 #include <ipmitool/ipmi_hpmfwupg.h> 37 #include <ipmitool/helper.h> 38 #include <ipmitool/ipmi_strings.h> 39 #include <ipmitool/log.h> 40 #include "../src/plugins/lan/md5.h" 41 #include <stdio.h> 42 #include <time.h> 43 #include <sys/param.h> 44 45 #if HAVE_CONFIG_H 46 # include <config.h> 47 #endif 48 49 extern int verbose; 50 51 int HpmfwupgUpgrade(struct ipmi_intf *intf, char *imageFilename, 52 int activate, int, int); 53 int HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx *pFwupgCtx); 54 int HpmfwupgPreparationStage(struct ipmi_intf *intf, 55 struct HpmfwupgUpgradeCtx *pFwupgCtx, int option); 56 int HpmfwupgUpgradeStage(struct ipmi_intf *intf, 57 struct HpmfwupgUpgradeCtx *pFwupgCtx, int option); 58 int HpmfwupgActivationStage(struct ipmi_intf *intf, 59 struct HpmfwupgUpgradeCtx *pFwupgCtx); 60 int HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf, 61 struct HpmfwupgGetTargetUpgCapabilitiesCtx *pCtx); 62 int HpmfwupgGetComponentProperties(struct ipmi_intf *intf, 63 struct HpmfwupgGetComponentPropertiesCtx *pCtx); 64 int HpmfwupgQuerySelftestResult(struct ipmi_intf *intf, 65 struct HpmfwupgQuerySelftestResultCtx *pCtx, 66 struct HpmfwupgUpgradeCtx *pFwupgCtx); 67 int HpmfwupgQueryRollbackStatus(struct ipmi_intf *intf, 68 struct HpmfwupgQueryRollbackStatusCtx *pCtx, 69 struct HpmfwupgUpgradeCtx *pFwupgCtx); 70 int HpmfwupgAbortUpgrade(struct ipmi_intf *intf, 71 struct HpmfwupgAbortUpgradeCtx *pCtx); 72 int HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf, 73 struct HpmfwupgInitiateUpgradeActionCtx *pCtx, 74 struct HpmfwupgUpgradeCtx *pFwupgCtx); 75 int HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf, 76 struct HpmfwupgUploadFirmwareBlockCtx *pCtx, 77 struct HpmfwupgUpgradeCtx *pFwupgCtx, int count, 78 unsigned int *pOffset, unsigned int *blockLen); 79 int HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf, 80 struct HpmfwupgFinishFirmwareUploadCtx *pCtx, 81 struct HpmfwupgUpgradeCtx *pFwupgCtx, int option); 82 int HpmfwupgActivateFirmware(struct ipmi_intf *intf, 83 struct HpmfwupgActivateFirmwareCtx *pCtx, 84 struct HpmfwupgUpgradeCtx *pFwupgCtx); 85 int HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf, 86 struct HpmfwupgGetUpgradeStatusCtx *pCtxstruct, 87 struct HpmfwupgUpgradeCtx *pFwupgCtx, int silent); 88 int HpmfwupgManualFirmwareRollback(struct ipmi_intf *intf, 89 struct HpmfwupgManualFirmwareRollbackCtx *pCtx); 90 void HpmfwupgPrintUsage(void); 91 unsigned char HpmfwupgCalculateChecksum(unsigned char *pData, 92 unsigned int length); 93 int HpmfwupgGetDeviceId(struct ipmi_intf *intf, 94 struct ipm_devid_rsp *pGetDevId); 95 int HpmfwupgGetBufferFromFile(char *imageFilename, 96 struct HpmfwupgUpgradeCtx *pFwupgCtx); 97 int HpmfwupgWaitLongDurationCmd(struct ipmi_intf *intf, 98 struct HpmfwupgUpgradeCtx *pFwupgCtx); 99 struct ipmi_rs *HpmfwupgSendCmd(struct ipmi_intf *intf, 100 struct ipmi_rq req, struct HpmfwupgUpgradeCtx* pFwupgCtx); 101 102 103 int HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components, 104 struct HpmfwupgUpgradeCtx* pFwupgCtx, 105 unsigned char **pImagePtr, 106 struct ipmi_intf *intf, 107 int option, 108 int *pFlagColdReset); 109 110 /* HpmGetuserInput - get input from user 111 * 112 * returns TRUE if its Yes or FALSE if its No 113 */ 114 int 115 HpmGetUserInput(char *str) 116 { 117 char userInput[2]; 118 int ret; 119 120 printf("%s", str); 121 ret = scanf("%s", userInput); 122 if (!ret) { 123 return 1; 124 } 125 if (toupper(userInput[0]) == 'Y') { 126 return 1; 127 } 128 return 0; 129 } 130 131 /* HpmDisplayLine - display the line with the given character 132 */ 133 void 134 HpmDisplayLine(char *s, int n) 135 { 136 while (n--) { 137 printf ("%c", *s); 138 } 139 printf("\n"); 140 } 141 142 /* HpmDisplayUpgradeHeader - display the Upgrade header information 143 */ 144 void 145 HpmDisplayUpgradeHeader(void) 146 { 147 printf("\n"); 148 HpmDisplayLine("-", 79); 149 printf( 150 "|ID | Name | Versions | %% |\n"); 151 printf( 152 "| | | Active | Backup | File | |\n"); 153 printf( 154 "|----|-------------|-----------------|-----------------|-----------------|----|\n"); 155 } 156 157 /* HpmDisplayUpgrade - display the progress of the upgrade; prints the "." 158 * for every 5% of its completion. 159 */ 160 void 161 HpmDisplayUpgrade(int skip, unsigned int totalSent, 162 unsigned int displayFWLength, time_t timeElapsed) 163 { 164 int percent; 165 static int old_percent = -1; 166 if (skip) { 167 printf("Skip|\n"); 168 return; 169 } 170 fflush(stdout); 171 172 percent = ((float)totalSent / displayFWLength) * 100; 173 if (percent != old_percent) { 174 if (old_percent != -1) { 175 printf("\b\b\b\b\b"); 176 } 177 printf("%3d%%|", percent); 178 old_percent = percent; 179 } 180 if (totalSent == displayFWLength) { 181 /* Display the time taken to complete the upgrade */ 182 printf( 183 "\n| |Upload Time: %02ld:%02ld | Image Size: %7d bytes |\n", 184 timeElapsed / 60, timeElapsed % 60, totalSent); 185 old_percent = -1; 186 } 187 } 188 189 /* HpmDisplayVersionHeader - display the information about version header 190 */ 191 void 192 HpmDisplayVersionHeader(int mode) 193 { 194 if (mode & IMAGE_VER) { 195 HpmDisplayLine("-", 74); 196 printf( 197 "|ID | Name | Versions |\n"); 198 printf( 199 "| | | Active | Backup | File |\n"); 200 HpmDisplayLine("-", 74); 201 } else { 202 HpmDisplayLine("-",74 ); 203 printf( 204 "|ID | Name | Versions |\n"); 205 printf( 206 "| | | Active | Backup | Deferred |\n"); 207 HpmDisplayLine("-", 74); 208 } 209 } 210 211 /* HpmDisplayVersion - display the version of the image and target 212 */ 213 void 214 HpmDisplayVersion(int mode, VERSIONINFO *pVersion, int upgradable) 215 { 216 /* 217 * If the cold reset is required then we can display * on it 218 * so that user is aware that he needs to do payload power 219 * cycle after upgrade 220 */ 221 printf("|%c%c%2d|%-13s|", 222 pVersion->coldResetRequired ? '*' : ' ', 223 upgradable ? '^' : ' ', 224 pVersion->componentId, pVersion->descString); 225 226 if (mode & TARGET_VER) { 227 if ((pVersion->targetMajor == 0xFF 228 || (pVersion->targetMajor == 0x7F)) 229 && pVersion->targetMinor == 0xFF) { 230 printf(" ---.-- -------- |"); 231 } else { 232 printf(" %3d.%02x %02X%02X%02X%02X |", 233 pVersion->targetMajor, 234 pVersion->targetMinor, 235 pVersion->targetAux[0], 236 pVersion->targetAux[1], 237 pVersion->targetAux[2], 238 pVersion->targetAux[3]); 239 } 240 if (mode & ROLLBACK_VER) { 241 if ((pVersion->rollbackMajor == 0xFF 242 || (pVersion->rollbackMajor == 0x7F)) 243 && pVersion->rollbackMinor == 0xFF) { 244 printf(" ---.-- -------- |"); 245 } else { 246 printf(" %3d.%02x %02X%02X%02X%02X |", 247 pVersion->rollbackMajor, 248 pVersion->rollbackMinor, 249 pVersion->rollbackAux[0], 250 pVersion->rollbackAux[1], 251 pVersion->rollbackAux[2], 252 pVersion->rollbackAux[3]); 253 } 254 } else { 255 printf(" ---.-- -------- |"); 256 } 257 } 258 if (mode & IMAGE_VER) { 259 if ((pVersion->imageMajor == 0xFF 260 || (pVersion->imageMajor == 0x7F)) 261 && pVersion->imageMinor == 0xFF) { 262 printf(" ---.-- |"); 263 } else { 264 printf(" %3d.%02x %02X%02X%02X%02X |", 265 pVersion->imageMajor, 266 pVersion->imageMinor, 267 pVersion->imageAux[0], 268 pVersion->imageAux[1], 269 pVersion->imageAux[2], 270 pVersion->imageAux[3]); 271 } 272 } else { 273 if ((pVersion->deferredMajor == 0xFF 274 || (pVersion->deferredMajor == 0x7F)) 275 && pVersion->deferredMinor == 0xFF) { 276 printf(" ---.-- -------- |"); 277 } else { 278 printf(" %3d.%02x %02X%02X%02X%02X |", 279 pVersion->deferredMajor, 280 pVersion->deferredMinor, 281 pVersion->deferredAux[0], 282 pVersion->deferredAux[1], 283 pVersion->deferredAux[2], 284 pVersion->deferredAux[3]); 285 } 286 } 287 } 288 289 /* HpmfwupgTargerCheck - get target information and displays it on the screen 290 */ 291 int 292 HpmfwupgTargetCheck(struct ipmi_intf *intf, int option) 293 { 294 struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; 295 int rc = HPMFWUPG_SUCCESS; 296 int componentId = 0; 297 int flagColdReset = FALSE; 298 struct ipm_devid_rsp devIdrsp; 299 struct HpmfwupgGetComponentPropertiesCtx getCompProp; 300 int mode = 0; 301 rc = HpmfwupgGetDeviceId(intf, &devIdrsp); 302 if (rc != HPMFWUPG_SUCCESS) { 303 lprintf(LOG_NOTICE, 304 "Verify whether the Target board is present \n"); 305 return HPMFWUPG_ERROR; 306 } 307 rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); 308 if (rc != HPMFWUPG_SUCCESS) { 309 /* That indicates the target is not responding to the command 310 * May be that there is no HPM support 311 */ 312 lprintf(LOG_NOTICE, 313 "Board might not be supporting the HPM.1 Standards\n"); 314 return rc; 315 } 316 if (option & VIEW_MODE) { 317 lprintf(LOG_NOTICE, "-------Target Information-------"); 318 lprintf(LOG_NOTICE, "Device Id : 0x%x", 319 devIdrsp.device_id); 320 lprintf(LOG_NOTICE, "Device Revision : 0x%x", 321 devIdrsp.device_revision); 322 lprintf(LOG_NOTICE, "Product Id : 0x%04x", 323 buf2short(devIdrsp.product_id)); 324 lprintf(LOG_NOTICE, "Manufacturer Id : 0x%04x (%s)\n\n", 325 buf2short(devIdrsp.manufacturer_id), 326 val2str(buf2short(devIdrsp.manufacturer_id),ipmi_oem_info)); 327 HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER); 328 } 329 for (componentId = HPMFWUPG_COMPONENT_ID_0; 330 componentId < HPMFWUPG_COMPONENT_ID_MAX; 331 componentId++ ) { 332 /* If the component is supported */ 333 if (((1 << componentId) & targetCapCmd.resp.componentsPresent.ComponentBits.byte)) { 334 memset((PVERSIONINFO)&gVersionInfo[componentId], 0x00, sizeof(VERSIONINFO)); 335 getCompProp.req.componentId = componentId; 336 getCompProp.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES; 337 rc = HpmfwupgGetComponentProperties(intf, &getCompProp); 338 if (rc != HPMFWUPG_SUCCESS) { 339 lprintf(LOG_NOTICE, "Get CompGenProp Failed for component Id %d\n", 340 componentId); 341 return rc; 342 } 343 gVersionInfo[componentId].rollbackSupported = getCompProp.resp.Response. 344 generalPropResp.GeneralCompProperties.bitfield.rollbackBackup; 345 gVersionInfo[componentId].coldResetRequired = getCompProp.resp.Response. 346 generalPropResp.GeneralCompProperties.bitfield.payloadColdReset; 347 gVersionInfo[componentId].deferredActivationSupported = getCompProp.resp.Response. 348 generalPropResp.GeneralCompProperties.bitfield.deferredActivation; 349 getCompProp.req.selector = HPMFWUPG_COMP_DESCRIPTION_STRING; 350 rc = HpmfwupgGetComponentProperties(intf, &getCompProp); 351 if (rc != HPMFWUPG_SUCCESS) { 352 lprintf(LOG_NOTICE, 353 "Get CompDescString Failed for component Id %d\n", 354 componentId); 355 return rc; 356 } 357 memcpy(gVersionInfo[componentId].descString, 358 getCompProp.resp.Response.descStringResp.descString, 359 HPMFWUPG_DESC_STRING_LENGTH); 360 gVersionInfo[componentId].descString[HPMFWUPG_DESC_STRING_LENGTH] = '\0'; 361 getCompProp.req.selector = HPMFWUPG_COMP_CURRENT_VERSION; 362 rc = HpmfwupgGetComponentProperties(intf, &getCompProp); 363 if (rc != HPMFWUPG_SUCCESS) { 364 lprintf(LOG_NOTICE, 365 "Get CompCurrentVersion Failed for component Id %d\n", 366 componentId); 367 return rc; 368 } 369 gVersionInfo[componentId].componentId = componentId; 370 gVersionInfo[componentId].targetMajor = getCompProp.resp.Response. 371 currentVersionResp.currentVersion[0]; 372 gVersionInfo[componentId].targetMinor = getCompProp.resp.Response. 373 currentVersionResp.currentVersion[1]; 374 gVersionInfo[componentId].targetAux[0] = getCompProp.resp.Response. 375 currentVersionResp.currentVersion[2]; 376 gVersionInfo[componentId].targetAux[1] = getCompProp.resp.Response. 377 currentVersionResp.currentVersion[3]; 378 gVersionInfo[componentId].targetAux[2] = getCompProp.resp.Response. 379 currentVersionResp.currentVersion[4]; 380 gVersionInfo[componentId].targetAux[3] = getCompProp.resp.Response. 381 currentVersionResp.currentVersion[5]; 382 mode = TARGET_VER; 383 if (gVersionInfo[componentId].rollbackSupported) { 384 getCompProp.req.selector = HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION; 385 rc = HpmfwupgGetComponentProperties(intf, &getCompProp); 386 if (rc != HPMFWUPG_SUCCESS) { 387 lprintf(LOG_NOTICE, 388 "Get CompRollbackVersion Failed for component Id %d\n", 389 componentId); 390 } else { 391 gVersionInfo[componentId].rollbackMajor = getCompProp.resp 392 .Response.rollbackFwVersionResp.rollbackFwVersion[0]; 393 gVersionInfo[componentId].rollbackMinor = getCompProp.resp 394 .Response.rollbackFwVersionResp.rollbackFwVersion[1]; 395 gVersionInfo[componentId].rollbackAux[0] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[2]; 396 gVersionInfo[componentId].rollbackAux[1] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[3]; 397 gVersionInfo[componentId].rollbackAux[2] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[4]; 398 gVersionInfo[componentId].rollbackAux[3] = getCompProp.resp.Response.rollbackFwVersionResp.rollbackFwVersion[5]; 399 } 400 mode |= ROLLBACK_VER; 401 } else { 402 gVersionInfo[componentId].rollbackMajor = 0xff; 403 gVersionInfo[componentId].rollbackMinor = 0xff; 404 gVersionInfo[componentId].rollbackAux[0] = 0xff; 405 gVersionInfo[componentId].rollbackAux[1] = 0xff; 406 gVersionInfo[componentId].rollbackAux[2] = 0xff; 407 gVersionInfo[componentId].rollbackAux[3] = 0xff; 408 } 409 if (gVersionInfo[componentId].deferredActivationSupported) { 410 getCompProp.req.selector = HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION; 411 rc = HpmfwupgGetComponentProperties(intf, &getCompProp); 412 if (rc != HPMFWUPG_SUCCESS) { 413 lprintf(LOG_NOTICE, 414 "Get CompRollbackVersion Failed for component Id %d\n", 415 componentId); 416 } else { 417 gVersionInfo[componentId].deferredMajor = getCompProp.resp 418 .Response.deferredFwVersionResp.deferredFwVersion[0]; 419 gVersionInfo[componentId].deferredMinor = getCompProp.resp 420 .Response.deferredFwVersionResp.deferredFwVersion[1]; 421 gVersionInfo[componentId].deferredAux[0] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[2]; 422 gVersionInfo[componentId].deferredAux[1] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[3]; 423 gVersionInfo[componentId].deferredAux[2] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[4]; 424 gVersionInfo[componentId].deferredAux[3] = getCompProp.resp.Response.deferredFwVersionResp.deferredFwVersion[5]; 425 } 426 } else { 427 gVersionInfo[componentId].deferredMajor = 0xff; 428 gVersionInfo[componentId].deferredMinor = 0xff; 429 gVersionInfo[componentId].deferredAux[0] = 0xff; 430 gVersionInfo[componentId].deferredAux[1] = 0xff; 431 gVersionInfo[componentId].deferredAux[2] = 0xff; 432 gVersionInfo[componentId].deferredAux[3] = 0xff; 433 } 434 if (gVersionInfo[componentId].coldResetRequired) { 435 /* 436 * If any of the component indicates that the Payload Cold reset is required 437 * then set the flag 438 */ 439 flagColdReset = TRUE; 440 } 441 if (option & VIEW_MODE) { 442 HpmDisplayVersion(mode, 443 &gVersionInfo[componentId], 444 0); 445 printf("\n"); 446 } 447 } 448 } 449 if (option & VIEW_MODE) { 450 HpmDisplayLine("-",74 ); 451 fflush(stdout); 452 lprintf(LOG_NOTICE, 453 "(*) Component requires Payload Cold Reset"); 454 printf("\n\n"); 455 } 456 return HPMFWUPG_SUCCESS; 457 } 458 459 /* HpmfwupgUpgrade - perform the HPM.1 firmware upgrade procedure as defined 460 * the IPM Controller Firmware Upgrade Specification version 1.0 461 */ 462 int 463 HpmfwupgUpgrade(struct ipmi_intf *intf, char *imageFilename, int activate, 464 int componentMask, int option) 465 { 466 int rc = HPMFWUPG_SUCCESS; 467 struct HpmfwupgUpgradeCtx fwupgCtx; 468 /* INITIALIZE UPGRADE CONTEXT */ 469 memset(&fwupgCtx, 0, sizeof (fwupgCtx)); 470 /* GET IMAGE BUFFER FROM FILE */ 471 rc = HpmfwupgGetBufferFromFile(imageFilename, &fwupgCtx); 472 /* VALIDATE IMAGE INTEGRITY */ 473 if (rc == HPMFWUPG_SUCCESS) { 474 printf("Validating firmware image integrity..."); 475 fflush(stdout); 476 rc = HpmfwupgValidateImageIntegrity(&fwupgCtx); 477 if (rc == HPMFWUPG_SUCCESS) { 478 printf("OK\n"); 479 fflush(stdout); 480 } 481 } 482 /* PREPARATION STAGE */ 483 if (rc == HPMFWUPG_SUCCESS) { 484 printf("Performing preparation stage..."); 485 fflush(stdout); 486 rc = HpmfwupgPreparationStage(intf, &fwupgCtx, option); 487 if (rc == HPMFWUPG_SUCCESS) { 488 printf("OK\n"); 489 fflush(stdout); 490 } 491 } 492 /* UPGRADE STAGE */ 493 if (rc == HPMFWUPG_SUCCESS) { 494 if (option & VIEW_MODE) { 495 lprintf(LOG_NOTICE, 496 "\nComparing Target & Image File version"); 497 } else if (option & COMPARE_MODE) { 498 lprintf(LOG_NOTICE, 499 "\nPerforming upload for compare stage:"); 500 } else { 501 lprintf(LOG_NOTICE, "\nPerforming upgrade stage:"); 502 } 503 if (option & VIEW_MODE) { 504 rc = HpmfwupgPreUpgradeCheck(intf, 505 &fwupgCtx,componentMask, VIEW_MODE); 506 } else { 507 rc = HpmfwupgPreUpgradeCheck(intf, &fwupgCtx, 508 componentMask, option); 509 if (rc == HPMFWUPG_SUCCESS) { 510 if (verbose) { 511 printf("Component update mask : 0x%02x\n", 512 fwupgCtx.compUpdateMask.ComponentBits.byte); 513 } 514 rc = HpmfwupgUpgradeStage(intf, &fwupgCtx, option); 515 } 516 } 517 } 518 /* ACTIVATION STAGE */ 519 if (rc == HPMFWUPG_SUCCESS && activate) { 520 /* check if upgrade components mask is non-zero */ 521 if (fwupgCtx.compUpdateMask.ComponentBits.byte) { 522 lprintf(LOG_NOTICE, "Performing activation stage: "); 523 rc = HpmfwupgActivationStage(intf, &fwupgCtx); 524 } else { 525 lprintf(LOG_NOTICE, 526 "No components updated. Skipping activation stage.\n"); 527 } 528 } 529 if (rc == HPMFWUPG_SUCCESS) { 530 if (option & VIEW_MODE) { 531 /* Dont display anything here in case we are just viewing it */ 532 lprintf(LOG_NOTICE," "); 533 } else if (option & COMPARE_MODE) { 534 lprintf(LOG_NOTICE, 535 "\nFirmware comparison procedure complete\n"); 536 } else { 537 lprintf(LOG_NOTICE, 538 "\nFirmware upgrade procedure successful\n"); 539 } 540 } else if (option & VIEW_MODE) { 541 /* Dont display anything here in case we are just viewing it */ 542 lprintf(LOG_NOTICE," "); 543 } else if (option & COMPARE_MODE) { 544 lprintf(LOG_NOTICE, 545 "Firmware comparison procedure failed\n"); 546 } else { 547 lprintf(LOG_NOTICE, "Firmware upgrade procedure failed\n"); 548 } 549 if (fwupgCtx.pImageData) { 550 free(fwupgCtx.pImageData); 551 fwupgCtx.pImageData = NULL; 552 } 553 return rc; 554 } 555 556 /* HpmfwupgValidateImageIntegrity - validate a HPM.1 firmware image file as 557 * defined in section 4 of the IPM Controller Firmware Upgrade Specification 558 * version 1.0 559 */ 560 int 561 HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx *pFwupgCtx) 562 { 563 struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*)pFwupgCtx->pImageData; 564 md5_state_t ctx; 565 static unsigned char md[HPMFWUPG_MD5_SIGNATURE_LENGTH]; 566 unsigned char *pMd5Sig = pFwupgCtx->pImageData 567 + (pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH); 568 /* Validate MD5 checksum */ 569 memset(md, 0, HPMFWUPG_MD5_SIGNATURE_LENGTH); 570 memset(&ctx, 0, sizeof(md5_state_t)); 571 md5_init(&ctx); 572 md5_append(&ctx, pFwupgCtx->pImageData, 573 pFwupgCtx->imageSize - HPMFWUPG_MD5_SIGNATURE_LENGTH); 574 md5_finish(&ctx, md); 575 if (memcmp(md, pMd5Sig, HPMFWUPG_MD5_SIGNATURE_LENGTH) != 0) { 576 lprintf(LOG_NOTICE, "\n Invalid MD5 signature"); 577 return HPMFWUPG_ERROR; 578 } 579 /* Validate Header signature */ 580 if(strncmp(pImageHeader->signature, 581 HPMFWUPG_IMAGE_SIGNATURE, 582 HPMFWUPG_HEADER_SIGNATURE_LENGTH) != 0) { 583 lprintf(LOG_NOTICE,"\n Invalid image signature"); 584 return HPMFWUPG_ERROR; 585 } 586 /* Validate Header image format version */ 587 if (pImageHeader->formatVersion != HPMFWUPG_IMAGE_HEADER_VERSION) { 588 lprintf(LOG_NOTICE,"\n Unrecognized image version"); 589 return HPMFWUPG_ERROR; 590 } 591 /* Validate header checksum */ 592 if (HpmfwupgCalculateChecksum((unsigned char*)pImageHeader, 593 sizeof(struct HpmfwupgImageHeader) 594 + pImageHeader->oemDataLength 595 + sizeof(unsigned char)/*checksum*/) != 0) { 596 lprintf(LOG_NOTICE,"\n Invalid header checksum"); 597 return HPMFWUPG_ERROR; 598 } 599 return HPMFWUPG_SUCCESS; 600 } 601 602 /* HpmfwupgPreparationStage - prepere stage of a firmware upgrade procedure as 603 * defined in section 3.2 of the IPM Controller Firmware Upgrade Specification 604 * version 1.0 605 */ 606 int 607 HpmfwupgPreparationStage(struct ipmi_intf *intf, 608 struct HpmfwupgUpgradeCtx *pFwupgCtx, int option) 609 { 610 int componentId; 611 int rc = HPMFWUPG_SUCCESS; 612 struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; 613 struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*) 614 pFwupgCtx->pImageData; 615 /* Get device ID */ 616 rc = HpmfwupgGetDeviceId(intf, &pFwupgCtx->devId); 617 /* Match current IPMC IDs with upgrade image */ 618 if (rc != HPMFWUPG_SUCCESS) { 619 return HPMFWUPG_ERROR; 620 } 621 /* Validate device ID */ 622 if (pImageHeader->deviceId == pFwupgCtx->devId.device_id) { 623 /* Validate product ID */ 624 if (memcmp(pImageHeader->prodId, 625 pFwupgCtx->devId.product_id, 626 HPMFWUPG_PRODUCT_ID_LENGTH ) == 0) { 627 /* Validate man ID */ 628 if (memcmp(pImageHeader->manId, 629 pFwupgCtx->devId.manufacturer_id, 630 HPMFWUPG_MANUFATURER_ID_LENGTH) != 0) { 631 lprintf(LOG_NOTICE, 632 "\n Invalid image file for manufacturer %u", 633 buf2short(pFwupgCtx->devId.manufacturer_id)); 634 rc = HPMFWUPG_ERROR; 635 } 636 } else { 637 lprintf(LOG_NOTICE, 638 "\n Invalid image file for product %u", 639 buf2short(pFwupgCtx->devId.product_id)); 640 rc = HPMFWUPG_ERROR; 641 } 642 } else { 643 lprintf(LOG_NOTICE, "\n Invalid device ID %x", 644 pFwupgCtx->devId.device_id); 645 rc = HPMFWUPG_ERROR; 646 } 647 if (rc != HPMFWUPG_SUCCESS) { 648 /* Giving one more chance to user to check whether its OK to continue even if the 649 * product ID does not match. This is helpful as sometimes we just want to update 650 * and dont care whether we have a different product Id. If the user says NO then 651 * we need to just bail out from here 652 */ 653 if (!((option & FORCE_MODE) || (option & VIEW_MODE))) { 654 printf("\n\n Use \"force\" option for copying all the components\n"); 655 return HPMFWUPG_ERROR; 656 } 657 printf("\n Image Information"); 658 printf("\n Device Id : 0x%x", pImageHeader->deviceId); 659 printf("\n Prod Id : 0x%02x%02x", 660 pImageHeader->prodId[1], pImageHeader->prodId[0]); 661 printf("\n Manuf Id : 0x%02x%02x%02x", 662 pImageHeader->manId[2], 663 pImageHeader->manId[1], 664 pImageHeader->manId[0]); 665 printf("\n Board Information"); 666 printf("\n Device Id : 0x%x", pFwupgCtx->devId.device_id); 667 printf("\n Prod Id : 0x%02x%02x", 668 pFwupgCtx->devId.product_id[1], pFwupgCtx->devId.product_id[0]); 669 printf("\n Manuf Id : 0x%02x%02x%02x", 670 pFwupgCtx->devId.manufacturer_id[2], 671 pFwupgCtx->devId.manufacturer_id[1], 672 pFwupgCtx->devId.manufacturer_id[0]); 673 if (HpmGetUserInput("\n Continue ignoring DeviceID/ProductID/ManufacturingID (Y/N): ")) { 674 rc = HPMFWUPG_SUCCESS; 675 } else { 676 return HPMFWUPG_ERROR; 677 } 678 } 679 /* Validate earliest compatible revision */ 680 /* Validate major & minor revision */ 681 if (pImageHeader->compRevision[0] > pFwupgCtx->devId.fw_rev1 682 || (pImageHeader->compRevision[0] == pFwupgCtx->devId.fw_rev1 683 && pImageHeader->compRevision[1] > pFwupgCtx->devId.fw_rev2)) { 684 /* Version not compatible for upgrade */ 685 lprintf(LOG_NOTICE, "\n Version: Major: %d", pImageHeader->compRevision[0]); 686 lprintf(LOG_NOTICE, " Minor: %x", pImageHeader->compRevision[1]); 687 lprintf(LOG_NOTICE, " Not compatible with "); 688 lprintf(LOG_NOTICE, " Version: Major: %d", pFwupgCtx->devId.fw_rev1); 689 lprintf(LOG_NOTICE, " Minor: %x", pFwupgCtx->devId.fw_rev2); 690 /* Confirming it once again */ 691 if (!((option & FORCE_MODE) || (option & VIEW_MODE))) { 692 return HPMFWUPG_ERROR; 693 } 694 if (HpmGetUserInput("\n Continue IGNORING Earliest compatibility (Y/N): ")) { 695 rc = HPMFWUPG_SUCCESS; 696 } else { 697 return HPMFWUPG_ERROR; 698 } 699 } 700 /* Get target upgrade capabilities */ 701 rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); 702 if (rc != HPMFWUPG_SUCCESS) { 703 return HPMFWUPG_ERROR; 704 } 705 /* Copy response to context */ 706 memcpy(&pFwupgCtx->targetCap, 707 &targetCapCmd.resp, 708 sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp)); 709 if (option & VIEW_MODE) { 710 /* do nothing */ 711 } else { 712 /* Make sure all component IDs defined in the 713 * upgrade image are supported by the IPMC 714 */ 715 if ((pImageHeader->components.ComponentBits.byte & 716 pFwupgCtx->targetCap.componentsPresent.ComponentBits.byte) != 717 pImageHeader->components.ComponentBits.byte) { 718 lprintf(LOG_NOTICE, 719 "\n Some components present in the image file are not supported by the IPMC"); 720 return HPMFWUPG_ERROR; 721 } 722 /* Make sure the upgrade is desirable rigth now */ 723 if (pFwupgCtx->targetCap.GlobalCapabilities.bitField.fwUpgUndesirable == 1) { 724 lprintf(LOG_NOTICE, "\n Upgrade undesirable at this moment"); 725 return HPMFWUPG_ERROR; 726 } 727 /* Get confimation from the user if he wants to continue when 728 * service affected during upgrade 729 */ 730 if (!(option & COMPARE_MODE) 731 && (pFwupgCtx->targetCap.GlobalCapabilities.bitField.servAffectDuringUpg == 1 732 || pImageHeader->imageCapabilities.bitField.servAffected == 1)) { 733 if (HpmGetUserInput("\nServices may be affected during upgrade. Do you wish to continue? (y/n): ")) { 734 rc = HPMFWUPG_SUCCESS; 735 } else { 736 return HPMFWUPG_ERROR; 737 } 738 } 739 } 740 /* Get the general properties of each component present in image */ 741 for (componentId = HPMFWUPG_COMPONENT_ID_0; 742 componentId < HPMFWUPG_COMPONENT_ID_MAX; 743 componentId++) { 744 /* Reset component properties */ 745 memset(&pFwupgCtx->genCompProp[componentId], 0, 746 sizeof (struct HpmfwupgGetGeneralPropResp)); 747 if ((1 << componentId & pImageHeader->components.ComponentBits.byte)) { 748 struct HpmfwupgGetComponentPropertiesCtx getCompPropCmd; 749 /* Get general component properties */ 750 getCompPropCmd.req.componentId = componentId; 751 getCompPropCmd.req.selector = HPMFWUPG_COMP_GEN_PROPERTIES; 752 rc = HpmfwupgGetComponentProperties(intf, &getCompPropCmd); 753 if (rc == HPMFWUPG_SUCCESS) { 754 /* Copy response to context */ 755 memcpy(&pFwupgCtx->genCompProp[componentId], 756 &getCompPropCmd.resp, 757 sizeof(struct HpmfwupgGetGeneralPropResp)); 758 } 759 } 760 } 761 return rc; 762 } 763 764 int 765 image_version_upgradable(VERSIONINFO *pVersionInfo) 766 { 767 /* If the image and active target versions are different, then 768 * upgrade */ 769 if ((pVersionInfo->imageMajor != pVersionInfo->targetMajor) 770 || (pVersionInfo->imageMinor != pVersionInfo->targetMinor) 771 || (pVersionInfo->imageAux[0] != pVersionInfo->targetAux[0]) 772 || (pVersionInfo->imageAux[1] != pVersionInfo->targetAux[1]) 773 || (pVersionInfo->imageAux[2] != pVersionInfo->targetAux[2]) 774 || (pVersionInfo->imageAux[3] != pVersionInfo->targetAux[3])) { 775 return (1); 776 } 777 /* If the image and active target versions are the same and rollback 778 * is not supported, then there's nothing to do, skip the upgrade 779 */ 780 if (!pVersionInfo->rollbackSupported) { 781 return (0); 782 } 783 /* If the image and rollback target versions are different, then 784 * go ahead and upgrade 785 */ 786 if ((pVersionInfo->imageMajor != pVersionInfo->rollbackMajor) 787 || (pVersionInfo->imageMinor != pVersionInfo->rollbackMinor) 788 || (pVersionInfo->imageAux[0] != pVersionInfo->rollbackAux[0]) 789 || (pVersionInfo->imageAux[1] != pVersionInfo->rollbackAux[1]) 790 || (pVersionInfo->imageAux[2] != pVersionInfo->rollbackAux[2]) 791 || (pVersionInfo->imageAux[3] != pVersionInfo->rollbackAux[3])) { 792 return (1); 793 } 794 /* Image and rollback target versions are the same too, skip it */ 795 return (0); 796 } 797 798 /* HpmfwupgValidateActionRecordChecksum - validate checksum of the specified 799 * action record header. 800 */ 801 int 802 HpmfwupgValidateActionRecordChecksum(struct HpmfwupgActionRecord *pActionRecord) 803 { 804 int rc = HPMFWUPG_SUCCESS; 805 /* Validate action record checksum */ 806 if (HpmfwupgCalculateChecksum((unsigned char*)pActionRecord, 807 sizeof(struct HpmfwupgActionRecord)) != 0) { 808 /* Due to ambiguity in the HPM.1 specification, for the case of 809 * the Upload Firmware Image action type, the record header length 810 * might be thought as either the first 3 bytes, or the first 34 bytes 811 * which precede the firmware image data. 812 * For the latter case we re-calculate the Upload Firmware Image 813 * record checksum for the 34 byte header length. 814 */ 815 if (pActionRecord->actionType != HPMFWUPG_ACTION_UPLOAD_FIRMWARE 816 || HpmfwupgCalculateChecksum((unsigned char*)pActionRecord, 817 sizeof(struct HpmfwupgActionRecord) 818 + sizeof(struct HpmfwupgFirmwareImage))) { 819 lprintf(LOG_NOTICE, " Invalid Action record."); 820 rc = HPMFWUPG_ERROR; 821 } 822 } 823 return rc; 824 } 825 826 /* HpmfwupgPreUpgradeCheck - make pre-Upgrade check, this mainly helps in 827 * checking which all version upgrade is skippable because the image version 828 * is same as target version. 829 */ 830 int 831 HpmfwupgPreUpgradeCheck(struct ipmi_intf *intf, 832 struct HpmfwupgUpgradeCtx *pFwupgCtx, 833 int componentMask, int option) 834 { 835 unsigned char *pImagePtr; 836 struct HpmfwupgActionRecord *pActionRecord; 837 struct HpmfwupgImageHeader *pImageHeader; 838 int componentId; 839 pImageHeader = (struct HpmfwupgImageHeader*)pFwupgCtx->pImageData; 840 /* Put pointer after image header */ 841 pImagePtr = (unsigned char*)(pFwupgCtx->pImageData 842 + sizeof(struct HpmfwupgImageHeader) 843 + pImageHeader->oemDataLength 844 + sizeof(unsigned char)/*chksum*/); 845 if (option & VIEW_MODE) { 846 HpmDisplayVersionHeader(TARGET_VER|ROLLBACK_VER|IMAGE_VER); 847 } 848 /* Perform actions defined in the image */ 849 while (pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize 850 - HPMFWUPG_MD5_SIGNATURE_LENGTH)) { 851 /* Get action record */ 852 pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr; 853 /* Validate action record checksum */ 854 if (HpmfwupgValidateActionRecordChecksum(pActionRecord) != HPMFWUPG_SUCCESS) { 855 return HPMFWUPG_ERROR; 856 } 857 /* Validate affected components */ 858 if (pActionRecord->components.ComponentBits.byte 859 && !pFwupgCtx->targetCap.componentsPresent.ComponentBits.byte) { 860 lprintf(LOG_NOTICE, 861 " Invalid action record. One or more affected components is not supported"); 862 return HPMFWUPG_ERROR; 863 } 864 switch (pActionRecord->actionType) { 865 case HPMFWUPG_ACTION_BACKUP_COMPONENTS: 866 { 867 /* Make sure every component specified by 868 * this action record 869 * supports the backup operation 870 */ 871 for (componentId = HPMFWUPG_COMPONENT_ID_0; 872 componentId < HPMFWUPG_COMPONENT_ID_MAX; 873 componentId++) { 874 if (((1 << componentId) & pActionRecord->components.ComponentBits.byte) 875 && pFwupgCtx->genCompProp[componentId].GeneralCompProperties.bitfield.rollbackBackup == 0) { 876 lprintf(LOG_NOTICE, 877 " Component ID %d does not support backup", 878 componentId); 879 return HPMFWUPG_ERROR; 880 } 881 } 882 pImagePtr += sizeof(struct HpmfwupgActionRecord); 883 } 884 break; 885 case HPMFWUPG_ACTION_PREPARE_COMPONENTS: 886 { 887 /* Make sure every components specified by 888 * this action 889 * supports the prepare operation 890 */ 891 for (componentId = HPMFWUPG_COMPONENT_ID_0; 892 componentId < HPMFWUPG_COMPONENT_ID_MAX; 893 componentId++) { 894 if (((1 << componentId) & pActionRecord->components.ComponentBits.byte) 895 && pFwupgCtx->genCompProp[componentId].GeneralCompProperties.bitfield.preparationSupport == 0) { 896 lprintf(LOG_NOTICE, 897 " Component ID %d does not support preparation", 898 componentId); 899 return HPMFWUPG_ERROR; 900 } 901 } 902 pImagePtr += sizeof(struct HpmfwupgActionRecord); 903 } 904 break; 905 case HPMFWUPG_ACTION_UPLOAD_FIRMWARE: 906 /* Upload all firmware blocks */ 907 { 908 struct HpmfwupgFirmwareImage *pFwImage; 909 unsigned char *pData; 910 unsigned int firmwareLength; 911 unsigned char mode; 912 unsigned char componentId; 913 unsigned char componentIdByte; 914 unsigned int upgrade_comp; 915 VERSIONINFO *pVersionInfo; 916 /* Save component ID on which the upload is done */ 917 componentIdByte = pActionRecord->components.ComponentBits.byte; 918 componentId = 0; 919 while ((componentIdByte >>= 1) != 0) { 920 componentId++; 921 } 922 pFwImage = (struct HpmfwupgFirmwareImage*)(pImagePtr 923 + sizeof(struct HpmfwupgActionRecord)); 924 pData = ((unsigned char*)pFwImage 925 + sizeof(struct HpmfwupgFirmwareImage)); 926 /* Get firmware length */ 927 firmwareLength = pFwImage->length[0]; 928 firmwareLength |= (pFwImage->length[1] << 8) & 0xff00; 929 firmwareLength |= (pFwImage->length[2] << 16) & 0xff0000; 930 firmwareLength |= (pFwImage->length[3] << 24) & 0xff000000; 931 932 pVersionInfo = &gVersionInfo[componentId]; 933 934 pVersionInfo->imageMajor = pFwImage->version[0]; 935 pVersionInfo->imageMinor = pFwImage->version[1]; 936 pVersionInfo->imageAux[0] = pFwImage->version[2]; 937 pVersionInfo->imageAux[1] = pFwImage->version[3]; 938 pVersionInfo->imageAux[2] = pFwImage->version[4]; 939 pVersionInfo->imageAux[3] = pFwImage->version[5]; 940 941 mode = TARGET_VER | IMAGE_VER; 942 /* check if component is selected for upgrade */ 943 upgrade_comp = !componentMask 944 || (componentMask & pActionRecord->components.ComponentBits.byte); 945 /* check if current component version requires upgrade */ 946 if (upgrade_comp && !(option & (FORCE_MODE|COMPARE_MODE))) { 947 upgrade_comp = image_version_upgradable(pVersionInfo); 948 } 949 if (verbose) { 950 lprintf(LOG_NOTICE, 951 "%s component %d", 952 (upgrade_comp ? "Updating" : "Skipping"), 953 componentId); 954 } 955 if (upgrade_comp) { 956 pFwupgCtx->compUpdateMask.ComponentBits.byte|= 1 << componentId; 957 } 958 if (option & VIEW_MODE) { 959 if (pVersionInfo->rollbackSupported) { 960 mode|= ROLLBACK_VER; 961 } 962 HpmDisplayVersion(mode,pVersionInfo, upgrade_comp); 963 printf("\n"); 964 } 965 pImagePtr = pData + firmwareLength; 966 } 967 break; 968 default: 969 lprintf(LOG_NOTICE, 970 " Invalid Action type. Cannot continue"); 971 return HPMFWUPG_ERROR; 972 break; 973 } 974 } 975 if (option & VIEW_MODE) { 976 HpmDisplayLine("-",74); 977 fflush(stdout); 978 lprintf(LOG_NOTICE, 979 "(*) Component requires Payload Cold Reset"); 980 lprintf(LOG_NOTICE, 981 "(^) Indicates component would be upgraded"); 982 } 983 return HPMFWUPG_SUCCESS; 984 } 985 986 /* HpmfwupgUpgradeStage - upgrade stage of a firmware upgrade procedure as 987 * defined in section 3.3 of the IPM Controller Firmware Upgrade Specification 988 * version 1.0 989 */ 990 int 991 HpmfwupgUpgradeStage(struct ipmi_intf *intf, 992 struct HpmfwupgUpgradeCtx *pFwupgCtx, int option) 993 { 994 struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*) 995 pFwupgCtx->pImageData; 996 struct HpmfwupgActionRecord* pActionRecord; 997 int rc = HPMFWUPG_SUCCESS; 998 unsigned char *pImagePtr; 999 unsigned int actionsSize; 1000 int flagColdReset = FALSE; 1001 time_t start,end; 1002 /* Put pointer after image header */ 1003 pImagePtr = (unsigned char*) 1004 (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) + 1005 pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/); 1006 /* Deternime actions size */ 1007 actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader); 1008 if (!(option & VIEW_MODE)) { 1009 HpmDisplayUpgradeHeader(); 1010 } 1011 /* Perform actions defined in the image */ 1012 while (( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize - 1013 HPMFWUPG_MD5_SIGNATURE_LENGTH)) 1014 && (rc == HPMFWUPG_SUCCESS)) { 1015 /* Get action record */ 1016 pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr; 1017 /* Validate action record checksum */ 1018 rc = HpmfwupgValidateActionRecordChecksum(pActionRecord); 1019 if (rc != HPMFWUPG_SUCCESS) { 1020 continue; 1021 } 1022 switch(pActionRecord->actionType) { 1023 case HPMFWUPG_ACTION_BACKUP_COMPONENTS: 1024 { 1025 if (!(option & COMPARE_MODE)) { 1026 /* Send Upgrade Action command */ 1027 struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; 1028 /* Affect only selected components */ 1029 initUpgActionCmd.req.componentsMask.ComponentBits.byte = 1030 pFwupgCtx->compUpdateMask.ComponentBits.byte & 1031 pActionRecord->components.ComponentBits.byte; 1032 /* Action is prepare components */ 1033 if (initUpgActionCmd.req.componentsMask.ComponentBits.byte) { 1034 initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_BACKUP; 1035 rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); 1036 } 1037 } 1038 pImagePtr+= sizeof(struct HpmfwupgActionRecord); 1039 } 1040 break; 1041 case HPMFWUPG_ACTION_PREPARE_COMPONENTS: 1042 { 1043 if (!(option & COMPARE_MODE)) { 1044 /* Send prepare components command */ 1045 struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; 1046 /* Affect only selected components */ 1047 initUpgActionCmd.req.componentsMask.ComponentBits.byte = 1048 pFwupgCtx->compUpdateMask.ComponentBits.byte & 1049 pActionRecord->components.ComponentBits.byte; 1050 if (initUpgActionCmd.req.componentsMask.ComponentBits.byte) { 1051 /* Action is prepare components */ 1052 initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_PREPARE; 1053 rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); 1054 } 1055 } 1056 pImagePtr+= sizeof(struct HpmfwupgActionRecord); 1057 } 1058 break; 1059 case HPMFWUPG_ACTION_UPLOAD_FIRMWARE: 1060 /* Upload all firmware blocks */ 1061 rc = HpmFwupgActionUploadFirmware(pActionRecord->components, 1062 pFwupgCtx, 1063 &pImagePtr, 1064 intf, 1065 option, 1066 &flagColdReset); 1067 break; 1068 default: 1069 lprintf(LOG_NOTICE, " Invalid Action type. Cannot continue"); 1070 rc = HPMFWUPG_ERROR; 1071 break; 1072 } 1073 } 1074 HpmDisplayLine("-", 79); 1075 fflush(stdout); 1076 lprintf(LOG_NOTICE, "(*) Component requires Payload Cold Reset"); 1077 return rc; 1078 } 1079 1080 int 1081 HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components, 1082 struct HpmfwupgUpgradeCtx *pFwupgCtx, 1083 unsigned char **pImagePtr, 1084 struct ipmi_intf *intf, 1085 int option, 1086 int *pFlagColdReset) 1087 { 1088 struct HpmfwupgFirmwareImage *pFwImage; 1089 struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; 1090 struct HpmfwupgUploadFirmwareBlockCtx uploadCmd; 1091 struct HpmfwupgFinishFirmwareUploadCtx finishCmd; 1092 VERSIONINFO *pVersionInfo; 1093 time_t start,end; 1094 1095 int rc = HPMFWUPG_SUCCESS; 1096 int skip = TRUE; 1097 unsigned char *pData, *pDataInitial; 1098 unsigned short count; 1099 unsigned int totalSent = 0; 1100 unsigned short bufLength = 0; 1101 unsigned short bufLengthIsSet = 0; 1102 unsigned int firmwareLength = 0; 1103 1104 unsigned int displayFWLength = 0; 1105 unsigned char *pDataTemp; 1106 unsigned int imageOffset = 0x00; 1107 unsigned int blockLength = 0x00; 1108 unsigned int lengthOfBlock = 0x00; 1109 unsigned int numTxPkts = 0; 1110 unsigned int numRxPkts = 0; 1111 unsigned char mode = 0; 1112 unsigned char componentId = 0x00; 1113 unsigned char componentIdByte = 0x00; 1114 uint16_t max_rq_size; 1115 1116 /* Save component ID on which the upload is done */ 1117 componentIdByte = components.ComponentBits.byte; 1118 while ((componentIdByte>>= 1) != 0) { 1119 componentId++; 1120 } 1121 pFwupgCtx->componentId = componentId; 1122 pVersionInfo = (VERSIONINFO *)&gVersionInfo[componentId]; 1123 pFwImage = (struct HpmfwupgFirmwareImage*)((*pImagePtr) 1124 + sizeof(struct HpmfwupgActionRecord)); 1125 pDataInitial = ((unsigned char *)pFwImage 1126 + sizeof(struct HpmfwupgFirmwareImage)); 1127 pData = pDataInitial; 1128 1129 /* Find max buffer length according the connection parameters */ 1130 max_rq_size = ipmi_intf_get_max_request_data_size(intf); 1131 1132 /* validate lower bound of max request size */ 1133 if (max_rq_size <= sizeof(struct HpmfwupgUploadFirmwareBlockReq)) { 1134 lprintf(LOG_ERROR, "Maximum request size is too small to " 1135 "send a upload request."); 1136 return HPMFWUPG_ERROR; 1137 } 1138 1139 bufLength = max_rq_size - sizeof(struct HpmfwupgUploadFirmwareBlockReq); 1140 1141 /* Get firmware length */ 1142 firmwareLength = pFwImage->length[0]; 1143 firmwareLength|= (pFwImage->length[1] << 8) & 0xff00; 1144 firmwareLength|= (pFwImage->length[2] << 16) & 0xff0000; 1145 firmwareLength|= (pFwImage->length[3] << 24) & 0xff000000; 1146 mode = TARGET_VER | IMAGE_VER; 1147 if (pVersionInfo->rollbackSupported) { 1148 mode |= ROLLBACK_VER; 1149 } 1150 if ((option & DEBUG_MODE)) { 1151 printf("\n\n Comp ID : %d [%-20s]\n", 1152 pVersionInfo->componentId, 1153 pFwImage->desc); 1154 } else { 1155 HpmDisplayVersion(mode, pVersionInfo, 0); 1156 } 1157 if ((1 << componentId) & pFwupgCtx->compUpdateMask.ComponentBits.byte) { 1158 if (verbose) { 1159 lprintf(LOG_NOTICE, "Do not skip %d", 1160 componentId); 1161 } 1162 skip = FALSE; 1163 } 1164 if (!skip) { 1165 HpmDisplayUpgrade(0,0,1,0); 1166 /* Initialize parameters */ 1167 uploadCmd.req = malloc(max_rq_size); 1168 if (!uploadCmd.req) { 1169 lprintf(LOG_ERR, "ipmitool: malloc failure"); 1170 return HPMFWUPG_ERROR; 1171 } 1172 uploadCmd.req->blockNumber = 0; 1173 /* Send Initiate Upgrade Action */ 1174 initUpgActionCmd.req.componentsMask = components; 1175 if (option & COMPARE_MODE) { 1176 /* Action is compare */ 1177 initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_COMPARE; 1178 } else { 1179 /* Action is upgrade */ 1180 initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_UPGRADE; 1181 } 1182 rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); 1183 if (rc != HPMFWUPG_SUCCESS) { 1184 skip = TRUE; 1185 } 1186 if ((pVersionInfo->coldResetRequired) && (!skip)) { 1187 *pFlagColdReset = TRUE; 1188 } 1189 /* pDataInitial is the starting pointer of the image data */ 1190 /* pDataTemp is one which we will move across */ 1191 pData = pDataInitial; 1192 pDataTemp = pDataInitial; 1193 lengthOfBlock = firmwareLength; 1194 totalSent = 0x00; 1195 displayFWLength= firmwareLength; 1196 time(&start); 1197 while ((pData < (pDataTemp+lengthOfBlock)) && (rc == HPMFWUPG_SUCCESS)) { 1198 if ((pData+bufLength) <= (pDataTemp+lengthOfBlock)) { 1199 count = bufLength; 1200 } else { 1201 count = (unsigned short)((pDataTemp+lengthOfBlock) - pData); 1202 } 1203 memcpy(&uploadCmd.req->data, pData, bufLength); 1204 imageOffset = 0x00; 1205 blockLength = 0x00; 1206 numTxPkts++; 1207 rc = HpmfwupgUploadFirmwareBlock(intf, &uploadCmd, 1208 pFwupgCtx, count, &imageOffset,&blockLength); 1209 numRxPkts++; 1210 if (rc != HPMFWUPG_SUCCESS) { 1211 if (rc == HPMFWUPG_UPLOAD_BLOCK_LENGTH && !bufLengthIsSet) { 1212 rc = HPMFWUPG_SUCCESS; 1213 /* Retry with a smaller buffer length */ 1214 if (strstr(intf->name,"lan") != NULL && bufLength > 8) { 1215 bufLength-= 8; 1216 lprintf(LOG_INFO, 1217 "Trying reduced buffer length: %d", 1218 bufLength); 1219 } else if (bufLength) { 1220 bufLength-= 1; 1221 lprintf(LOG_INFO, 1222 "Trying reduced buffer length: %d", 1223 bufLength); 1224 } else { 1225 rc = HPMFWUPG_ERROR; 1226 } 1227 } else if (rc == HPMFWUPG_UPLOAD_RETRY) { 1228 rc = HPMFWUPG_SUCCESS; 1229 } else { 1230 fflush(stdout); 1231 lprintf(LOG_NOTICE, 1232 "\n Error in Upload FIRMWARE command [rc=%d]\n", 1233 rc); 1234 lprintf(LOG_NOTICE, 1235 "\n TotalSent:0x%x ", 1236 totalSent); 1237 /* Exiting from the function */ 1238 rc = HPMFWUPG_ERROR; 1239 } 1240 } else { 1241 /* success, buf length is valid */ 1242 bufLengthIsSet = 1; 1243 if (imageOffset + blockLength > firmwareLength || 1244 imageOffset + blockLength < blockLength) { 1245 /* 1246 * blockLength is the remaining length of the firmware to upload so 1247 * if imageOffset and blockLength sum is greater than the firmware 1248 * length then its kind of error 1249 */ 1250 lprintf(LOG_NOTICE, 1251 "\n Error in Upload FIRMWARE command [rc=%d]\n", 1252 rc); 1253 lprintf(LOG_NOTICE, 1254 "\n TotalSent:0x%x Img offset:0x%x Blk length:0x%x Fwlen:0x%x\n", 1255 totalSent,imageOffset,blockLength,firmwareLength); 1256 rc = HPMFWUPG_ERROR; 1257 continue; 1258 } 1259 totalSent += count; 1260 if (imageOffset != 0x00) { 1261 /* block Length is valid */ 1262 lengthOfBlock = blockLength; 1263 pDataTemp = pDataInitial + imageOffset; 1264 pData = pDataTemp; 1265 if (displayFWLength == firmwareLength) { 1266 /* This is basically used only to make sure that we display uptil 100% */ 1267 displayFWLength = blockLength + totalSent; 1268 } 1269 } else { 1270 pData += count; 1271 } 1272 time(&end); 1273 /* 1274 * Just added debug mode in case we need to see exactly how many bytes have 1275 * gone through - Its a hidden option used mainly should be used for debugging 1276 */ 1277 if (option & DEBUG_MODE) { 1278 fflush(stdout); 1279 printf(" Blk Num : %02x Bytes : %05x ", 1280 uploadCmd.req->blockNumber,totalSent); 1281 if (imageOffset || blockLength) { 1282 printf("\n--> ImgOff : %x BlkLen : %x\n", 1283 imageOffset,blockLength); 1284 } 1285 if (displayFWLength == totalSent) { 1286 printf("\n Time Taken %02ld:%02ld", 1287 (end-start)/60, (end-start)%60); 1288 printf("\n\n"); 1289 } 1290 } else { 1291 HpmDisplayUpgrade(0, totalSent, 1292 displayFWLength, (end-start)); 1293 } 1294 uploadCmd.req->blockNumber++; 1295 } 1296 } 1297 /* free buffer */ 1298 free(uploadCmd.req); 1299 uploadCmd.req = NULL; 1300 } 1301 if (skip) { 1302 HpmDisplayUpgrade(1,0,0,0); 1303 if ((option & COMPARE_MODE) 1304 && !pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.comparisonSupport) { 1305 printf("| |Comparison isn't supported for given compenent. |\n"); 1306 } 1307 *pImagePtr = pDataInitial + firmwareLength; 1308 } 1309 if (rc == HPMFWUPG_SUCCESS && !skip) { 1310 /* Send finish component */ 1311 /* Set image length */ 1312 finishCmd.req.componentId = componentId; 1313 /* We need to send the actual data that is sent 1314 * not the comlete firmware image length 1315 */ 1316 finishCmd.req.imageLength[0] = totalSent & 0xFF; 1317 finishCmd.req.imageLength[1] = (totalSent >> 8) & 0xFF; 1318 finishCmd.req.imageLength[2] = (totalSent >> 16) & 0xFF; 1319 finishCmd.req.imageLength[3] = (totalSent >> 24) & 0xFF; 1320 rc = HpmfwupgFinishFirmwareUpload(intf, &finishCmd, 1321 pFwupgCtx, option); 1322 *pImagePtr = pDataInitial + firmwareLength; 1323 } 1324 return rc; 1325 } 1326 1327 /* HpmfwupgActivationStage - validate stage of a firmware upgrade procedure as 1328 * defined in section 3.4 of the IPM Controller Firmware Upgrade Specification 1329 * version 1.0 1330 */ 1331 int 1332 HpmfwupgActivationStage(struct ipmi_intf *intf, 1333 struct HpmfwupgUpgradeCtx *pFwupgCtx) 1334 { 1335 int rc = HPMFWUPG_SUCCESS; 1336 struct HpmfwupgActivateFirmwareCtx activateCmd; 1337 struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*) 1338 pFwupgCtx->pImageData; 1339 /* Print out stuf...*/ 1340 printf(" "); 1341 fflush(stdout); 1342 /* Activate new firmware */ 1343 activateCmd.req.rollback_override = 0; 1344 rc = HpmfwupgActivateFirmware(intf, &activateCmd, pFwupgCtx); 1345 if (rc == HPMFWUPG_SUCCESS) { 1346 /* Query self test result if supported by target and new image */ 1347 if ((pFwupgCtx->targetCap.GlobalCapabilities.bitField.ipmcSelftestCap == 1) 1348 || (pImageHeader->imageCapabilities.bitField.imageSelfTest == 1)) { 1349 struct HpmfwupgQuerySelftestResultCtx selfTestCmd; 1350 rc = HpmfwupgQuerySelftestResult(intf, &selfTestCmd, 1351 pFwupgCtx); 1352 if (rc == HPMFWUPG_SUCCESS) { 1353 /* Get the self test result */ 1354 if (selfTestCmd.resp.result1 != 0x55) { 1355 /* Perform manual rollback if necessary */ 1356 /* BACKUP/ MANUAL ROLLBACK not supported by this UA */ 1357 lprintf(LOG_NOTICE, " Self test failed:"); 1358 lprintf(LOG_NOTICE, " Result1 = %x", 1359 selfTestCmd.resp.result1); 1360 lprintf(LOG_NOTICE, " Result2 = %x", 1361 selfTestCmd.resp.result2); 1362 rc = HPMFWUPG_ERROR; 1363 } 1364 } else { 1365 /* Perform manual rollback if necessary */ 1366 /* BACKUP / MANUAL ROLLBACK not supported by this UA */ 1367 lprintf(LOG_NOTICE," Self test failed."); 1368 } 1369 } 1370 } 1371 /* If activation / self test failed, query rollback 1372 * status if automatic rollback supported 1373 */ 1374 if (rc == HPMFWUPG_ERROR) { 1375 if ((pFwupgCtx->targetCap.GlobalCapabilities.bitField.autRollback == 1) 1376 && (pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.rollbackBackup != 0x00)) { 1377 struct HpmfwupgQueryRollbackStatusCtx rollCmd; 1378 lprintf(LOG_NOTICE," Getting rollback status..."); 1379 fflush(stdout); 1380 rc = HpmfwupgQueryRollbackStatus(intf, 1381 &rollCmd, pFwupgCtx); 1382 } 1383 } 1384 return rc; 1385 } 1386 1387 int 1388 HpmfwupgGetBufferFromFile(char *imageFilename, 1389 struct HpmfwupgUpgradeCtx *pFwupgCtx) 1390 { 1391 int rc = HPMFWUPG_SUCCESS; 1392 int ret = 0; 1393 FILE *pImageFile = fopen(imageFilename, "rb"); 1394 if (pImageFile == NULL) { 1395 lprintf(LOG_ERR, "Cannot open image file '%s'", 1396 imageFilename); 1397 return HPMFWUPG_ERROR; 1398 } 1399 /* Get the raw data in file */ 1400 fseek(pImageFile, 0, SEEK_END); 1401 pFwupgCtx->imageSize = ftell(pImageFile); 1402 pFwupgCtx->pImageData = malloc(sizeof(unsigned char)*pFwupgCtx->imageSize); 1403 if (pFwupgCtx->pImageData == NULL) { 1404 lprintf(LOG_ERR, "ipmitool: malloc failure"); 1405 fclose(pImageFile); 1406 return HPMFWUPG_ERROR; 1407 } 1408 rewind(pImageFile); 1409 ret = fread(pFwupgCtx->pImageData, 1410 sizeof(unsigned char), 1411 pFwupgCtx->imageSize, 1412 pImageFile); 1413 if (ret != pFwupgCtx->imageSize) { 1414 lprintf(LOG_ERR, 1415 "Failed to read file %s size %d", 1416 imageFilename, 1417 pFwupgCtx->imageSize); 1418 rc = HPMFWUPG_ERROR; 1419 } 1420 fclose(pImageFile); 1421 return rc; 1422 } 1423 1424 int 1425 HpmfwupgGetDeviceId(struct ipmi_intf *intf, struct ipm_devid_rsp *pGetDevId) 1426 { 1427 struct ipmi_rs *rsp; 1428 struct ipmi_rq req; 1429 memset(&req, 0, sizeof(req)); 1430 req.msg.netfn = IPMI_NETFN_APP; 1431 req.msg.cmd = BMC_GET_DEVICE_ID; 1432 req.msg.data_len = 0; 1433 rsp = HpmfwupgSendCmd(intf, req, NULL); 1434 if (rsp == NULL) { 1435 lprintf(LOG_ERR, "Error getting device ID."); 1436 return HPMFWUPG_ERROR; 1437 } 1438 if (rsp->ccode != 0x00) { 1439 lprintf(LOG_ERR, "Error getting device ID."); 1440 lprintf(LOG_ERR, "compcode=0x%x: %s", 1441 rsp->ccode, 1442 val2str(rsp->ccode, completion_code_vals)); 1443 return HPMFWUPG_ERROR; 1444 } 1445 memcpy(pGetDevId, rsp->data, sizeof(struct ipm_devid_rsp)); 1446 return HPMFWUPG_SUCCESS; 1447 } 1448 1449 int 1450 HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf, 1451 struct HpmfwupgGetTargetUpgCapabilitiesCtx *pCtx) 1452 { 1453 struct ipmi_rs *rsp; 1454 struct ipmi_rq req; 1455 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1456 memset(&req, 0, sizeof(req)); 1457 req.msg.netfn = IPMI_NETFN_PICMG; 1458 req.msg.cmd = HPMFWUPG_GET_TARGET_UPG_CAPABILITIES; 1459 req.msg.data = (unsigned char*)&pCtx->req; 1460 req.msg.data_len = sizeof(struct HpmfwupgGetTargetUpgCapabilitiesReq); 1461 rsp = HpmfwupgSendCmd(intf, req, NULL); 1462 if (rsp == NULL) { 1463 lprintf(LOG_ERR, 1464 "Error getting target upgrade capabilities."); 1465 return HPMFWUPG_ERROR; 1466 } 1467 if (rsp->ccode != 0x00) { 1468 lprintf(LOG_ERR, 1469 "Error getting target upgrade capabilities, ccode: 0x%x: %s", 1470 rsp->ccode, 1471 val2str(rsp->ccode, completion_code_vals)); 1472 return HPMFWUPG_ERROR; 1473 } 1474 memcpy(&pCtx->resp, rsp->data, 1475 sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp)); 1476 if (verbose) { 1477 lprintf(LOG_NOTICE, "TARGET UPGRADE CAPABILITIES"); 1478 lprintf(LOG_NOTICE, "-------------------------------"); 1479 lprintf(LOG_NOTICE, "HPM.1 version............%d ", 1480 pCtx->resp.hpmVersion); 1481 lprintf(LOG_NOTICE, "Component 0 presence....[%c] ", 1482 pCtx->resp.componentsPresent.ComponentBits.bitField.component0 ? 'y' : 'n'); 1483 lprintf(LOG_NOTICE, "Component 1 presence....[%c] ", 1484 pCtx->resp.componentsPresent.ComponentBits.bitField.component1 ? 'y' : 'n'); 1485 lprintf(LOG_NOTICE, "Component 2 presence....[%c] ", 1486 pCtx->resp.componentsPresent.ComponentBits.bitField.component2 ? 'y' : 'n'); 1487 lprintf(LOG_NOTICE, "Component 3 presence....[%c] ", 1488 pCtx->resp.componentsPresent.ComponentBits.bitField.component3 ? 'y' : 'n'); 1489 lprintf(LOG_NOTICE, "Component 4 presence....[%c] ", 1490 pCtx->resp.componentsPresent.ComponentBits.bitField.component4 ? 'y' : 'n'); 1491 lprintf(LOG_NOTICE, "Component 5 presence....[%c] ", 1492 pCtx->resp.componentsPresent.ComponentBits.bitField.component5 ? 'y' : 'n'); 1493 lprintf(LOG_NOTICE, "Component 6 presence....[%c] ", 1494 pCtx->resp.componentsPresent.ComponentBits.bitField.component6 ? 'y' : 'n'); 1495 lprintf(LOG_NOTICE, "Component 7 presence....[%c] ", 1496 pCtx->resp.componentsPresent.ComponentBits.bitField.component7 ? 'y' : 'n'); 1497 lprintf(LOG_NOTICE, "Upgrade undesirable.....[%c] ", 1498 pCtx->resp.GlobalCapabilities.bitField.fwUpgUndesirable ? 'y' : 'n'); 1499 lprintf(LOG_NOTICE, "Aut rollback override...[%c] ", 1500 pCtx->resp.GlobalCapabilities.bitField.autRollbackOverride ? 'y' : 'n'); 1501 lprintf(LOG_NOTICE, "IPMC degraded...........[%c] ", 1502 pCtx->resp.GlobalCapabilities.bitField.ipmcDegradedDurinUpg ? 'y' : 'n'); 1503 lprintf(LOG_NOTICE, "Defered activation......[%c] ", 1504 pCtx->resp.GlobalCapabilities.bitField.deferActivation ? 'y' : 'n'); 1505 lprintf(LOG_NOTICE, "Service affected........[%c] ", 1506 pCtx->resp.GlobalCapabilities.bitField.servAffectDuringUpg ? 'y' : 'n'); 1507 lprintf(LOG_NOTICE, "Manual rollback.........[%c] ", 1508 pCtx->resp.GlobalCapabilities.bitField.manualRollback ? 'y' : 'n'); 1509 lprintf(LOG_NOTICE, "Automatic rollback......[%c] ", 1510 pCtx->resp.GlobalCapabilities.bitField.autRollback ? 'y' : 'n'); 1511 lprintf(LOG_NOTICE, "Self test...............[%c] ", 1512 pCtx->resp.GlobalCapabilities.bitField.ipmcSelftestCap ? 'y' : 'n'); 1513 lprintf(LOG_NOTICE, "Upgrade timeout.........[%d sec] ", 1514 pCtx->resp.upgradeTimeout*5); 1515 lprintf(LOG_NOTICE, "Self test timeout.......[%d sec] ", 1516 pCtx->resp.selftestTimeout*5); 1517 lprintf(LOG_NOTICE, "Rollback timeout........[%d sec] ", 1518 pCtx->resp.rollbackTimeout*5); 1519 lprintf(LOG_NOTICE, "Inaccessibility timeout.[%d sec] \n", 1520 pCtx->resp.inaccessTimeout*5); 1521 } 1522 return HPMFWUPG_SUCCESS; 1523 } 1524 1525 int 1526 HpmfwupgGetComponentProperties(struct ipmi_intf *intf, 1527 struct HpmfwupgGetComponentPropertiesCtx *pCtx) 1528 { 1529 int rc = HPMFWUPG_SUCCESS; 1530 struct ipmi_rs * rsp; 1531 struct ipmi_rq req; 1532 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1533 memset(&req, 0, sizeof(req)); 1534 req.msg.netfn = IPMI_NETFN_PICMG; 1535 req.msg.cmd = HPMFWUPG_GET_COMPONENT_PROPERTIES; 1536 req.msg.data = (unsigned char*)&pCtx->req; 1537 req.msg.data_len = sizeof(struct HpmfwupgGetComponentPropertiesReq); 1538 rsp = HpmfwupgSendCmd(intf, req, NULL); 1539 if (rsp == NULL) { 1540 lprintf(LOG_NOTICE, 1541 "Error getting component properties\n"); 1542 return HPMFWUPG_ERROR; 1543 } 1544 if (rsp->ccode != 0x00) { 1545 lprintf(LOG_NOTICE, 1546 "Error getting component properties"); 1547 lprintf(LOG_NOTICE, 1548 "compcode=0x%x: %s", 1549 rsp->ccode, 1550 val2str(rsp->ccode, completion_code_vals)); 1551 return HPMFWUPG_ERROR; 1552 } 1553 switch (pCtx->req.selector) { 1554 case HPMFWUPG_COMP_GEN_PROPERTIES: 1555 memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetGeneralPropResp)); 1556 if (verbose) { 1557 lprintf(LOG_NOTICE, "GENERAL PROPERTIES"); 1558 lprintf(LOG_NOTICE, "-------------------------------"); 1559 lprintf(LOG_NOTICE, "Payload cold reset req....[%c] ", 1560 pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.payloadColdReset ? 'y' : 'n'); 1561 lprintf(LOG_NOTICE, "Def. activation supported.[%c] ", 1562 pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.deferredActivation ? 'y' : 'n'); 1563 lprintf(LOG_NOTICE, "Comparison supported......[%c] ", 1564 pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.comparisonSupport ? 'y' : 'n'); 1565 lprintf(LOG_NOTICE, "Preparation supported.....[%c] ", 1566 pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.preparationSupport ? 'y' : 'n'); 1567 lprintf(LOG_NOTICE, "Rollback supported........[%c] \n", 1568 pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.rollbackBackup ? 'y' : 'n'); 1569 } 1570 break; 1571 case HPMFWUPG_COMP_CURRENT_VERSION: 1572 memcpy(&pCtx->resp, rsp->data, 1573 sizeof(struct HpmfwupgGetCurrentVersionResp)); 1574 if (verbose) { 1575 lprintf(LOG_NOTICE, "Current Version: "); 1576 lprintf(LOG_NOTICE, " Major: %d", 1577 pCtx->resp.Response.currentVersionResp.currentVersion[0]); 1578 lprintf(LOG_NOTICE, " Minor: %x", 1579 pCtx->resp.Response.currentVersionResp.currentVersion[1]); 1580 lprintf(LOG_NOTICE, " Aux : %03d %03d %03d %03d\n", 1581 pCtx->resp.Response.currentVersionResp.currentVersion[2], 1582 pCtx->resp.Response.currentVersionResp.currentVersion[3], 1583 pCtx->resp.Response.currentVersionResp.currentVersion[4], 1584 pCtx->resp.Response.currentVersionResp.currentVersion[5]); 1585 } 1586 break; 1587 case HPMFWUPG_COMP_DESCRIPTION_STRING: 1588 memcpy(&pCtx->resp, rsp->data, 1589 sizeof(struct HpmfwupgGetDescStringResp)); 1590 if (verbose) { 1591 char descString[HPMFWUPG_DESC_STRING_LENGTH + 1]; 1592 memcpy(descString, 1593 pCtx->resp.Response.descStringResp.descString, 1594 HPMFWUPG_DESC_STRING_LENGTH); 1595 descString[HPMFWUPG_DESC_STRING_LENGTH] = '\0'; 1596 lprintf(LOG_NOTICE, 1597 "Description string: %s\n", 1598 descString); 1599 } 1600 break; 1601 case HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION: 1602 memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetRollbackFwVersionResp)); 1603 if (verbose) { 1604 lprintf(LOG_NOTICE, "Rollback FW Version: "); 1605 lprintf(LOG_NOTICE, " Major: %d", 1606 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[0]); 1607 lprintf(LOG_NOTICE, " Minor: %x", 1608 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[1]); 1609 lprintf(LOG_NOTICE, " Aux : %03d %03d %03d %03d\n", 1610 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[2], 1611 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[3], 1612 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[4], 1613 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[5]); 1614 } 1615 break; 1616 case HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION: 1617 memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDeferredFwVersionResp)); 1618 if (verbose) { 1619 lprintf(LOG_NOTICE, "Deferred FW Version: "); 1620 lprintf(LOG_NOTICE, " Major: %d", 1621 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[0]); 1622 lprintf(LOG_NOTICE, " Minor: %x", 1623 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[1]); 1624 lprintf(LOG_NOTICE, " Aux : %03d %03d %03d %03d\n", 1625 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[2], 1626 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[3], 1627 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[4], 1628 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[5]); 1629 } 1630 break; 1631 case HPMFWUPG_COMP_OEM_PROPERTIES: 1632 /* OEM Properties command */ 1633 memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetOemProperties)); 1634 if (verbose) { 1635 unsigned char i = 0; 1636 lprintf(LOG_NOTICE,"OEM Properties: "); 1637 for (i=0; i < HPMFWUPG_OEM_LENGTH; i++) { 1638 lprintf(LOG_NOTICE, " 0x%x ", 1639 pCtx->resp.Response.oemProperties.oemRspData[i]); 1640 } 1641 } 1642 break; 1643 default: 1644 lprintf(LOG_NOTICE,"Unsupported component selector"); 1645 rc = HPMFWUPG_ERROR; 1646 break; 1647 } 1648 return rc; 1649 } 1650 1651 int 1652 HpmfwupgAbortUpgrade(struct ipmi_intf *intf, 1653 struct HpmfwupgAbortUpgradeCtx *pCtx) 1654 { 1655 int rc = HPMFWUPG_SUCCESS; 1656 struct ipmi_rs *rsp; 1657 struct ipmi_rq req; 1658 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1659 memset(&req, 0, sizeof(req)); 1660 req.msg.netfn = IPMI_NETFN_PICMG; 1661 req.msg.cmd = HPMFWUPG_ABORT_UPGRADE; 1662 req.msg.data = (unsigned char*)&pCtx->req; 1663 req.msg.data_len = sizeof(struct HpmfwupgAbortUpgradeReq); 1664 rsp = HpmfwupgSendCmd(intf, req, NULL); 1665 if (rsp == NULL) { 1666 lprintf(LOG_ERR, "Error - aborting upgrade."); 1667 return HPMFWUPG_ERROR; 1668 } 1669 if (rsp->ccode != 0x00) { 1670 lprintf(LOG_ERR, "Error aborting upgrade"); 1671 lprintf(LOG_ERR, "compcode=0x%x: %s", 1672 rsp->ccode, 1673 val2str(rsp->ccode, completion_code_vals)); 1674 rc = HPMFWUPG_ERROR; 1675 } 1676 return rc; 1677 } 1678 1679 int 1680 HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf, 1681 struct HpmfwupgInitiateUpgradeActionCtx *pCtx, 1682 struct HpmfwupgUpgradeCtx *pFwupgCtx) 1683 { 1684 int rc = HPMFWUPG_SUCCESS; 1685 struct ipmi_rs *rsp; 1686 struct ipmi_rq req; 1687 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1688 memset(&req, 0, sizeof(req)); 1689 req.msg.netfn = IPMI_NETFN_PICMG; 1690 req.msg.cmd = HPMFWUPG_INITIATE_UPGRADE_ACTION; 1691 req.msg.data = (unsigned char*)&pCtx->req; 1692 req.msg.data_len = sizeof(struct HpmfwupgInitiateUpgradeActionReq); 1693 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 1694 if (rsp == NULL) { 1695 lprintf(LOG_ERR, "Error initiating upgrade action."); 1696 return HPMFWUPG_ERROR; 1697 } 1698 /* Long duration command handling */ 1699 if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { 1700 rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); 1701 } else if (rsp->ccode != 0x00) { 1702 lprintf(LOG_NOTICE,"Error initiating upgrade action"); 1703 lprintf(LOG_NOTICE, "compcode=0x%x: %s", 1704 rsp->ccode, 1705 val2str(rsp->ccode, completion_code_vals)); 1706 rc = HPMFWUPG_ERROR; 1707 } 1708 return rc; 1709 } 1710 1711 int 1712 HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf, 1713 struct HpmfwupgUploadFirmwareBlockCtx *pCtx, 1714 struct HpmfwupgUpgradeCtx *pFwupgCtx, int count, 1715 unsigned int *imageOffset, unsigned int *blockLength) 1716 { 1717 int rc = HPMFWUPG_SUCCESS; 1718 struct ipmi_rs *rsp; 1719 struct ipmi_rq req; 1720 pCtx->req->picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1721 memset(&req, 0, sizeof(req)); 1722 req.msg.netfn = IPMI_NETFN_PICMG; 1723 req.msg.cmd = HPMFWUPG_UPLOAD_FIRMWARE_BLOCK; 1724 req.msg.data = (unsigned char *)pCtx->req; 1725 /* 2 is the size of the upload struct - data */ 1726 req.msg.data_len = 2 + count; 1727 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 1728 if (rsp == NULL) { 1729 lprintf(LOG_NOTICE, "Error uploading firmware block."); 1730 return HPMFWUPG_ERROR; 1731 } 1732 if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS 1733 || rsp->ccode == 0x00) { 1734 /* 1735 * We need to check if the response also contains the next upload firmware offset 1736 * and the firmware length in its response - These are optional but very vital 1737 */ 1738 if (rsp->data_len > 1) { 1739 /* 1740 * If the response data length is greater than 1 it should contain both the 1741 * the Section offset and section length. Because we cannot just have 1742 * Section offset without section length so the length should be 9 1743 */ 1744 if (rsp->data_len == 9) { 1745 /* rsp->data[1] - LSB rsp->data[2] - rsp->data[3] = MSB */ 1746 *imageOffset = (rsp->data[4] << 24) + (rsp->data[3] << 16) + (rsp->data[2] << 8) + rsp->data[1]; 1747 *blockLength = (rsp->data[8] << 24) + (rsp->data[7] << 16) + (rsp->data[6] << 8) + rsp->data[5]; 1748 } else { 1749 /* 1750 * The Spec does not say much for this kind of errors where the 1751 * firmware returned only offset and length so currently returning it 1752 * as 0x82 - Internal CheckSum Error 1753 */ 1754 lprintf(LOG_NOTICE, 1755 "Error wrong rsp->datalen %d for Upload Firmware block command\n", 1756 rsp->data_len); 1757 rsp->ccode = HPMFWUPG_INT_CHECKSUM_ERROR; 1758 } 1759 } 1760 } 1761 /* Long duration command handling */ 1762 if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { 1763 rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); 1764 } else if (rsp->ccode != 0x00) { 1765 /* PATCH --> This validation is to handle retryables errors codes on IPMB bus. 1766 * This will be fixed in the next release of open ipmi and this 1767 * check will have to be removed. (Buggy version = 39) 1768 */ 1769 if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) { 1770 lprintf(LOG_DEBUG, "HPM: [PATCH]Retryable error detected"); 1771 rc = HPMFWUPG_UPLOAD_RETRY; 1772 } else if (rsp->ccode == IPMI_CC_REQ_DATA_INV_LENGTH || 1773 rsp->ccode == IPMI_CC_REQ_DATA_FIELD_EXCEED) { 1774 /* If completion code = 0xc7(0xc8), we will retry with a reduced buffer length. 1775 * Do not print error. 1776 */ 1777 rc = HPMFWUPG_UPLOAD_BLOCK_LENGTH; 1778 } else { 1779 lprintf(LOG_ERR, "Error uploading firmware block"); 1780 lprintf(LOG_ERR, "compcode=0x%x: %s", 1781 rsp->ccode, 1782 val2str(rsp->ccode, 1783 completion_code_vals)); 1784 rc = HPMFWUPG_ERROR; 1785 } 1786 } 1787 return rc; 1788 } 1789 1790 int 1791 HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf, 1792 struct HpmfwupgFinishFirmwareUploadCtx *pCtx, 1793 struct HpmfwupgUpgradeCtx *pFwupgCtx, int option) 1794 { 1795 int rc = HPMFWUPG_SUCCESS; 1796 struct ipmi_rs *rsp; 1797 struct ipmi_rq req; 1798 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1799 memset(&req, 0, sizeof(req)); 1800 req.msg.netfn = IPMI_NETFN_PICMG; 1801 req.msg.cmd = HPMFWUPG_FINISH_FIRMWARE_UPLOAD; 1802 req.msg.data = (unsigned char*)&pCtx->req; 1803 req.msg.data_len = sizeof(struct HpmfwupgFinishFirmwareUploadReq); 1804 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 1805 if (rsp == NULL) { 1806 lprintf(LOG_ERR, "Error fininshing firmware upload."); 1807 return HPMFWUPG_ERROR; 1808 } 1809 /* Long duration command handling */ 1810 if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { 1811 rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); 1812 } else if ((option & COMPARE_MODE) && rsp->ccode == 0x83) { 1813 printf("| |Component's active copy doesn't match the upgrade image |\n"); 1814 } else if ((option & COMPARE_MODE) && rsp->ccode == IPMI_CC_OK) { 1815 printf("| |Comparison passed |\n"); 1816 } else if ( rsp->ccode != IPMI_CC_OK ) { 1817 lprintf(LOG_ERR, "Error finishing firmware upload"); 1818 lprintf(LOG_ERR, "compcode=0x%x: %s", 1819 rsp->ccode, 1820 val2str(rsp->ccode, completion_code_vals)); 1821 rc = HPMFWUPG_ERROR; 1822 } 1823 return rc; 1824 } 1825 1826 int 1827 HpmfwupgActivateFirmware(struct ipmi_intf *intf, 1828 struct HpmfwupgActivateFirmwareCtx *pCtx, 1829 struct HpmfwupgUpgradeCtx *pFwupgCtx) 1830 { 1831 int rc = HPMFWUPG_SUCCESS; 1832 struct ipmi_rs *rsp; 1833 struct ipmi_rq req; 1834 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1835 memset(&req, 0, sizeof(req)); 1836 req.msg.netfn = IPMI_NETFN_PICMG; 1837 req.msg.cmd = HPMFWUPG_ACTIVATE_FIRMWARE; 1838 req.msg.data = (unsigned char*)&pCtx->req; 1839 req.msg.data_len = sizeof(struct HpmfwupgActivateFirmwareReq) 1840 - (!pCtx->req.rollback_override ? 1 : 0); 1841 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 1842 if (rsp == NULL) { 1843 lprintf(LOG_ERR, "Error activating firmware."); 1844 return HPMFWUPG_ERROR; 1845 } 1846 /* Long duration command handling */ 1847 if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { 1848 printf("Waiting firmware activation..."); 1849 fflush(stdout); 1850 rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); 1851 if (rc == HPMFWUPG_SUCCESS) { 1852 lprintf(LOG_NOTICE, "OK"); 1853 } else { 1854 lprintf(LOG_NOTICE, "Failed"); 1855 } 1856 } else if (rsp->ccode != IPMI_CC_OK) { 1857 lprintf(LOG_ERR, "Error activating firmware"); 1858 lprintf(LOG_ERR, "compcode=0x%x: %s", 1859 rsp->ccode, 1860 val2str(rsp->ccode, completion_code_vals)); 1861 rc = HPMFWUPG_ERROR; 1862 } 1863 return rc; 1864 } 1865 1866 int 1867 HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf, 1868 struct HpmfwupgGetUpgradeStatusCtx *pCtx, 1869 struct HpmfwupgUpgradeCtx *pFwupgCtx, 1870 int silent) 1871 { 1872 int rc = HPMFWUPG_SUCCESS; 1873 struct ipmi_rs *rsp; 1874 struct ipmi_rq req; 1875 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1876 memset(&req, 0, sizeof(req)); 1877 req.msg.netfn = IPMI_NETFN_PICMG; 1878 req.msg.cmd = HPMFWUPG_GET_UPGRADE_STATUS; 1879 req.msg.data = (unsigned char*)&pCtx->req; 1880 req.msg.data_len = sizeof(struct HpmfwupgGetUpgradeStatusReq); 1881 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 1882 if (!rsp) { 1883 lprintf(LOG_NOTICE, 1884 "Error getting upgrade status. Failed to get response."); 1885 return HPMFWUPG_ERROR; 1886 } 1887 if (rsp->ccode == 0x00) { 1888 memcpy(&pCtx->resp, rsp->data, 1889 sizeof(struct HpmfwupgGetUpgradeStatusResp)); 1890 if (!silent) { 1891 lprintf(LOG_NOTICE, "Upgrade status:"); 1892 lprintf(LOG_NOTICE, 1893 " Command in progress: %x", 1894 pCtx->resp.cmdInProcess); 1895 lprintf(LOG_NOTICE, 1896 " Last command completion code: %x", 1897 pCtx->resp.lastCmdCompCode); 1898 } 1899 } else if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) { 1900 /* PATCH --> This validation is to handle retryable errors 1901 * codes on the IPMB bus. 1902 * This will be fixed in the next release of 1903 * open ipmi and this check can be removed. 1904 * (Buggy version = 39) 1905 */ 1906 if (!silent) { 1907 lprintf(LOG_DEBUG, "HPM: Retryable error detected"); 1908 } 1909 pCtx->resp.lastCmdCompCode = HPMFWUPG_COMMAND_IN_PROGRESS; 1910 } else { 1911 lprintf(LOG_NOTICE, "Error getting upgrade status"); 1912 lprintf(LOG_NOTICE, "compcode=0x%x: %s", rsp->ccode, 1913 val2str(rsp->ccode, completion_code_vals)); 1914 return HPMFWUPG_ERROR; 1915 } 1916 return HPMFWUPG_SUCCESS; 1917 } 1918 1919 int 1920 HpmfwupgManualFirmwareRollback(struct ipmi_intf *intf, 1921 struct HpmfwupgManualFirmwareRollbackCtx *pCtx) 1922 { 1923 struct HpmfwupgUpgradeCtx fwupgCtx; 1924 struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; 1925 int rc = HPMFWUPG_SUCCESS; 1926 struct ipmi_rs *rsp; 1927 struct ipmi_rq req; 1928 /* prepare fake upgrade context */ 1929 memset(&fwupgCtx, 0, sizeof (fwupgCtx)); 1930 verbose--; 1931 rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); 1932 verbose++; 1933 if (rc != HPMFWUPG_SUCCESS) { 1934 return rc; 1935 } 1936 memcpy(&fwupgCtx.targetCap, &targetCapCmd.resp, sizeof(targetCapCmd.resp)); 1937 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1938 memset(&req, 0, sizeof(req)); 1939 req.msg.netfn = IPMI_NETFN_PICMG; 1940 req.msg.cmd = HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK; 1941 req.msg.data = (unsigned char*)&pCtx->req; 1942 req.msg.data_len = sizeof(struct HpmfwupgManualFirmwareRollbackReq); 1943 rsp = HpmfwupgSendCmd(intf, req, &fwupgCtx); 1944 if (rsp == NULL) { 1945 lprintf(LOG_ERR, "Error sending manual rollback."); 1946 return HPMFWUPG_ERROR; 1947 } 1948 /* Long duration command handling */ 1949 if (rsp->ccode == IPMI_CC_OK 1950 || rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { 1951 struct HpmfwupgQueryRollbackStatusCtx resCmd; 1952 printf("Waiting firmware rollback..."); 1953 fflush(stdout); 1954 rc = HpmfwupgQueryRollbackStatus(intf, &resCmd, &fwupgCtx); 1955 } else if ( rsp->ccode != 0x00 ) { 1956 lprintf(LOG_ERR, "Error sending manual rollback"); 1957 lprintf(LOG_ERR, "compcode=0x%x: %s", 1958 rsp->ccode, 1959 val2str(rsp->ccode, completion_code_vals)); 1960 rc = HPMFWUPG_ERROR; 1961 } 1962 return rc; 1963 } 1964 1965 int 1966 HpmfwupgQueryRollbackStatus(struct ipmi_intf *intf, 1967 struct HpmfwupgQueryRollbackStatusCtx *pCtx, 1968 struct HpmfwupgUpgradeCtx *pFwupgCtx) 1969 { 1970 int rc = HPMFWUPG_SUCCESS; 1971 struct ipmi_rs *rsp; 1972 struct ipmi_rq req; 1973 unsigned int rollbackTimeout = 0; 1974 unsigned int timeoutSec1, timeoutSec2; 1975 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1976 memset(&req, 0, sizeof(req)); 1977 req.msg.netfn = IPMI_NETFN_PICMG; 1978 req.msg.cmd = HPMFWUPG_QUERY_ROLLBACK_STATUS; 1979 req.msg.data = (unsigned char*)&pCtx->req; 1980 req.msg.data_len = sizeof(struct HpmfwupgQueryRollbackStatusReq); 1981 /* If we are not in upgrade context, we use default timeout values */ 1982 if (pFwupgCtx != NULL) { 1983 struct HpmfwupgImageHeader *pImageHeader; 1984 if (pFwupgCtx->pImageData) { 1985 pImageHeader = (struct HpmfwupgImageHeader*)pFwupgCtx->pImageData; 1986 rollbackTimeout = pImageHeader->rollbackTimeout; 1987 } else { 1988 rollbackTimeout = 0; 1989 } 1990 /* Use the greater of the two timeouts (header and target caps) */ 1991 rollbackTimeout = MAX(rollbackTimeout, 1992 pFwupgCtx->targetCap.rollbackTimeout) * 5; 1993 } else { 1994 rollbackTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; 1995 } 1996 /* Poll rollback status until completion or timeout */ 1997 timeoutSec1 = time(NULL); 1998 timeoutSec2 = time(NULL); 1999 do { 2000 /* Must wait at least 100 ms between status requests */ 2001 usleep(100000); 2002 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 2003 /* PATCH --> This validation is to handle retryables errors codes on IPMB bus. 2004 * This will be fixed in the next release of open ipmi and this 2005 * check will have to be removed. (Buggy version = 39) 2006 */ 2007 if (rsp) { 2008 if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) { 2009 lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); 2010 rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS; 2011 } 2012 } 2013 timeoutSec2 = time(NULL); 2014 } while (rsp 2015 && ((rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) 2016 || (rsp->ccode == IPMI_CC_TIMEOUT)) 2017 && (timeoutSec2 - timeoutSec1 < rollbackTimeout)); 2018 if (rsp == NULL) { 2019 lprintf(LOG_ERR, "Error getting upgrade status."); 2020 return HPMFWUPG_ERROR; 2021 } 2022 if (rsp->ccode == 0x00) { 2023 memcpy(&pCtx->resp, rsp->data, 2024 sizeof(struct HpmfwupgQueryRollbackStatusResp)); 2025 if (pCtx->resp.rollbackComp.ComponentBits.byte != 0) { 2026 /* Rollback occured */ 2027 lprintf(LOG_NOTICE, 2028 "Rollback occured on component mask: 0x%02x", 2029 pCtx->resp.rollbackComp.ComponentBits.byte); 2030 } else { 2031 lprintf(LOG_NOTICE, 2032 "No Firmware rollback occured"); 2033 } 2034 } else if (rsp->ccode == 0x81) { 2035 lprintf(LOG_ERR, 2036 "Rollback failed on component mask: 0x%02x", 2037 pCtx->resp.rollbackComp.ComponentBits.byte); 2038 rc = HPMFWUPG_ERROR; 2039 } else { 2040 lprintf(LOG_ERR, 2041 "Error getting rollback status"); 2042 lprintf(LOG_ERR, 2043 "compcode=0x%x: %s", 2044 rsp->ccode, 2045 val2str(rsp->ccode, completion_code_vals)); 2046 rc = HPMFWUPG_ERROR; 2047 } 2048 return rc; 2049 } 2050 2051 int 2052 HpmfwupgQuerySelftestResult(struct ipmi_intf *intf, struct HpmfwupgQuerySelftestResultCtx *pCtx, 2053 struct HpmfwupgUpgradeCtx *pFwupgCtx) 2054 { 2055 int rc = HPMFWUPG_SUCCESS; 2056 struct ipmi_rs *rsp; 2057 struct ipmi_rq req; 2058 unsigned char selfTestTimeout = 0; 2059 unsigned int timeoutSec1, timeoutSec2; 2060 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 2061 /* If we are not in upgrade context, we use default timeout values */ 2062 if (pFwupgCtx != NULL) { 2063 /* Getting selftest timeout from new image */ 2064 struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*) 2065 pFwupgCtx->pImageData; 2066 selfTestTimeout = MAX(pImageHeader->selfTestTimeout, 2067 pFwupgCtx->targetCap.selftestTimeout) * 5; 2068 } else { 2069 selfTestTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; 2070 } 2071 memset(&req, 0, sizeof(req)); 2072 req.msg.netfn = IPMI_NETFN_PICMG; 2073 req.msg.cmd = HPMFWUPG_QUERY_SELFTEST_RESULT; 2074 req.msg.data = (unsigned char*)&pCtx->req; 2075 req.msg.data_len = sizeof(struct HpmfwupgQuerySelftestResultReq); 2076 /* Poll rollback status until completion or timeout */ 2077 timeoutSec1 = time(NULL); 2078 timeoutSec2 = time(NULL); 2079 do { 2080 /* Must wait at least 100 ms between status requests */ 2081 usleep(100000); 2082 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 2083 /* PATCH --> This validation is to handle retryables errors codes on IPMB bus. 2084 * This will be fixed in the next release of open ipmi and this 2085 * check will have to be removed. (Buggy version = 39) 2086 */ 2087 if (rsp) { 2088 if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) { 2089 lprintf(LOG_DEBUG, 2090 "HPM: [PATCH]Retryable error detected"); 2091 rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS; 2092 } 2093 } 2094 timeoutSec2 = time(NULL); 2095 } while (rsp 2096 && (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) 2097 && (timeoutSec2 - timeoutSec1 < selfTestTimeout)); 2098 if (rsp == NULL) { 2099 lprintf(LOG_NOTICE, "Error getting upgrade status\n"); 2100 return HPMFWUPG_ERROR; 2101 } 2102 if (rsp->ccode == 0x00) { 2103 memcpy(&pCtx->resp, rsp->data, 2104 sizeof(struct HpmfwupgQuerySelftestResultResp)); 2105 if (verbose) { 2106 lprintf(LOG_NOTICE, "Self test results:"); 2107 lprintf(LOG_NOTICE, "Result1 = %x", 2108 pCtx->resp.result1); 2109 lprintf(LOG_NOTICE, "Result2 = %x", 2110 pCtx->resp.result2); 2111 } 2112 } else { 2113 lprintf(LOG_NOTICE, "Error getting self test results"); 2114 lprintf(LOG_NOTICE, "compcode=0x%x: %s", 2115 rsp->ccode, 2116 val2str(rsp->ccode, completion_code_vals)); 2117 rc = HPMFWUPG_ERROR; 2118 } 2119 return rc; 2120 } 2121 2122 struct ipmi_rs * 2123 HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req, 2124 struct HpmfwupgUpgradeCtx *pFwupgCtx) 2125 { 2126 struct ipmi_rs *rsp; 2127 unsigned int inaccessTimeout = 0, inaccessTimeoutCounter = 0; 2128 unsigned int upgradeTimeout = 0, upgradeTimeoutCounter = 0; 2129 unsigned int timeoutSec1, timeoutSec2; 2130 unsigned char retry = 0; 2131 /* If we are not in upgrade context, we use default timeout values */ 2132 if (pFwupgCtx != NULL) { 2133 inaccessTimeout = pFwupgCtx->targetCap.inaccessTimeout*5; 2134 upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5; 2135 } else { 2136 /* keeping the inaccessTimeout to 60 seconds results in almost 2900 retries 2137 * So if the target is not available it will be retrying the command for 2900 2138 * times which is not effecient -So reducing the Timout to 5 seconds which is 2139 * almost 200 retries if it continuously recieves 0xC3 as completion code. 2140 */ 2141 inaccessTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; 2142 upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; 2143 } 2144 timeoutSec1 = time(NULL); 2145 do { 2146 static unsigned char isValidSize = FALSE; 2147 rsp = intf->sendrecv(intf, &req); 2148 if (rsp == NULL) { 2149 #define HPM_LAN_PACKET_RESIZE_LIMIT 6 2150 /* also covers lanplus */ 2151 if (strstr(intf->name, "lan") != NULL) { 2152 static int errorCount=0; 2153 static struct ipmi_rs fakeRsp; 2154 lprintf(LOG_DEBUG, 2155 "HPM: no response available"); 2156 lprintf(LOG_DEBUG, 2157 "HPM: the command may be rejected for security reasons"); 2158 if (req.msg.netfn == IPMI_NETFN_PICMG 2159 && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK 2160 && errorCount < HPM_LAN_PACKET_RESIZE_LIMIT 2161 && (!isValidSize)) { 2162 lprintf(LOG_DEBUG, 2163 "HPM: upload firmware block API called"); 2164 lprintf(LOG_DEBUG, 2165 "HPM: returning length error to force resize"); 2166 fakeRsp.ccode = IPMI_CC_REQ_DATA_INV_LENGTH; 2167 rsp = &fakeRsp; 2168 errorCount++; 2169 } else if (req.msg.netfn == IPMI_NETFN_PICMG 2170 && (req.msg.cmd == HPMFWUPG_ACTIVATE_FIRMWARE 2171 || req.msg.cmd == HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK)) { 2172 /* 2173 * rsp == NULL and command activate firmware or manual firmware 2174 * rollback most likely occurs when we have sent a firmware activation 2175 * request. Fake a command in progress response. 2176 */ 2177 lprintf(LOG_DEBUG, 2178 "HPM: activate/rollback firmware API called"); 2179 lprintf(LOG_DEBUG, 2180 "HPM: returning in progress to handle IOL session lost"); 2181 fakeRsp.ccode = HPMFWUPG_COMMAND_IN_PROGRESS; 2182 rsp = &fakeRsp; 2183 } else if (req.msg.netfn == IPMI_NETFN_PICMG 2184 && (req.msg.cmd == HPMFWUPG_QUERY_ROLLBACK_STATUS 2185 || req.msg.cmd == HPMFWUPG_GET_UPGRADE_STATUS 2186 || req.msg.cmd == HPMFWUPG_QUERY_SELFTEST_RESULT) 2187 && ( !intf->target_addr || intf->target_addr == intf->my_addr)) { 2188 /* reopen session only if target IPMC is directly accessed */ 2189 /* 2190 * rsp == NULL and command get upgrade status or query rollback 2191 * status most likely occurs when we are waiting for firmware 2192 * activation. Try to re-open the IOL session (re-open will work 2193 * once the IPMC recovers from firmware activation. 2194 */ 2195 lprintf(LOG_DEBUG, "HPM: upg/rollback status firmware API called"); 2196 lprintf(LOG_DEBUG, "HPM: try to re-open IOL session"); 2197 { 2198 /* force session re-open */ 2199 intf->opened = 0; 2200 intf->session->authtype = IPMI_SESSION_AUTHTYPE_NONE; 2201 intf->session->session_id = 0; 2202 intf->session->in_seq = 0; 2203 intf->session->out_seq = 0; 2204 intf->session->active = 0; 2205 intf->session->retry = 10; 2206 while (intf->open(intf) == HPMFWUPG_ERROR 2207 && inaccessTimeoutCounter < inaccessTimeout) { 2208 inaccessTimeoutCounter += (time(NULL) - timeoutSec1); 2209 timeoutSec1 = time(NULL); 2210 } 2211 /* Fake timeout to retry command */ 2212 fakeRsp.ccode = 0xc3; 2213 rsp = &fakeRsp; 2214 } 2215 } 2216 } 2217 } 2218 /* Handle inaccessibility timeout (rsp = NULL if IOL) */ 2219 if (rsp == NULL || rsp->ccode == 0xff || rsp->ccode == 0xc3 || rsp->ccode == 0xd3) { 2220 if (inaccessTimeoutCounter < inaccessTimeout) { 2221 timeoutSec2 = time(NULL); 2222 if (timeoutSec2 > timeoutSec1) { 2223 inaccessTimeoutCounter += timeoutSec2 - timeoutSec1; 2224 timeoutSec1 = time(NULL); 2225 } 2226 usleep(100000); 2227 retry = 1; 2228 } else { 2229 retry = 0; 2230 } 2231 } else if ( rsp->ccode == 0xc0 ) { 2232 /* Handle node busy timeout */ 2233 if (upgradeTimeoutCounter < upgradeTimeout) { 2234 timeoutSec2 = time(NULL); 2235 if (timeoutSec2 > timeoutSec1) { 2236 timeoutSec1 = time(NULL); 2237 upgradeTimeoutCounter += timeoutSec2 - timeoutSec1; 2238 } 2239 usleep(100000); 2240 retry = 1; 2241 } else { 2242 retry = 0; 2243 } 2244 } else { 2245 # ifdef ENABLE_OPENIPMI_V39_PATCH 2246 if (rsp->ccode == IPMI_CC_OK) { 2247 errorCount = 0 ; 2248 } 2249 # endif 2250 retry = 0; 2251 if (req.msg.netfn == IPMI_NETFN_PICMG 2252 && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK 2253 && (!isValidSize)) { 2254 lprintf(LOG_INFO, 2255 "Buffer length is now considered valid"); 2256 isValidSize = TRUE; 2257 } 2258 } 2259 } while (retry); 2260 return rsp; 2261 } 2262 2263 int 2264 HpmfwupgWaitLongDurationCmd(struct ipmi_intf *intf, 2265 struct HpmfwupgUpgradeCtx *pFwupgCtx) 2266 { 2267 int rc = HPMFWUPG_SUCCESS; 2268 unsigned int upgradeTimeout = 0; 2269 unsigned int timeoutSec1, timeoutSec2; 2270 struct HpmfwupgGetUpgradeStatusCtx upgStatusCmd; 2271 /* If we are not in upgrade context, we use default timeout values */ 2272 if (pFwupgCtx != NULL) { 2273 upgradeTimeout = (unsigned int)(pFwupgCtx->targetCap.upgradeTimeout*5); 2274 if (verbose) { 2275 printf("Use File Upgrade Capabilities: %i seconds\n", 2276 upgradeTimeout); 2277 } 2278 } else { 2279 /* Try to retreive from Caps */ 2280 struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; 2281 if(HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd) != HPMFWUPG_SUCCESS) { 2282 upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; 2283 if (verbose) { 2284 printf("Use default timeout: %i seconds\n", 2285 upgradeTimeout); 2286 } 2287 } else { 2288 upgradeTimeout = (unsigned int)(targetCapCmd.resp.upgradeTimeout * 5); 2289 if (verbose) { 2290 printf("Use Command Upgrade Capabilities Timeout: %i seconds\n", 2291 upgradeTimeout); 2292 } 2293 } 2294 } 2295 if (rc == HPMFWUPG_SUCCESS) { 2296 /* Poll upgrade status until completion or timeout*/ 2297 timeoutSec1 = time(NULL); 2298 timeoutSec2 = time(NULL); 2299 rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, 2300 pFwupgCtx, 1); 2301 } 2302 while ( 2303 /* With KCS: Cover the case where we sometime 2304 * receive d5 (on the first get status) from 2305 * the ipmi driver. 2306 */ 2307 (upgStatusCmd.resp.lastCmdCompCode == 0x80 || 2308 upgStatusCmd.resp.lastCmdCompCode == 0xD5) 2309 && ((timeoutSec2 - timeoutSec1) < upgradeTimeout ) 2310 && (rc == HPMFWUPG_SUCCESS)) { 2311 /* Must wait at least 1000 ms between status requests */ 2312 usleep(1000000); 2313 timeoutSec2 = time(NULL); 2314 rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx, 1); 2315 /* 2316 * printf("Get Status: %x - %x = %x _ %x [%x]\n", 2317 ( timeoutSec2, timeoutSec1, 2318 * (timeoutSec2 - timeoutSec1), 2319 * upgradeTimeout, rc); 2320 */ 2321 } 2322 if (upgStatusCmd.resp.lastCmdCompCode != 0x00) { 2323 if (verbose) { 2324 lprintf(LOG_NOTICE, 2325 "Error waiting for command %x, compcode = %x", 2326 upgStatusCmd.resp.cmdInProcess, 2327 upgStatusCmd.resp.lastCmdCompCode); 2328 } 2329 rc = HPMFWUPG_ERROR; 2330 } 2331 return rc; 2332 } 2333 2334 unsigned char 2335 HpmfwupgCalculateChecksum(unsigned char *pData, unsigned int length) 2336 { 2337 unsigned char checksum = 0; 2338 int dataIdx = 0; 2339 for (dataIdx = 0; dataIdx < length; dataIdx++) { 2340 checksum += pData[dataIdx]; 2341 } 2342 return checksum; 2343 } 2344 2345 void 2346 HpmfwupgPrintUsage(void) 2347 { 2348 lprintf(LOG_NOTICE, 2349 "help - This help menu."); 2350 lprintf(LOG_NOTICE, 2351 ""); 2352 lprintf(LOG_NOTICE, 2353 "check - Check the target information."); 2354 lprintf(LOG_NOTICE, 2355 "check <file> - If the user is unsure of what update is going to be "); 2356 lprintf(LOG_NOTICE, 2357 " This will display the existing target version and"); 2358 lprintf(LOG_NOTICE, 2359 " image version on the screen"); 2360 lprintf(LOG_NOTICE, 2361 ""); 2362 lprintf(LOG_NOTICE, 2363 "upgrade <file> [component x...] [force] [activate]"); 2364 lprintf(LOG_NOTICE, 2365 " - Copies components from a valid HPM.1 image to the target."); 2366 lprintf(LOG_NOTICE, 2367 " If one or more components specified by \"component\","); 2368 lprintf(LOG_NOTICE, 2369 " only the specified components are copied."); 2370 lprintf(LOG_NOTICE, 2371 " Otherwise, all the image components are copied."); 2372 lprintf(LOG_NOTICE, 2373 " Before copy, each image component undergoes a version check"); 2374 lprintf(LOG_NOTICE, 2375 " and can be skipped if the target component version"); 2376 lprintf(LOG_NOTICE, 2377 " is the same or more recent."); 2378 lprintf(LOG_NOTICE, 2379 " Use \"force\" to bypass the version check results."); 2380 lprintf(LOG_NOTICE, 2381 " Make sure to check the versions first using the"); 2382 lprintf(LOG_NOTICE, 2383 " \"check <file>\" command."); 2384 lprintf(LOG_NOTICE, 2385 " If \"activate\" is specified, the newly uploaded firmware"); 2386 lprintf(LOG_NOTICE, 2387 " is activated."); 2388 lprintf(LOG_NOTICE, 2389 "upgstatus - Returns the status of the last long duration command."); 2390 lprintf(LOG_NOTICE, 2391 ""); 2392 lprintf(LOG_NOTICE, 2393 "compare <file> - Perform \"Comparison of the Active Copy\" action for all the"); 2394 lprintf(LOG_NOTICE, 2395 " components present in the file."); 2396 lprintf(LOG_NOTICE, 2397 "compare <file> component x - Compare only component <x> from the given <file>"); 2398 lprintf(LOG_NOTICE, 2399 "activate - Activate the newly uploaded firmware."); 2400 lprintf(LOG_NOTICE, 2401 "activate norollback - Activate the newly uploaded firmware but inform"); 2402 lprintf(LOG_NOTICE, 2403 " the target to not automatically rollback if "); 2404 lprintf(LOG_NOTICE, 2405 " the upgrade fails."); 2406 lprintf(LOG_NOTICE, 2407 ""); 2408 lprintf(LOG_NOTICE, 2409 "targetcap - Get the target upgrade capabilities."); 2410 lprintf(LOG_NOTICE, 2411 ""); 2412 lprintf(LOG_NOTICE, 2413 "compprop <id> <prop> - Get specified component properties from the target."); 2414 lprintf(LOG_NOTICE, 2415 " Valid component <id>: 0-7 "); 2416 lprintf(LOG_NOTICE, 2417 " Properties <prop> can be one of the following: "); 2418 lprintf(LOG_NOTICE, 2419 " 0- General properties"); 2420 lprintf(LOG_NOTICE, 2421 " 1- Current firmware version"); 2422 lprintf(LOG_NOTICE, 2423 " 2- Description string"); 2424 lprintf(LOG_NOTICE, 2425 " 3- Rollback firmware version"); 2426 lprintf(LOG_NOTICE, 2427 " 4- Deferred firmware version"); 2428 lprintf(LOG_NOTICE, 2429 ""); 2430 lprintf(LOG_NOTICE, 2431 "abort - Abort the on-going firmware upgrade."); 2432 lprintf(LOG_NOTICE, 2433 ""); 2434 lprintf(LOG_NOTICE, 2435 "rollback - Performs a manual rollback on the IPM Controller."); 2436 lprintf(LOG_NOTICE, 2437 " firmware"); 2438 lprintf(LOG_NOTICE, 2439 "rollbackstatus - Query the rollback status."); 2440 lprintf(LOG_NOTICE, 2441 ""); 2442 lprintf(LOG_NOTICE, 2443 "selftestresult - Query the self test results.\n"); 2444 } 2445 2446 int 2447 ipmi_hpmfwupg_main(struct ipmi_intf *intf, int argc, char **argv) 2448 { 2449 int rc = HPMFWUPG_SUCCESS; 2450 int activateFlag = 0x00; 2451 int componentMask = 0; 2452 int componentId = 0; 2453 int option = 0; 2454 2455 lprintf(LOG_DEBUG,"ipmi_hpmfwupg_main()"); 2456 lprintf(LOG_NOTICE, "\nPICMG HPM.1 Upgrade Agent %d.%d.%d: \n", 2457 HPMFWUPG_VERSION_MAJOR, HPMFWUPG_VERSION_MINOR, 2458 HPMFWUPG_VERSION_SUBMINOR); 2459 if (argc < 1) { 2460 lprintf(LOG_ERR, "Not enough parameters given."); 2461 HpmfwupgPrintUsage(); 2462 return HPMFWUPG_ERROR; 2463 } 2464 if (strcmp(argv[0], "help") == 0) { 2465 HpmfwupgPrintUsage(); 2466 return HPMFWUPG_SUCCESS; 2467 } else if ((strcmp(argv[0], "check") == 0)) { 2468 /* hpm check */ 2469 if (argv[1] == NULL) { 2470 rc = HpmfwupgTargetCheck(intf,VIEW_MODE); 2471 } else { 2472 /* hpm check <filename> */ 2473 rc = HpmfwupgTargetCheck(intf,0); 2474 if (rc == HPMFWUPG_SUCCESS) { 2475 rc = HpmfwupgUpgrade(intf, argv[1], 0, 2476 0, VIEW_MODE); 2477 } 2478 } 2479 } else if (strcmp(argv[0], "upgrade") == 0) { 2480 int i =0; 2481 for (i=1; i< argc ; i++) { 2482 if (strcmp(argv[i],"activate") == 0) { 2483 activateFlag = 1; 2484 } 2485 /* hpm upgrade <filename> force */ 2486 if (strcmp(argv[i],"force") == 0) { 2487 option |= FORCE_MODE; 2488 } 2489 /* hpm upgrade <filename> component <comp Id> */ 2490 if (strcmp(argv[i],"component") == 0) { 2491 if (i+1 < argc) { 2492 /* Error Checking */ 2493 if (str2int(argv[i+1], &componentId) != 0 2494 || componentId < 0 2495 || componentId > HPMFWUPG_COMPONENT_ID_MAX) { 2496 lprintf(LOG_ERR, 2497 "Given Component ID '%s' is invalid.", 2498 argv[i+1]); 2499 lprintf(LOG_ERR, 2500 "Valid Compoment ID is: <0..7>"); 2501 return HPMFWUPG_ERROR; 2502 } 2503 if( verbose ) { 2504 lprintf(LOG_NOTICE, 2505 "Component Id %d provided", 2506 componentId ); 2507 } 2508 componentMask |= 1 << componentId; 2509 } else { 2510 /* That indicates the user has 2511 * given component on console but 2512 * not given any ID 2513 */ 2514 lprintf(LOG_NOTICE, 2515 "No component Id provided\n"); 2516 return HPMFWUPG_ERROR; 2517 } 2518 } 2519 if (strcmp(argv[i],"debug") == 0) { 2520 option |= DEBUG_MODE; 2521 } 2522 } 2523 rc = HpmfwupgTargetCheck(intf, 0); 2524 if (rc == HPMFWUPG_SUCCESS) { 2525 /* Call the Upgrade function to start the upgrade */ 2526 rc = HpmfwupgUpgrade(intf, argv[1], activateFlag, 2527 componentMask, option); 2528 } 2529 } else if (strcmp(argv[0], "compare") == 0) { 2530 int i = 0; 2531 for (i=1; i< argc; i++) { 2532 /* hpm compare <file> [component x...] */ 2533 if (strcmp(argv[i],"component") == 0) { 2534 if (i+1 < argc) { 2535 /* Error Checking */ 2536 if (str2int(argv[i+1], &componentId) != 0 2537 || componentId < 0 2538 || componentId > HPMFWUPG_COMPONENT_ID_MAX) { 2539 lprintf(LOG_ERR, 2540 "Given Component ID '%s' is invalid.", 2541 argv[i+1]); 2542 lprintf(LOG_ERR, 2543 "Valid Compoment ID is: <0..7>"); 2544 return HPMFWUPG_ERROR; 2545 } 2546 if( verbose ) { 2547 lprintf(LOG_NOTICE, 2548 "Component Id %d provided", 2549 componentId); 2550 } 2551 componentMask|= 1 << componentId; 2552 } else { 2553 /* That indicates the user 2554 * has given component on 2555 * console but not 2556 * given any ID 2557 */ 2558 lprintf(LOG_NOTICE, 2559 "No component Id provided\n"); 2560 return HPMFWUPG_ERROR; 2561 } 2562 } else if (strcmp(argv[i],"debug") == 0) { 2563 option|= DEBUG_MODE; 2564 } 2565 } 2566 option|= (COMPARE_MODE); 2567 rc = HpmfwupgTargetCheck(intf, 0); 2568 if (rc == HPMFWUPG_SUCCESS) { 2569 rc = HpmfwupgUpgrade(intf, argv[1], 0, 2570 componentMask, option); 2571 } 2572 } else if ((argc >= 1) && (strcmp(argv[0], "activate") == 0)) { 2573 struct HpmfwupgActivateFirmwareCtx cmdCtx; 2574 if ((argc == 2) && (strcmp(argv[1], "norollback") == 0)) { 2575 cmdCtx.req.rollback_override = 1; 2576 } else { 2577 cmdCtx.req.rollback_override = 0; 2578 } 2579 rc = HpmfwupgActivateFirmware(intf, &cmdCtx, NULL); 2580 } else if ((argc == 1) && (strcmp(argv[0], "targetcap") == 0)) { 2581 struct HpmfwupgGetTargetUpgCapabilitiesCtx cmdCtx; 2582 verbose++; 2583 rc = HpmfwupgGetTargetUpgCapabilities(intf, &cmdCtx); 2584 } else if ((argc == 3) && (strcmp(argv[0], "compprop") == 0)) { 2585 struct HpmfwupgGetComponentPropertiesCtx cmdCtx; 2586 if (str2uchar(argv[1], &(cmdCtx.req.componentId)) != 0 2587 || cmdCtx.req.componentId > 7) { 2588 lprintf(LOG_ERR, 2589 "Given Component ID '%s' is invalid.", 2590 argv[1]); 2591 lprintf(LOG_ERR, 2592 "Valid Compoment ID is: <0..7>"); 2593 return (-1); 2594 } 2595 if (str2uchar(argv[2], &(cmdCtx.req.selector)) != 0 2596 || cmdCtx.req.selector > 4) { 2597 lprintf(LOG_ERR, 2598 "Given Properties selector '%s' is invalid.", 2599 argv[2]); 2600 lprintf(LOG_ERR, 2601 "Valid Properties selector is: <0..4>"); 2602 return (-1); 2603 } 2604 verbose++; 2605 rc = HpmfwupgGetComponentProperties(intf, &cmdCtx); 2606 } else if ((argc == 1) && (strcmp(argv[0], "abort") == 0)) { 2607 struct HpmfwupgAbortUpgradeCtx cmdCtx; 2608 verbose++; 2609 rc = HpmfwupgAbortUpgrade(intf, &cmdCtx); 2610 } else if ((argc == 1) && (strcmp(argv[0], "upgstatus") == 0)) { 2611 struct HpmfwupgGetUpgradeStatusCtx cmdCtx; 2612 verbose++; 2613 rc = HpmfwupgGetUpgradeStatus(intf, &cmdCtx, NULL, 0); 2614 } else if ((argc == 1) && (strcmp(argv[0], "rollback") == 0)) { 2615 struct HpmfwupgManualFirmwareRollbackCtx cmdCtx; 2616 verbose++; 2617 rc = HpmfwupgManualFirmwareRollback(intf, &cmdCtx); 2618 } else if ((argc == 1) && (strcmp(argv[0], "rollbackstatus") == 0)) { 2619 struct HpmfwupgQueryRollbackStatusCtx cmdCtx; 2620 verbose++; 2621 rc = HpmfwupgQueryRollbackStatus(intf, &cmdCtx, NULL); 2622 } else if ((argc == 1) && (strcmp(argv[0], "selftestresult") == 0)) { 2623 struct HpmfwupgQuerySelftestResultCtx cmdCtx; 2624 verbose++; 2625 rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL); 2626 } else { 2627 lprintf(LOG_ERR, "Invalid HPM command: %s", argv[0]); 2628 HpmfwupgPrintUsage(); 2629 rc = HPMFWUPG_ERROR; 2630 } 2631 return rc; 2632 } 2633 2634