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 /* Put pointer after image header */ 1002 pImagePtr = (unsigned char*) 1003 (pFwupgCtx->pImageData + sizeof(struct HpmfwupgImageHeader) + 1004 pImageHeader->oemDataLength + sizeof(unsigned char)/*checksum*/); 1005 /* Deternime actions size */ 1006 actionsSize = pFwupgCtx->imageSize - sizeof(struct HpmfwupgImageHeader); 1007 if (!(option & VIEW_MODE)) { 1008 HpmDisplayUpgradeHeader(); 1009 } 1010 /* Perform actions defined in the image */ 1011 while (( pImagePtr < (pFwupgCtx->pImageData + pFwupgCtx->imageSize - 1012 HPMFWUPG_MD5_SIGNATURE_LENGTH)) 1013 && (rc == HPMFWUPG_SUCCESS)) { 1014 /* Get action record */ 1015 pActionRecord = (struct HpmfwupgActionRecord*)pImagePtr; 1016 /* Validate action record checksum */ 1017 rc = HpmfwupgValidateActionRecordChecksum(pActionRecord); 1018 if (rc != HPMFWUPG_SUCCESS) { 1019 continue; 1020 } 1021 switch(pActionRecord->actionType) { 1022 case HPMFWUPG_ACTION_BACKUP_COMPONENTS: 1023 { 1024 if (!(option & COMPARE_MODE)) { 1025 /* Send Upgrade Action command */ 1026 struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; 1027 /* Affect only selected components */ 1028 initUpgActionCmd.req.componentsMask.ComponentBits.byte = 1029 pFwupgCtx->compUpdateMask.ComponentBits.byte & 1030 pActionRecord->components.ComponentBits.byte; 1031 /* Action is prepare components */ 1032 if (initUpgActionCmd.req.componentsMask.ComponentBits.byte) { 1033 initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_BACKUP; 1034 rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); 1035 } 1036 } 1037 pImagePtr+= sizeof(struct HpmfwupgActionRecord); 1038 } 1039 break; 1040 case HPMFWUPG_ACTION_PREPARE_COMPONENTS: 1041 { 1042 if (!(option & COMPARE_MODE)) { 1043 /* Send prepare components command */ 1044 struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; 1045 /* Affect only selected components */ 1046 initUpgActionCmd.req.componentsMask.ComponentBits.byte = 1047 pFwupgCtx->compUpdateMask.ComponentBits.byte & 1048 pActionRecord->components.ComponentBits.byte; 1049 if (initUpgActionCmd.req.componentsMask.ComponentBits.byte) { 1050 /* Action is prepare components */ 1051 initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_PREPARE; 1052 rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); 1053 } 1054 } 1055 pImagePtr+= sizeof(struct HpmfwupgActionRecord); 1056 } 1057 break; 1058 case HPMFWUPG_ACTION_UPLOAD_FIRMWARE: 1059 /* Upload all firmware blocks */ 1060 rc = HpmFwupgActionUploadFirmware(pActionRecord->components, 1061 pFwupgCtx, 1062 &pImagePtr, 1063 intf, 1064 option, 1065 &flagColdReset); 1066 break; 1067 default: 1068 lprintf(LOG_NOTICE, " Invalid Action type. Cannot continue"); 1069 rc = HPMFWUPG_ERROR; 1070 break; 1071 } 1072 } 1073 HpmDisplayLine("-", 79); 1074 fflush(stdout); 1075 lprintf(LOG_NOTICE, "(*) Component requires Payload Cold Reset"); 1076 return rc; 1077 } 1078 1079 int 1080 HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components, 1081 struct HpmfwupgUpgradeCtx *pFwupgCtx, 1082 unsigned char **pImagePtr, 1083 struct ipmi_intf *intf, 1084 int option, 1085 int *pFlagColdReset) 1086 { 1087 struct HpmfwupgFirmwareImage *pFwImage; 1088 struct HpmfwupgInitiateUpgradeActionCtx initUpgActionCmd; 1089 struct HpmfwupgUploadFirmwareBlockCtx uploadCmd; 1090 struct HpmfwupgFinishFirmwareUploadCtx finishCmd; 1091 VERSIONINFO *pVersionInfo; 1092 time_t start,end; 1093 1094 int rc = HPMFWUPG_SUCCESS; 1095 int skip = TRUE; 1096 unsigned char *pData, *pDataInitial; 1097 unsigned short count; 1098 unsigned int totalSent = 0; 1099 unsigned short bufLength = 0; 1100 unsigned short bufLengthIsSet = 0; 1101 unsigned int firmwareLength = 0; 1102 1103 unsigned int displayFWLength = 0; 1104 unsigned char *pDataTemp; 1105 unsigned int imageOffset = 0x00; 1106 unsigned int blockLength = 0x00; 1107 unsigned int lengthOfBlock = 0x00; 1108 unsigned int numTxPkts = 0; 1109 unsigned int numRxPkts = 0; 1110 unsigned char mode = 0; 1111 unsigned char componentId = 0x00; 1112 unsigned char componentIdByte = 0x00; 1113 uint16_t max_rq_size; 1114 1115 /* Save component ID on which the upload is done */ 1116 componentIdByte = components.ComponentBits.byte; 1117 while ((componentIdByte>>= 1) != 0) { 1118 componentId++; 1119 } 1120 pFwupgCtx->componentId = componentId; 1121 pVersionInfo = (VERSIONINFO *)&gVersionInfo[componentId]; 1122 pFwImage = (struct HpmfwupgFirmwareImage*)((*pImagePtr) 1123 + sizeof(struct HpmfwupgActionRecord)); 1124 pDataInitial = ((unsigned char *)pFwImage 1125 + sizeof(struct HpmfwupgFirmwareImage)); 1126 pData = pDataInitial; 1127 1128 /* Find max buffer length according the connection parameters */ 1129 max_rq_size = ipmi_intf_get_max_request_data_size(intf); 1130 1131 /* validate lower bound of max request size */ 1132 if (max_rq_size <= sizeof(struct HpmfwupgUploadFirmwareBlockReq)) { 1133 lprintf(LOG_ERROR, "Maximum request size is too small to " 1134 "send a upload request."); 1135 return HPMFWUPG_ERROR; 1136 } 1137 1138 bufLength = max_rq_size - sizeof(struct HpmfwupgUploadFirmwareBlockReq); 1139 1140 /* Get firmware length */ 1141 firmwareLength = pFwImage->length[0]; 1142 firmwareLength|= (pFwImage->length[1] << 8) & 0xff00; 1143 firmwareLength|= (pFwImage->length[2] << 16) & 0xff0000; 1144 firmwareLength|= (pFwImage->length[3] << 24) & 0xff000000; 1145 mode = TARGET_VER | IMAGE_VER; 1146 if (pVersionInfo->rollbackSupported) { 1147 mode |= ROLLBACK_VER; 1148 } 1149 if ((option & DEBUG_MODE)) { 1150 printf("\n\n Comp ID : %d [%-20s]\n", 1151 pVersionInfo->componentId, 1152 pFwImage->desc); 1153 } else { 1154 HpmDisplayVersion(mode, pVersionInfo, 0); 1155 } 1156 if ((1 << componentId) & pFwupgCtx->compUpdateMask.ComponentBits.byte) { 1157 if (verbose) { 1158 lprintf(LOG_NOTICE, "Do not skip %d", 1159 componentId); 1160 } 1161 skip = FALSE; 1162 } 1163 if (!skip) { 1164 HpmDisplayUpgrade(0,0,1,0); 1165 /* Initialize parameters */ 1166 uploadCmd.req = malloc(max_rq_size); 1167 if (!uploadCmd.req) { 1168 lprintf(LOG_ERR, "ipmitool: malloc failure"); 1169 return HPMFWUPG_ERROR; 1170 } 1171 uploadCmd.req->blockNumber = 0; 1172 /* Send Initiate Upgrade Action */ 1173 initUpgActionCmd.req.componentsMask = components; 1174 if (option & COMPARE_MODE) { 1175 /* Action is compare */ 1176 initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_COMPARE; 1177 } else { 1178 /* Action is upgrade */ 1179 initUpgActionCmd.req.upgradeAction = HPMFWUPG_UPGRADE_ACTION_UPGRADE; 1180 } 1181 rc = HpmfwupgInitiateUpgradeAction(intf, &initUpgActionCmd, pFwupgCtx); 1182 if (rc != HPMFWUPG_SUCCESS) { 1183 skip = TRUE; 1184 } 1185 if ((pVersionInfo->coldResetRequired) && (!skip)) { 1186 *pFlagColdReset = TRUE; 1187 } 1188 /* pDataInitial is the starting pointer of the image data */ 1189 /* pDataTemp is one which we will move across */ 1190 pData = pDataInitial; 1191 pDataTemp = pDataInitial; 1192 lengthOfBlock = firmwareLength; 1193 totalSent = 0x00; 1194 displayFWLength= firmwareLength; 1195 time(&start); 1196 while ((pData < (pDataTemp+lengthOfBlock)) && (rc == HPMFWUPG_SUCCESS)) { 1197 if ((pData+bufLength) <= (pDataTemp+lengthOfBlock)) { 1198 count = bufLength; 1199 } else { 1200 count = (unsigned short)((pDataTemp+lengthOfBlock) - pData); 1201 } 1202 memcpy(&uploadCmd.req->data, pData, bufLength); 1203 imageOffset = 0x00; 1204 blockLength = 0x00; 1205 numTxPkts++; 1206 rc = HpmfwupgUploadFirmwareBlock(intf, &uploadCmd, 1207 pFwupgCtx, count, &imageOffset,&blockLength); 1208 numRxPkts++; 1209 if (rc != HPMFWUPG_SUCCESS) { 1210 if (rc == HPMFWUPG_UPLOAD_BLOCK_LENGTH && !bufLengthIsSet) { 1211 rc = HPMFWUPG_SUCCESS; 1212 /* Retry with a smaller buffer length */ 1213 if (strstr(intf->name,"lan") != NULL && bufLength > 8) { 1214 bufLength-= 8; 1215 lprintf(LOG_INFO, 1216 "Trying reduced buffer length: %d", 1217 bufLength); 1218 } else if (bufLength) { 1219 bufLength-= 1; 1220 lprintf(LOG_INFO, 1221 "Trying reduced buffer length: %d", 1222 bufLength); 1223 } else { 1224 rc = HPMFWUPG_ERROR; 1225 } 1226 } else if (rc == HPMFWUPG_UPLOAD_RETRY) { 1227 rc = HPMFWUPG_SUCCESS; 1228 } else { 1229 fflush(stdout); 1230 lprintf(LOG_NOTICE, 1231 "\n Error in Upload FIRMWARE command [rc=%d]\n", 1232 rc); 1233 lprintf(LOG_NOTICE, 1234 "\n TotalSent:0x%x ", 1235 totalSent); 1236 /* Exiting from the function */ 1237 rc = HPMFWUPG_ERROR; 1238 } 1239 } else { 1240 /* success, buf length is valid */ 1241 bufLengthIsSet = 1; 1242 if (imageOffset + blockLength > firmwareLength || 1243 imageOffset + blockLength < blockLength) { 1244 /* 1245 * blockLength is the remaining length of the firmware to upload so 1246 * if imageOffset and blockLength sum is greater than the firmware 1247 * length then its kind of error 1248 */ 1249 lprintf(LOG_NOTICE, 1250 "\n Error in Upload FIRMWARE command [rc=%d]\n", 1251 rc); 1252 lprintf(LOG_NOTICE, 1253 "\n TotalSent:0x%x Img offset:0x%x Blk length:0x%x Fwlen:0x%x\n", 1254 totalSent,imageOffset,blockLength,firmwareLength); 1255 rc = HPMFWUPG_ERROR; 1256 continue; 1257 } 1258 totalSent += count; 1259 if (imageOffset != 0x00) { 1260 /* block Length is valid */ 1261 lengthOfBlock = blockLength; 1262 pDataTemp = pDataInitial + imageOffset; 1263 pData = pDataTemp; 1264 if (displayFWLength == firmwareLength) { 1265 /* This is basically used only to make sure that we display uptil 100% */ 1266 displayFWLength = blockLength + totalSent; 1267 } 1268 } else { 1269 pData += count; 1270 } 1271 time(&end); 1272 /* 1273 * Just added debug mode in case we need to see exactly how many bytes have 1274 * gone through - Its a hidden option used mainly should be used for debugging 1275 */ 1276 if (option & DEBUG_MODE) { 1277 fflush(stdout); 1278 printf(" Blk Num : %02x Bytes : %05x ", 1279 uploadCmd.req->blockNumber,totalSent); 1280 if (imageOffset || blockLength) { 1281 printf("\n--> ImgOff : %x BlkLen : %x\n", 1282 imageOffset,blockLength); 1283 } 1284 if (displayFWLength == totalSent) { 1285 printf("\n Time Taken %02ld:%02ld", 1286 (end-start)/60, (end-start)%60); 1287 printf("\n\n"); 1288 } 1289 } else { 1290 HpmDisplayUpgrade(0, totalSent, 1291 displayFWLength, (end-start)); 1292 } 1293 uploadCmd.req->blockNumber++; 1294 } 1295 } 1296 /* free buffer */ 1297 free(uploadCmd.req); 1298 uploadCmd.req = NULL; 1299 } 1300 if (skip) { 1301 HpmDisplayUpgrade(1,0,0,0); 1302 if ((option & COMPARE_MODE) 1303 && !pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.comparisonSupport) { 1304 printf("| |Comparison isn't supported for given compenent. |\n"); 1305 } 1306 *pImagePtr = pDataInitial + firmwareLength; 1307 } 1308 if (rc == HPMFWUPG_SUCCESS && !skip) { 1309 /* Send finish component */ 1310 /* Set image length */ 1311 finishCmd.req.componentId = componentId; 1312 /* We need to send the actual data that is sent 1313 * not the comlete firmware image length 1314 */ 1315 finishCmd.req.imageLength[0] = totalSent & 0xFF; 1316 finishCmd.req.imageLength[1] = (totalSent >> 8) & 0xFF; 1317 finishCmd.req.imageLength[2] = (totalSent >> 16) & 0xFF; 1318 finishCmd.req.imageLength[3] = (totalSent >> 24) & 0xFF; 1319 rc = HpmfwupgFinishFirmwareUpload(intf, &finishCmd, 1320 pFwupgCtx, option); 1321 *pImagePtr = pDataInitial + firmwareLength; 1322 } 1323 return rc; 1324 } 1325 1326 /* HpmfwupgActivationStage - validate stage of a firmware upgrade procedure as 1327 * defined in section 3.4 of the IPM Controller Firmware Upgrade Specification 1328 * version 1.0 1329 */ 1330 int 1331 HpmfwupgActivationStage(struct ipmi_intf *intf, 1332 struct HpmfwupgUpgradeCtx *pFwupgCtx) 1333 { 1334 int rc = HPMFWUPG_SUCCESS; 1335 struct HpmfwupgActivateFirmwareCtx activateCmd; 1336 struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*) 1337 pFwupgCtx->pImageData; 1338 /* Print out stuf...*/ 1339 printf(" "); 1340 fflush(stdout); 1341 /* Activate new firmware */ 1342 activateCmd.req.rollback_override = 0; 1343 rc = HpmfwupgActivateFirmware(intf, &activateCmd, pFwupgCtx); 1344 if (rc == HPMFWUPG_SUCCESS) { 1345 /* Query self test result if supported by target and new image */ 1346 if ((pFwupgCtx->targetCap.GlobalCapabilities.bitField.ipmcSelftestCap == 1) 1347 || (pImageHeader->imageCapabilities.bitField.imageSelfTest == 1)) { 1348 struct HpmfwupgQuerySelftestResultCtx selfTestCmd; 1349 rc = HpmfwupgQuerySelftestResult(intf, &selfTestCmd, 1350 pFwupgCtx); 1351 if (rc == HPMFWUPG_SUCCESS) { 1352 /* Get the self test result */ 1353 if (selfTestCmd.resp.result1 != 0x55) { 1354 /* Perform manual rollback if necessary */ 1355 /* BACKUP/ MANUAL ROLLBACK not supported by this UA */ 1356 lprintf(LOG_NOTICE, " Self test failed:"); 1357 lprintf(LOG_NOTICE, " Result1 = %x", 1358 selfTestCmd.resp.result1); 1359 lprintf(LOG_NOTICE, " Result2 = %x", 1360 selfTestCmd.resp.result2); 1361 rc = HPMFWUPG_ERROR; 1362 } 1363 } else { 1364 /* Perform manual rollback if necessary */ 1365 /* BACKUP / MANUAL ROLLBACK not supported by this UA */ 1366 lprintf(LOG_NOTICE," Self test failed."); 1367 } 1368 } 1369 } 1370 /* If activation / self test failed, query rollback 1371 * status if automatic rollback supported 1372 */ 1373 if (rc == HPMFWUPG_ERROR) { 1374 if ((pFwupgCtx->targetCap.GlobalCapabilities.bitField.autRollback == 1) 1375 && (pFwupgCtx->genCompProp[pFwupgCtx->componentId].GeneralCompProperties.bitfield.rollbackBackup != 0x00)) { 1376 struct HpmfwupgQueryRollbackStatusCtx rollCmd; 1377 lprintf(LOG_NOTICE," Getting rollback status..."); 1378 fflush(stdout); 1379 rc = HpmfwupgQueryRollbackStatus(intf, 1380 &rollCmd, pFwupgCtx); 1381 } 1382 } 1383 return rc; 1384 } 1385 1386 int 1387 HpmfwupgGetBufferFromFile(char *imageFilename, 1388 struct HpmfwupgUpgradeCtx *pFwupgCtx) 1389 { 1390 int rc = HPMFWUPG_SUCCESS; 1391 int ret = 0; 1392 FILE *pImageFile = fopen(imageFilename, "rb"); 1393 if (pImageFile == NULL) { 1394 lprintf(LOG_ERR, "Cannot open image file '%s'", 1395 imageFilename); 1396 return HPMFWUPG_ERROR; 1397 } 1398 /* Get the raw data in file */ 1399 fseek(pImageFile, 0, SEEK_END); 1400 pFwupgCtx->imageSize = ftell(pImageFile); 1401 pFwupgCtx->pImageData = malloc(sizeof(unsigned char)*pFwupgCtx->imageSize); 1402 if (pFwupgCtx->pImageData == NULL) { 1403 lprintf(LOG_ERR, "ipmitool: malloc failure"); 1404 fclose(pImageFile); 1405 return HPMFWUPG_ERROR; 1406 } 1407 rewind(pImageFile); 1408 ret = fread(pFwupgCtx->pImageData, 1409 sizeof(unsigned char), 1410 pFwupgCtx->imageSize, 1411 pImageFile); 1412 if (ret != pFwupgCtx->imageSize) { 1413 lprintf(LOG_ERR, 1414 "Failed to read file %s size %d", 1415 imageFilename, 1416 pFwupgCtx->imageSize); 1417 rc = HPMFWUPG_ERROR; 1418 } 1419 fclose(pImageFile); 1420 return rc; 1421 } 1422 1423 int 1424 HpmfwupgGetDeviceId(struct ipmi_intf *intf, struct ipm_devid_rsp *pGetDevId) 1425 { 1426 struct ipmi_rs *rsp; 1427 struct ipmi_rq req; 1428 memset(&req, 0, sizeof(req)); 1429 req.msg.netfn = IPMI_NETFN_APP; 1430 req.msg.cmd = BMC_GET_DEVICE_ID; 1431 req.msg.data_len = 0; 1432 rsp = HpmfwupgSendCmd(intf, req, NULL); 1433 if (rsp == NULL) { 1434 lprintf(LOG_ERR, "Error getting device ID."); 1435 return HPMFWUPG_ERROR; 1436 } 1437 if (rsp->ccode != 0x00) { 1438 lprintf(LOG_ERR, "Error getting device ID."); 1439 lprintf(LOG_ERR, "compcode=0x%x: %s", 1440 rsp->ccode, 1441 val2str(rsp->ccode, completion_code_vals)); 1442 return HPMFWUPG_ERROR; 1443 } 1444 memcpy(pGetDevId, rsp->data, sizeof(struct ipm_devid_rsp)); 1445 return HPMFWUPG_SUCCESS; 1446 } 1447 1448 int 1449 HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf *intf, 1450 struct HpmfwupgGetTargetUpgCapabilitiesCtx *pCtx) 1451 { 1452 struct ipmi_rs *rsp; 1453 struct ipmi_rq req; 1454 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1455 memset(&req, 0, sizeof(req)); 1456 req.msg.netfn = IPMI_NETFN_PICMG; 1457 req.msg.cmd = HPMFWUPG_GET_TARGET_UPG_CAPABILITIES; 1458 req.msg.data = (unsigned char*)&pCtx->req; 1459 req.msg.data_len = sizeof(struct HpmfwupgGetTargetUpgCapabilitiesReq); 1460 rsp = HpmfwupgSendCmd(intf, req, NULL); 1461 if (rsp == NULL) { 1462 lprintf(LOG_ERR, 1463 "Error getting target upgrade capabilities."); 1464 return HPMFWUPG_ERROR; 1465 } 1466 if (rsp->ccode != 0x00) { 1467 lprintf(LOG_ERR, 1468 "Error getting target upgrade capabilities, ccode: 0x%x: %s", 1469 rsp->ccode, 1470 val2str(rsp->ccode, completion_code_vals)); 1471 return HPMFWUPG_ERROR; 1472 } 1473 memcpy(&pCtx->resp, rsp->data, 1474 sizeof(struct HpmfwupgGetTargetUpgCapabilitiesResp)); 1475 if (verbose) { 1476 lprintf(LOG_NOTICE, "TARGET UPGRADE CAPABILITIES"); 1477 lprintf(LOG_NOTICE, "-------------------------------"); 1478 lprintf(LOG_NOTICE, "HPM.1 version............%d ", 1479 pCtx->resp.hpmVersion); 1480 lprintf(LOG_NOTICE, "Component 0 presence....[%c] ", 1481 pCtx->resp.componentsPresent.ComponentBits.bitField.component0 ? 'y' : 'n'); 1482 lprintf(LOG_NOTICE, "Component 1 presence....[%c] ", 1483 pCtx->resp.componentsPresent.ComponentBits.bitField.component1 ? 'y' : 'n'); 1484 lprintf(LOG_NOTICE, "Component 2 presence....[%c] ", 1485 pCtx->resp.componentsPresent.ComponentBits.bitField.component2 ? 'y' : 'n'); 1486 lprintf(LOG_NOTICE, "Component 3 presence....[%c] ", 1487 pCtx->resp.componentsPresent.ComponentBits.bitField.component3 ? 'y' : 'n'); 1488 lprintf(LOG_NOTICE, "Component 4 presence....[%c] ", 1489 pCtx->resp.componentsPresent.ComponentBits.bitField.component4 ? 'y' : 'n'); 1490 lprintf(LOG_NOTICE, "Component 5 presence....[%c] ", 1491 pCtx->resp.componentsPresent.ComponentBits.bitField.component5 ? 'y' : 'n'); 1492 lprintf(LOG_NOTICE, "Component 6 presence....[%c] ", 1493 pCtx->resp.componentsPresent.ComponentBits.bitField.component6 ? 'y' : 'n'); 1494 lprintf(LOG_NOTICE, "Component 7 presence....[%c] ", 1495 pCtx->resp.componentsPresent.ComponentBits.bitField.component7 ? 'y' : 'n'); 1496 lprintf(LOG_NOTICE, "Upgrade undesirable.....[%c] ", 1497 pCtx->resp.GlobalCapabilities.bitField.fwUpgUndesirable ? 'y' : 'n'); 1498 lprintf(LOG_NOTICE, "Aut rollback override...[%c] ", 1499 pCtx->resp.GlobalCapabilities.bitField.autRollbackOverride ? 'y' : 'n'); 1500 lprintf(LOG_NOTICE, "IPMC degraded...........[%c] ", 1501 pCtx->resp.GlobalCapabilities.bitField.ipmcDegradedDurinUpg ? 'y' : 'n'); 1502 lprintf(LOG_NOTICE, "Defered activation......[%c] ", 1503 pCtx->resp.GlobalCapabilities.bitField.deferActivation ? 'y' : 'n'); 1504 lprintf(LOG_NOTICE, "Service affected........[%c] ", 1505 pCtx->resp.GlobalCapabilities.bitField.servAffectDuringUpg ? 'y' : 'n'); 1506 lprintf(LOG_NOTICE, "Manual rollback.........[%c] ", 1507 pCtx->resp.GlobalCapabilities.bitField.manualRollback ? 'y' : 'n'); 1508 lprintf(LOG_NOTICE, "Automatic rollback......[%c] ", 1509 pCtx->resp.GlobalCapabilities.bitField.autRollback ? 'y' : 'n'); 1510 lprintf(LOG_NOTICE, "Self test...............[%c] ", 1511 pCtx->resp.GlobalCapabilities.bitField.ipmcSelftestCap ? 'y' : 'n'); 1512 lprintf(LOG_NOTICE, "Upgrade timeout.........[%d sec] ", 1513 pCtx->resp.upgradeTimeout*5); 1514 lprintf(LOG_NOTICE, "Self test timeout.......[%d sec] ", 1515 pCtx->resp.selftestTimeout*5); 1516 lprintf(LOG_NOTICE, "Rollback timeout........[%d sec] ", 1517 pCtx->resp.rollbackTimeout*5); 1518 lprintf(LOG_NOTICE, "Inaccessibility timeout.[%d sec] \n", 1519 pCtx->resp.inaccessTimeout*5); 1520 } 1521 return HPMFWUPG_SUCCESS; 1522 } 1523 1524 int 1525 HpmfwupgGetComponentProperties(struct ipmi_intf *intf, 1526 struct HpmfwupgGetComponentPropertiesCtx *pCtx) 1527 { 1528 int rc = HPMFWUPG_SUCCESS; 1529 struct ipmi_rs * rsp; 1530 struct ipmi_rq req; 1531 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1532 memset(&req, 0, sizeof(req)); 1533 req.msg.netfn = IPMI_NETFN_PICMG; 1534 req.msg.cmd = HPMFWUPG_GET_COMPONENT_PROPERTIES; 1535 req.msg.data = (unsigned char*)&pCtx->req; 1536 req.msg.data_len = sizeof(struct HpmfwupgGetComponentPropertiesReq); 1537 rsp = HpmfwupgSendCmd(intf, req, NULL); 1538 if (rsp == NULL) { 1539 lprintf(LOG_NOTICE, 1540 "Error getting component properties\n"); 1541 return HPMFWUPG_ERROR; 1542 } 1543 if (rsp->ccode != 0x00) { 1544 lprintf(LOG_NOTICE, 1545 "Error getting component properties"); 1546 lprintf(LOG_NOTICE, 1547 "compcode=0x%x: %s", 1548 rsp->ccode, 1549 val2str(rsp->ccode, completion_code_vals)); 1550 return HPMFWUPG_ERROR; 1551 } 1552 switch (pCtx->req.selector) { 1553 case HPMFWUPG_COMP_GEN_PROPERTIES: 1554 memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetGeneralPropResp)); 1555 if (verbose) { 1556 lprintf(LOG_NOTICE, "GENERAL PROPERTIES"); 1557 lprintf(LOG_NOTICE, "-------------------------------"); 1558 lprintf(LOG_NOTICE, "Payload cold reset req....[%c] ", 1559 pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.payloadColdReset ? 'y' : 'n'); 1560 lprintf(LOG_NOTICE, "Def. activation supported.[%c] ", 1561 pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.deferredActivation ? 'y' : 'n'); 1562 lprintf(LOG_NOTICE, "Comparison supported......[%c] ", 1563 pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.comparisonSupport ? 'y' : 'n'); 1564 lprintf(LOG_NOTICE, "Preparation supported.....[%c] ", 1565 pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.preparationSupport ? 'y' : 'n'); 1566 lprintf(LOG_NOTICE, "Rollback supported........[%c] \n", 1567 pCtx->resp.Response.generalPropResp.GeneralCompProperties.bitfield.rollbackBackup ? 'y' : 'n'); 1568 } 1569 break; 1570 case HPMFWUPG_COMP_CURRENT_VERSION: 1571 memcpy(&pCtx->resp, rsp->data, 1572 sizeof(struct HpmfwupgGetCurrentVersionResp)); 1573 if (verbose) { 1574 lprintf(LOG_NOTICE, "Current Version: "); 1575 lprintf(LOG_NOTICE, " Major: %d", 1576 pCtx->resp.Response.currentVersionResp.currentVersion[0]); 1577 lprintf(LOG_NOTICE, " Minor: %x", 1578 pCtx->resp.Response.currentVersionResp.currentVersion[1]); 1579 lprintf(LOG_NOTICE, " Aux : %03d %03d %03d %03d\n", 1580 pCtx->resp.Response.currentVersionResp.currentVersion[2], 1581 pCtx->resp.Response.currentVersionResp.currentVersion[3], 1582 pCtx->resp.Response.currentVersionResp.currentVersion[4], 1583 pCtx->resp.Response.currentVersionResp.currentVersion[5]); 1584 } 1585 break; 1586 case HPMFWUPG_COMP_DESCRIPTION_STRING: 1587 memcpy(&pCtx->resp, rsp->data, 1588 sizeof(struct HpmfwupgGetDescStringResp)); 1589 if (verbose) { 1590 char descString[HPMFWUPG_DESC_STRING_LENGTH + 1]; 1591 memcpy(descString, 1592 pCtx->resp.Response.descStringResp.descString, 1593 HPMFWUPG_DESC_STRING_LENGTH); 1594 descString[HPMFWUPG_DESC_STRING_LENGTH] = '\0'; 1595 lprintf(LOG_NOTICE, 1596 "Description string: %s\n", 1597 descString); 1598 } 1599 break; 1600 case HPMFWUPG_COMP_ROLLBACK_FIRMWARE_VERSION: 1601 memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetRollbackFwVersionResp)); 1602 if (verbose) { 1603 lprintf(LOG_NOTICE, "Rollback FW Version: "); 1604 lprintf(LOG_NOTICE, " Major: %d", 1605 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[0]); 1606 lprintf(LOG_NOTICE, " Minor: %x", 1607 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[1]); 1608 lprintf(LOG_NOTICE, " Aux : %03d %03d %03d %03d\n", 1609 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[2], 1610 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[3], 1611 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[4], 1612 pCtx->resp.Response.rollbackFwVersionResp.rollbackFwVersion[5]); 1613 } 1614 break; 1615 case HPMFWUPG_COMP_DEFERRED_FIRMWARE_VERSION: 1616 memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetDeferredFwVersionResp)); 1617 if (verbose) { 1618 lprintf(LOG_NOTICE, "Deferred FW Version: "); 1619 lprintf(LOG_NOTICE, " Major: %d", 1620 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[0]); 1621 lprintf(LOG_NOTICE, " Minor: %x", 1622 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[1]); 1623 lprintf(LOG_NOTICE, " Aux : %03d %03d %03d %03d\n", 1624 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[2], 1625 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[3], 1626 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[4], 1627 pCtx->resp.Response.deferredFwVersionResp.deferredFwVersion[5]); 1628 } 1629 break; 1630 case HPMFWUPG_COMP_OEM_PROPERTIES: 1631 /* OEM Properties command */ 1632 memcpy(&pCtx->resp, rsp->data, sizeof(struct HpmfwupgGetOemProperties)); 1633 if (verbose) { 1634 unsigned char i = 0; 1635 lprintf(LOG_NOTICE,"OEM Properties: "); 1636 for (i=0; i < HPMFWUPG_OEM_LENGTH; i++) { 1637 lprintf(LOG_NOTICE, " 0x%x ", 1638 pCtx->resp.Response.oemProperties.oemRspData[i]); 1639 } 1640 } 1641 break; 1642 default: 1643 lprintf(LOG_NOTICE,"Unsupported component selector"); 1644 rc = HPMFWUPG_ERROR; 1645 break; 1646 } 1647 return rc; 1648 } 1649 1650 int 1651 HpmfwupgAbortUpgrade(struct ipmi_intf *intf, 1652 struct HpmfwupgAbortUpgradeCtx *pCtx) 1653 { 1654 int rc = HPMFWUPG_SUCCESS; 1655 struct ipmi_rs *rsp; 1656 struct ipmi_rq req; 1657 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1658 memset(&req, 0, sizeof(req)); 1659 req.msg.netfn = IPMI_NETFN_PICMG; 1660 req.msg.cmd = HPMFWUPG_ABORT_UPGRADE; 1661 req.msg.data = (unsigned char*)&pCtx->req; 1662 req.msg.data_len = sizeof(struct HpmfwupgAbortUpgradeReq); 1663 rsp = HpmfwupgSendCmd(intf, req, NULL); 1664 if (rsp == NULL) { 1665 lprintf(LOG_ERR, "Error - aborting upgrade."); 1666 return HPMFWUPG_ERROR; 1667 } 1668 if (rsp->ccode != 0x00) { 1669 lprintf(LOG_ERR, "Error aborting upgrade"); 1670 lprintf(LOG_ERR, "compcode=0x%x: %s", 1671 rsp->ccode, 1672 val2str(rsp->ccode, completion_code_vals)); 1673 rc = HPMFWUPG_ERROR; 1674 } 1675 return rc; 1676 } 1677 1678 int 1679 HpmfwupgInitiateUpgradeAction(struct ipmi_intf *intf, 1680 struct HpmfwupgInitiateUpgradeActionCtx *pCtx, 1681 struct HpmfwupgUpgradeCtx *pFwupgCtx) 1682 { 1683 int rc = HPMFWUPG_SUCCESS; 1684 struct ipmi_rs *rsp; 1685 struct ipmi_rq req; 1686 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1687 memset(&req, 0, sizeof(req)); 1688 req.msg.netfn = IPMI_NETFN_PICMG; 1689 req.msg.cmd = HPMFWUPG_INITIATE_UPGRADE_ACTION; 1690 req.msg.data = (unsigned char*)&pCtx->req; 1691 req.msg.data_len = sizeof(struct HpmfwupgInitiateUpgradeActionReq); 1692 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 1693 if (rsp == NULL) { 1694 lprintf(LOG_ERR, "Error initiating upgrade action."); 1695 return HPMFWUPG_ERROR; 1696 } 1697 /* Long duration command handling */ 1698 if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { 1699 rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); 1700 } else if (rsp->ccode != 0x00) { 1701 lprintf(LOG_NOTICE,"Error initiating upgrade action"); 1702 lprintf(LOG_NOTICE, "compcode=0x%x: %s", 1703 rsp->ccode, 1704 val2str(rsp->ccode, completion_code_vals)); 1705 rc = HPMFWUPG_ERROR; 1706 } 1707 return rc; 1708 } 1709 1710 int 1711 HpmfwupgUploadFirmwareBlock(struct ipmi_intf *intf, 1712 struct HpmfwupgUploadFirmwareBlockCtx *pCtx, 1713 struct HpmfwupgUpgradeCtx *pFwupgCtx, int count, 1714 unsigned int *imageOffset, unsigned int *blockLength) 1715 { 1716 int rc = HPMFWUPG_SUCCESS; 1717 struct ipmi_rs *rsp; 1718 struct ipmi_rq req; 1719 pCtx->req->picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1720 memset(&req, 0, sizeof(req)); 1721 req.msg.netfn = IPMI_NETFN_PICMG; 1722 req.msg.cmd = HPMFWUPG_UPLOAD_FIRMWARE_BLOCK; 1723 req.msg.data = (unsigned char *)pCtx->req; 1724 /* 2 is the size of the upload struct - data */ 1725 req.msg.data_len = 2 + count; 1726 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 1727 if (rsp == NULL) { 1728 lprintf(LOG_NOTICE, "Error uploading firmware block."); 1729 return HPMFWUPG_ERROR; 1730 } 1731 if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS 1732 || rsp->ccode == 0x00) { 1733 /* 1734 * We need to check if the response also contains the next upload firmware offset 1735 * and the firmware length in its response - These are optional but very vital 1736 */ 1737 if (rsp->data_len > 1) { 1738 /* 1739 * If the response data length is greater than 1 it should contain both the 1740 * the Section offset and section length. Because we cannot just have 1741 * Section offset without section length so the length should be 9 1742 */ 1743 if (rsp->data_len == 9) { 1744 /* rsp->data[1] - LSB rsp->data[2] - rsp->data[3] = MSB */ 1745 *imageOffset = (rsp->data[4] << 24) + (rsp->data[3] << 16) + (rsp->data[2] << 8) + rsp->data[1]; 1746 *blockLength = (rsp->data[8] << 24) + (rsp->data[7] << 16) + (rsp->data[6] << 8) + rsp->data[5]; 1747 } else { 1748 /* 1749 * The Spec does not say much for this kind of errors where the 1750 * firmware returned only offset and length so currently returning it 1751 * as 0x82 - Internal CheckSum Error 1752 */ 1753 lprintf(LOG_NOTICE, 1754 "Error wrong rsp->datalen %d for Upload Firmware block command\n", 1755 rsp->data_len); 1756 rsp->ccode = HPMFWUPG_INT_CHECKSUM_ERROR; 1757 } 1758 } 1759 } 1760 /* Long duration command handling */ 1761 if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { 1762 rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); 1763 } else if (rsp->ccode != 0x00) { 1764 /* PATCH --> This validation is to handle retryables errors codes on IPMB bus. 1765 * This will be fixed in the next release of open ipmi and this 1766 * check will have to be removed. (Buggy version = 39) 1767 */ 1768 if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) { 1769 lprintf(LOG_DEBUG, "HPM: [PATCH]Retryable error detected"); 1770 rc = HPMFWUPG_UPLOAD_RETRY; 1771 } else if (rsp->ccode == IPMI_CC_REQ_DATA_INV_LENGTH || 1772 rsp->ccode == IPMI_CC_REQ_DATA_FIELD_EXCEED) { 1773 /* If completion code = 0xc7(0xc8), we will retry with a reduced buffer length. 1774 * Do not print error. 1775 */ 1776 rc = HPMFWUPG_UPLOAD_BLOCK_LENGTH; 1777 } else { 1778 lprintf(LOG_ERR, "Error uploading firmware block"); 1779 lprintf(LOG_ERR, "compcode=0x%x: %s", 1780 rsp->ccode, 1781 val2str(rsp->ccode, 1782 completion_code_vals)); 1783 rc = HPMFWUPG_ERROR; 1784 } 1785 } 1786 return rc; 1787 } 1788 1789 int 1790 HpmfwupgFinishFirmwareUpload(struct ipmi_intf *intf, 1791 struct HpmfwupgFinishFirmwareUploadCtx *pCtx, 1792 struct HpmfwupgUpgradeCtx *pFwupgCtx, int option) 1793 { 1794 int rc = HPMFWUPG_SUCCESS; 1795 struct ipmi_rs *rsp; 1796 struct ipmi_rq req; 1797 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1798 memset(&req, 0, sizeof(req)); 1799 req.msg.netfn = IPMI_NETFN_PICMG; 1800 req.msg.cmd = HPMFWUPG_FINISH_FIRMWARE_UPLOAD; 1801 req.msg.data = (unsigned char*)&pCtx->req; 1802 req.msg.data_len = sizeof(struct HpmfwupgFinishFirmwareUploadReq); 1803 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 1804 if (rsp == NULL) { 1805 lprintf(LOG_ERR, "Error fininshing firmware upload."); 1806 return HPMFWUPG_ERROR; 1807 } 1808 /* Long duration command handling */ 1809 if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { 1810 rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); 1811 } else if ((option & COMPARE_MODE) && rsp->ccode == 0x83) { 1812 printf("| |Component's active copy doesn't match the upgrade image |\n"); 1813 } else if ((option & COMPARE_MODE) && rsp->ccode == IPMI_CC_OK) { 1814 printf("| |Comparison passed |\n"); 1815 } else if ( rsp->ccode != IPMI_CC_OK ) { 1816 lprintf(LOG_ERR, "Error finishing firmware upload"); 1817 lprintf(LOG_ERR, "compcode=0x%x: %s", 1818 rsp->ccode, 1819 val2str(rsp->ccode, completion_code_vals)); 1820 rc = HPMFWUPG_ERROR; 1821 } 1822 return rc; 1823 } 1824 1825 int 1826 HpmfwupgActivateFirmware(struct ipmi_intf *intf, 1827 struct HpmfwupgActivateFirmwareCtx *pCtx, 1828 struct HpmfwupgUpgradeCtx *pFwupgCtx) 1829 { 1830 int rc = HPMFWUPG_SUCCESS; 1831 struct ipmi_rs *rsp; 1832 struct ipmi_rq req; 1833 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1834 memset(&req, 0, sizeof(req)); 1835 req.msg.netfn = IPMI_NETFN_PICMG; 1836 req.msg.cmd = HPMFWUPG_ACTIVATE_FIRMWARE; 1837 req.msg.data = (unsigned char*)&pCtx->req; 1838 req.msg.data_len = sizeof(struct HpmfwupgActivateFirmwareReq) 1839 - (!pCtx->req.rollback_override ? 1 : 0); 1840 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 1841 if (rsp == NULL) { 1842 lprintf(LOG_ERR, "Error activating firmware."); 1843 return HPMFWUPG_ERROR; 1844 } 1845 /* Long duration command handling */ 1846 if (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { 1847 printf("Waiting firmware activation..."); 1848 fflush(stdout); 1849 rc = HpmfwupgWaitLongDurationCmd(intf, pFwupgCtx); 1850 if (rc == HPMFWUPG_SUCCESS) { 1851 lprintf(LOG_NOTICE, "OK"); 1852 } else { 1853 lprintf(LOG_NOTICE, "Failed"); 1854 } 1855 } else if (rsp->ccode != IPMI_CC_OK) { 1856 lprintf(LOG_ERR, "Error activating firmware"); 1857 lprintf(LOG_ERR, "compcode=0x%x: %s", 1858 rsp->ccode, 1859 val2str(rsp->ccode, completion_code_vals)); 1860 rc = HPMFWUPG_ERROR; 1861 } 1862 return rc; 1863 } 1864 1865 int 1866 HpmfwupgGetUpgradeStatus(struct ipmi_intf *intf, 1867 struct HpmfwupgGetUpgradeStatusCtx *pCtx, 1868 struct HpmfwupgUpgradeCtx *pFwupgCtx, 1869 int silent) 1870 { 1871 struct ipmi_rs *rsp; 1872 struct ipmi_rq req; 1873 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1874 memset(&req, 0, sizeof(req)); 1875 req.msg.netfn = IPMI_NETFN_PICMG; 1876 req.msg.cmd = HPMFWUPG_GET_UPGRADE_STATUS; 1877 req.msg.data = (unsigned char*)&pCtx->req; 1878 req.msg.data_len = sizeof(struct HpmfwupgGetUpgradeStatusReq); 1879 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 1880 if (!rsp) { 1881 lprintf(LOG_NOTICE, 1882 "Error getting upgrade status. Failed to get response."); 1883 return HPMFWUPG_ERROR; 1884 } 1885 if (rsp->ccode == 0x00) { 1886 memcpy(&pCtx->resp, rsp->data, 1887 sizeof(struct HpmfwupgGetUpgradeStatusResp)); 1888 if (!silent) { 1889 lprintf(LOG_NOTICE, "Upgrade status:"); 1890 lprintf(LOG_NOTICE, 1891 " Command in progress: %x", 1892 pCtx->resp.cmdInProcess); 1893 lprintf(LOG_NOTICE, 1894 " Last command completion code: %x", 1895 pCtx->resp.lastCmdCompCode); 1896 } 1897 } else if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) { 1898 /* PATCH --> This validation is to handle retryable errors 1899 * codes on the IPMB bus. 1900 * This will be fixed in the next release of 1901 * open ipmi and this check can be removed. 1902 * (Buggy version = 39) 1903 */ 1904 if (!silent) { 1905 lprintf(LOG_DEBUG, "HPM: Retryable error detected"); 1906 } 1907 pCtx->resp.lastCmdCompCode = HPMFWUPG_COMMAND_IN_PROGRESS; 1908 } else { 1909 lprintf(LOG_NOTICE, "Error getting upgrade status"); 1910 lprintf(LOG_NOTICE, "compcode=0x%x: %s", rsp->ccode, 1911 val2str(rsp->ccode, completion_code_vals)); 1912 return HPMFWUPG_ERROR; 1913 } 1914 return HPMFWUPG_SUCCESS; 1915 } 1916 1917 int 1918 HpmfwupgManualFirmwareRollback(struct ipmi_intf *intf, 1919 struct HpmfwupgManualFirmwareRollbackCtx *pCtx) 1920 { 1921 struct HpmfwupgUpgradeCtx fwupgCtx; 1922 struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; 1923 int rc = HPMFWUPG_SUCCESS; 1924 struct ipmi_rs *rsp; 1925 struct ipmi_rq req; 1926 /* prepare fake upgrade context */ 1927 memset(&fwupgCtx, 0, sizeof (fwupgCtx)); 1928 verbose--; 1929 rc = HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd); 1930 verbose++; 1931 if (rc != HPMFWUPG_SUCCESS) { 1932 return rc; 1933 } 1934 memcpy(&fwupgCtx.targetCap, &targetCapCmd.resp, sizeof(targetCapCmd.resp)); 1935 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1936 memset(&req, 0, sizeof(req)); 1937 req.msg.netfn = IPMI_NETFN_PICMG; 1938 req.msg.cmd = HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK; 1939 req.msg.data = (unsigned char*)&pCtx->req; 1940 req.msg.data_len = sizeof(struct HpmfwupgManualFirmwareRollbackReq); 1941 rsp = HpmfwupgSendCmd(intf, req, &fwupgCtx); 1942 if (rsp == NULL) { 1943 lprintf(LOG_ERR, "Error sending manual rollback."); 1944 return HPMFWUPG_ERROR; 1945 } 1946 /* Long duration command handling */ 1947 if (rsp->ccode == IPMI_CC_OK 1948 || rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) { 1949 struct HpmfwupgQueryRollbackStatusCtx resCmd; 1950 printf("Waiting firmware rollback..."); 1951 fflush(stdout); 1952 rc = HpmfwupgQueryRollbackStatus(intf, &resCmd, &fwupgCtx); 1953 } else if ( rsp->ccode != 0x00 ) { 1954 lprintf(LOG_ERR, "Error sending manual rollback"); 1955 lprintf(LOG_ERR, "compcode=0x%x: %s", 1956 rsp->ccode, 1957 val2str(rsp->ccode, completion_code_vals)); 1958 rc = HPMFWUPG_ERROR; 1959 } 1960 return rc; 1961 } 1962 1963 int 1964 HpmfwupgQueryRollbackStatus(struct ipmi_intf *intf, 1965 struct HpmfwupgQueryRollbackStatusCtx *pCtx, 1966 struct HpmfwupgUpgradeCtx *pFwupgCtx) 1967 { 1968 int rc = HPMFWUPG_SUCCESS; 1969 struct ipmi_rs *rsp; 1970 struct ipmi_rq req; 1971 unsigned int rollbackTimeout = 0; 1972 unsigned int timeoutSec1, timeoutSec2; 1973 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 1974 memset(&req, 0, sizeof(req)); 1975 req.msg.netfn = IPMI_NETFN_PICMG; 1976 req.msg.cmd = HPMFWUPG_QUERY_ROLLBACK_STATUS; 1977 req.msg.data = (unsigned char*)&pCtx->req; 1978 req.msg.data_len = sizeof(struct HpmfwupgQueryRollbackStatusReq); 1979 /* If we are not in upgrade context, we use default timeout values */ 1980 if (pFwupgCtx != NULL) { 1981 struct HpmfwupgImageHeader *pImageHeader; 1982 if (pFwupgCtx->pImageData) { 1983 pImageHeader = (struct HpmfwupgImageHeader*)pFwupgCtx->pImageData; 1984 rollbackTimeout = pImageHeader->rollbackTimeout; 1985 } else { 1986 rollbackTimeout = 0; 1987 } 1988 /* Use the greater of the two timeouts (header and target caps) */ 1989 rollbackTimeout = MAX(rollbackTimeout, 1990 pFwupgCtx->targetCap.rollbackTimeout) * 5; 1991 } else { 1992 rollbackTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; 1993 } 1994 /* Poll rollback status until completion or timeout */ 1995 timeoutSec1 = time(NULL); 1996 timeoutSec2 = time(NULL); 1997 do { 1998 /* Must wait at least 100 ms between status requests */ 1999 usleep(100000); 2000 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 2001 /* PATCH --> This validation is to handle retryables errors codes on IPMB bus. 2002 * This will be fixed in the next release of open ipmi and this 2003 * check will have to be removed. (Buggy version = 39) 2004 */ 2005 if (rsp) { 2006 if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) { 2007 lprintf(LOG_DEBUG,"HPM: [PATCH]Retryable error detected"); 2008 rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS; 2009 } 2010 } 2011 timeoutSec2 = time(NULL); 2012 } while (rsp 2013 && ((rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) 2014 || (rsp->ccode == IPMI_CC_TIMEOUT)) 2015 && (timeoutSec2 - timeoutSec1 < rollbackTimeout)); 2016 if (rsp == NULL) { 2017 lprintf(LOG_ERR, "Error getting upgrade status."); 2018 return HPMFWUPG_ERROR; 2019 } 2020 if (rsp->ccode == 0x00) { 2021 memcpy(&pCtx->resp, rsp->data, 2022 sizeof(struct HpmfwupgQueryRollbackStatusResp)); 2023 if (pCtx->resp.rollbackComp.ComponentBits.byte != 0) { 2024 /* Rollback occured */ 2025 lprintf(LOG_NOTICE, 2026 "Rollback occured on component mask: 0x%02x", 2027 pCtx->resp.rollbackComp.ComponentBits.byte); 2028 } else { 2029 lprintf(LOG_NOTICE, 2030 "No Firmware rollback occured"); 2031 } 2032 } else if (rsp->ccode == 0x81) { 2033 lprintf(LOG_ERR, 2034 "Rollback failed on component mask: 0x%02x", 2035 pCtx->resp.rollbackComp.ComponentBits.byte); 2036 rc = HPMFWUPG_ERROR; 2037 } else { 2038 lprintf(LOG_ERR, 2039 "Error getting rollback status"); 2040 lprintf(LOG_ERR, 2041 "compcode=0x%x: %s", 2042 rsp->ccode, 2043 val2str(rsp->ccode, completion_code_vals)); 2044 rc = HPMFWUPG_ERROR; 2045 } 2046 return rc; 2047 } 2048 2049 int 2050 HpmfwupgQuerySelftestResult(struct ipmi_intf *intf, struct HpmfwupgQuerySelftestResultCtx *pCtx, 2051 struct HpmfwupgUpgradeCtx *pFwupgCtx) 2052 { 2053 int rc = HPMFWUPG_SUCCESS; 2054 struct ipmi_rs *rsp; 2055 struct ipmi_rq req; 2056 unsigned char selfTestTimeout = 0; 2057 unsigned int timeoutSec1, timeoutSec2; 2058 pCtx->req.picmgId = HPMFWUPG_PICMG_IDENTIFIER; 2059 /* If we are not in upgrade context, we use default timeout values */ 2060 if (pFwupgCtx != NULL) { 2061 /* Getting selftest timeout from new image */ 2062 struct HpmfwupgImageHeader *pImageHeader = (struct HpmfwupgImageHeader*) 2063 pFwupgCtx->pImageData; 2064 selfTestTimeout = MAX(pImageHeader->selfTestTimeout, 2065 pFwupgCtx->targetCap.selftestTimeout) * 5; 2066 } else { 2067 selfTestTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; 2068 } 2069 memset(&req, 0, sizeof(req)); 2070 req.msg.netfn = IPMI_NETFN_PICMG; 2071 req.msg.cmd = HPMFWUPG_QUERY_SELFTEST_RESULT; 2072 req.msg.data = (unsigned char*)&pCtx->req; 2073 req.msg.data_len = sizeof(struct HpmfwupgQuerySelftestResultReq); 2074 /* Poll rollback status until completion or timeout */ 2075 timeoutSec1 = time(NULL); 2076 timeoutSec2 = time(NULL); 2077 do { 2078 /* Must wait at least 100 ms between status requests */ 2079 usleep(100000); 2080 rsp = HpmfwupgSendCmd(intf, req, pFwupgCtx); 2081 /* PATCH --> This validation is to handle retryables errors codes on IPMB bus. 2082 * This will be fixed in the next release of open ipmi and this 2083 * check will have to be removed. (Buggy version = 39) 2084 */ 2085 if (rsp) { 2086 if (HPMFWUPG_IS_RETRYABLE(rsp->ccode)) { 2087 lprintf(LOG_DEBUG, 2088 "HPM: [PATCH]Retryable error detected"); 2089 rsp->ccode = HPMFWUPG_COMMAND_IN_PROGRESS; 2090 } 2091 } 2092 timeoutSec2 = time(NULL); 2093 } while (rsp 2094 && (rsp->ccode == HPMFWUPG_COMMAND_IN_PROGRESS) 2095 && (timeoutSec2 - timeoutSec1 < selfTestTimeout)); 2096 if (rsp == NULL) { 2097 lprintf(LOG_NOTICE, "Error getting upgrade status\n"); 2098 return HPMFWUPG_ERROR; 2099 } 2100 if (rsp->ccode == 0x00) { 2101 memcpy(&pCtx->resp, rsp->data, 2102 sizeof(struct HpmfwupgQuerySelftestResultResp)); 2103 if (verbose) { 2104 lprintf(LOG_NOTICE, "Self test results:"); 2105 lprintf(LOG_NOTICE, "Result1 = %x", 2106 pCtx->resp.result1); 2107 lprintf(LOG_NOTICE, "Result2 = %x", 2108 pCtx->resp.result2); 2109 } 2110 } else { 2111 lprintf(LOG_NOTICE, "Error getting self test results"); 2112 lprintf(LOG_NOTICE, "compcode=0x%x: %s", 2113 rsp->ccode, 2114 val2str(rsp->ccode, completion_code_vals)); 2115 rc = HPMFWUPG_ERROR; 2116 } 2117 return rc; 2118 } 2119 2120 struct ipmi_rs * 2121 HpmfwupgSendCmd(struct ipmi_intf *intf, struct ipmi_rq req, 2122 struct HpmfwupgUpgradeCtx *pFwupgCtx) 2123 { 2124 struct ipmi_rs *rsp; 2125 unsigned int inaccessTimeout = 0, inaccessTimeoutCounter = 0; 2126 unsigned int upgradeTimeout = 0, upgradeTimeoutCounter = 0; 2127 unsigned int timeoutSec1, timeoutSec2; 2128 unsigned char retry = 0; 2129 /* If we are not in upgrade context, we use default timeout values */ 2130 if (pFwupgCtx != NULL) { 2131 inaccessTimeout = pFwupgCtx->targetCap.inaccessTimeout*5; 2132 upgradeTimeout = pFwupgCtx->targetCap.upgradeTimeout*5; 2133 } else { 2134 /* keeping the inaccessTimeout to 60 seconds results in almost 2900 retries 2135 * So if the target is not available it will be retrying the command for 2900 2136 * times which is not effecient -So reducing the Timout to 5 seconds which is 2137 * almost 200 retries if it continuously recieves 0xC3 as completion code. 2138 */ 2139 inaccessTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; 2140 upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; 2141 } 2142 timeoutSec1 = time(NULL); 2143 do { 2144 static unsigned char isValidSize = FALSE; 2145 rsp = intf->sendrecv(intf, &req); 2146 if (rsp == NULL) { 2147 #define HPM_LAN_PACKET_RESIZE_LIMIT 6 2148 /* also covers lanplus */ 2149 if (strstr(intf->name, "lan") != NULL) { 2150 static int errorCount=0; 2151 static struct ipmi_rs fakeRsp; 2152 lprintf(LOG_DEBUG, 2153 "HPM: no response available"); 2154 lprintf(LOG_DEBUG, 2155 "HPM: the command may be rejected for security reasons"); 2156 if (req.msg.netfn == IPMI_NETFN_PICMG 2157 && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK 2158 && errorCount < HPM_LAN_PACKET_RESIZE_LIMIT 2159 && (!isValidSize)) { 2160 lprintf(LOG_DEBUG, 2161 "HPM: upload firmware block API called"); 2162 lprintf(LOG_DEBUG, 2163 "HPM: returning length error to force resize"); 2164 fakeRsp.ccode = IPMI_CC_REQ_DATA_INV_LENGTH; 2165 rsp = &fakeRsp; 2166 errorCount++; 2167 } else if (req.msg.netfn == IPMI_NETFN_PICMG 2168 && (req.msg.cmd == HPMFWUPG_ACTIVATE_FIRMWARE 2169 || req.msg.cmd == HPMFWUPG_MANUAL_FIRMWARE_ROLLBACK)) { 2170 /* 2171 * rsp == NULL and command activate firmware or manual firmware 2172 * rollback most likely occurs when we have sent a firmware activation 2173 * request. Fake a command in progress response. 2174 */ 2175 lprintf(LOG_DEBUG, 2176 "HPM: activate/rollback firmware API called"); 2177 lprintf(LOG_DEBUG, 2178 "HPM: returning in progress to handle IOL session lost"); 2179 fakeRsp.ccode = HPMFWUPG_COMMAND_IN_PROGRESS; 2180 rsp = &fakeRsp; 2181 } else if (req.msg.netfn == IPMI_NETFN_PICMG 2182 && (req.msg.cmd == HPMFWUPG_QUERY_ROLLBACK_STATUS 2183 || req.msg.cmd == HPMFWUPG_GET_UPGRADE_STATUS 2184 || req.msg.cmd == HPMFWUPG_QUERY_SELFTEST_RESULT) 2185 && ( !intf->target_addr || intf->target_addr == intf->my_addr)) { 2186 /* reopen session only if target IPMC is directly accessed */ 2187 /* 2188 * rsp == NULL and command get upgrade status or query rollback 2189 * status most likely occurs when we are waiting for firmware 2190 * activation. Try to re-open the IOL session (re-open will work 2191 * once the IPMC recovers from firmware activation. 2192 */ 2193 lprintf(LOG_DEBUG, "HPM: upg/rollback status firmware API called"); 2194 lprintf(LOG_DEBUG, "HPM: try to re-open IOL session"); 2195 { 2196 /* force session re-open */ 2197 intf->opened = 0; 2198 intf->session->authtype = IPMI_SESSION_AUTHTYPE_NONE; 2199 intf->session->session_id = 0; 2200 intf->session->in_seq = 0; 2201 intf->session->out_seq = 0; 2202 intf->session->active = 0; 2203 intf->session->retry = 10; 2204 while (intf->open(intf) == HPMFWUPG_ERROR 2205 && inaccessTimeoutCounter < inaccessTimeout) { 2206 inaccessTimeoutCounter += (time(NULL) - timeoutSec1); 2207 timeoutSec1 = time(NULL); 2208 } 2209 /* Fake timeout to retry command */ 2210 fakeRsp.ccode = 0xc3; 2211 rsp = &fakeRsp; 2212 } 2213 } 2214 } 2215 } 2216 /* Handle inaccessibility timeout (rsp = NULL if IOL) */ 2217 if (rsp == NULL || rsp->ccode == 0xff || rsp->ccode == 0xc3 || rsp->ccode == 0xd3) { 2218 if (inaccessTimeoutCounter < inaccessTimeout) { 2219 timeoutSec2 = time(NULL); 2220 if (timeoutSec2 > timeoutSec1) { 2221 inaccessTimeoutCounter += timeoutSec2 - timeoutSec1; 2222 timeoutSec1 = time(NULL); 2223 } 2224 usleep(100000); 2225 retry = 1; 2226 } else { 2227 retry = 0; 2228 } 2229 } else if ( rsp->ccode == 0xc0 ) { 2230 /* Handle node busy timeout */ 2231 if (upgradeTimeoutCounter < upgradeTimeout) { 2232 timeoutSec2 = time(NULL); 2233 if (timeoutSec2 > timeoutSec1) { 2234 timeoutSec1 = time(NULL); 2235 upgradeTimeoutCounter += timeoutSec2 - timeoutSec1; 2236 } 2237 usleep(100000); 2238 retry = 1; 2239 } else { 2240 retry = 0; 2241 } 2242 } else { 2243 # ifdef ENABLE_OPENIPMI_V39_PATCH 2244 if (rsp->ccode == IPMI_CC_OK) { 2245 errorCount = 0 ; 2246 } 2247 # endif 2248 retry = 0; 2249 if (req.msg.netfn == IPMI_NETFN_PICMG 2250 && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK 2251 && (!isValidSize)) { 2252 lprintf(LOG_INFO, 2253 "Buffer length is now considered valid"); 2254 isValidSize = TRUE; 2255 } 2256 } 2257 } while (retry); 2258 return rsp; 2259 } 2260 2261 int 2262 HpmfwupgWaitLongDurationCmd(struct ipmi_intf *intf, 2263 struct HpmfwupgUpgradeCtx *pFwupgCtx) 2264 { 2265 int rc = HPMFWUPG_SUCCESS; 2266 unsigned int upgradeTimeout = 0; 2267 unsigned int timeoutSec1, timeoutSec2; 2268 struct HpmfwupgGetUpgradeStatusCtx upgStatusCmd; 2269 /* If we are not in upgrade context, we use default timeout values */ 2270 if (pFwupgCtx != NULL) { 2271 upgradeTimeout = (unsigned int)(pFwupgCtx->targetCap.upgradeTimeout*5); 2272 if (verbose) { 2273 printf("Use File Upgrade Capabilities: %i seconds\n", 2274 upgradeTimeout); 2275 } 2276 } else { 2277 /* Try to retreive from Caps */ 2278 struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd; 2279 if(HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd) != HPMFWUPG_SUCCESS) { 2280 upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT; 2281 if (verbose) { 2282 printf("Use default timeout: %i seconds\n", 2283 upgradeTimeout); 2284 } 2285 } else { 2286 upgradeTimeout = (unsigned int)(targetCapCmd.resp.upgradeTimeout * 5); 2287 if (verbose) { 2288 printf("Use Command Upgrade Capabilities Timeout: %i seconds\n", 2289 upgradeTimeout); 2290 } 2291 } 2292 } 2293 if (rc == HPMFWUPG_SUCCESS) { 2294 /* Poll upgrade status until completion or timeout*/ 2295 timeoutSec1 = time(NULL); 2296 timeoutSec2 = time(NULL); 2297 rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, 2298 pFwupgCtx, 1); 2299 } 2300 while ( 2301 /* With KCS: Cover the case where we sometime 2302 * receive d5 (on the first get status) from 2303 * the ipmi driver. 2304 */ 2305 (upgStatusCmd.resp.lastCmdCompCode == 0x80 || 2306 upgStatusCmd.resp.lastCmdCompCode == 0xD5) 2307 && ((timeoutSec2 - timeoutSec1) < upgradeTimeout ) 2308 && (rc == HPMFWUPG_SUCCESS)) { 2309 /* Must wait at least 1000 ms between status requests */ 2310 usleep(1000000); 2311 timeoutSec2 = time(NULL); 2312 rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx, 1); 2313 /* 2314 * printf("Get Status: %x - %x = %x _ %x [%x]\n", 2315 ( timeoutSec2, timeoutSec1, 2316 * (timeoutSec2 - timeoutSec1), 2317 * upgradeTimeout, rc); 2318 */ 2319 } 2320 if (upgStatusCmd.resp.lastCmdCompCode != 0x00) { 2321 if (verbose) { 2322 lprintf(LOG_NOTICE, 2323 "Error waiting for command %x, compcode = %x", 2324 upgStatusCmd.resp.cmdInProcess, 2325 upgStatusCmd.resp.lastCmdCompCode); 2326 } 2327 rc = HPMFWUPG_ERROR; 2328 } 2329 return rc; 2330 } 2331 2332 unsigned char 2333 HpmfwupgCalculateChecksum(unsigned char *pData, unsigned int length) 2334 { 2335 unsigned char checksum = 0; 2336 int dataIdx = 0; 2337 for (dataIdx = 0; dataIdx < length; dataIdx++) { 2338 checksum += pData[dataIdx]; 2339 } 2340 return checksum; 2341 } 2342 2343 void 2344 HpmfwupgPrintUsage(void) 2345 { 2346 lprintf(LOG_NOTICE, 2347 "help - This help menu."); 2348 lprintf(LOG_NOTICE, 2349 ""); 2350 lprintf(LOG_NOTICE, 2351 "check - Check the target information."); 2352 lprintf(LOG_NOTICE, 2353 "check <file> - If the user is unsure of what update is going to be "); 2354 lprintf(LOG_NOTICE, 2355 " This will display the existing target version and"); 2356 lprintf(LOG_NOTICE, 2357 " image version on the screen"); 2358 lprintf(LOG_NOTICE, 2359 ""); 2360 lprintf(LOG_NOTICE, 2361 "upgrade <file> [component x...] [force] [activate]"); 2362 lprintf(LOG_NOTICE, 2363 " - Copies components from a valid HPM.1 image to the target."); 2364 lprintf(LOG_NOTICE, 2365 " If one or more components specified by \"component\","); 2366 lprintf(LOG_NOTICE, 2367 " only the specified components are copied."); 2368 lprintf(LOG_NOTICE, 2369 " Otherwise, all the image components are copied."); 2370 lprintf(LOG_NOTICE, 2371 " Before copy, each image component undergoes a version check"); 2372 lprintf(LOG_NOTICE, 2373 " and can be skipped if the target component version"); 2374 lprintf(LOG_NOTICE, 2375 " is the same or more recent."); 2376 lprintf(LOG_NOTICE, 2377 " Use \"force\" to bypass the version check results."); 2378 lprintf(LOG_NOTICE, 2379 " Make sure to check the versions first using the"); 2380 lprintf(LOG_NOTICE, 2381 " \"check <file>\" command."); 2382 lprintf(LOG_NOTICE, 2383 " If \"activate\" is specified, the newly uploaded firmware"); 2384 lprintf(LOG_NOTICE, 2385 " is activated."); 2386 lprintf(LOG_NOTICE, 2387 "upgstatus - Returns the status of the last long duration command."); 2388 lprintf(LOG_NOTICE, 2389 ""); 2390 lprintf(LOG_NOTICE, 2391 "compare <file> - Perform \"Comparison of the Active Copy\" action for all the"); 2392 lprintf(LOG_NOTICE, 2393 " components present in the file."); 2394 lprintf(LOG_NOTICE, 2395 "compare <file> component x - Compare only component <x> from the given <file>"); 2396 lprintf(LOG_NOTICE, 2397 "activate - Activate the newly uploaded firmware."); 2398 lprintf(LOG_NOTICE, 2399 "activate norollback - Activate the newly uploaded firmware but inform"); 2400 lprintf(LOG_NOTICE, 2401 " the target to not automatically rollback if "); 2402 lprintf(LOG_NOTICE, 2403 " the upgrade fails."); 2404 lprintf(LOG_NOTICE, 2405 ""); 2406 lprintf(LOG_NOTICE, 2407 "targetcap - Get the target upgrade capabilities."); 2408 lprintf(LOG_NOTICE, 2409 ""); 2410 lprintf(LOG_NOTICE, 2411 "compprop <id> <prop> - Get specified component properties from the target."); 2412 lprintf(LOG_NOTICE, 2413 " Valid component <id>: 0-7 "); 2414 lprintf(LOG_NOTICE, 2415 " Properties <prop> can be one of the following: "); 2416 lprintf(LOG_NOTICE, 2417 " 0- General properties"); 2418 lprintf(LOG_NOTICE, 2419 " 1- Current firmware version"); 2420 lprintf(LOG_NOTICE, 2421 " 2- Description string"); 2422 lprintf(LOG_NOTICE, 2423 " 3- Rollback firmware version"); 2424 lprintf(LOG_NOTICE, 2425 " 4- Deferred firmware version"); 2426 lprintf(LOG_NOTICE, 2427 ""); 2428 lprintf(LOG_NOTICE, 2429 "abort - Abort the on-going firmware upgrade."); 2430 lprintf(LOG_NOTICE, 2431 ""); 2432 lprintf(LOG_NOTICE, 2433 "rollback - Performs a manual rollback on the IPM Controller."); 2434 lprintf(LOG_NOTICE, 2435 " firmware"); 2436 lprintf(LOG_NOTICE, 2437 "rollbackstatus - Query the rollback status."); 2438 lprintf(LOG_NOTICE, 2439 ""); 2440 lprintf(LOG_NOTICE, 2441 "selftestresult - Query the self test results.\n"); 2442 } 2443 2444 int 2445 ipmi_hpmfwupg_main(struct ipmi_intf *intf, int argc, char **argv) 2446 { 2447 int rc = HPMFWUPG_SUCCESS; 2448 int activateFlag = 0x00; 2449 int componentMask = 0; 2450 int componentId = 0; 2451 int option = 0; 2452 2453 lprintf(LOG_DEBUG,"ipmi_hpmfwupg_main()"); 2454 lprintf(LOG_NOTICE, "\nPICMG HPM.1 Upgrade Agent %d.%d.%d: \n", 2455 HPMFWUPG_VERSION_MAJOR, HPMFWUPG_VERSION_MINOR, 2456 HPMFWUPG_VERSION_SUBMINOR); 2457 if (argc < 1) { 2458 lprintf(LOG_ERR, "Not enough parameters given."); 2459 HpmfwupgPrintUsage(); 2460 return HPMFWUPG_ERROR; 2461 } 2462 if (strcmp(argv[0], "help") == 0) { 2463 HpmfwupgPrintUsage(); 2464 return HPMFWUPG_SUCCESS; 2465 } else if ((strcmp(argv[0], "check") == 0)) { 2466 /* hpm check */ 2467 if (argv[1] == NULL) { 2468 rc = HpmfwupgTargetCheck(intf,VIEW_MODE); 2469 } else { 2470 /* hpm check <filename> */ 2471 rc = HpmfwupgTargetCheck(intf,0); 2472 if (rc == HPMFWUPG_SUCCESS) { 2473 rc = HpmfwupgUpgrade(intf, argv[1], 0, 2474 0, VIEW_MODE); 2475 } 2476 } 2477 } else if (strcmp(argv[0], "upgrade") == 0) { 2478 int i =0; 2479 for (i=1; i< argc ; i++) { 2480 if (strcmp(argv[i],"activate") == 0) { 2481 activateFlag = 1; 2482 } 2483 /* hpm upgrade <filename> force */ 2484 if (strcmp(argv[i],"force") == 0) { 2485 option |= FORCE_MODE; 2486 } 2487 /* hpm upgrade <filename> component <comp Id> */ 2488 if (strcmp(argv[i],"component") == 0) { 2489 if (i+1 < argc) { 2490 /* Error Checking */ 2491 if (str2int(argv[i+1], &componentId) != 0 2492 || componentId < 0 2493 || componentId > HPMFWUPG_COMPONENT_ID_MAX) { 2494 lprintf(LOG_ERR, 2495 "Given Component ID '%s' is invalid.", 2496 argv[i+1]); 2497 lprintf(LOG_ERR, 2498 "Valid Compoment ID is: <0..7>"); 2499 return HPMFWUPG_ERROR; 2500 } 2501 if( verbose ) { 2502 lprintf(LOG_NOTICE, 2503 "Component Id %d provided", 2504 componentId ); 2505 } 2506 componentMask |= 1 << componentId; 2507 } else { 2508 /* That indicates the user has 2509 * given component on console but 2510 * not given any ID 2511 */ 2512 lprintf(LOG_NOTICE, 2513 "No component Id provided\n"); 2514 return HPMFWUPG_ERROR; 2515 } 2516 } 2517 if (strcmp(argv[i],"debug") == 0) { 2518 option |= DEBUG_MODE; 2519 } 2520 } 2521 rc = HpmfwupgTargetCheck(intf, 0); 2522 if (rc == HPMFWUPG_SUCCESS) { 2523 /* Call the Upgrade function to start the upgrade */ 2524 rc = HpmfwupgUpgrade(intf, argv[1], activateFlag, 2525 componentMask, option); 2526 } 2527 } else if (strcmp(argv[0], "compare") == 0) { 2528 int i = 0; 2529 for (i=1; i< argc; i++) { 2530 /* hpm compare <file> [component x...] */ 2531 if (strcmp(argv[i],"component") == 0) { 2532 if (i+1 < argc) { 2533 /* Error Checking */ 2534 if (str2int(argv[i+1], &componentId) != 0 2535 || componentId < 0 2536 || componentId > HPMFWUPG_COMPONENT_ID_MAX) { 2537 lprintf(LOG_ERR, 2538 "Given Component ID '%s' is invalid.", 2539 argv[i+1]); 2540 lprintf(LOG_ERR, 2541 "Valid Compoment ID is: <0..7>"); 2542 return HPMFWUPG_ERROR; 2543 } 2544 if( verbose ) { 2545 lprintf(LOG_NOTICE, 2546 "Component Id %d provided", 2547 componentId); 2548 } 2549 componentMask|= 1 << componentId; 2550 } else { 2551 /* That indicates the user 2552 * has given component on 2553 * console but not 2554 * given any ID 2555 */ 2556 lprintf(LOG_NOTICE, 2557 "No component Id provided\n"); 2558 return HPMFWUPG_ERROR; 2559 } 2560 } else if (strcmp(argv[i],"debug") == 0) { 2561 option|= DEBUG_MODE; 2562 } 2563 } 2564 option|= (COMPARE_MODE); 2565 rc = HpmfwupgTargetCheck(intf, 0); 2566 if (rc == HPMFWUPG_SUCCESS) { 2567 rc = HpmfwupgUpgrade(intf, argv[1], 0, 2568 componentMask, option); 2569 } 2570 } else if ((argc >= 1) && (strcmp(argv[0], "activate") == 0)) { 2571 struct HpmfwupgActivateFirmwareCtx cmdCtx; 2572 if ((argc == 2) && (strcmp(argv[1], "norollback") == 0)) { 2573 cmdCtx.req.rollback_override = 1; 2574 } else { 2575 cmdCtx.req.rollback_override = 0; 2576 } 2577 rc = HpmfwupgActivateFirmware(intf, &cmdCtx, NULL); 2578 } else if ((argc == 1) && (strcmp(argv[0], "targetcap") == 0)) { 2579 struct HpmfwupgGetTargetUpgCapabilitiesCtx cmdCtx; 2580 verbose++; 2581 rc = HpmfwupgGetTargetUpgCapabilities(intf, &cmdCtx); 2582 } else if ((argc == 3) && (strcmp(argv[0], "compprop") == 0)) { 2583 struct HpmfwupgGetComponentPropertiesCtx cmdCtx; 2584 if (str2uchar(argv[1], &(cmdCtx.req.componentId)) != 0 2585 || cmdCtx.req.componentId > 7) { 2586 lprintf(LOG_ERR, 2587 "Given Component ID '%s' is invalid.", 2588 argv[1]); 2589 lprintf(LOG_ERR, 2590 "Valid Compoment ID is: <0..7>"); 2591 return (-1); 2592 } 2593 if (str2uchar(argv[2], &(cmdCtx.req.selector)) != 0 2594 || cmdCtx.req.selector > 4) { 2595 lprintf(LOG_ERR, 2596 "Given Properties selector '%s' is invalid.", 2597 argv[2]); 2598 lprintf(LOG_ERR, 2599 "Valid Properties selector is: <0..4>"); 2600 return (-1); 2601 } 2602 verbose++; 2603 rc = HpmfwupgGetComponentProperties(intf, &cmdCtx); 2604 } else if ((argc == 1) && (strcmp(argv[0], "abort") == 0)) { 2605 struct HpmfwupgAbortUpgradeCtx cmdCtx; 2606 verbose++; 2607 rc = HpmfwupgAbortUpgrade(intf, &cmdCtx); 2608 } else if ((argc == 1) && (strcmp(argv[0], "upgstatus") == 0)) { 2609 struct HpmfwupgGetUpgradeStatusCtx cmdCtx; 2610 verbose++; 2611 rc = HpmfwupgGetUpgradeStatus(intf, &cmdCtx, NULL, 0); 2612 } else if ((argc == 1) && (strcmp(argv[0], "rollback") == 0)) { 2613 struct HpmfwupgManualFirmwareRollbackCtx cmdCtx; 2614 verbose++; 2615 rc = HpmfwupgManualFirmwareRollback(intf, &cmdCtx); 2616 } else if ((argc == 1) && (strcmp(argv[0], "rollbackstatus") == 0)) { 2617 struct HpmfwupgQueryRollbackStatusCtx cmdCtx; 2618 verbose++; 2619 rc = HpmfwupgQueryRollbackStatus(intf, &cmdCtx, NULL); 2620 } else if ((argc == 1) && (strcmp(argv[0], "selftestresult") == 0)) { 2621 struct HpmfwupgQuerySelftestResultCtx cmdCtx; 2622 verbose++; 2623 rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL); 2624 } else { 2625 lprintf(LOG_ERR, "Invalid HPM command: %s", argv[0]); 2626 HpmfwupgPrintUsage(); 2627 rc = HPMFWUPG_ERROR; 2628 } 2629 return rc; 2630 } 2631 2632