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