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