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
HpmGetUserInput(char * str)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
HpmDisplayLine(char * s,int n)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
HpmDisplayUpgradeHeader(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
HpmDisplayUpgrade(int skip,unsigned int totalSent,unsigned int displayFWLength,time_t timeElapsed)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
HpmDisplayVersionHeader(int mode)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
HpmDisplayVersion(int mode,VERSIONINFO * pVersion,int upgradable)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
HpmfwupgTargetCheck(struct ipmi_intf * intf,int option)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
HpmfwupgUpgrade(struct ipmi_intf * intf,char * imageFilename,int activate,int componentMask,int option)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
HpmfwupgValidateImageIntegrity(struct HpmfwupgUpgradeCtx * pFwupgCtx)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
HpmfwupgPreparationStage(struct ipmi_intf * intf,struct HpmfwupgUpgradeCtx * pFwupgCtx,int option)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
image_version_upgradable(VERSIONINFO * pVersionInfo)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
HpmfwupgValidateActionRecordChecksum(struct HpmfwupgActionRecord * pActionRecord)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
HpmfwupgPreUpgradeCheck(struct ipmi_intf * intf,struct HpmfwupgUpgradeCtx * pFwupgCtx,int componentMask,int option)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
HpmfwupgUpgradeStage(struct ipmi_intf * intf,struct HpmfwupgUpgradeCtx * pFwupgCtx,int option)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
HpmFwupgActionUploadFirmware(struct HpmfwupgComponentBitMask components,struct HpmfwupgUpgradeCtx * pFwupgCtx,unsigned char ** pImagePtr,struct ipmi_intf * intf,int option,int * pFlagColdReset)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, count);
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
HpmfwupgActivationStage(struct ipmi_intf * intf,struct HpmfwupgUpgradeCtx * pFwupgCtx)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
HpmfwupgGetBufferFromFile(char * imageFilename,struct HpmfwupgUpgradeCtx * pFwupgCtx)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
HpmfwupgGetDeviceId(struct ipmi_intf * intf,struct ipm_devid_rsp * pGetDevId)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
HpmfwupgGetTargetUpgCapabilities(struct ipmi_intf * intf,struct HpmfwupgGetTargetUpgCapabilitiesCtx * pCtx)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
HpmfwupgGetComponentProperties(struct ipmi_intf * intf,struct HpmfwupgGetComponentPropertiesCtx * pCtx)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
HpmfwupgAbortUpgrade(struct ipmi_intf * intf,struct HpmfwupgAbortUpgradeCtx * pCtx)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
HpmfwupgInitiateUpgradeAction(struct ipmi_intf * intf,struct HpmfwupgInitiateUpgradeActionCtx * pCtx,struct HpmfwupgUpgradeCtx * pFwupgCtx)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
HpmfwupgUploadFirmwareBlock(struct ipmi_intf * intf,struct HpmfwupgUploadFirmwareBlockCtx * pCtx,struct HpmfwupgUpgradeCtx * pFwupgCtx,int count,unsigned int * imageOffset,unsigned int * blockLength)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
HpmfwupgFinishFirmwareUpload(struct ipmi_intf * intf,struct HpmfwupgFinishFirmwareUploadCtx * pCtx,struct HpmfwupgUpgradeCtx * pFwupgCtx,int option)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
HpmfwupgActivateFirmware(struct ipmi_intf * intf,struct HpmfwupgActivateFirmwareCtx * pCtx,struct HpmfwupgUpgradeCtx * pFwupgCtx)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
HpmfwupgGetUpgradeStatus(struct ipmi_intf * intf,struct HpmfwupgGetUpgradeStatusCtx * pCtx,struct HpmfwupgUpgradeCtx * pFwupgCtx,int silent)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
HpmfwupgManualFirmwareRollback(struct ipmi_intf * intf,struct HpmfwupgManualFirmwareRollbackCtx * pCtx)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
HpmfwupgQueryRollbackStatus(struct ipmi_intf * intf,struct HpmfwupgQueryRollbackStatusCtx * pCtx,struct HpmfwupgUpgradeCtx * pFwupgCtx)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
HpmfwupgQuerySelftestResult(struct ipmi_intf * intf,struct HpmfwupgQuerySelftestResultCtx * pCtx,struct HpmfwupgUpgradeCtx * pFwupgCtx)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 *
HpmfwupgSendCmd(struct ipmi_intf * intf,struct ipmi_rq req,struct HpmfwupgUpgradeCtx * pFwupgCtx)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->abort = 1;
2198 intf->close(intf);
2199
2200 while (intf->open(intf) == HPMFWUPG_ERROR
2201 && inaccessTimeoutCounter < inaccessTimeout) {
2202 inaccessTimeoutCounter += (time(NULL) - timeoutSec1);
2203 timeoutSec1 = time(NULL);
2204 }
2205
2206 /* Fake timeout to retry command */
2207 fakeRsp.ccode = 0xc3;
2208 rsp = &fakeRsp;
2209 }
2210 }
2211 }
2212 }
2213 /* Handle inaccessibility timeout (rsp = NULL if IOL) */
2214 if (rsp == NULL || rsp->ccode == 0xff || rsp->ccode == 0xc3 || rsp->ccode == 0xd3) {
2215 if (inaccessTimeoutCounter < inaccessTimeout) {
2216 timeoutSec2 = time(NULL);
2217 if (timeoutSec2 > timeoutSec1) {
2218 inaccessTimeoutCounter += timeoutSec2 - timeoutSec1;
2219 timeoutSec1 = time(NULL);
2220 }
2221 usleep(100000);
2222 retry = 1;
2223 } else {
2224 retry = 0;
2225 }
2226 } else if ( rsp->ccode == 0xc0 ) {
2227 /* Handle node busy timeout */
2228 if (upgradeTimeoutCounter < upgradeTimeout) {
2229 timeoutSec2 = time(NULL);
2230 if (timeoutSec2 > timeoutSec1) {
2231 timeoutSec1 = time(NULL);
2232 upgradeTimeoutCounter += timeoutSec2 - timeoutSec1;
2233 }
2234 usleep(100000);
2235 retry = 1;
2236 } else {
2237 retry = 0;
2238 }
2239 } else {
2240 # ifdef ENABLE_OPENIPMI_V39_PATCH
2241 if (rsp->ccode == IPMI_CC_OK) {
2242 errorCount = 0 ;
2243 }
2244 # endif
2245 retry = 0;
2246 if (req.msg.netfn == IPMI_NETFN_PICMG
2247 && req.msg.cmd == HPMFWUPG_UPLOAD_FIRMWARE_BLOCK
2248 && (!isValidSize)) {
2249 lprintf(LOG_INFO,
2250 "Buffer length is now considered valid");
2251 isValidSize = TRUE;
2252 }
2253 }
2254 } while (retry);
2255 return rsp;
2256 }
2257
2258 int
HpmfwupgWaitLongDurationCmd(struct ipmi_intf * intf,struct HpmfwupgUpgradeCtx * pFwupgCtx)2259 HpmfwupgWaitLongDurationCmd(struct ipmi_intf *intf,
2260 struct HpmfwupgUpgradeCtx *pFwupgCtx)
2261 {
2262 int rc = HPMFWUPG_SUCCESS;
2263 unsigned int upgradeTimeout = 0;
2264 unsigned int timeoutSec1, timeoutSec2;
2265 struct HpmfwupgGetUpgradeStatusCtx upgStatusCmd;
2266 /* If we are not in upgrade context, we use default timeout values */
2267 if (pFwupgCtx != NULL) {
2268 upgradeTimeout = (unsigned int)(pFwupgCtx->targetCap.upgradeTimeout*5);
2269 if (verbose) {
2270 printf("Use File Upgrade Capabilities: %i seconds\n",
2271 upgradeTimeout);
2272 }
2273 } else {
2274 /* Try to retreive from Caps */
2275 struct HpmfwupgGetTargetUpgCapabilitiesCtx targetCapCmd;
2276 if(HpmfwupgGetTargetUpgCapabilities(intf, &targetCapCmd) != HPMFWUPG_SUCCESS) {
2277 upgradeTimeout = HPMFWUPG_DEFAULT_UPGRADE_TIMEOUT;
2278 if (verbose) {
2279 printf("Use default timeout: %i seconds\n",
2280 upgradeTimeout);
2281 }
2282 } else {
2283 upgradeTimeout = (unsigned int)(targetCapCmd.resp.upgradeTimeout * 5);
2284 if (verbose) {
2285 printf("Use Command Upgrade Capabilities Timeout: %i seconds\n",
2286 upgradeTimeout);
2287 }
2288 }
2289 }
2290 if (rc == HPMFWUPG_SUCCESS) {
2291 /* Poll upgrade status until completion or timeout*/
2292 timeoutSec1 = time(NULL);
2293 timeoutSec2 = time(NULL);
2294 rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd,
2295 pFwupgCtx, 1);
2296 }
2297 while (
2298 /* With KCS: Cover the case where we sometime
2299 * receive d5 (on the first get status) from
2300 * the ipmi driver.
2301 */
2302 (upgStatusCmd.resp.lastCmdCompCode == 0x80 ||
2303 upgStatusCmd.resp.lastCmdCompCode == 0xD5)
2304 && ((timeoutSec2 - timeoutSec1) < upgradeTimeout )
2305 && (rc == HPMFWUPG_SUCCESS)) {
2306 /* Must wait at least 1000 ms between status requests */
2307 usleep(1000000);
2308 timeoutSec2 = time(NULL);
2309 rc = HpmfwupgGetUpgradeStatus(intf, &upgStatusCmd, pFwupgCtx, 1);
2310 /*
2311 * printf("Get Status: %x - %x = %x _ %x [%x]\n",
2312 ( timeoutSec2, timeoutSec1,
2313 * (timeoutSec2 - timeoutSec1),
2314 * upgradeTimeout, rc);
2315 */
2316 }
2317 if (upgStatusCmd.resp.lastCmdCompCode != 0x00) {
2318 if (verbose) {
2319 lprintf(LOG_NOTICE,
2320 "Error waiting for command %x, compcode = %x",
2321 upgStatusCmd.resp.cmdInProcess,
2322 upgStatusCmd.resp.lastCmdCompCode);
2323 }
2324 rc = HPMFWUPG_ERROR;
2325 }
2326 return rc;
2327 }
2328
2329 unsigned char
HpmfwupgCalculateChecksum(unsigned char * pData,unsigned int length)2330 HpmfwupgCalculateChecksum(unsigned char *pData, unsigned int length)
2331 {
2332 unsigned char checksum = 0;
2333 int dataIdx = 0;
2334 for (dataIdx = 0; dataIdx < length; dataIdx++) {
2335 checksum += pData[dataIdx];
2336 }
2337 return checksum;
2338 }
2339
2340 void
HpmfwupgPrintUsage(void)2341 HpmfwupgPrintUsage(void)
2342 {
2343 lprintf(LOG_NOTICE,
2344 "help - This help menu.");
2345 lprintf(LOG_NOTICE,
2346 "");
2347 lprintf(LOG_NOTICE,
2348 "check - Check the target information.");
2349 lprintf(LOG_NOTICE,
2350 "check <file> - If the user is unsure of what update is going to be ");
2351 lprintf(LOG_NOTICE,
2352 " This will display the existing target version and");
2353 lprintf(LOG_NOTICE,
2354 " image version on the screen");
2355 lprintf(LOG_NOTICE,
2356 "");
2357 lprintf(LOG_NOTICE,
2358 "upgrade <file> [component x...] [force] [activate]");
2359 lprintf(LOG_NOTICE,
2360 " - Copies components from a valid HPM.1 image to the target.");
2361 lprintf(LOG_NOTICE,
2362 " If one or more components specified by \"component\",");
2363 lprintf(LOG_NOTICE,
2364 " only the specified components are copied.");
2365 lprintf(LOG_NOTICE,
2366 " Otherwise, all the image components are copied.");
2367 lprintf(LOG_NOTICE,
2368 " Before copy, each image component undergoes a version check");
2369 lprintf(LOG_NOTICE,
2370 " and can be skipped if the target component version");
2371 lprintf(LOG_NOTICE,
2372 " is the same or more recent.");
2373 lprintf(LOG_NOTICE,
2374 " Use \"force\" to bypass the version check results.");
2375 lprintf(LOG_NOTICE,
2376 " Make sure to check the versions first using the");
2377 lprintf(LOG_NOTICE,
2378 " \"check <file>\" command.");
2379 lprintf(LOG_NOTICE,
2380 " If \"activate\" is specified, the newly uploaded firmware");
2381 lprintf(LOG_NOTICE,
2382 " is activated.");
2383 lprintf(LOG_NOTICE,
2384 "upgstatus - Returns the status of the last long duration command.");
2385 lprintf(LOG_NOTICE,
2386 "");
2387 lprintf(LOG_NOTICE,
2388 "compare <file> - Perform \"Comparison of the Active Copy\" action for all the");
2389 lprintf(LOG_NOTICE,
2390 " components present in the file.");
2391 lprintf(LOG_NOTICE,
2392 "compare <file> component x - Compare only component <x> from the given <file>");
2393 lprintf(LOG_NOTICE,
2394 "activate - Activate the newly uploaded firmware.");
2395 lprintf(LOG_NOTICE,
2396 "activate norollback - Activate the newly uploaded firmware but inform");
2397 lprintf(LOG_NOTICE,
2398 " the target to not automatically rollback if ");
2399 lprintf(LOG_NOTICE,
2400 " the upgrade fails.");
2401 lprintf(LOG_NOTICE,
2402 "");
2403 lprintf(LOG_NOTICE,
2404 "targetcap - Get the target upgrade capabilities.");
2405 lprintf(LOG_NOTICE,
2406 "");
2407 lprintf(LOG_NOTICE,
2408 "compprop <id> <prop> - Get specified component properties from the target.");
2409 lprintf(LOG_NOTICE,
2410 " Valid component <id>: 0-7 ");
2411 lprintf(LOG_NOTICE,
2412 " Properties <prop> can be one of the following: ");
2413 lprintf(LOG_NOTICE,
2414 " 0- General properties");
2415 lprintf(LOG_NOTICE,
2416 " 1- Current firmware version");
2417 lprintf(LOG_NOTICE,
2418 " 2- Description string");
2419 lprintf(LOG_NOTICE,
2420 " 3- Rollback firmware version");
2421 lprintf(LOG_NOTICE,
2422 " 4- Deferred firmware version");
2423 lprintf(LOG_NOTICE,
2424 "");
2425 lprintf(LOG_NOTICE,
2426 "abort - Abort the on-going firmware upgrade.");
2427 lprintf(LOG_NOTICE,
2428 "");
2429 lprintf(LOG_NOTICE,
2430 "rollback - Performs a manual rollback on the IPM Controller.");
2431 lprintf(LOG_NOTICE,
2432 " firmware");
2433 lprintf(LOG_NOTICE,
2434 "rollbackstatus - Query the rollback status.");
2435 lprintf(LOG_NOTICE,
2436 "");
2437 lprintf(LOG_NOTICE,
2438 "selftestresult - Query the self test results.\n");
2439 }
2440
2441 int
ipmi_hpmfwupg_main(struct ipmi_intf * intf,int argc,char ** argv)2442 ipmi_hpmfwupg_main(struct ipmi_intf *intf, int argc, char **argv)
2443 {
2444 int rc = HPMFWUPG_SUCCESS;
2445 int activateFlag = 0x00;
2446 int componentMask = 0;
2447 int componentId = 0;
2448 int option = 0;
2449
2450 lprintf(LOG_DEBUG,"ipmi_hpmfwupg_main()");
2451 lprintf(LOG_NOTICE, "\nPICMG HPM.1 Upgrade Agent %d.%d.%d: \n",
2452 HPMFWUPG_VERSION_MAJOR, HPMFWUPG_VERSION_MINOR,
2453 HPMFWUPG_VERSION_SUBMINOR);
2454 if (argc < 1) {
2455 lprintf(LOG_ERR, "Not enough parameters given.");
2456 HpmfwupgPrintUsage();
2457 return HPMFWUPG_ERROR;
2458 }
2459 if (strcmp(argv[0], "help") == 0) {
2460 HpmfwupgPrintUsage();
2461 return HPMFWUPG_SUCCESS;
2462 } else if ((strcmp(argv[0], "check") == 0)) {
2463 /* hpm check */
2464 if (argv[1] == NULL) {
2465 rc = HpmfwupgTargetCheck(intf,VIEW_MODE);
2466 } else {
2467 /* hpm check <filename> */
2468 rc = HpmfwupgTargetCheck(intf,0);
2469 if (rc == HPMFWUPG_SUCCESS) {
2470 rc = HpmfwupgUpgrade(intf, argv[1], 0,
2471 0, VIEW_MODE);
2472 }
2473 }
2474 } else if (strcmp(argv[0], "upgrade") == 0) {
2475 int i =0;
2476 for (i=1; i< argc ; i++) {
2477 if (strcmp(argv[i],"activate") == 0) {
2478 activateFlag = 1;
2479 }
2480 /* hpm upgrade <filename> force */
2481 if (strcmp(argv[i],"force") == 0) {
2482 option |= FORCE_MODE;
2483 }
2484 /* hpm upgrade <filename> component <comp Id> */
2485 if (strcmp(argv[i],"component") == 0) {
2486 if (i+1 < argc) {
2487 /* Error Checking */
2488 if (str2int(argv[i+1], &componentId) != 0
2489 || componentId < 0
2490 || componentId > HPMFWUPG_COMPONENT_ID_MAX) {
2491 lprintf(LOG_ERR,
2492 "Given Component ID '%s' is invalid.",
2493 argv[i+1]);
2494 lprintf(LOG_ERR,
2495 "Valid Compoment ID is: <0..7>");
2496 return HPMFWUPG_ERROR;
2497 }
2498 if( verbose ) {
2499 lprintf(LOG_NOTICE,
2500 "Component Id %d provided",
2501 componentId );
2502 }
2503 componentMask |= 1 << componentId;
2504 } else {
2505 /* That indicates the user has
2506 * given component on console but
2507 * not given any ID
2508 */
2509 lprintf(LOG_NOTICE,
2510 "No component Id provided\n");
2511 return HPMFWUPG_ERROR;
2512 }
2513 }
2514 if (strcmp(argv[i],"debug") == 0) {
2515 option |= DEBUG_MODE;
2516 }
2517 }
2518 rc = HpmfwupgTargetCheck(intf, 0);
2519 if (rc == HPMFWUPG_SUCCESS) {
2520 /* Call the Upgrade function to start the upgrade */
2521 rc = HpmfwupgUpgrade(intf, argv[1], activateFlag,
2522 componentMask, option);
2523 }
2524 } else if (strcmp(argv[0], "compare") == 0) {
2525 int i = 0;
2526 for (i=1; i< argc; i++) {
2527 /* hpm compare <file> [component x...] */
2528 if (strcmp(argv[i],"component") == 0) {
2529 if (i+1 < argc) {
2530 /* Error Checking */
2531 if (str2int(argv[i+1], &componentId) != 0
2532 || componentId < 0
2533 || componentId > HPMFWUPG_COMPONENT_ID_MAX) {
2534 lprintf(LOG_ERR,
2535 "Given Component ID '%s' is invalid.",
2536 argv[i+1]);
2537 lprintf(LOG_ERR,
2538 "Valid Compoment ID is: <0..7>");
2539 return HPMFWUPG_ERROR;
2540 }
2541 if( verbose ) {
2542 lprintf(LOG_NOTICE,
2543 "Component Id %d provided",
2544 componentId);
2545 }
2546 componentMask|= 1 << componentId;
2547 } else {
2548 /* That indicates the user
2549 * has given component on
2550 * console but not
2551 * given any ID
2552 */
2553 lprintf(LOG_NOTICE,
2554 "No component Id provided\n");
2555 return HPMFWUPG_ERROR;
2556 }
2557 } else if (strcmp(argv[i],"debug") == 0) {
2558 option|= DEBUG_MODE;
2559 }
2560 }
2561 option|= (COMPARE_MODE);
2562 rc = HpmfwupgTargetCheck(intf, 0);
2563 if (rc == HPMFWUPG_SUCCESS) {
2564 rc = HpmfwupgUpgrade(intf, argv[1], 0,
2565 componentMask, option);
2566 }
2567 } else if ((argc >= 1) && (strcmp(argv[0], "activate") == 0)) {
2568 struct HpmfwupgActivateFirmwareCtx cmdCtx;
2569 if ((argc == 2) && (strcmp(argv[1], "norollback") == 0)) {
2570 cmdCtx.req.rollback_override = 1;
2571 } else {
2572 cmdCtx.req.rollback_override = 0;
2573 }
2574 rc = HpmfwupgActivateFirmware(intf, &cmdCtx, NULL);
2575 } else if ((argc == 1) && (strcmp(argv[0], "targetcap") == 0)) {
2576 struct HpmfwupgGetTargetUpgCapabilitiesCtx cmdCtx;
2577 verbose++;
2578 rc = HpmfwupgGetTargetUpgCapabilities(intf, &cmdCtx);
2579 } else if ((argc == 3) && (strcmp(argv[0], "compprop") == 0)) {
2580 struct HpmfwupgGetComponentPropertiesCtx cmdCtx;
2581 if (str2uchar(argv[1], &(cmdCtx.req.componentId)) != 0
2582 || cmdCtx.req.componentId > 7) {
2583 lprintf(LOG_ERR,
2584 "Given Component ID '%s' is invalid.",
2585 argv[1]);
2586 lprintf(LOG_ERR,
2587 "Valid Compoment ID is: <0..7>");
2588 return (-1);
2589 }
2590 if (str2uchar(argv[2], &(cmdCtx.req.selector)) != 0
2591 || cmdCtx.req.selector > 4) {
2592 lprintf(LOG_ERR,
2593 "Given Properties selector '%s' is invalid.",
2594 argv[2]);
2595 lprintf(LOG_ERR,
2596 "Valid Properties selector is: <0..4>");
2597 return (-1);
2598 }
2599 verbose++;
2600 rc = HpmfwupgGetComponentProperties(intf, &cmdCtx);
2601 } else if ((argc == 1) && (strcmp(argv[0], "abort") == 0)) {
2602 struct HpmfwupgAbortUpgradeCtx cmdCtx;
2603 verbose++;
2604 rc = HpmfwupgAbortUpgrade(intf, &cmdCtx);
2605 } else if ((argc == 1) && (strcmp(argv[0], "upgstatus") == 0)) {
2606 struct HpmfwupgGetUpgradeStatusCtx cmdCtx;
2607 verbose++;
2608 rc = HpmfwupgGetUpgradeStatus(intf, &cmdCtx, NULL, 0);
2609 } else if ((argc == 1) && (strcmp(argv[0], "rollback") == 0)) {
2610 struct HpmfwupgManualFirmwareRollbackCtx cmdCtx;
2611 verbose++;
2612 rc = HpmfwupgManualFirmwareRollback(intf, &cmdCtx);
2613 } else if ((argc == 1) && (strcmp(argv[0], "rollbackstatus") == 0)) {
2614 struct HpmfwupgQueryRollbackStatusCtx cmdCtx;
2615 verbose++;
2616 rc = HpmfwupgQueryRollbackStatus(intf, &cmdCtx, NULL);
2617 } else if ((argc == 1) && (strcmp(argv[0], "selftestresult") == 0)) {
2618 struct HpmfwupgQuerySelftestResultCtx cmdCtx;
2619 verbose++;
2620 rc = HpmfwupgQuerySelftestResult(intf, &cmdCtx, NULL);
2621 } else {
2622 lprintf(LOG_ERR, "Invalid HPM command: %s", argv[0]);
2623 HpmfwupgPrintUsage();
2624 rc = HPMFWUPG_ERROR;
2625 }
2626 return rc;
2627 }
2628
2629