1c18ec02fSPetter Reinholdtsen /*
2c18ec02fSPetter Reinholdtsen * Copyright (c) 2004 Kontron Canada, Inc. All Rights Reserved.
3c18ec02fSPetter Reinholdtsen *
4c18ec02fSPetter Reinholdtsen * Base on code from
5c18ec02fSPetter Reinholdtsen * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
6c18ec02fSPetter Reinholdtsen *
7c18ec02fSPetter Reinholdtsen * Redistribution and use in source and binary forms, with or without
8c18ec02fSPetter Reinholdtsen * modification, are permitted provided that the following conditions
9c18ec02fSPetter Reinholdtsen * are met:
10c18ec02fSPetter Reinholdtsen *
11c18ec02fSPetter Reinholdtsen * Redistribution of source code must retain the above copyright
12c18ec02fSPetter Reinholdtsen * notice, this list of conditions and the following disclaimer.
13c18ec02fSPetter Reinholdtsen *
14c18ec02fSPetter Reinholdtsen * Redistribution in binary form must reproduce the above copyright
15c18ec02fSPetter Reinholdtsen * notice, this list of conditions and the following disclaimer in the
16c18ec02fSPetter Reinholdtsen * documentation and/or other materials provided with the distribution.
17c18ec02fSPetter Reinholdtsen *
18c18ec02fSPetter Reinholdtsen * Neither the name of Sun Microsystems, Inc. or the names of
19c18ec02fSPetter Reinholdtsen * contributors may be used to endorse or promote products derived
20c18ec02fSPetter Reinholdtsen * from this software without specific prior written permission.
21c18ec02fSPetter Reinholdtsen *
22c18ec02fSPetter Reinholdtsen * This software is provided "AS IS," without a warranty of any kind.
23c18ec02fSPetter Reinholdtsen * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
24c18ec02fSPetter Reinholdtsen * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
25c18ec02fSPetter Reinholdtsen * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
26c18ec02fSPetter Reinholdtsen * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
27c18ec02fSPetter Reinholdtsen * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
28c18ec02fSPetter Reinholdtsen * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
29c18ec02fSPetter Reinholdtsen * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
30c18ec02fSPetter Reinholdtsen * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
31c18ec02fSPetter Reinholdtsen * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
32c18ec02fSPetter Reinholdtsen * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
33c18ec02fSPetter Reinholdtsen * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34c18ec02fSPetter Reinholdtsen */
35c18ec02fSPetter Reinholdtsen
36c18ec02fSPetter Reinholdtsen #include <string.h>
37c18ec02fSPetter Reinholdtsen #include <math.h>
38c18ec02fSPetter Reinholdtsen #include <time.h>
39c18ec02fSPetter Reinholdtsen #include <unistd.h>
40c18ec02fSPetter Reinholdtsen
41c18ec02fSPetter Reinholdtsen #include <ipmitool/log.h>
42c18ec02fSPetter Reinholdtsen #include <ipmitool/helper.h>
43c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi.h>
44c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_fwum.h>
45c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_intf.h>
46c18ec02fSPetter Reinholdtsen #include <ipmitool/ipmi_mc.h>
47c18ec02fSPetter Reinholdtsen
48c18ec02fSPetter Reinholdtsen extern int verbose;
49c18ec02fSPetter Reinholdtsen unsigned char firmBuf[1024*512];
50c18ec02fSPetter Reinholdtsen tKFWUM_SaveFirmwareInfo save_fw_nfo;
51c18ec02fSPetter Reinholdtsen
52c18ec02fSPetter Reinholdtsen int KfwumGetFileSize(const char *pFileName,
53c18ec02fSPetter Reinholdtsen unsigned long *pFileSize);
54c18ec02fSPetter Reinholdtsen int KfwumSetupBuffersFromFile(const char *pFileName,
55c18ec02fSPetter Reinholdtsen unsigned long fileSize);
56c18ec02fSPetter Reinholdtsen void KfwumShowProgress(const char *task, unsigned long current,
57c18ec02fSPetter Reinholdtsen unsigned long total);
58c18ec02fSPetter Reinholdtsen unsigned short KfwumCalculateChecksumPadding(unsigned char *pBuffer,
59c18ec02fSPetter Reinholdtsen unsigned long totalSize);
60c18ec02fSPetter Reinholdtsen int KfwumGetInfo(struct ipmi_intf *intf, unsigned char output,
61c18ec02fSPetter Reinholdtsen unsigned char *pNumBank);
62c18ec02fSPetter Reinholdtsen int KfwumGetDeviceInfo(struct ipmi_intf *intf,
63c18ec02fSPetter Reinholdtsen unsigned char output, tKFWUM_BoardInfo *pBoardInfo);
64c18ec02fSPetter Reinholdtsen int KfwumGetStatus(struct ipmi_intf *intf);
65c18ec02fSPetter Reinholdtsen int KfwumManualRollback(struct ipmi_intf *intf);
66c18ec02fSPetter Reinholdtsen int KfwumStartFirmwareImage(struct ipmi_intf *intf,
67c18ec02fSPetter Reinholdtsen unsigned long length, unsigned short padding);
68c18ec02fSPetter Reinholdtsen int KfwumSaveFirmwareImage(struct ipmi_intf *intf,
69c18ec02fSPetter Reinholdtsen unsigned char sequenceNumber, unsigned long address,
70c18ec02fSPetter Reinholdtsen unsigned char *pFirmBuf, unsigned char *pInBufLength);
71c18ec02fSPetter Reinholdtsen int KfwumFinishFirmwareImage(struct ipmi_intf *intf,
72c18ec02fSPetter Reinholdtsen tKFWUM_InFirmwareInfo firmInfo);
73c18ec02fSPetter Reinholdtsen int KfwumUploadFirmware(struct ipmi_intf *intf,
74c18ec02fSPetter Reinholdtsen unsigned char *pBuffer, unsigned long totalSize);
75c18ec02fSPetter Reinholdtsen int KfwumStartFirmwareUpgrade(struct ipmi_intf *intf);
76c18ec02fSPetter Reinholdtsen int KfwumGetInfoFromFirmware(unsigned char *pBuf,
77c18ec02fSPetter Reinholdtsen unsigned long bufSize, tKFWUM_InFirmwareInfo *pInfo);
78c18ec02fSPetter Reinholdtsen void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo *pInfo);
79c18ec02fSPetter Reinholdtsen int KfwumGetTraceLog(struct ipmi_intf *intf);
80c18ec02fSPetter Reinholdtsen int ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo,
81c18ec02fSPetter Reinholdtsen tKFWUM_InFirmwareInfo firmInfo);
82c18ec02fSPetter Reinholdtsen
83c18ec02fSPetter Reinholdtsen int ipmi_fwum_fwupgrade(struct ipmi_intf *intf, char *file, int action);
84c18ec02fSPetter Reinholdtsen int ipmi_fwum_info(struct ipmi_intf *intf);
85c18ec02fSPetter Reinholdtsen int ipmi_fwum_status(struct ipmi_intf *intf);
86c18ec02fSPetter Reinholdtsen void printf_kfwum_help(void);
87c18ec02fSPetter Reinholdtsen void printf_kfwum_info(tKFWUM_BoardInfo boardInfo,
88c18ec02fSPetter Reinholdtsen tKFWUM_InFirmwareInfo firmInfo);
89c18ec02fSPetter Reinholdtsen
90c18ec02fSPetter Reinholdtsen /* String table */
91c18ec02fSPetter Reinholdtsen /* Must match eFWUM_CmdId */
92c18ec02fSPetter Reinholdtsen const char *CMD_ID_STRING[] = {
93c18ec02fSPetter Reinholdtsen "GetFwInfo",
94c18ec02fSPetter Reinholdtsen "KickWatchdog",
95c18ec02fSPetter Reinholdtsen "GetLastAnswer",
96c18ec02fSPetter Reinholdtsen "BootHandshake",
97c18ec02fSPetter Reinholdtsen "ReportStatus",
98c18ec02fSPetter Reinholdtsen "CtrlIPMBLine",
99c18ec02fSPetter Reinholdtsen "SetFwState",
100c18ec02fSPetter Reinholdtsen "GetFwStatus",
101c18ec02fSPetter Reinholdtsen "GetSpiMemStatus",
102c18ec02fSPetter Reinholdtsen "StartFwUpdate",
103c18ec02fSPetter Reinholdtsen "StartFwImage",
104c18ec02fSPetter Reinholdtsen "SaveFwImage",
105c18ec02fSPetter Reinholdtsen "FinishFwImage",
106c18ec02fSPetter Reinholdtsen "ReadFwImage",
107c18ec02fSPetter Reinholdtsen "ManualRollback",
108c18ec02fSPetter Reinholdtsen "GetTraceLog"
109c18ec02fSPetter Reinholdtsen };
110c18ec02fSPetter Reinholdtsen
111c18ec02fSPetter Reinholdtsen const char *EXT_CMD_ID_STRING[] = {
112c18ec02fSPetter Reinholdtsen "FwUpgradeLock",
113c18ec02fSPetter Reinholdtsen "ProcessFwUpg",
114c18ec02fSPetter Reinholdtsen "ProcessFwRb",
115c18ec02fSPetter Reinholdtsen "WaitHSAfterUpg",
116c18ec02fSPetter Reinholdtsen "WaitFirstHSUpg",
117c18ec02fSPetter Reinholdtsen "FwInfoStateChange"
118c18ec02fSPetter Reinholdtsen };
119c18ec02fSPetter Reinholdtsen
120c18ec02fSPetter Reinholdtsen const char *CMD_STATE_STRING[] = {
121c18ec02fSPetter Reinholdtsen "Invalid",
122c18ec02fSPetter Reinholdtsen "Begin",
123c18ec02fSPetter Reinholdtsen "Progress",
124c18ec02fSPetter Reinholdtsen "Completed"
125c18ec02fSPetter Reinholdtsen };
126c18ec02fSPetter Reinholdtsen
127c18ec02fSPetter Reinholdtsen const struct valstr bankStateValS[] = {
128c18ec02fSPetter Reinholdtsen { 0x00, "Not programmed" },
129c18ec02fSPetter Reinholdtsen { 0x01, "New firmware" },
130c18ec02fSPetter Reinholdtsen { 0x02, "Wait for validation" },
131c18ec02fSPetter Reinholdtsen { 0x03, "Last Known Good" },
132c18ec02fSPetter Reinholdtsen { 0x04, "Previous Good" }
133c18ec02fSPetter Reinholdtsen };
134c18ec02fSPetter Reinholdtsen
135c18ec02fSPetter Reinholdtsen /* ipmi_fwum_main - entry point for this ipmitool mode
136c18ec02fSPetter Reinholdtsen *
137c18ec02fSPetter Reinholdtsen * @intf: ipmi interface
138c18ec02fSPetter Reinholdtsen * @arc: number of arguments
139c18ec02fSPetter Reinholdtsen * @argv: point to argument array
140c18ec02fSPetter Reinholdtsen *
141c18ec02fSPetter Reinholdtsen * returns 0 on success
142c18ec02fSPetter Reinholdtsen * returns -1 on error
143c18ec02fSPetter Reinholdtsen */
144c18ec02fSPetter Reinholdtsen int
ipmi_fwum_main(struct ipmi_intf * intf,int argc,char ** argv)145c18ec02fSPetter Reinholdtsen ipmi_fwum_main(struct ipmi_intf *intf, int argc, char **argv)
146c18ec02fSPetter Reinholdtsen {
147c18ec02fSPetter Reinholdtsen int rc = 0;
148c18ec02fSPetter Reinholdtsen printf("FWUM extension Version %d.%d\n", VER_MAJOR, VER_MINOR);
149c18ec02fSPetter Reinholdtsen if (argc < 1) {
150c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Not enough parameters given.");
151c18ec02fSPetter Reinholdtsen printf_kfwum_help();
152c18ec02fSPetter Reinholdtsen return (-1);
153c18ec02fSPetter Reinholdtsen }
154c18ec02fSPetter Reinholdtsen if (strncmp(argv[0], "help", 4) == 0) {
155c18ec02fSPetter Reinholdtsen printf_kfwum_help();
156c18ec02fSPetter Reinholdtsen rc = 0;
157c18ec02fSPetter Reinholdtsen } else if (strncmp(argv[0], "info", 4) == 0) {
158c18ec02fSPetter Reinholdtsen rc = ipmi_fwum_info(intf);
159c18ec02fSPetter Reinholdtsen } else if (strncmp(argv[0], "status", 6) == 0) {
160c18ec02fSPetter Reinholdtsen rc = ipmi_fwum_status(intf);
161c18ec02fSPetter Reinholdtsen } else if (strncmp(argv[0], "rollback", 8) == 0) {
162c18ec02fSPetter Reinholdtsen rc = KfwumManualRollback(intf);
163c18ec02fSPetter Reinholdtsen } else if (strncmp(argv[0], "download", 8) == 0) {
164c18ec02fSPetter Reinholdtsen if ((argc < 2) || (strlen(argv[1]) < 1)) {
165c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
166c18ec02fSPetter Reinholdtsen "Path and file name must be specified.");
167c18ec02fSPetter Reinholdtsen return (-1);
168c18ec02fSPetter Reinholdtsen }
169c18ec02fSPetter Reinholdtsen printf("Firmware File Name : %s\n", argv[1]);
170c18ec02fSPetter Reinholdtsen rc = ipmi_fwum_fwupgrade(intf, argv[1], 0);
171c18ec02fSPetter Reinholdtsen } else if (strncmp(argv[0], "upgrade", 7) == 0) {
172c18ec02fSPetter Reinholdtsen if ((argc >= 2) && (strlen(argv[1]) > 0)) {
173c18ec02fSPetter Reinholdtsen printf("Upgrading using file name %s\n", argv[1]);
174c18ec02fSPetter Reinholdtsen rc = ipmi_fwum_fwupgrade(intf, argv[1], 1);
175c18ec02fSPetter Reinholdtsen } else {
176c18ec02fSPetter Reinholdtsen rc = KfwumStartFirmwareUpgrade(intf);
177c18ec02fSPetter Reinholdtsen }
178c18ec02fSPetter Reinholdtsen } else if (strncmp(argv[0], "tracelog", 8) == 0) {
179c18ec02fSPetter Reinholdtsen rc = KfwumGetTraceLog(intf);
180c18ec02fSPetter Reinholdtsen } else {
181c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Invalid KFWUM command: %s", argv[0]);
182c18ec02fSPetter Reinholdtsen printf_kfwum_help();
183c18ec02fSPetter Reinholdtsen rc = (-1);
184c18ec02fSPetter Reinholdtsen }
185c18ec02fSPetter Reinholdtsen return rc;
186c18ec02fSPetter Reinholdtsen }
187c18ec02fSPetter Reinholdtsen
188c18ec02fSPetter Reinholdtsen void
printf_kfwum_help(void)189c18ec02fSPetter Reinholdtsen printf_kfwum_help(void)
190c18ec02fSPetter Reinholdtsen {
191c18ec02fSPetter Reinholdtsen lprintf(LOG_NOTICE,
192c18ec02fSPetter Reinholdtsen "KFWUM Commands: info status download upgrade rollback tracelog");
193c18ec02fSPetter Reinholdtsen }
194c18ec02fSPetter Reinholdtsen
195c18ec02fSPetter Reinholdtsen /* private definitions and macros */
196c18ec02fSPetter Reinholdtsen typedef enum eFWUM_CmdId
197c18ec02fSPetter Reinholdtsen {
198c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_GET_FIRMWARE_INFO = 0,
199c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_KICK_IPMC_WATCHDOG = 1,
200c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_GET_LAST_ANSWER = 2,
201c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_BOOT_HANDSHAKE = 3,
202c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_REPORT_STATUS = 4,
203c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_GET_FIRMWARE_STATUS = 7,
204c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_START_FIRMWARE_UPDATE = 9,
205c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_START_FIRMWARE_IMAGE = 0x0a,
206c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE = 0x0b,
207c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE = 0x0c,
208c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_READ_FIRMWARE_IMAGE = 0x0d,
209c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_MANUAL_ROLLBACK = 0x0e,
210c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_GET_TRACE_LOG = 0x0f,
211c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_STD_MAX_CMD,
212c18ec02fSPetter Reinholdtsen KFWUM_CMD_ID_EXTENDED_CMD = 0xC0
213c18ec02fSPetter Reinholdtsen } tKFWUM_CmdId;
214c18ec02fSPetter Reinholdtsen
215c18ec02fSPetter Reinholdtsen int
ipmi_fwum_info(struct ipmi_intf * intf)216c18ec02fSPetter Reinholdtsen ipmi_fwum_info(struct ipmi_intf *intf)
217c18ec02fSPetter Reinholdtsen {
218c18ec02fSPetter Reinholdtsen tKFWUM_BoardInfo b_info;
219c18ec02fSPetter Reinholdtsen int rc = 0;
220c18ec02fSPetter Reinholdtsen unsigned char not_used;
221c18ec02fSPetter Reinholdtsen if (verbose) {
222c18ec02fSPetter Reinholdtsen printf("Getting Kontron FWUM Info\n");
223c18ec02fSPetter Reinholdtsen }
224c18ec02fSPetter Reinholdtsen if (KfwumGetDeviceInfo(intf, 1, &b_info) != 0) {
225c18ec02fSPetter Reinholdtsen rc = (-1);
226c18ec02fSPetter Reinholdtsen }
227c18ec02fSPetter Reinholdtsen if (KfwumGetInfo(intf, 1, ¬_used) != 0) {
228c18ec02fSPetter Reinholdtsen rc = (-1);
229c18ec02fSPetter Reinholdtsen }
230c18ec02fSPetter Reinholdtsen return rc;
231c18ec02fSPetter Reinholdtsen }
232c18ec02fSPetter Reinholdtsen
233c18ec02fSPetter Reinholdtsen int
ipmi_fwum_status(struct ipmi_intf * intf)234c18ec02fSPetter Reinholdtsen ipmi_fwum_status(struct ipmi_intf *intf)
235c18ec02fSPetter Reinholdtsen {
236c18ec02fSPetter Reinholdtsen if (verbose) {
237c18ec02fSPetter Reinholdtsen printf("Getting Kontron FWUM Status\n");
238c18ec02fSPetter Reinholdtsen }
239c18ec02fSPetter Reinholdtsen if (KfwumGetStatus(intf) != 0) {
240c18ec02fSPetter Reinholdtsen return (-1);
241c18ec02fSPetter Reinholdtsen }
242c18ec02fSPetter Reinholdtsen return 0;
243c18ec02fSPetter Reinholdtsen }
244c18ec02fSPetter Reinholdtsen
245c18ec02fSPetter Reinholdtsen /* ipmi_fwum_fwupgrade - function implements download/upload of the firmware
246c18ec02fSPetter Reinholdtsen * data received as parameters
247c18ec02fSPetter Reinholdtsen *
248c18ec02fSPetter Reinholdtsen * @file: fw file
249c18ec02fSPetter Reinholdtsen * @action: 0 = download, 1 = upload/start upload
250c18ec02fSPetter Reinholdtsen *
251c18ec02fSPetter Reinholdtsen * returns 0 on success, otherwise (-1)
252c18ec02fSPetter Reinholdtsen */
253c18ec02fSPetter Reinholdtsen int
ipmi_fwum_fwupgrade(struct ipmi_intf * intf,char * file,int action)254c18ec02fSPetter Reinholdtsen ipmi_fwum_fwupgrade(struct ipmi_intf *intf, char *file, int action)
255c18ec02fSPetter Reinholdtsen {
256c18ec02fSPetter Reinholdtsen tKFWUM_BoardInfo b_info;
257c18ec02fSPetter Reinholdtsen tKFWUM_InFirmwareInfo fw_info = { 0 };
258c18ec02fSPetter Reinholdtsen unsigned short padding;
259c18ec02fSPetter Reinholdtsen unsigned long fsize = 0;
260c18ec02fSPetter Reinholdtsen unsigned char not_used;
261c18ec02fSPetter Reinholdtsen if (file == NULL) {
262c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "No file given.");
263c18ec02fSPetter Reinholdtsen return (-1);
264c18ec02fSPetter Reinholdtsen }
265c18ec02fSPetter Reinholdtsen if (KfwumGetFileSize(file, &fsize) != 0) {
266c18ec02fSPetter Reinholdtsen return (-1);
267c18ec02fSPetter Reinholdtsen }
268c18ec02fSPetter Reinholdtsen if (KfwumSetupBuffersFromFile(file, fsize) != 0) {
269c18ec02fSPetter Reinholdtsen return (-1);
270c18ec02fSPetter Reinholdtsen }
271c18ec02fSPetter Reinholdtsen padding = KfwumCalculateChecksumPadding(firmBuf, fsize);
272c18ec02fSPetter Reinholdtsen if (KfwumGetInfoFromFirmware(firmBuf, fsize, &fw_info) != 0) {
273c18ec02fSPetter Reinholdtsen return (-1);
274c18ec02fSPetter Reinholdtsen }
275c18ec02fSPetter Reinholdtsen if (KfwumGetDeviceInfo(intf, 0, &b_info) != 0) {
276c18ec02fSPetter Reinholdtsen return (-1);
277c18ec02fSPetter Reinholdtsen }
278c18ec02fSPetter Reinholdtsen if (ipmi_kfwum_checkfwcompat(b_info, fw_info) != 0) {
279c18ec02fSPetter Reinholdtsen return (-1);
280c18ec02fSPetter Reinholdtsen }
281c18ec02fSPetter Reinholdtsen KfwumGetInfo(intf, 0, ¬_used);
282c18ec02fSPetter Reinholdtsen printf_kfwum_info(b_info, fw_info);
283c18ec02fSPetter Reinholdtsen if (KfwumStartFirmwareImage(intf, fsize, padding) != 0) {
284c18ec02fSPetter Reinholdtsen return (-1);
285c18ec02fSPetter Reinholdtsen }
286c18ec02fSPetter Reinholdtsen if (KfwumUploadFirmware(intf, firmBuf, fsize) != 0) {
287c18ec02fSPetter Reinholdtsen return (-1);
288c18ec02fSPetter Reinholdtsen }
289c18ec02fSPetter Reinholdtsen if (KfwumFinishFirmwareImage(intf, fw_info) != 0) {
290c18ec02fSPetter Reinholdtsen return (-1);
291c18ec02fSPetter Reinholdtsen }
292c18ec02fSPetter Reinholdtsen if (KfwumGetStatus(intf) != 0) {
293c18ec02fSPetter Reinholdtsen return (-1);
294c18ec02fSPetter Reinholdtsen }
295c18ec02fSPetter Reinholdtsen if (action != 0) {
296c18ec02fSPetter Reinholdtsen if (KfwumStartFirmwareUpgrade(intf) != 0) {
297c18ec02fSPetter Reinholdtsen return (-1);
298c18ec02fSPetter Reinholdtsen }
299c18ec02fSPetter Reinholdtsen }
300c18ec02fSPetter Reinholdtsen return 0;
301c18ec02fSPetter Reinholdtsen }
302c18ec02fSPetter Reinholdtsen
303c18ec02fSPetter Reinholdtsen /* KfwumGetFileSize - gets the file size
304c18ec02fSPetter Reinholdtsen *
305c18ec02fSPetter Reinholdtsen * @pFileName : filename ptr
306c18ec02fSPetter Reinholdtsen * @pFileSize : output ptr for filesize
307c18ec02fSPetter Reinholdtsen *
308c18ec02fSPetter Reinholdtsen * returns 0 on success, otherwise (-1)
309c18ec02fSPetter Reinholdtsen */
310c18ec02fSPetter Reinholdtsen int
KfwumGetFileSize(const char * pFileName,unsigned long * pFileSize)311c18ec02fSPetter Reinholdtsen KfwumGetFileSize(const char *pFileName, unsigned long *pFileSize)
312c18ec02fSPetter Reinholdtsen {
313c18ec02fSPetter Reinholdtsen FILE *pFileHandle = NULL;
314c18ec02fSPetter Reinholdtsen pFileHandle = fopen(pFileName, "rb");
315c18ec02fSPetter Reinholdtsen if (pFileHandle == NULL) {
316c18ec02fSPetter Reinholdtsen return (-1);
317c18ec02fSPetter Reinholdtsen }
318c18ec02fSPetter Reinholdtsen if (fseek(pFileHandle, 0L , SEEK_END) == 0) {
319c18ec02fSPetter Reinholdtsen *pFileSize = ftell(pFileHandle);
320c18ec02fSPetter Reinholdtsen }
321c18ec02fSPetter Reinholdtsen fclose(pFileHandle);
322c18ec02fSPetter Reinholdtsen if (*pFileSize != 0) {
323c18ec02fSPetter Reinholdtsen return 0;
324c18ec02fSPetter Reinholdtsen }
325c18ec02fSPetter Reinholdtsen return (-1);
326c18ec02fSPetter Reinholdtsen }
327c18ec02fSPetter Reinholdtsen
328c18ec02fSPetter Reinholdtsen /* KfwumSetupBuffersFromFile - small buffers are used to store the file data
329c18ec02fSPetter Reinholdtsen *
330c18ec02fSPetter Reinholdtsen * @pFileName : filename ptr
331c18ec02fSPetter Reinholdtsen * unsigned long : filesize
332c18ec02fSPetter Reinholdtsen *
333c18ec02fSPetter Reinholdtsen * returns 0 on success, otherwise (-1)
334c18ec02fSPetter Reinholdtsen */
335c18ec02fSPetter Reinholdtsen int
KfwumSetupBuffersFromFile(const char * pFileName,unsigned long fileSize)336c18ec02fSPetter Reinholdtsen KfwumSetupBuffersFromFile(const char *pFileName, unsigned long fileSize)
337c18ec02fSPetter Reinholdtsen {
338c18ec02fSPetter Reinholdtsen int rc = (-1);
339c18ec02fSPetter Reinholdtsen FILE *pFileHandle = NULL;
340c18ec02fSPetter Reinholdtsen int count;
341c18ec02fSPetter Reinholdtsen int modulus;
342c18ec02fSPetter Reinholdtsen int qty = 0;
343c18ec02fSPetter Reinholdtsen
344c18ec02fSPetter Reinholdtsen pFileHandle = fopen(pFileName, "rb");
345c18ec02fSPetter Reinholdtsen if (pFileHandle == NULL) {
346c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Failed to open '%s' for reading.",
347c18ec02fSPetter Reinholdtsen pFileName);
348c18ec02fSPetter Reinholdtsen return (-1);
349c18ec02fSPetter Reinholdtsen }
350c18ec02fSPetter Reinholdtsen count = fileSize / MAX_BUFFER_SIZE;
351c18ec02fSPetter Reinholdtsen modulus = fileSize % MAX_BUFFER_SIZE;
352c18ec02fSPetter Reinholdtsen
353c18ec02fSPetter Reinholdtsen rewind(pFileHandle);
354c18ec02fSPetter Reinholdtsen for (qty = 0; qty < count; qty++) {
355c18ec02fSPetter Reinholdtsen KfwumShowProgress("Reading Firmware from File",
356c18ec02fSPetter Reinholdtsen qty, count);
357c18ec02fSPetter Reinholdtsen if (fread(&firmBuf[qty * MAX_BUFFER_SIZE], 1,
358c18ec02fSPetter Reinholdtsen MAX_BUFFER_SIZE,
359c18ec02fSPetter Reinholdtsen pFileHandle) == MAX_BUFFER_SIZE) {
360c18ec02fSPetter Reinholdtsen rc = 0;
361c18ec02fSPetter Reinholdtsen }
362c18ec02fSPetter Reinholdtsen }
363c18ec02fSPetter Reinholdtsen if (modulus) {
364c18ec02fSPetter Reinholdtsen if (fread(&firmBuf[qty * MAX_BUFFER_SIZE], 1,
365c18ec02fSPetter Reinholdtsen modulus, pFileHandle) == modulus) {
366c18ec02fSPetter Reinholdtsen rc = 0;
367c18ec02fSPetter Reinholdtsen }
368c18ec02fSPetter Reinholdtsen }
369c18ec02fSPetter Reinholdtsen if (rc == 0) {
370c18ec02fSPetter Reinholdtsen KfwumShowProgress("Reading Firmware from File", 100, 100);
371c18ec02fSPetter Reinholdtsen }
372c18ec02fSPetter Reinholdtsen fclose(pFileHandle);
373c18ec02fSPetter Reinholdtsen return rc;
374c18ec02fSPetter Reinholdtsen }
375c18ec02fSPetter Reinholdtsen
376c18ec02fSPetter Reinholdtsen /* KfwumShowProgress - helper routine to display progress bar
377c18ec02fSPetter Reinholdtsen *
378c18ec02fSPetter Reinholdtsen * Converts current/total in percent
379c18ec02fSPetter Reinholdtsen *
380c18ec02fSPetter Reinholdtsen * *task : string identifying current operation
381c18ec02fSPetter Reinholdtsen * current: progress
382c18ec02fSPetter Reinholdtsen * total : limit
383c18ec02fSPetter Reinholdtsen */
384c18ec02fSPetter Reinholdtsen void
KfwumShowProgress(const char * task,unsigned long current,unsigned long total)385c18ec02fSPetter Reinholdtsen KfwumShowProgress(const char *task, unsigned long current, unsigned long total)
386c18ec02fSPetter Reinholdtsen {
387c18ec02fSPetter Reinholdtsen # define PROG_LENGTH 42
388c18ec02fSPetter Reinholdtsen static unsigned long staticProgress=0xffffffff;
389c18ec02fSPetter Reinholdtsen unsigned char spaces[PROG_LENGTH + 1];
390c18ec02fSPetter Reinholdtsen unsigned short hash;
391c18ec02fSPetter Reinholdtsen float percent = ((float)current / total);
392c18ec02fSPetter Reinholdtsen unsigned long progress = 100 * (percent);
393c18ec02fSPetter Reinholdtsen
394c18ec02fSPetter Reinholdtsen if (staticProgress == progress) {
395c18ec02fSPetter Reinholdtsen /* We displayed the same last time.. so don't do it */
396c18ec02fSPetter Reinholdtsen return;
397c18ec02fSPetter Reinholdtsen }
398c18ec02fSPetter Reinholdtsen staticProgress = progress;
399c18ec02fSPetter Reinholdtsen printf("%-25s : ", task); /* total 20 bytes */
400c18ec02fSPetter Reinholdtsen hash = (percent * PROG_LENGTH);
401c18ec02fSPetter Reinholdtsen memset(spaces, '#', hash);
402c18ec02fSPetter Reinholdtsen spaces[hash] = '\0';
403c18ec02fSPetter Reinholdtsen
404c18ec02fSPetter Reinholdtsen printf("%s", spaces);
405c18ec02fSPetter Reinholdtsen memset(spaces, ' ', (PROG_LENGTH - hash));
406c18ec02fSPetter Reinholdtsen spaces[(PROG_LENGTH - hash)] = '\0';
407c18ec02fSPetter Reinholdtsen printf("%s", spaces );
408c18ec02fSPetter Reinholdtsen
409c18ec02fSPetter Reinholdtsen printf(" %3ld %%\r", progress); /* total 7 bytes */
410c18ec02fSPetter Reinholdtsen if (progress == 100) {
411c18ec02fSPetter Reinholdtsen printf("\n");
412c18ec02fSPetter Reinholdtsen }
413c18ec02fSPetter Reinholdtsen fflush(stdout);
414c18ec02fSPetter Reinholdtsen }
415c18ec02fSPetter Reinholdtsen
416c18ec02fSPetter Reinholdtsen /* KfwumCalculateChecksumPadding - TBD
417c18ec02fSPetter Reinholdtsen */
418c18ec02fSPetter Reinholdtsen unsigned short
KfwumCalculateChecksumPadding(unsigned char * pBuffer,unsigned long totalSize)419c18ec02fSPetter Reinholdtsen KfwumCalculateChecksumPadding(unsigned char *pBuffer, unsigned long totalSize)
420c18ec02fSPetter Reinholdtsen {
421c18ec02fSPetter Reinholdtsen unsigned short sumOfBytes = 0;
422c18ec02fSPetter Reinholdtsen unsigned short padding;
423c18ec02fSPetter Reinholdtsen unsigned long counter;
424c18ec02fSPetter Reinholdtsen for (counter = 0; counter < totalSize; counter ++) {
425c18ec02fSPetter Reinholdtsen sumOfBytes += pBuffer[counter];
426c18ec02fSPetter Reinholdtsen }
427c18ec02fSPetter Reinholdtsen padding = 0 - sumOfBytes;
428c18ec02fSPetter Reinholdtsen return padding;
429c18ec02fSPetter Reinholdtsen }
430c18ec02fSPetter Reinholdtsen
431c18ec02fSPetter Reinholdtsen /* KfwumGetInfo - Get Firmware Update Manager (FWUM) information
432c18ec02fSPetter Reinholdtsen *
433c18ec02fSPetter Reinholdtsen * *intf : IPMI interface
434c18ec02fSPetter Reinholdtsen * output : when set to non zero, queried information is displayed
435c18ec02fSPetter Reinholdtsen * pNumBank: output ptr for number of banks
436c18ec02fSPetter Reinholdtsen *
437c18ec02fSPetter Reinholdtsen * returns 0 on success, otherwise (-1)
438c18ec02fSPetter Reinholdtsen */
439c18ec02fSPetter Reinholdtsen int
KfwumGetInfo(struct ipmi_intf * intf,unsigned char output,unsigned char * pNumBank)440c18ec02fSPetter Reinholdtsen KfwumGetInfo(struct ipmi_intf *intf, unsigned char output,
441c18ec02fSPetter Reinholdtsen unsigned char *pNumBank)
442c18ec02fSPetter Reinholdtsen {
443c18ec02fSPetter Reinholdtsen int rc = 0;
444c18ec02fSPetter Reinholdtsen static struct KfwumGetInfoResp *pGetInfo;
445c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
446c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
447c18ec02fSPetter Reinholdtsen
448c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
449c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_FIRMWARE;
450c18ec02fSPetter Reinholdtsen req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_INFO;
451c18ec02fSPetter Reinholdtsen req.msg.data_len = 0;
452c18ec02fSPetter Reinholdtsen
453c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
454c18ec02fSPetter Reinholdtsen if (!rsp) {
455c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error in FWUM Firmware Get Info Command.");
456c18ec02fSPetter Reinholdtsen return (-1);
457c18ec02fSPetter Reinholdtsen } else if (rsp->ccode != 0) {
458c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "FWUM Firmware Get Info returned %x",
459c18ec02fSPetter Reinholdtsen rsp->ccode);
460c18ec02fSPetter Reinholdtsen return (-1);
461c18ec02fSPetter Reinholdtsen }
462c18ec02fSPetter Reinholdtsen
463c18ec02fSPetter Reinholdtsen pGetInfo = (struct KfwumGetInfoResp *)rsp->data;
464c18ec02fSPetter Reinholdtsen if (output) {
465c18ec02fSPetter Reinholdtsen printf("\nFWUM info\n");
466c18ec02fSPetter Reinholdtsen printf("=========\n");
467c18ec02fSPetter Reinholdtsen printf("Protocol Revision : %02Xh\n",
468c18ec02fSPetter Reinholdtsen pGetInfo->protocolRevision);
469c18ec02fSPetter Reinholdtsen printf("Controller Device Id : %02Xh\n",
470c18ec02fSPetter Reinholdtsen pGetInfo->controllerDeviceId);
471c18ec02fSPetter Reinholdtsen printf("Firmware Revision : %u.%u%u",
472c18ec02fSPetter Reinholdtsen pGetInfo->firmRev1, pGetInfo->firmRev2 >> 4,
473c18ec02fSPetter Reinholdtsen pGetInfo->firmRev2 & 0x0f);
474c18ec02fSPetter Reinholdtsen if (pGetInfo->byte.mode != 0) {
475c18ec02fSPetter Reinholdtsen printf(" - DEBUG BUILD\n");
476c18ec02fSPetter Reinholdtsen } else {
477c18ec02fSPetter Reinholdtsen printf("\n");
478c18ec02fSPetter Reinholdtsen }
479c18ec02fSPetter Reinholdtsen printf("Number Of Memory Bank : %u\n", pGetInfo->numBank);
480c18ec02fSPetter Reinholdtsen }
481c18ec02fSPetter Reinholdtsen *pNumBank = pGetInfo->numBank;
482c18ec02fSPetter Reinholdtsen /* Determine wich type of download to use: */
483c18ec02fSPetter Reinholdtsen /* Old FWUM or Old IPMC fw (data_len < 7)
484c18ec02fSPetter Reinholdtsen * --> Address with small buffer size
485c18ec02fSPetter Reinholdtsen */
486c18ec02fSPetter Reinholdtsen if ((pGetInfo->protocolRevision) <= 0x05 || (rsp->data_len < 7 )) {
487c18ec02fSPetter Reinholdtsen save_fw_nfo.downloadType = KFWUM_DOWNLOAD_TYPE_ADDRESS;
488c18ec02fSPetter Reinholdtsen save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
489c18ec02fSPetter Reinholdtsen save_fw_nfo.overheadSize = KFWUM_OLD_CMD_OVERHEAD;
490c18ec02fSPetter Reinholdtsen if (verbose) {
491c18ec02fSPetter Reinholdtsen printf("Protocol Revision :");
492c18ec02fSPetter Reinholdtsen printf(" <= 5 detected, adjusting buffers\n");
493c18ec02fSPetter Reinholdtsen }
494c18ec02fSPetter Reinholdtsen } else {
495c18ec02fSPetter Reinholdtsen /* Both fw are using the new protocol */
496c18ec02fSPetter Reinholdtsen save_fw_nfo.downloadType = KFWUM_DOWNLOAD_TYPE_SEQUENCE;
497c18ec02fSPetter Reinholdtsen save_fw_nfo.overheadSize = KFWUM_NEW_CMD_OVERHEAD;
498c18ec02fSPetter Reinholdtsen /* Buffer size depending on access type (Local or remote) */
499c18ec02fSPetter Reinholdtsen /* Look if we run remote or locally */
500c18ec02fSPetter Reinholdtsen if (verbose) {
501c18ec02fSPetter Reinholdtsen printf("Protocol Revision :");
502c18ec02fSPetter Reinholdtsen printf(" > 5 optimizing buffers\n");
503c18ec02fSPetter Reinholdtsen }
504c18ec02fSPetter Reinholdtsen if (strstr(intf->name,"lan") != NULL) {
505c18ec02fSPetter Reinholdtsen /* also covers lanplus */
506c18ec02fSPetter Reinholdtsen save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
507c18ec02fSPetter Reinholdtsen if (verbose) {
508c18ec02fSPetter Reinholdtsen printf("IOL payload size : %d\n",
509c18ec02fSPetter Reinholdtsen save_fw_nfo.bufferSize);
510c18ec02fSPetter Reinholdtsen }
511c18ec02fSPetter Reinholdtsen } else if ((strstr(intf->name,"open")!= NULL)
512c18ec02fSPetter Reinholdtsen && intf->target_addr != IPMI_BMC_SLAVE_ADDR
513c18ec02fSPetter Reinholdtsen && (intf->target_addr != intf->my_addr)) {
514c18ec02fSPetter Reinholdtsen save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
515c18ec02fSPetter Reinholdtsen if (verbose) {
516c18ec02fSPetter Reinholdtsen printf("IPMB payload size : %d\n",
517c18ec02fSPetter Reinholdtsen save_fw_nfo.bufferSize);
518c18ec02fSPetter Reinholdtsen }
519c18ec02fSPetter Reinholdtsen } else {
520c18ec02fSPetter Reinholdtsen save_fw_nfo.bufferSize = KFWUM_BIG_BUFFER;
521c18ec02fSPetter Reinholdtsen if (verbose) {
522c18ec02fSPetter Reinholdtsen printf("SMI payload size : %d\n",
523c18ec02fSPetter Reinholdtsen save_fw_nfo.bufferSize);
524c18ec02fSPetter Reinholdtsen }
525c18ec02fSPetter Reinholdtsen }
526c18ec02fSPetter Reinholdtsen }
527c18ec02fSPetter Reinholdtsen return rc;
528c18ec02fSPetter Reinholdtsen }
529c18ec02fSPetter Reinholdtsen
530c18ec02fSPetter Reinholdtsen /* KfwumGetDeviceInfo - Get IPMC/Board information
531c18ec02fSPetter Reinholdtsen *
532c18ec02fSPetter Reinholdtsen * *intf: IPMI interface
533c18ec02fSPetter Reinholdtsen * output: when set to non zero, queried information is displayed
534c18ec02fSPetter Reinholdtsen * tKFWUM_BoardInfo: output ptr for IPMC/Board information
535c18ec02fSPetter Reinholdtsen *
536c18ec02fSPetter Reinholdtsen * returns 0 on success, otherwise (-1)
537c18ec02fSPetter Reinholdtsen */
538c18ec02fSPetter Reinholdtsen int
KfwumGetDeviceInfo(struct ipmi_intf * intf,unsigned char output,tKFWUM_BoardInfo * pBoardInfo)539c18ec02fSPetter Reinholdtsen KfwumGetDeviceInfo(struct ipmi_intf *intf, unsigned char output,
540c18ec02fSPetter Reinholdtsen tKFWUM_BoardInfo *pBoardInfo)
541c18ec02fSPetter Reinholdtsen {
542c18ec02fSPetter Reinholdtsen struct ipm_devid_rsp *pGetDevId;
543c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
544c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
545c18ec02fSPetter Reinholdtsen /* Send Get Device Id */
546c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
547c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_APP;
548c18ec02fSPetter Reinholdtsen req.msg.cmd = BMC_GET_DEVICE_ID;
549c18ec02fSPetter Reinholdtsen req.msg.data_len = 0;
550c18ec02fSPetter Reinholdtsen
551c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
552c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
553c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error in Get Device Id Command");
554c18ec02fSPetter Reinholdtsen return (-1);
555c18ec02fSPetter Reinholdtsen } else if (rsp->ccode != 0) {
556c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Get Device Id returned %x",
557c18ec02fSPetter Reinholdtsen rsp->ccode);
558c18ec02fSPetter Reinholdtsen return (-1);
559c18ec02fSPetter Reinholdtsen }
560c18ec02fSPetter Reinholdtsen pGetDevId = (struct ipm_devid_rsp *)rsp->data;
561c18ec02fSPetter Reinholdtsen pBoardInfo->iana = IPM_DEV_MANUFACTURER_ID(pGetDevId->manufacturer_id);
562c18ec02fSPetter Reinholdtsen pBoardInfo->boardId = buf2short(pGetDevId->product_id);
563c18ec02fSPetter Reinholdtsen if (output) {
564c18ec02fSPetter Reinholdtsen printf("\nIPMC Info\n");
565c18ec02fSPetter Reinholdtsen printf("=========\n");
566c18ec02fSPetter Reinholdtsen printf("Manufacturer Id : %u\n",
567c18ec02fSPetter Reinholdtsen pBoardInfo->iana);
568c18ec02fSPetter Reinholdtsen printf("Board Id : %u\n",
569c18ec02fSPetter Reinholdtsen pBoardInfo->boardId);
570c18ec02fSPetter Reinholdtsen printf("Firmware Revision : %u.%u%u",
571c18ec02fSPetter Reinholdtsen pGetDevId->fw_rev1, pGetDevId->fw_rev2 >> 4,
572c18ec02fSPetter Reinholdtsen pGetDevId->fw_rev2 & 0x0f);
573c18ec02fSPetter Reinholdtsen if (((pBoardInfo->iana == IPMI_OEM_KONTRON)
574fb69b5dcSZdenek Styblik && (pBoardInfo->boardId == KFWUM_BOARD_KONTRON_5002))) {
575c18ec02fSPetter Reinholdtsen printf(" SDR %u", pGetDevId->aux_fw_rev[0]);
576c18ec02fSPetter Reinholdtsen }
577c18ec02fSPetter Reinholdtsen printf("\n");
578c18ec02fSPetter Reinholdtsen }
579c18ec02fSPetter Reinholdtsen return 0;
580c18ec02fSPetter Reinholdtsen }
581c18ec02fSPetter Reinholdtsen
582c18ec02fSPetter Reinholdtsen /* KfwumGetStatus - Get (and prints) FWUM banks information
583c18ec02fSPetter Reinholdtsen *
584c18ec02fSPetter Reinholdtsen * *intf : IPMI interface
585c18ec02fSPetter Reinholdtsen *
586c18ec02fSPetter Reinholdtsen * returns 0 on success, otherwise (-1)
587c18ec02fSPetter Reinholdtsen */
588c18ec02fSPetter Reinholdtsen int
KfwumGetStatus(struct ipmi_intf * intf)589c18ec02fSPetter Reinholdtsen KfwumGetStatus(struct ipmi_intf * intf)
590c18ec02fSPetter Reinholdtsen {
591c18ec02fSPetter Reinholdtsen int rc = 0;
592c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
593c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
594c18ec02fSPetter Reinholdtsen struct KfwumGetStatusResp *pGetStatus;
595c18ec02fSPetter Reinholdtsen unsigned char numBank;
596c18ec02fSPetter Reinholdtsen unsigned char counter;
597c18ec02fSPetter Reinholdtsen unsigned long firmLength;
598c18ec02fSPetter Reinholdtsen if (verbose) {
599c18ec02fSPetter Reinholdtsen printf(" Getting Status!\n");
600c18ec02fSPetter Reinholdtsen }
601c18ec02fSPetter Reinholdtsen /* Retreive the number of bank */
602c18ec02fSPetter Reinholdtsen rc = KfwumGetInfo(intf, 0, &numBank);
603c18ec02fSPetter Reinholdtsen for(counter = 0;
604c18ec02fSPetter Reinholdtsen (counter < numBank) && (rc == 0);
605c18ec02fSPetter Reinholdtsen counter ++) {
606c18ec02fSPetter Reinholdtsen /* Retreive the status of each bank */
607c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
608c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_FIRMWARE;
609c18ec02fSPetter Reinholdtsen req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_STATUS;
610c18ec02fSPetter Reinholdtsen req.msg.data = &counter;
611c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
612c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
613c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
614c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
615c18ec02fSPetter Reinholdtsen "Error in FWUM Firmware Get Status Command.");
616c18ec02fSPetter Reinholdtsen rc = (-1);
617c18ec02fSPetter Reinholdtsen break;
618c18ec02fSPetter Reinholdtsen } else if (rsp->ccode) {
619c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
620c18ec02fSPetter Reinholdtsen "FWUM Firmware Get Status returned %x",
621c18ec02fSPetter Reinholdtsen rsp->ccode);
622c18ec02fSPetter Reinholdtsen rc = (-1);
623c18ec02fSPetter Reinholdtsen break;
624c18ec02fSPetter Reinholdtsen }
625c18ec02fSPetter Reinholdtsen pGetStatus = (struct KfwumGetStatusResp *) rsp->data;
626c18ec02fSPetter Reinholdtsen printf("\nBank State %d : %s\n",
627c18ec02fSPetter Reinholdtsen counter,
628c18ec02fSPetter Reinholdtsen val2str(pGetStatus->bankState, bankStateValS));
629c18ec02fSPetter Reinholdtsen if (!pGetStatus->bankState) {
630c18ec02fSPetter Reinholdtsen continue;
631c18ec02fSPetter Reinholdtsen }
632c18ec02fSPetter Reinholdtsen firmLength = pGetStatus->firmLengthMSB;
633c18ec02fSPetter Reinholdtsen firmLength = firmLength << 8;
634c18ec02fSPetter Reinholdtsen firmLength |= pGetStatus->firmLengthMid;
635c18ec02fSPetter Reinholdtsen firmLength = firmLength << 8;
636c18ec02fSPetter Reinholdtsen firmLength |= pGetStatus->firmLengthLSB;
637c18ec02fSPetter Reinholdtsen printf("Firmware Length : %ld bytes\n",
638c18ec02fSPetter Reinholdtsen firmLength);
639c18ec02fSPetter Reinholdtsen printf("Firmware Revision : %u.%u%u SDR %u\n",
640c18ec02fSPetter Reinholdtsen pGetStatus->firmRev1,
641c18ec02fSPetter Reinholdtsen pGetStatus->firmRev2 >> 4,
642c18ec02fSPetter Reinholdtsen pGetStatus->firmRev2 & 0x0f,
643c18ec02fSPetter Reinholdtsen pGetStatus->firmRev3);
644c18ec02fSPetter Reinholdtsen }
645c18ec02fSPetter Reinholdtsen printf("\n");
646c18ec02fSPetter Reinholdtsen return rc;
647c18ec02fSPetter Reinholdtsen }
648c18ec02fSPetter Reinholdtsen
649c18ec02fSPetter Reinholdtsen /* KfwumManualRollback - Ask IPMC to rollback to previous version
650c18ec02fSPetter Reinholdtsen *
651c18ec02fSPetter Reinholdtsen * *intf : IPMI interface
652c18ec02fSPetter Reinholdtsen *
653c18ec02fSPetter Reinholdtsen * returns 0 on success
654c18ec02fSPetter Reinholdtsen * returns (-1) on error
655c18ec02fSPetter Reinholdtsen */
656c18ec02fSPetter Reinholdtsen int
KfwumManualRollback(struct ipmi_intf * intf)657c18ec02fSPetter Reinholdtsen KfwumManualRollback(struct ipmi_intf *intf)
658c18ec02fSPetter Reinholdtsen {
659c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
660c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
661c18ec02fSPetter Reinholdtsen struct KfwumManualRollbackReq thisReq;
662c18ec02fSPetter Reinholdtsen
663c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
664c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_FIRMWARE;
665c18ec02fSPetter Reinholdtsen req.msg.cmd = KFWUM_CMD_ID_MANUAL_ROLLBACK;
666c18ec02fSPetter Reinholdtsen thisReq.type = 0; /* Wait BMC shutdown */
667c18ec02fSPetter Reinholdtsen req.msg.data = (unsigned char *)&thisReq;
668c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
669c18ec02fSPetter Reinholdtsen
670c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
671c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
672c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR, "Error in FWUM Manual Rollback Command.");
673c18ec02fSPetter Reinholdtsen return (-1);
674c18ec02fSPetter Reinholdtsen } else if (rsp->ccode != 0) {
675c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
676c18ec02fSPetter Reinholdtsen "Error in FWUM Manual Rollback Command returned %x",
677c18ec02fSPetter Reinholdtsen rsp->ccode);
678c18ec02fSPetter Reinholdtsen return (-1);
679c18ec02fSPetter Reinholdtsen }
680c18ec02fSPetter Reinholdtsen printf("FWUM Starting Manual Rollback \n");
681c18ec02fSPetter Reinholdtsen return 0;
682c18ec02fSPetter Reinholdtsen }
683c18ec02fSPetter Reinholdtsen
684c18ec02fSPetter Reinholdtsen int
KfwumStartFirmwareImage(struct ipmi_intf * intf,unsigned long length,unsigned short padding)685c18ec02fSPetter Reinholdtsen KfwumStartFirmwareImage(struct ipmi_intf *intf, unsigned long length,
686c18ec02fSPetter Reinholdtsen unsigned short padding)
687c18ec02fSPetter Reinholdtsen {
688c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
689c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
690c18ec02fSPetter Reinholdtsen struct KfwumStartFirmwareDownloadResp *pResp;
691c18ec02fSPetter Reinholdtsen struct KfwumStartFirmwareDownloadReq thisReq;
692c18ec02fSPetter Reinholdtsen
693c18ec02fSPetter Reinholdtsen thisReq.lengthLSB = length & 0x000000ff;
694c18ec02fSPetter Reinholdtsen thisReq.lengthMid = (length >> 8) & 0x000000ff;
695c18ec02fSPetter Reinholdtsen thisReq.lengthMSB = (length >> 16) & 0x000000ff;
696c18ec02fSPetter Reinholdtsen thisReq.paddingLSB = padding & 0x00ff;
697c18ec02fSPetter Reinholdtsen thisReq.paddingMSB = (padding>> 8) & 0x00ff;
698c18ec02fSPetter Reinholdtsen thisReq.useSequence = 0x01;
699c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
700c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_FIRMWARE;
701c18ec02fSPetter Reinholdtsen req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_IMAGE;
702c18ec02fSPetter Reinholdtsen req.msg.data = (unsigned char *) &thisReq;
703c18ec02fSPetter Reinholdtsen /* Look for download type */
704c18ec02fSPetter Reinholdtsen if (save_fw_nfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS) {
705c18ec02fSPetter Reinholdtsen req.msg.data_len = 5;
706c18ec02fSPetter Reinholdtsen } else {
707c18ec02fSPetter Reinholdtsen req.msg.data_len = 6;
708c18ec02fSPetter Reinholdtsen }
709c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
710c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
711c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
712c18ec02fSPetter Reinholdtsen "Error in FWUM Firmware Start Firmware Image Download Command.");
713c18ec02fSPetter Reinholdtsen return (-1);
714c18ec02fSPetter Reinholdtsen } else if (rsp->ccode) {
715c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
716c18ec02fSPetter Reinholdtsen "FWUM Firmware Start Firmware Image Download returned %x",
717c18ec02fSPetter Reinholdtsen rsp->ccode);
718c18ec02fSPetter Reinholdtsen return (-1);
719c18ec02fSPetter Reinholdtsen }
720c18ec02fSPetter Reinholdtsen pResp = (struct KfwumStartFirmwareDownloadResp *)rsp->data;
721c18ec02fSPetter Reinholdtsen printf("Bank holding new firmware : %d\n", pResp->bank);
722c18ec02fSPetter Reinholdtsen sleep(5);
723c18ec02fSPetter Reinholdtsen return 0;
724c18ec02fSPetter Reinholdtsen }
725c18ec02fSPetter Reinholdtsen
726c18ec02fSPetter Reinholdtsen int
KfwumSaveFirmwareImage(struct ipmi_intf * intf,unsigned char sequenceNumber,unsigned long address,unsigned char * pFirmBuf,unsigned char * pInBufLength)727c18ec02fSPetter Reinholdtsen KfwumSaveFirmwareImage(struct ipmi_intf *intf, unsigned char sequenceNumber,
728c18ec02fSPetter Reinholdtsen unsigned long address, unsigned char *pFirmBuf,
729c18ec02fSPetter Reinholdtsen unsigned char *pInBufLength)
730c18ec02fSPetter Reinholdtsen {
731c18ec02fSPetter Reinholdtsen int rc = 0;
732c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
733c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
734c18ec02fSPetter Reinholdtsen struct KfwumSaveFirmwareAddressReq addr_req;
735c18ec02fSPetter Reinholdtsen struct KfwumSaveFirmwareSequenceReq seq_req;
736c18ec02fSPetter Reinholdtsen int retry = 0;
737c18ec02fSPetter Reinholdtsen int no_rsp = 0;
738c18ec02fSPetter Reinholdtsen do {
739c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
740c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_FIRMWARE;
741c18ec02fSPetter Reinholdtsen req.msg.cmd = KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE;
742c18ec02fSPetter Reinholdtsen if (save_fw_nfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS) {
743c18ec02fSPetter Reinholdtsen addr_req.addressLSB = address & 0x000000ff;
744c18ec02fSPetter Reinholdtsen addr_req.addressMid = (address >> 8) & 0x000000ff;
745c18ec02fSPetter Reinholdtsen addr_req.addressMSB = (address >> 16) & 0x000000ff;
746c18ec02fSPetter Reinholdtsen addr_req.numBytes = *pInBufLength;
747c18ec02fSPetter Reinholdtsen memcpy(addr_req.txBuf, pFirmBuf, *pInBufLength);
748c18ec02fSPetter Reinholdtsen req.msg.data = (unsigned char *)&addr_req;
749c18ec02fSPetter Reinholdtsen req.msg.data_len = *pInBufLength + 4;
750c18ec02fSPetter Reinholdtsen } else {
751c18ec02fSPetter Reinholdtsen seq_req.sequenceNumber = sequenceNumber;
752c18ec02fSPetter Reinholdtsen memcpy(seq_req.txBuf, pFirmBuf, *pInBufLength);
753c18ec02fSPetter Reinholdtsen req.msg.data = (unsigned char *)&seq_req;
754c18ec02fSPetter Reinholdtsen req.msg.data_len = *pInBufLength + sizeof(unsigned char);
755c18ec02fSPetter Reinholdtsen /* + 1 => sequenceNumber*/
756c18ec02fSPetter Reinholdtsen }
757c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
758c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
759c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
760c18ec02fSPetter Reinholdtsen "Error in FWUM Firmware Save Firmware Image Download Command.");
761c18ec02fSPetter Reinholdtsen /* We don't receive "C7" on errors with IOL,
762c18ec02fSPetter Reinholdtsen * instead we receive nothing
763c18ec02fSPetter Reinholdtsen */
764c18ec02fSPetter Reinholdtsen if (strstr(intf->name, "lan") != NULL) {
765c18ec02fSPetter Reinholdtsen no_rsp++;
766c18ec02fSPetter Reinholdtsen if (no_rsp < FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT) {
767c18ec02fSPetter Reinholdtsen *pInBufLength -= 1;
768c18ec02fSPetter Reinholdtsen continue;
769c18ec02fSPetter Reinholdtsen }
770c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
771c18ec02fSPetter Reinholdtsen "Error, too many commands without response.");
772c18ec02fSPetter Reinholdtsen *pInBufLength = 0;
773c18ec02fSPetter Reinholdtsen break;
774c18ec02fSPetter Reinholdtsen } /* For other interface keep trying */
775c18ec02fSPetter Reinholdtsen } else if (rsp->ccode != 0) {
776c18ec02fSPetter Reinholdtsen if (rsp->ccode == 0xc0) {
777c18ec02fSPetter Reinholdtsen sleep(1);
778c18ec02fSPetter Reinholdtsen } else if ((rsp->ccode == 0xc7)
779c18ec02fSPetter Reinholdtsen || ((rsp->ccode == 0xc3)
780c18ec02fSPetter Reinholdtsen && (sequenceNumber == 0))) {
781c18ec02fSPetter Reinholdtsen *pInBufLength -= 1;
782c18ec02fSPetter Reinholdtsen retry = 1;
783c18ec02fSPetter Reinholdtsen } else if (rsp->ccode == 0x82) {
784c18ec02fSPetter Reinholdtsen /* Double sent, continue */
785c18ec02fSPetter Reinholdtsen rc = 0;
786c18ec02fSPetter Reinholdtsen break;
787c18ec02fSPetter Reinholdtsen } else if (rsp->ccode == 0x83) {
788c18ec02fSPetter Reinholdtsen if (retry == 0) {
789c18ec02fSPetter Reinholdtsen retry = 1;
790c18ec02fSPetter Reinholdtsen continue;
791c18ec02fSPetter Reinholdtsen }
792c18ec02fSPetter Reinholdtsen rc = (-1);
793c18ec02fSPetter Reinholdtsen break;
794c18ec02fSPetter Reinholdtsen } else if (rsp->ccode == 0xcf) {
795c18ec02fSPetter Reinholdtsen /* Ok if receive duplicated request */
796c18ec02fSPetter Reinholdtsen retry = 1;
797c18ec02fSPetter Reinholdtsen } else if (rsp->ccode == 0xc3) {
798c18ec02fSPetter Reinholdtsen if (retry == 0) {
799c18ec02fSPetter Reinholdtsen retry = 1;
800c18ec02fSPetter Reinholdtsen continue;
801c18ec02fSPetter Reinholdtsen }
802c18ec02fSPetter Reinholdtsen rc = (-1);
803c18ec02fSPetter Reinholdtsen break;
804c18ec02fSPetter Reinholdtsen } else {
805c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
806c18ec02fSPetter Reinholdtsen "FWUM Firmware Save Firmware Image Download returned %x",
807c18ec02fSPetter Reinholdtsen rsp->ccode);
808c18ec02fSPetter Reinholdtsen rc = (-1);
809c18ec02fSPetter Reinholdtsen break;
810c18ec02fSPetter Reinholdtsen }
811c18ec02fSPetter Reinholdtsen } else {
812c18ec02fSPetter Reinholdtsen break;
813c18ec02fSPetter Reinholdtsen }
814c18ec02fSPetter Reinholdtsen } while (1);
815c18ec02fSPetter Reinholdtsen return rc;
816c18ec02fSPetter Reinholdtsen }
817c18ec02fSPetter Reinholdtsen
818c18ec02fSPetter Reinholdtsen int
KfwumFinishFirmwareImage(struct ipmi_intf * intf,tKFWUM_InFirmwareInfo firmInfo)819c18ec02fSPetter Reinholdtsen KfwumFinishFirmwareImage(struct ipmi_intf *intf, tKFWUM_InFirmwareInfo firmInfo)
820c18ec02fSPetter Reinholdtsen {
821c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
822c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
823c18ec02fSPetter Reinholdtsen struct KfwumFinishFirmwareDownloadReq thisReq;
824c18ec02fSPetter Reinholdtsen
825c18ec02fSPetter Reinholdtsen thisReq.versionMaj = firmInfo.versMajor;
826c18ec02fSPetter Reinholdtsen thisReq.versionMinSub = ((firmInfo.versMinor <<4)
827c18ec02fSPetter Reinholdtsen | firmInfo.versSubMinor);
828c18ec02fSPetter Reinholdtsen thisReq.versionSdr = firmInfo.sdrRev;
829c18ec02fSPetter Reinholdtsen thisReq.reserved = 0;
830c18ec02fSPetter Reinholdtsen /* Byte 4 reserved, write 0 */
831c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
832c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_FIRMWARE;
833c18ec02fSPetter Reinholdtsen req.msg.cmd = KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE;
834c18ec02fSPetter Reinholdtsen req.msg.data = (unsigned char *)&thisReq;
835c18ec02fSPetter Reinholdtsen req.msg.data_len = 4;
836c18ec02fSPetter Reinholdtsen /* Infinite loop if BMC doesn't reply or replies 0xc0 every time. */
837c18ec02fSPetter Reinholdtsen do {
838c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
839c18ec02fSPetter Reinholdtsen } while (rsp == NULL || rsp->ccode == 0xc0);
840*8775af38SZdenek Styblik
841*8775af38SZdenek Styblik if (rsp->ccode != 0) {
842c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
843c18ec02fSPetter Reinholdtsen "FWUM Firmware Finish Firmware Image Download returned %x",
844c18ec02fSPetter Reinholdtsen rsp->ccode);
845c18ec02fSPetter Reinholdtsen return (-1);
846c18ec02fSPetter Reinholdtsen }
847c18ec02fSPetter Reinholdtsen return 0;
848c18ec02fSPetter Reinholdtsen }
849c18ec02fSPetter Reinholdtsen
850c18ec02fSPetter Reinholdtsen int
KfwumUploadFirmware(struct ipmi_intf * intf,unsigned char * pBuffer,unsigned long totalSize)851c18ec02fSPetter Reinholdtsen KfwumUploadFirmware(struct ipmi_intf *intf, unsigned char *pBuffer,
852c18ec02fSPetter Reinholdtsen unsigned long totalSize)
853c18ec02fSPetter Reinholdtsen {
854c18ec02fSPetter Reinholdtsen int rc = (-1);
855c18ec02fSPetter Reinholdtsen unsigned long address = 0x0;
856c18ec02fSPetter Reinholdtsen unsigned char writeSize;
857c18ec02fSPetter Reinholdtsen unsigned char oldWriteSize;
858c18ec02fSPetter Reinholdtsen unsigned long lastAddress = 0;
859c18ec02fSPetter Reinholdtsen unsigned char sequenceNumber = 0;
860c18ec02fSPetter Reinholdtsen unsigned char retry = FWUM_MAX_UPLOAD_RETRY;
861c18ec02fSPetter Reinholdtsen do {
862c18ec02fSPetter Reinholdtsen writeSize = save_fw_nfo.bufferSize - save_fw_nfo.overheadSize;
863c18ec02fSPetter Reinholdtsen /* Reach the end */
864c18ec02fSPetter Reinholdtsen if (address + writeSize > totalSize) {
865c18ec02fSPetter Reinholdtsen writeSize = (totalSize - address);
866c18ec02fSPetter Reinholdtsen } else if (((address % KFWUM_PAGE_SIZE)
867c18ec02fSPetter Reinholdtsen + writeSize) > KFWUM_PAGE_SIZE) {
868c18ec02fSPetter Reinholdtsen /* Reach boundary end */
869c18ec02fSPetter Reinholdtsen writeSize = (KFWUM_PAGE_SIZE - (address % KFWUM_PAGE_SIZE));
870c18ec02fSPetter Reinholdtsen }
871c18ec02fSPetter Reinholdtsen oldWriteSize = writeSize;
872c18ec02fSPetter Reinholdtsen rc = KfwumSaveFirmwareImage(intf, sequenceNumber,
873c18ec02fSPetter Reinholdtsen address, &pBuffer[address], &writeSize);
874c18ec02fSPetter Reinholdtsen if ((rc != 0) && (retry-- != 0)) {
875c18ec02fSPetter Reinholdtsen address = lastAddress;
876c18ec02fSPetter Reinholdtsen rc = 0;
877c18ec02fSPetter Reinholdtsen } else if ( writeSize == 0) {
878c18ec02fSPetter Reinholdtsen rc = (-1);
879c18ec02fSPetter Reinholdtsen } else {
880c18ec02fSPetter Reinholdtsen if (writeSize != oldWriteSize) {
881c18ec02fSPetter Reinholdtsen printf("Adjusting length to %d bytes \n",
882c18ec02fSPetter Reinholdtsen writeSize);
883c18ec02fSPetter Reinholdtsen save_fw_nfo.bufferSize -= (oldWriteSize - writeSize);
884c18ec02fSPetter Reinholdtsen }
885c18ec02fSPetter Reinholdtsen retry = FWUM_MAX_UPLOAD_RETRY;
886c18ec02fSPetter Reinholdtsen lastAddress = address;
887c18ec02fSPetter Reinholdtsen address+= writeSize;
888c18ec02fSPetter Reinholdtsen }
889c18ec02fSPetter Reinholdtsen if (rc == 0) {
890c18ec02fSPetter Reinholdtsen if ((address % 1024) == 0) {
8916d25903aSZdenek Styblik KfwumShowProgress("Writing Firmware in Flash",
892c18ec02fSPetter Reinholdtsen address, totalSize);
893c18ec02fSPetter Reinholdtsen }
894c18ec02fSPetter Reinholdtsen sequenceNumber++;
895c18ec02fSPetter Reinholdtsen }
896c18ec02fSPetter Reinholdtsen } while ((rc == 0) && (address < totalSize));
897c18ec02fSPetter Reinholdtsen if (rc == 0) {
8986d25903aSZdenek Styblik KfwumShowProgress("Writing Firmware in Flash",
899c18ec02fSPetter Reinholdtsen 100, 100);
900c18ec02fSPetter Reinholdtsen }
901c18ec02fSPetter Reinholdtsen return rc;
902c18ec02fSPetter Reinholdtsen }
903c18ec02fSPetter Reinholdtsen
904c18ec02fSPetter Reinholdtsen int
KfwumStartFirmwareUpgrade(struct ipmi_intf * intf)905c18ec02fSPetter Reinholdtsen KfwumStartFirmwareUpgrade(struct ipmi_intf *intf)
906c18ec02fSPetter Reinholdtsen {
907c18ec02fSPetter Reinholdtsen int rc = 0;
908c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
909c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
910c18ec02fSPetter Reinholdtsen /* Upgrade type, wait BMC shutdown */
911c18ec02fSPetter Reinholdtsen unsigned char upgType = 0 ;
912c18ec02fSPetter Reinholdtsen
913c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
914c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_FIRMWARE;
915c18ec02fSPetter Reinholdtsen req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_UPDATE;
916c18ec02fSPetter Reinholdtsen req.msg.data = (unsigned char *) &upgType;
917c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
918c18ec02fSPetter Reinholdtsen
919c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
920c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
921c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
922c18ec02fSPetter Reinholdtsen "Error in FWUM Firmware Start Firmware Upgrade Command");
923c18ec02fSPetter Reinholdtsen rc = (-1);
924c18ec02fSPetter Reinholdtsen } else if (rsp->ccode) {
925c18ec02fSPetter Reinholdtsen if (rsp->ccode == 0xd5) {
926c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
927c18ec02fSPetter Reinholdtsen "No firmware available for upgrade. Download Firmware first.");
928c18ec02fSPetter Reinholdtsen } else {
929c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
930c18ec02fSPetter Reinholdtsen "FWUM Firmware Start Firmware Upgrade returned %x",
931c18ec02fSPetter Reinholdtsen rsp->ccode);
932c18ec02fSPetter Reinholdtsen }
933c18ec02fSPetter Reinholdtsen rc = (-1);
934c18ec02fSPetter Reinholdtsen }
935c18ec02fSPetter Reinholdtsen return rc;
936c18ec02fSPetter Reinholdtsen }
937c18ec02fSPetter Reinholdtsen
938c18ec02fSPetter Reinholdtsen int
KfwumGetTraceLog(struct ipmi_intf * intf)939c18ec02fSPetter Reinholdtsen KfwumGetTraceLog(struct ipmi_intf *intf)
940c18ec02fSPetter Reinholdtsen {
941c18ec02fSPetter Reinholdtsen int rc = 0;
942c18ec02fSPetter Reinholdtsen struct ipmi_rs *rsp;
943c18ec02fSPetter Reinholdtsen struct ipmi_rq req;
944c18ec02fSPetter Reinholdtsen unsigned char chunkIdx;
945c18ec02fSPetter Reinholdtsen unsigned char cmdIdx;
946c18ec02fSPetter Reinholdtsen if (verbose) {
947c18ec02fSPetter Reinholdtsen printf(" Getting Trace Log!\n");
948c18ec02fSPetter Reinholdtsen }
949c18ec02fSPetter Reinholdtsen for (chunkIdx = 0;
950c18ec02fSPetter Reinholdtsen (chunkIdx < TRACE_LOG_CHUNK_COUNT)
951c18ec02fSPetter Reinholdtsen && (rc == 0);
952c18ec02fSPetter Reinholdtsen chunkIdx++) {
953c18ec02fSPetter Reinholdtsen /* Retreive each log chunk and print it */
954c18ec02fSPetter Reinholdtsen memset(&req, 0, sizeof(req));
955c18ec02fSPetter Reinholdtsen req.msg.netfn = IPMI_NETFN_FIRMWARE;
956c18ec02fSPetter Reinholdtsen req.msg.cmd = KFWUM_CMD_ID_GET_TRACE_LOG;
957c18ec02fSPetter Reinholdtsen req.msg.data = &chunkIdx;
958c18ec02fSPetter Reinholdtsen req.msg.data_len = 1;
959c18ec02fSPetter Reinholdtsen
960c18ec02fSPetter Reinholdtsen rsp = intf->sendrecv(intf, &req);
961c18ec02fSPetter Reinholdtsen if (rsp == NULL) {
962c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
963c18ec02fSPetter Reinholdtsen "Error in FWUM Firmware Get Trace Log Command");
964c18ec02fSPetter Reinholdtsen rc = (-1);
965c18ec02fSPetter Reinholdtsen break;
966c18ec02fSPetter Reinholdtsen } else if (rsp->ccode) {
967c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
968c18ec02fSPetter Reinholdtsen "FWUM Firmware Get Trace Log returned %x",
969c18ec02fSPetter Reinholdtsen rsp->ccode);
970c18ec02fSPetter Reinholdtsen rc = (-1);
971c18ec02fSPetter Reinholdtsen break;
972c18ec02fSPetter Reinholdtsen }
973c18ec02fSPetter Reinholdtsen for (cmdIdx=0; cmdIdx < TRACE_LOG_CHUNK_SIZE; cmdIdx++) {
974c18ec02fSPetter Reinholdtsen /* Don't diplay commands with an invalid state */
975c18ec02fSPetter Reinholdtsen if ((rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1] != 0)
976c18ec02fSPetter Reinholdtsen && (rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx] < KFWUM_CMD_ID_STD_MAX_CMD)) {
977c18ec02fSPetter Reinholdtsen printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
978c18ec02fSPetter Reinholdtsen CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx]],
979c18ec02fSPetter Reinholdtsen CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1]],
980c18ec02fSPetter Reinholdtsen rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 2]);
981c18ec02fSPetter Reinholdtsen } else if ((rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1] != 0)
982c18ec02fSPetter Reinholdtsen && (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] >= KFWUM_CMD_ID_EXTENDED_CMD)) {
983c18ec02fSPetter Reinholdtsen printf(" Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
984c18ec02fSPetter Reinholdtsen EXT_CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx] - KFWUM_CMD_ID_EXTENDED_CMD],
985c18ec02fSPetter Reinholdtsen CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1]],
986c18ec02fSPetter Reinholdtsen rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 2]);
987c18ec02fSPetter Reinholdtsen }
988c18ec02fSPetter Reinholdtsen }
989c18ec02fSPetter Reinholdtsen }
990c18ec02fSPetter Reinholdtsen printf("\n");
991c18ec02fSPetter Reinholdtsen return rc;
992c18ec02fSPetter Reinholdtsen }
993c18ec02fSPetter Reinholdtsen
994c18ec02fSPetter Reinholdtsen int
KfwumGetInfoFromFirmware(unsigned char * pBuf,unsigned long bufSize,tKFWUM_InFirmwareInfo * pInfo)995c18ec02fSPetter Reinholdtsen KfwumGetInfoFromFirmware(unsigned char *pBuf, unsigned long bufSize,
996c18ec02fSPetter Reinholdtsen tKFWUM_InFirmwareInfo *pInfo)
997c18ec02fSPetter Reinholdtsen {
998c18ec02fSPetter Reinholdtsen unsigned long offset = 0;
999c18ec02fSPetter Reinholdtsen if (bufSize < (IN_FIRMWARE_INFO_OFFSET_LOCATION + IN_FIRMWARE_INFO_SIZE)) {
1000c18ec02fSPetter Reinholdtsen return (-1);
1001c18ec02fSPetter Reinholdtsen }
1002c18ec02fSPetter Reinholdtsen offset = IN_FIRMWARE_INFO_OFFSET_LOCATION;
1003c18ec02fSPetter Reinholdtsen
1004c18ec02fSPetter Reinholdtsen /* Now, fill the structure with read informations */
1005c18ec02fSPetter Reinholdtsen pInfo->checksum = (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
1006c18ec02fSPetter Reinholdtsen offset + 0 + IN_FIRMWARE_INFO_OFFSET_CHECKSUM ) << 8;
1007c18ec02fSPetter Reinholdtsen
1008c18ec02fSPetter Reinholdtsen pInfo->checksum|= (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
1009c18ec02fSPetter Reinholdtsen offset + 1 + IN_FIRMWARE_INFO_OFFSET_CHECKSUM);
1010c18ec02fSPetter Reinholdtsen
1011c18ec02fSPetter Reinholdtsen pInfo->sumToRemoveFromChecksum = KWUM_GET_BYTE_AT_OFFSET(pBuf,
1012c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_CHECKSUM);
1013c18ec02fSPetter Reinholdtsen
1014c18ec02fSPetter Reinholdtsen pInfo->sumToRemoveFromChecksum+= KWUM_GET_BYTE_AT_OFFSET(pBuf,
1015c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_CHECKSUM + 1);
1016c18ec02fSPetter Reinholdtsen
1017c18ec02fSPetter Reinholdtsen pInfo->fileSize = KWUM_GET_BYTE_AT_OFFSET(pBuf,
1018c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 0) << 24;
1019c18ec02fSPetter Reinholdtsen
1020c18ec02fSPetter Reinholdtsen pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
1021c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 1) << 16;
1022c18ec02fSPetter Reinholdtsen
1023c18ec02fSPetter Reinholdtsen pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
1024c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 2) << 8;
1025c18ec02fSPetter Reinholdtsen
1026c18ec02fSPetter Reinholdtsen pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
1027c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 3);
1028c18ec02fSPetter Reinholdtsen
1029c18ec02fSPetter Reinholdtsen pInfo->boardId = KWUM_GET_BYTE_AT_OFFSET(pBuf,
1030c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_BOARD_ID + 0) << 8;
1031c18ec02fSPetter Reinholdtsen
1032c18ec02fSPetter Reinholdtsen pInfo->boardId|= KWUM_GET_BYTE_AT_OFFSET(pBuf,
1033c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_BOARD_ID + 1);
1034c18ec02fSPetter Reinholdtsen
1035c18ec02fSPetter Reinholdtsen pInfo->deviceId = KWUM_GET_BYTE_AT_OFFSET(pBuf,
1036c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_DEVICE_ID);
1037c18ec02fSPetter Reinholdtsen
1038c18ec02fSPetter Reinholdtsen pInfo->tableVers = KWUM_GET_BYTE_AT_OFFSET(pBuf,
1039c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION);
1040c18ec02fSPetter Reinholdtsen
1041c18ec02fSPetter Reinholdtsen pInfo->implRev = KWUM_GET_BYTE_AT_OFFSET(pBuf,
1042c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV);
1043c18ec02fSPetter Reinholdtsen
1044c18ec02fSPetter Reinholdtsen pInfo->versMajor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
1045c18ec02fSPetter Reinholdtsen offset
1046c18ec02fSPetter Reinholdtsen + IN_FIRMWARE_INFO_OFFSET_VER_MAJOROR)) & 0x0f;
1047c18ec02fSPetter Reinholdtsen
1048c18ec02fSPetter Reinholdtsen pInfo->versMinor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
1049c18ec02fSPetter Reinholdtsen offset
1050c18ec02fSPetter Reinholdtsen + IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB) >> 4) & 0x0f;
1051c18ec02fSPetter Reinholdtsen
1052c18ec02fSPetter Reinholdtsen pInfo->versSubMinor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
1053c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB)) & 0x0f;
1054c18ec02fSPetter Reinholdtsen
1055c18ec02fSPetter Reinholdtsen pInfo->sdrRev = KWUM_GET_BYTE_AT_OFFSET(pBuf,
1056c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_SDR_REV);
1057c18ec02fSPetter Reinholdtsen
1058c18ec02fSPetter Reinholdtsen pInfo->iana = KWUM_GET_BYTE_AT_OFFSET(pBuf,
1059c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_IANA2) << 16;
1060c18ec02fSPetter Reinholdtsen
1061c18ec02fSPetter Reinholdtsen pInfo->iana|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
1062c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_IANA1) << 8;
1063c18ec02fSPetter Reinholdtsen
1064c18ec02fSPetter Reinholdtsen pInfo->iana|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
1065c18ec02fSPetter Reinholdtsen offset + IN_FIRMWARE_INFO_OFFSET_IANA0);
1066c18ec02fSPetter Reinholdtsen
1067c18ec02fSPetter Reinholdtsen KfwumFixTableVersionForOldFirmware(pInfo);
1068c18ec02fSPetter Reinholdtsen return 0;
1069c18ec02fSPetter Reinholdtsen }
1070c18ec02fSPetter Reinholdtsen
1071c18ec02fSPetter Reinholdtsen void
KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo)1072c18ec02fSPetter Reinholdtsen KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo)
1073c18ec02fSPetter Reinholdtsen {
1074c18ec02fSPetter Reinholdtsen switch(pInfo->boardId) {
1075c18ec02fSPetter Reinholdtsen case KFWUM_BOARD_KONTRON_UNKNOWN:
1076c18ec02fSPetter Reinholdtsen pInfo->tableVers = 0xff;
1077c18ec02fSPetter Reinholdtsen break;
1078c18ec02fSPetter Reinholdtsen default:
1079c18ec02fSPetter Reinholdtsen /* pInfo->tableVers is already set for
1080c18ec02fSPetter Reinholdtsen * the right version
1081c18ec02fSPetter Reinholdtsen */
1082c18ec02fSPetter Reinholdtsen break;
1083c18ec02fSPetter Reinholdtsen }
1084c18ec02fSPetter Reinholdtsen }
1085c18ec02fSPetter Reinholdtsen
1086c18ec02fSPetter Reinholdtsen /* ipmi_kfwum_checkfwcompat - check whether firmware we're about to upload is
1087c18ec02fSPetter Reinholdtsen * compatible with board.
1088c18ec02fSPetter Reinholdtsen *
1089c18ec02fSPetter Reinholdtsen * @boardInfo:
1090c18ec02fSPetter Reinholdtsen * @firmInfo:
1091c18ec02fSPetter Reinholdtsen *
1092c18ec02fSPetter Reinholdtsen * returns 0 if compatible, otherwise (-1)
1093c18ec02fSPetter Reinholdtsen */
1094c18ec02fSPetter Reinholdtsen int
ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo,tKFWUM_InFirmwareInfo firmInfo)1095c18ec02fSPetter Reinholdtsen ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo,
1096c18ec02fSPetter Reinholdtsen tKFWUM_InFirmwareInfo firmInfo)
1097c18ec02fSPetter Reinholdtsen {
1098c18ec02fSPetter Reinholdtsen int compatible = 0;
1099c18ec02fSPetter Reinholdtsen if (boardInfo.iana != firmInfo.iana) {
1100c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
1101c18ec02fSPetter Reinholdtsen "Board IANA does not match firmware IANA.");
1102c18ec02fSPetter Reinholdtsen compatible = (-1);
1103c18ec02fSPetter Reinholdtsen }
1104c18ec02fSPetter Reinholdtsen if (boardInfo.boardId != firmInfo.boardId) {
1105c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
1106c18ec02fSPetter Reinholdtsen "Board IANA does not match firmware IANA.");
1107c18ec02fSPetter Reinholdtsen compatible = (-1);
1108c18ec02fSPetter Reinholdtsen }
1109c18ec02fSPetter Reinholdtsen if (compatible != 0) {
1110c18ec02fSPetter Reinholdtsen lprintf(LOG_ERR,
1111c18ec02fSPetter Reinholdtsen "Firmware invalid for target board. Download of upgrade aborted.");
1112c18ec02fSPetter Reinholdtsen }
1113c18ec02fSPetter Reinholdtsen return compatible;
1114c18ec02fSPetter Reinholdtsen }
1115c18ec02fSPetter Reinholdtsen
1116c18ec02fSPetter Reinholdtsen void
printf_kfwum_info(tKFWUM_BoardInfo boardInfo,tKFWUM_InFirmwareInfo firmInfo)1117c18ec02fSPetter Reinholdtsen printf_kfwum_info(tKFWUM_BoardInfo boardInfo, tKFWUM_InFirmwareInfo firmInfo)
1118c18ec02fSPetter Reinholdtsen {
1119c18ec02fSPetter Reinholdtsen printf(
1120c18ec02fSPetter Reinholdtsen "Target Board Id : %u\n", boardInfo.boardId);
1121c18ec02fSPetter Reinholdtsen printf(
1122c18ec02fSPetter Reinholdtsen "Target IANA number : %u\n", boardInfo.iana);
1123c18ec02fSPetter Reinholdtsen printf(
1124c18ec02fSPetter Reinholdtsen "File Size : %lu bytes\n", firmInfo.fileSize);
1125c18ec02fSPetter Reinholdtsen printf(
1126c18ec02fSPetter Reinholdtsen "Firmware Version : %d.%d%d SDR %d\n", firmInfo.versMajor,
1127c18ec02fSPetter Reinholdtsen firmInfo.versMinor, firmInfo.versSubMinor, firmInfo.sdrRev);
1128c18ec02fSPetter Reinholdtsen }
1129