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