Blame lib/ipmi_fwum.c

Packit d14fb6
/*
Packit d14fb6
 * Copyright (c) 2004 Kontron Canada, Inc.  All Rights Reserved.
Packit d14fb6
 *
Packit d14fb6
 * Base on code from
Packit d14fb6
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
Packit d14fb6
 *
Packit d14fb6
 * Redistribution and use in source and binary forms, with or without
Packit d14fb6
 * modification, are permitted provided that the following conditions
Packit d14fb6
 * are met:
Packit d14fb6
 *
Packit d14fb6
 * Redistribution of source code must retain the above copyright
Packit d14fb6
 * notice, this list of conditions and the following disclaimer.
Packit d14fb6
 *
Packit d14fb6
 * Redistribution in binary form must reproduce the above copyright
Packit d14fb6
 * notice, this list of conditions and the following disclaimer in the
Packit d14fb6
 * documentation and/or other materials provided with the distribution.
Packit d14fb6
 *
Packit d14fb6
 * Neither the name of Sun Microsystems, Inc. or the names of
Packit d14fb6
 * contributors may be used to endorse or promote products derived
Packit d14fb6
 * from this software without specific prior written permission.
Packit d14fb6
 *
Packit d14fb6
 * This software is provided "AS IS," without a warranty of any kind.
Packit d14fb6
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
Packit d14fb6
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
Packit d14fb6
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
Packit d14fb6
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
Packit d14fb6
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
Packit d14fb6
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
Packit d14fb6
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
Packit d14fb6
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
Packit d14fb6
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
Packit d14fb6
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
Packit d14fb6
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit d14fb6
 */
Packit d14fb6
Packit d14fb6
#include <string.h>
Packit d14fb6
#include <math.h>
Packit d14fb6
#include <time.h>
Packit d14fb6
#include <unistd.h>
Packit d14fb6
Packit d14fb6
#include <ipmitool/log.h>
Packit d14fb6
#include <ipmitool/helper.h>
Packit d14fb6
#include <ipmitool/ipmi.h>
Packit d14fb6
#include <ipmitool/ipmi_fwum.h>
Packit d14fb6
#include <ipmitool/ipmi_intf.h>
Packit d14fb6
#include <ipmitool/ipmi_mc.h>
Packit d14fb6
Packit d14fb6
extern int verbose;
Packit d14fb6
unsigned char firmBuf[1024*512];
Packit d14fb6
tKFWUM_SaveFirmwareInfo save_fw_nfo;
Packit d14fb6
Packit d14fb6
int KfwumGetFileSize(const char *pFileName,
Packit d14fb6
		unsigned long *pFileSize);
Packit d14fb6
int KfwumSetupBuffersFromFile(const char *pFileName,
Packit d14fb6
		unsigned long fileSize);
Packit d14fb6
void KfwumShowProgress(const char *task, unsigned long current,
Packit d14fb6
		unsigned long total);
Packit d14fb6
unsigned short KfwumCalculateChecksumPadding(unsigned char *pBuffer,
Packit d14fb6
		unsigned long totalSize);
Packit d14fb6
int KfwumGetInfo(struct ipmi_intf *intf, unsigned char output,
Packit d14fb6
		unsigned char *pNumBank);
Packit d14fb6
int KfwumGetDeviceInfo(struct ipmi_intf *intf,
Packit d14fb6
		unsigned char output, tKFWUM_BoardInfo *pBoardInfo);
Packit d14fb6
int KfwumGetStatus(struct ipmi_intf *intf);
Packit d14fb6
int KfwumManualRollback(struct ipmi_intf *intf);
Packit d14fb6
int KfwumStartFirmwareImage(struct ipmi_intf *intf,
Packit d14fb6
		unsigned long length, unsigned short padding);
Packit d14fb6
int KfwumSaveFirmwareImage(struct ipmi_intf *intf,
Packit d14fb6
		unsigned char sequenceNumber, unsigned long address,
Packit d14fb6
		unsigned char *pFirmBuf, unsigned char *pInBufLength);
Packit d14fb6
int KfwumFinishFirmwareImage(struct ipmi_intf *intf,
Packit d14fb6
		tKFWUM_InFirmwareInfo firmInfo);
Packit d14fb6
int KfwumUploadFirmware(struct ipmi_intf *intf,
Packit d14fb6
		unsigned char *pBuffer, unsigned long totalSize);
Packit d14fb6
int KfwumStartFirmwareUpgrade(struct ipmi_intf *intf);
Packit d14fb6
int KfwumGetInfoFromFirmware(unsigned char *pBuf,
Packit d14fb6
		unsigned long bufSize, tKFWUM_InFirmwareInfo *pInfo);
Packit d14fb6
void KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo *pInfo);
Packit d14fb6
int KfwumGetTraceLog(struct ipmi_intf *intf);
Packit d14fb6
int ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo,
Packit d14fb6
		tKFWUM_InFirmwareInfo firmInfo);
Packit d14fb6
Packit d14fb6
int ipmi_fwum_fwupgrade(struct ipmi_intf *intf, char *file, int action);
Packit d14fb6
int ipmi_fwum_info(struct ipmi_intf *intf);
Packit d14fb6
int ipmi_fwum_status(struct ipmi_intf *intf);
Packit d14fb6
void printf_kfwum_help(void);
Packit d14fb6
void printf_kfwum_info(tKFWUM_BoardInfo boardInfo,
Packit d14fb6
		tKFWUM_InFirmwareInfo firmInfo);
Packit d14fb6
Packit d14fb6
/* String table */
Packit d14fb6
/* Must match eFWUM_CmdId */
Packit d14fb6
const char *CMD_ID_STRING[] = {
Packit d14fb6
	"GetFwInfo",
Packit d14fb6
	"KickWatchdog",
Packit d14fb6
	"GetLastAnswer",
Packit d14fb6
	"BootHandshake",
Packit d14fb6
	"ReportStatus",
Packit d14fb6
	"CtrlIPMBLine",
Packit d14fb6
	"SetFwState",
Packit d14fb6
	"GetFwStatus",
Packit d14fb6
	"GetSpiMemStatus",
Packit d14fb6
	"StartFwUpdate",
Packit d14fb6
	"StartFwImage",
Packit d14fb6
	"SaveFwImage",
Packit d14fb6
	"FinishFwImage",
Packit d14fb6
	"ReadFwImage",
Packit d14fb6
	"ManualRollback",
Packit d14fb6
	"GetTraceLog"
Packit d14fb6
};
Packit d14fb6
Packit d14fb6
const char *EXT_CMD_ID_STRING[] = {
Packit d14fb6
	"FwUpgradeLock",
Packit d14fb6
	"ProcessFwUpg",
Packit d14fb6
	"ProcessFwRb",
Packit d14fb6
	"WaitHSAfterUpg",
Packit d14fb6
	"WaitFirstHSUpg",
Packit d14fb6
	"FwInfoStateChange"
Packit d14fb6
};
Packit d14fb6
Packit d14fb6
const char *CMD_STATE_STRING[] = {
Packit d14fb6
	"Invalid",
Packit d14fb6
	"Begin",
Packit d14fb6
	"Progress",
Packit d14fb6
	"Completed"
Packit d14fb6
};
Packit d14fb6
Packit d14fb6
const struct valstr bankStateValS[] = {
Packit d14fb6
	{ 0x00, "Not programmed" },
Packit d14fb6
	{ 0x01, "New firmware" },
Packit d14fb6
	{ 0x02, "Wait for validation" },
Packit d14fb6
	{ 0x03, "Last Known Good" },
Packit d14fb6
	{ 0x04, "Previous Good" }
Packit d14fb6
};
Packit d14fb6
Packit d14fb6
/* ipmi_fwum_main  -  entry point for this ipmitool mode
Packit d14fb6
 *
Packit d14fb6
 * @intf: ipmi interface
Packit d14fb6
 * @arc: number of arguments
Packit d14fb6
 * @argv: point to argument array
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success
Packit d14fb6
 * returns -1 on error
Packit d14fb6
 */
Packit d14fb6
int
Packit d14fb6
ipmi_fwum_main(struct ipmi_intf *intf, int argc, char **argv)
Packit d14fb6
{
Packit d14fb6
	int rc = 0;
Packit d14fb6
	printf("FWUM extension Version %d.%d\n", VER_MAJOR, VER_MINOR);
Packit d14fb6
	if (argc < 1) {
Packit d14fb6
		lprintf(LOG_ERR, "Not enough parameters given.");
Packit d14fb6
		printf_kfwum_help();
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (strncmp(argv[0], "help", 4) == 0) {
Packit d14fb6
		printf_kfwum_help();
Packit d14fb6
		rc = 0;
Packit d14fb6
	} else if (strncmp(argv[0], "info", 4) == 0) {
Packit d14fb6
		rc = ipmi_fwum_info(intf);
Packit d14fb6
	} else if (strncmp(argv[0], "status", 6) == 0) {
Packit d14fb6
		rc = ipmi_fwum_status(intf);
Packit d14fb6
	} else if (strncmp(argv[0], "rollback", 8) == 0) {
Packit d14fb6
		rc = KfwumManualRollback(intf);
Packit d14fb6
	} else if (strncmp(argv[0], "download", 8) == 0) {
Packit d14fb6
		if ((argc < 2) || (strlen(argv[1]) < 1)) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"Path and file name must be specified.");
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
		printf("Firmware File Name         : %s\n", argv[1]);
Packit d14fb6
		rc = ipmi_fwum_fwupgrade(intf, argv[1], 0);
Packit d14fb6
	} else if (strncmp(argv[0], "upgrade", 7) == 0) {
Packit d14fb6
		if ((argc >= 2) && (strlen(argv[1]) > 0)) {
Packit d14fb6
			printf("Upgrading using file name %s\n", argv[1]);
Packit d14fb6
			rc = ipmi_fwum_fwupgrade(intf, argv[1], 1);
Packit d14fb6
		} else {
Packit d14fb6
			rc = KfwumStartFirmwareUpgrade(intf);
Packit d14fb6
		}
Packit d14fb6
	} else if (strncmp(argv[0], "tracelog", 8) == 0) {
Packit d14fb6
		rc = KfwumGetTraceLog(intf);
Packit d14fb6
	} else {
Packit d14fb6
		lprintf(LOG_ERR, "Invalid KFWUM command: %s", argv[0]);
Packit d14fb6
		printf_kfwum_help();
Packit d14fb6
		rc = (-1);
Packit d14fb6
	}
Packit d14fb6
	return rc;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
printf_kfwum_help(void)
Packit d14fb6
{
Packit d14fb6
	lprintf(LOG_NOTICE,
Packit d14fb6
"KFWUM Commands:  info status download upgrade rollback tracelog");
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/*  private definitions and macros */
Packit d14fb6
typedef enum eFWUM_CmdId
Packit d14fb6
{
Packit d14fb6
	KFWUM_CMD_ID_GET_FIRMWARE_INFO                         = 0,
Packit d14fb6
	KFWUM_CMD_ID_KICK_IPMC_WATCHDOG                        = 1,
Packit d14fb6
	KFWUM_CMD_ID_GET_LAST_ANSWER                           = 2,
Packit d14fb6
	KFWUM_CMD_ID_BOOT_HANDSHAKE                            = 3,
Packit d14fb6
	KFWUM_CMD_ID_REPORT_STATUS                             = 4,
Packit d14fb6
	KFWUM_CMD_ID_GET_FIRMWARE_STATUS                       = 7,
Packit d14fb6
	KFWUM_CMD_ID_START_FIRMWARE_UPDATE                     = 9,
Packit d14fb6
	KFWUM_CMD_ID_START_FIRMWARE_IMAGE                      = 0x0a,
Packit d14fb6
	KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE                       = 0x0b,
Packit d14fb6
	KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE                     = 0x0c,
Packit d14fb6
	KFWUM_CMD_ID_READ_FIRMWARE_IMAGE                       = 0x0d,
Packit d14fb6
	KFWUM_CMD_ID_MANUAL_ROLLBACK                           = 0x0e,
Packit d14fb6
	KFWUM_CMD_ID_GET_TRACE_LOG                             = 0x0f,
Packit d14fb6
	KFWUM_CMD_ID_STD_MAX_CMD,
Packit d14fb6
	KFWUM_CMD_ID_EXTENDED_CMD                              = 0xC0
Packit d14fb6
}  tKFWUM_CmdId;
Packit d14fb6
Packit d14fb6
int
Packit d14fb6
ipmi_fwum_info(struct ipmi_intf *intf)
Packit d14fb6
{
Packit d14fb6
	tKFWUM_BoardInfo b_info;
Packit d14fb6
	int rc = 0;
Packit d14fb6
	unsigned char not_used;
Packit d14fb6
	if (verbose) {
Packit d14fb6
		printf("Getting Kontron FWUM Info\n");
Packit d14fb6
	}
Packit d14fb6
	if (KfwumGetDeviceInfo(intf, 1, &b_info) != 0) {
Packit d14fb6
		rc = (-1);
Packit d14fb6
	}
Packit d14fb6
	if (KfwumGetInfo(intf, 1, &not_used) != 0) {
Packit d14fb6
		rc = (-1);
Packit d14fb6
	}
Packit d14fb6
	return rc;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
int
Packit d14fb6
ipmi_fwum_status(struct ipmi_intf *intf)
Packit d14fb6
{
Packit d14fb6
	if (verbose) {
Packit d14fb6
		printf("Getting Kontron FWUM Status\n");
Packit d14fb6
	}
Packit d14fb6
	if (KfwumGetStatus(intf) != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* ipmi_fwum_fwupgrade - function implements download/upload of the firmware
Packit d14fb6
 * data received as parameters
Packit d14fb6
 *
Packit d14fb6
 * @file: fw file
Packit d14fb6
 * @action: 0 = download, 1 = upload/start upload
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success, otherwise (-1)
Packit d14fb6
 */
Packit d14fb6
int
Packit d14fb6
ipmi_fwum_fwupgrade(struct ipmi_intf *intf, char *file, int action)
Packit d14fb6
{
Packit d14fb6
	tKFWUM_BoardInfo b_info;
Packit d14fb6
	tKFWUM_InFirmwareInfo fw_info = { 0 };
Packit d14fb6
	unsigned short padding;
Packit d14fb6
	unsigned long fsize = 0;
Packit d14fb6
	unsigned char not_used;
Packit d14fb6
	if (file == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "No file given.");
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (KfwumGetFileSize(file, &fsize) != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (KfwumSetupBuffersFromFile(file, fsize) != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	padding = KfwumCalculateChecksumPadding(firmBuf, fsize);
Packit d14fb6
	if (KfwumGetInfoFromFirmware(firmBuf, fsize, &fw_info) != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (KfwumGetDeviceInfo(intf, 0, &b_info) != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (ipmi_kfwum_checkfwcompat(b_info, fw_info) != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	KfwumGetInfo(intf, 0, &not_used);
Packit d14fb6
	printf_kfwum_info(b_info, fw_info);
Packit d14fb6
	if (KfwumStartFirmwareImage(intf, fsize, padding) != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (KfwumUploadFirmware(intf, firmBuf, fsize) != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (KfwumFinishFirmwareImage(intf, fw_info) != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (KfwumGetStatus(intf) != 0) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (action != 0) {
Packit d14fb6
		if (KfwumStartFirmwareUpgrade(intf) != 0) {
Packit d14fb6
			return (-1);
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* KfwumGetFileSize  -  gets the file size
Packit d14fb6
 *
Packit d14fb6
 * @pFileName : filename ptr
Packit d14fb6
 * @pFileSize : output ptr for filesize
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success, otherwise (-1)
Packit d14fb6
 */
Packit d14fb6
int
Packit d14fb6
KfwumGetFileSize(const char *pFileName, unsigned long *pFileSize)
Packit d14fb6
{
Packit d14fb6
	FILE *pFileHandle = NULL;
Packit d14fb6
	pFileHandle = fopen(pFileName, "rb");
Packit d14fb6
	if (pFileHandle == NULL) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	if (fseek(pFileHandle, 0L , SEEK_END) == 0) {
Packit d14fb6
		*pFileSize = ftell(pFileHandle);
Packit d14fb6
	}
Packit d14fb6
	fclose(pFileHandle);
Packit d14fb6
	if (*pFileSize != 0) {
Packit d14fb6
		return 0;
Packit d14fb6
	}
Packit d14fb6
	return (-1);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* KfwumSetupBuffersFromFile  -  small buffers are used to store the file data
Packit d14fb6
 *
Packit d14fb6
 * @pFileName : filename ptr
Packit d14fb6
 * unsigned long : filesize
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success, otherwise (-1)
Packit d14fb6
 */
Packit d14fb6
int
Packit d14fb6
KfwumSetupBuffersFromFile(const char *pFileName, unsigned long fileSize)
Packit d14fb6
{
Packit d14fb6
	int rc = (-1);
Packit d14fb6
	FILE *pFileHandle = NULL;
Packit d14fb6
	int count;
Packit d14fb6
	int modulus;
Packit d14fb6
	int qty = 0;
Packit d14fb6
Packit d14fb6
	pFileHandle = fopen(pFileName, "rb");
Packit d14fb6
	if (pFileHandle == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Failed to open '%s' for reading.",
Packit d14fb6
				pFileName);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	count = fileSize / MAX_BUFFER_SIZE;
Packit d14fb6
	modulus = fileSize % MAX_BUFFER_SIZE;
Packit d14fb6
Packit d14fb6
	rewind(pFileHandle);
Packit d14fb6
	for (qty = 0; qty < count; qty++) {
Packit d14fb6
		KfwumShowProgress("Reading Firmware from File",
Packit d14fb6
				qty, count);
Packit d14fb6
		if (fread(&firmBuf[qty * MAX_BUFFER_SIZE], 1,
Packit d14fb6
					MAX_BUFFER_SIZE,
Packit d14fb6
					pFileHandle) == MAX_BUFFER_SIZE) {
Packit d14fb6
			rc = 0;
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	if (modulus) {
Packit d14fb6
		if (fread(&firmBuf[qty * MAX_BUFFER_SIZE], 1,
Packit d14fb6
					modulus, pFileHandle) == modulus) {
Packit d14fb6
			rc = 0;
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	if (rc == 0) {
Packit d14fb6
		KfwumShowProgress("Reading Firmware from File", 100, 100);
Packit d14fb6
	}
Packit d14fb6
	fclose(pFileHandle);
Packit d14fb6
	return rc;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* KfwumShowProgress  -  helper routine to display progress bar
Packit d14fb6
 *
Packit d14fb6
 * Converts current/total in percent
Packit d14fb6
 *
Packit d14fb6
 * *task  : string identifying current operation
Packit d14fb6
 * current: progress
Packit d14fb6
 * total  : limit
Packit d14fb6
 */
Packit d14fb6
void
Packit d14fb6
KfwumShowProgress(const char *task, unsigned long current, unsigned long total)
Packit d14fb6
{
Packit d14fb6
# define PROG_LENGTH 42
Packit d14fb6
	static unsigned long staticProgress=0xffffffff;
Packit d14fb6
	unsigned char spaces[PROG_LENGTH + 1];
Packit d14fb6
	unsigned short hash;
Packit d14fb6
	float percent = ((float)current / total);
Packit d14fb6
	unsigned long progress =  100 * (percent);
Packit d14fb6
Packit d14fb6
	if (staticProgress == progress) {
Packit d14fb6
		/* We displayed the same last time.. so don't do it */
Packit d14fb6
		return;
Packit d14fb6
	}
Packit d14fb6
	staticProgress = progress;
Packit d14fb6
	printf("%-25s : ", task); /* total 20 bytes */
Packit d14fb6
	hash = (percent * PROG_LENGTH);
Packit d14fb6
	memset(spaces, '#', hash);
Packit d14fb6
	spaces[hash] = '\0';
Packit d14fb6
Packit d14fb6
	printf("%s", spaces);
Packit d14fb6
	memset(spaces, ' ', (PROG_LENGTH - hash));
Packit d14fb6
	spaces[(PROG_LENGTH - hash)] = '\0';
Packit d14fb6
	printf("%s", spaces );
Packit d14fb6
Packit d14fb6
	printf(" %3ld %%\r", progress); /* total 7 bytes */
Packit d14fb6
	if (progress == 100) {
Packit d14fb6
		printf("\n");
Packit d14fb6
	}
Packit d14fb6
	fflush(stdout);
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* KfwumCalculateChecksumPadding - TBD
Packit d14fb6
 */
Packit d14fb6
unsigned short
Packit d14fb6
KfwumCalculateChecksumPadding(unsigned char *pBuffer, unsigned long totalSize)
Packit d14fb6
{
Packit d14fb6
	unsigned short sumOfBytes = 0;
Packit d14fb6
	unsigned short padding;
Packit d14fb6
	unsigned long  counter;
Packit d14fb6
	for (counter = 0; counter < totalSize; counter ++) {
Packit d14fb6
		sumOfBytes += pBuffer[counter];
Packit d14fb6
	}
Packit d14fb6
	padding = 0 - sumOfBytes;
Packit d14fb6
	return padding;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* KfwumGetInfo  -  Get Firmware Update Manager (FWUM) information
Packit d14fb6
 *
Packit d14fb6
 * *intf  : IPMI interface
Packit d14fb6
 * output  : when set to non zero, queried information is displayed
Packit d14fb6
 * pNumBank: output ptr for number of banks
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success, otherwise (-1)
Packit d14fb6
 */
Packit d14fb6
int
Packit d14fb6
KfwumGetInfo(struct ipmi_intf *intf, unsigned char output,
Packit d14fb6
		unsigned char *pNumBank)
Packit d14fb6
{
Packit d14fb6
	int rc = 0;
Packit d14fb6
	static struct KfwumGetInfoResp *pGetInfo;
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_FIRMWARE;
Packit d14fb6
	req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_INFO;
Packit d14fb6
	req.msg.data_len = 0;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (!rsp) {
Packit d14fb6
		lprintf(LOG_ERR, "Error in FWUM Firmware Get Info Command.");
Packit d14fb6
		return (-1);
Packit d14fb6
	} else if (rsp->ccode != 0) {
Packit d14fb6
		lprintf(LOG_ERR, "FWUM Firmware Get Info returned %x",
Packit d14fb6
				rsp->ccode);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
Packit d14fb6
	pGetInfo = (struct KfwumGetInfoResp *)rsp->data;
Packit d14fb6
	if (output) {
Packit d14fb6
		printf("\nFWUM info\n");
Packit d14fb6
		printf("=========\n");
Packit d14fb6
		printf("Protocol Revision         : %02Xh\n",
Packit d14fb6
				pGetInfo->protocolRevision);
Packit d14fb6
		printf("Controller Device Id      : %02Xh\n",
Packit d14fb6
				pGetInfo->controllerDeviceId);
Packit d14fb6
		printf("Firmware Revision         : %u.%u%u",
Packit d14fb6
				pGetInfo->firmRev1, pGetInfo->firmRev2 >> 4,
Packit d14fb6
				pGetInfo->firmRev2 & 0x0f);
Packit d14fb6
		if (pGetInfo->byte.mode != 0) {
Packit d14fb6
			printf(" - DEBUG BUILD\n");
Packit d14fb6
		} else {
Packit d14fb6
			printf("\n");
Packit d14fb6
		}
Packit d14fb6
		printf("Number Of Memory Bank     : %u\n", pGetInfo->numBank);
Packit d14fb6
	}
Packit d14fb6
	*pNumBank = pGetInfo->numBank;
Packit d14fb6
	/* Determine wich type of download to use: */
Packit d14fb6
	/* Old FWUM or Old IPMC fw (data_len < 7)
Packit d14fb6
	 * --> Address with small buffer size
Packit d14fb6
	 */
Packit d14fb6
	if ((pGetInfo->protocolRevision) <= 0x05 || (rsp->data_len < 7 )) {
Packit d14fb6
		save_fw_nfo.downloadType = KFWUM_DOWNLOAD_TYPE_ADDRESS;
Packit d14fb6
		save_fw_nfo.bufferSize   = KFWUM_SMALL_BUFFER;
Packit d14fb6
		save_fw_nfo.overheadSize = KFWUM_OLD_CMD_OVERHEAD;
Packit d14fb6
		if (verbose) {
Packit d14fb6
			printf("Protocol Revision          :");
Packit d14fb6
			printf(" <= 5 detected, adjusting buffers\n");
Packit d14fb6
		}
Packit d14fb6
	} else {
Packit d14fb6
		/* Both fw are using the new protocol */
Packit d14fb6
		save_fw_nfo.downloadType = KFWUM_DOWNLOAD_TYPE_SEQUENCE;
Packit d14fb6
		save_fw_nfo.overheadSize = KFWUM_NEW_CMD_OVERHEAD;
Packit d14fb6
		/* Buffer size depending on access type (Local or remote) */
Packit d14fb6
		/* Look if we run remote or locally */
Packit d14fb6
		if (verbose) {
Packit d14fb6
			printf("Protocol Revision          :");
Packit d14fb6
			printf(" > 5 optimizing buffers\n");
Packit d14fb6
		}
Packit d14fb6
		if (strstr(intf->name,"lan") != NULL) {
Packit d14fb6
			/* also covers lanplus */
Packit d14fb6
			save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
Packit d14fb6
			if (verbose) {
Packit d14fb6
				printf("IOL payload size           : %d\n",
Packit d14fb6
						save_fw_nfo.bufferSize);
Packit d14fb6
			}
Packit d14fb6
		} else if ((strstr(intf->name,"open")!= NULL)
Packit d14fb6
				&& intf->target_addr != IPMI_BMC_SLAVE_ADDR 
Packit d14fb6
				&& (intf->target_addr !=  intf->my_addr)) {
Packit d14fb6
			save_fw_nfo.bufferSize = KFWUM_SMALL_BUFFER;
Packit d14fb6
			if (verbose) {
Packit d14fb6
				printf("IPMB payload size          : %d\n",
Packit d14fb6
						save_fw_nfo.bufferSize);
Packit d14fb6
			}
Packit d14fb6
		} else {
Packit d14fb6
			save_fw_nfo.bufferSize = KFWUM_BIG_BUFFER;
Packit d14fb6
			if (verbose) {
Packit d14fb6
				printf("SMI payload size           : %d\n",
Packit d14fb6
						save_fw_nfo.bufferSize);
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	return rc;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* KfwumGetDeviceInfo - Get IPMC/Board information
Packit d14fb6
 *
Packit d14fb6
 * *intf: IPMI interface
Packit d14fb6
 * output: when set to non zero, queried information is displayed
Packit d14fb6
 * tKFWUM_BoardInfo: output ptr for IPMC/Board information
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success, otherwise (-1)
Packit d14fb6
 */
Packit d14fb6
int
Packit d14fb6
KfwumGetDeviceInfo(struct ipmi_intf *intf, unsigned char output,
Packit d14fb6
		tKFWUM_BoardInfo *pBoardInfo)
Packit d14fb6
{
Packit d14fb6
	struct ipm_devid_rsp *pGetDevId;
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	/* Send Get Device Id */
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_APP;
Packit d14fb6
	req.msg.cmd = BMC_GET_DEVICE_ID;
Packit d14fb6
	req.msg.data_len = 0;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Error in Get Device Id Command");
Packit d14fb6
		return (-1);
Packit d14fb6
	} else if (rsp->ccode != 0) {
Packit d14fb6
		lprintf(LOG_ERR, "Get Device Id returned %x",
Packit d14fb6
				rsp->ccode);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	pGetDevId = (struct ipm_devid_rsp *)rsp->data;
Packit d14fb6
	pBoardInfo->iana = IPM_DEV_MANUFACTURER_ID(pGetDevId->manufacturer_id);
Packit d14fb6
	pBoardInfo->boardId = buf2short(pGetDevId->product_id);
Packit d14fb6
	if (output) {
Packit d14fb6
		printf("\nIPMC Info\n");
Packit d14fb6
		printf("=========\n");
Packit d14fb6
		printf("Manufacturer Id           : %u\n",
Packit d14fb6
				pBoardInfo->iana);
Packit d14fb6
		printf("Board Id                  : %u\n",
Packit d14fb6
				pBoardInfo->boardId);
Packit d14fb6
		printf("Firmware Revision         : %u.%u%u",
Packit d14fb6
				pGetDevId->fw_rev1, pGetDevId->fw_rev2 >> 4,
Packit d14fb6
				pGetDevId->fw_rev2 & 0x0f);
Packit d14fb6
		if (((pBoardInfo->iana == IPMI_OEM_KONTRON)
Packit d14fb6
					&& (pBoardInfo->boardId == KFWUM_BOARD_KONTRON_5002))) {
Packit d14fb6
			printf(" SDR %u", pGetDevId->aux_fw_rev[0]);
Packit d14fb6
		}
Packit d14fb6
		printf("\n");
Packit d14fb6
	}
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* KfwumGetStatus  -  Get (and prints) FWUM  banks information
Packit d14fb6
 *
Packit d14fb6
 * *intf  : IPMI interface
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success, otherwise (-1)
Packit d14fb6
 */
Packit d14fb6
int
Packit d14fb6
KfwumGetStatus(struct ipmi_intf * intf)
Packit d14fb6
{
Packit d14fb6
	int rc = 0;
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	struct KfwumGetStatusResp *pGetStatus;
Packit d14fb6
	unsigned char numBank;
Packit d14fb6
	unsigned char counter;
Packit d14fb6
	unsigned long firmLength;
Packit d14fb6
	if (verbose) {
Packit d14fb6
		printf(" Getting Status!\n");
Packit d14fb6
	}
Packit d14fb6
	/* Retreive the number of bank */
Packit d14fb6
	rc = KfwumGetInfo(intf, 0, &numBank);
Packit d14fb6
	for(counter = 0;
Packit d14fb6
			(counter < numBank) && (rc == 0);
Packit d14fb6
			counter ++) {
Packit d14fb6
		/* Retreive the status of each bank */
Packit d14fb6
		memset(&req, 0, sizeof(req));
Packit d14fb6
		req.msg.netfn = IPMI_NETFN_FIRMWARE;
Packit d14fb6
		req.msg.cmd = KFWUM_CMD_ID_GET_FIRMWARE_STATUS;
Packit d14fb6
		req.msg.data = &counter;
Packit d14fb6
		req.msg.data_len = 1;
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"Error in FWUM Firmware Get Status Command.");
Packit d14fb6
			rc = (-1);
Packit d14fb6
			break;
Packit d14fb6
		} else if (rsp->ccode) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"FWUM Firmware Get Status returned %x",
Packit d14fb6
					rsp->ccode);
Packit d14fb6
			rc = (-1);
Packit d14fb6
			break;
Packit d14fb6
		}
Packit d14fb6
		pGetStatus = (struct KfwumGetStatusResp *) rsp->data;
Packit d14fb6
		printf("\nBank State %d               : %s\n",
Packit d14fb6
				counter,
Packit d14fb6
				val2str(pGetStatus->bankState, bankStateValS));
Packit d14fb6
		if (!pGetStatus->bankState) {
Packit d14fb6
			continue;
Packit d14fb6
		}
Packit d14fb6
		firmLength  = pGetStatus->firmLengthMSB;
Packit d14fb6
		firmLength  = firmLength << 8;
Packit d14fb6
		firmLength |= pGetStatus->firmLengthMid;
Packit d14fb6
		firmLength  = firmLength << 8;
Packit d14fb6
		firmLength |= pGetStatus->firmLengthLSB;
Packit d14fb6
		printf("Firmware Length            : %ld bytes\n",
Packit d14fb6
				firmLength);
Packit d14fb6
		printf("Firmware Revision          : %u.%u%u SDR %u\n",
Packit d14fb6
				pGetStatus->firmRev1,
Packit d14fb6
				pGetStatus->firmRev2 >> 4,
Packit d14fb6
				pGetStatus->firmRev2 & 0x0f,
Packit d14fb6
				pGetStatus->firmRev3);
Packit d14fb6
	}
Packit d14fb6
	printf("\n");
Packit d14fb6
	return rc;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* KfwumManualRollback  -  Ask IPMC to rollback to previous version
Packit d14fb6
 *
Packit d14fb6
 * *intf  : IPMI interface
Packit d14fb6
 *
Packit d14fb6
 * returns 0 on success
Packit d14fb6
 * returns (-1) on error
Packit d14fb6
 */
Packit d14fb6
int
Packit d14fb6
KfwumManualRollback(struct ipmi_intf *intf)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	struct KfwumManualRollbackReq thisReq;
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_FIRMWARE;
Packit d14fb6
	req.msg.cmd = KFWUM_CMD_ID_MANUAL_ROLLBACK;
Packit d14fb6
	thisReq.type = 0; /* Wait BMC shutdown */
Packit d14fb6
	req.msg.data = (unsigned char *)&thisReq;
Packit d14fb6
	req.msg.data_len = 1;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR, "Error in FWUM Manual Rollback Command.");
Packit d14fb6
		return (-1);
Packit d14fb6
	} else if (rsp->ccode != 0) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Error in FWUM Manual Rollback Command returned %x",
Packit d14fb6
				rsp->ccode);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	printf("FWUM Starting Manual Rollback \n");
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
int
Packit d14fb6
KfwumStartFirmwareImage(struct ipmi_intf *intf, unsigned long length,
Packit d14fb6
		unsigned short padding)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	struct KfwumStartFirmwareDownloadResp *pResp;
Packit d14fb6
	struct KfwumStartFirmwareDownloadReq thisReq;
Packit d14fb6
Packit d14fb6
	thisReq.lengthLSB  = length         & 0x000000ff;
Packit d14fb6
	thisReq.lengthMid  = (length >>  8) & 0x000000ff;
Packit d14fb6
	thisReq.lengthMSB  = (length >> 16) & 0x000000ff;
Packit d14fb6
	thisReq.paddingLSB = padding        & 0x00ff;
Packit d14fb6
	thisReq.paddingMSB = (padding>>  8) & 0x00ff;
Packit d14fb6
	thisReq.useSequence = 0x01;
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_FIRMWARE;
Packit d14fb6
	req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_IMAGE;
Packit d14fb6
	req.msg.data = (unsigned char *) &thisReq;
Packit d14fb6
	/* Look for download type */
Packit d14fb6
	if (save_fw_nfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS) {
Packit d14fb6
		req.msg.data_len = 5;
Packit d14fb6
	} else {
Packit d14fb6
		req.msg.data_len = 6;
Packit d14fb6
	}
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Error in FWUM Firmware Start Firmware Image Download Command.");
Packit d14fb6
		return (-1);
Packit d14fb6
	} else if (rsp->ccode) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"FWUM Firmware Start Firmware Image Download returned %x",
Packit d14fb6
				rsp->ccode);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	pResp = (struct KfwumStartFirmwareDownloadResp *)rsp->data;
Packit d14fb6
	printf("Bank holding new firmware  : %d\n", pResp->bank);
Packit d14fb6
	sleep(5);
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
int
Packit d14fb6
KfwumSaveFirmwareImage(struct ipmi_intf *intf, unsigned char sequenceNumber,
Packit d14fb6
		unsigned long address, unsigned char *pFirmBuf,
Packit d14fb6
		unsigned char *pInBufLength)
Packit d14fb6
{
Packit d14fb6
	int rc = 0;
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	struct KfwumSaveFirmwareAddressReq addr_req;
Packit d14fb6
	struct KfwumSaveFirmwareSequenceReq seq_req;
Packit d14fb6
	int retry = 0;
Packit d14fb6
	int no_rsp = 0;
Packit d14fb6
	do {
Packit d14fb6
		memset(&req, 0, sizeof(req));
Packit d14fb6
		req.msg.netfn = IPMI_NETFN_FIRMWARE;
Packit d14fb6
		req.msg.cmd = KFWUM_CMD_ID_SAVE_FIRMWARE_IMAGE;
Packit d14fb6
		if (save_fw_nfo.downloadType == KFWUM_DOWNLOAD_TYPE_ADDRESS) {
Packit d14fb6
			addr_req.addressLSB  = address         & 0x000000ff;
Packit d14fb6
			addr_req.addressMid  = (address >>  8) & 0x000000ff;
Packit d14fb6
			addr_req.addressMSB  = (address >> 16) & 0x000000ff;
Packit d14fb6
			addr_req.numBytes    = *pInBufLength;
Packit d14fb6
			memcpy(addr_req.txBuf, pFirmBuf, *pInBufLength);
Packit d14fb6
			req.msg.data = (unsigned char *)&addr_req;
Packit d14fb6
			req.msg.data_len = *pInBufLength + 4;
Packit d14fb6
		} else {
Packit d14fb6
			seq_req.sequenceNumber = sequenceNumber;
Packit d14fb6
			memcpy(seq_req.txBuf, pFirmBuf, *pInBufLength);
Packit d14fb6
			req.msg.data = (unsigned char *)&seq_req;
Packit d14fb6
			req.msg.data_len = *pInBufLength + sizeof(unsigned char);
Packit d14fb6
			/* + 1 => sequenceNumber*/
Packit d14fb6
		}
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"Error in FWUM Firmware Save Firmware Image Download Command.");
Packit d14fb6
			/* We don't receive "C7" on errors with IOL,
Packit d14fb6
			 * instead we receive nothing
Packit d14fb6
			 */
Packit d14fb6
			if (strstr(intf->name, "lan") != NULL) {
Packit d14fb6
				no_rsp++;
Packit d14fb6
				if (no_rsp < FWUM_SAVE_FIRMWARE_NO_RESPONSE_LIMIT) {
Packit d14fb6
					*pInBufLength -= 1;
Packit d14fb6
					continue;
Packit d14fb6
				}
Packit d14fb6
				lprintf(LOG_ERR,
Packit d14fb6
						"Error, too many commands without response.");
Packit d14fb6
				*pInBufLength = 0;
Packit d14fb6
				break;
Packit d14fb6
			} /* For other interface keep trying */
Packit d14fb6
		} else if (rsp->ccode != 0) {
Packit d14fb6
			if (rsp->ccode == 0xc0) {
Packit d14fb6
				sleep(1);
Packit d14fb6
			} else if ((rsp->ccode == 0xc7)
Packit d14fb6
					|| ((rsp->ccode == 0xc3)
Packit d14fb6
						&& (sequenceNumber == 0))) {
Packit d14fb6
				*pInBufLength -= 1;
Packit d14fb6
				retry = 1;
Packit d14fb6
			} else if (rsp->ccode == 0x82) {
Packit d14fb6
				/* Double sent, continue */
Packit d14fb6
				rc = 0;
Packit d14fb6
				break;
Packit d14fb6
			} else if (rsp->ccode == 0x83) {
Packit d14fb6
				if (retry == 0) {
Packit d14fb6
					retry = 1;
Packit d14fb6
					continue;
Packit d14fb6
				}
Packit d14fb6
				rc = (-1);
Packit d14fb6
				break;
Packit d14fb6
			} else if (rsp->ccode == 0xcf) {
Packit d14fb6
				/* Ok if receive duplicated request */
Packit d14fb6
				retry = 1;
Packit d14fb6
			} else if (rsp->ccode == 0xc3) {
Packit d14fb6
				if (retry == 0) {
Packit d14fb6
					retry = 1;
Packit d14fb6
					continue;
Packit d14fb6
				}
Packit d14fb6
				rc = (-1);
Packit d14fb6
				break;
Packit d14fb6
			} else {
Packit d14fb6
				lprintf(LOG_ERR,
Packit d14fb6
						"FWUM Firmware Save Firmware Image Download returned %x",
Packit d14fb6
						rsp->ccode);
Packit d14fb6
				rc = (-1);
Packit d14fb6
				break;
Packit d14fb6
			}
Packit d14fb6
		} else {
Packit d14fb6
			break;
Packit d14fb6
		}
Packit d14fb6
	} while (1);
Packit d14fb6
	return rc;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
int
Packit d14fb6
KfwumFinishFirmwareImage(struct ipmi_intf *intf, tKFWUM_InFirmwareInfo firmInfo)
Packit d14fb6
{
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	struct KfwumFinishFirmwareDownloadReq thisReq;
Packit d14fb6
Packit d14fb6
	thisReq.versionMaj = firmInfo.versMajor;
Packit d14fb6
	thisReq.versionMinSub = ((firmInfo.versMinor <<4)
Packit d14fb6
			| firmInfo.versSubMinor);
Packit d14fb6
	thisReq.versionSdr = firmInfo.sdrRev;
Packit d14fb6
	thisReq.reserved = 0;
Packit d14fb6
	/* Byte 4 reserved, write 0 */
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_FIRMWARE;
Packit d14fb6
	req.msg.cmd = KFWUM_CMD_ID_FINISH_FIRMWARE_IMAGE;
Packit d14fb6
	req.msg.data = (unsigned char *)&thisReq;
Packit d14fb6
	req.msg.data_len = 4;
Packit d14fb6
	/* Infinite loop if BMC doesn't reply or replies 0xc0 every time. */
Packit d14fb6
	do {
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	} while (rsp == NULL || rsp->ccode == 0xc0);
Packit d14fb6
Packit d14fb6
	if (rsp->ccode != 0) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"FWUM Firmware Finish Firmware Image Download returned %x",
Packit d14fb6
				rsp->ccode);
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
int
Packit d14fb6
KfwumUploadFirmware(struct ipmi_intf *intf, unsigned char *pBuffer,
Packit d14fb6
		unsigned long totalSize)
Packit d14fb6
{
Packit d14fb6
	int rc = (-1);
Packit d14fb6
	unsigned long address = 0x0;
Packit d14fb6
	unsigned char writeSize;
Packit d14fb6
	unsigned char oldWriteSize;
Packit d14fb6
	unsigned long lastAddress = 0;
Packit d14fb6
	unsigned char sequenceNumber = 0;
Packit d14fb6
	unsigned char retry = FWUM_MAX_UPLOAD_RETRY;
Packit d14fb6
	do {
Packit d14fb6
		writeSize = save_fw_nfo.bufferSize - save_fw_nfo.overheadSize;
Packit d14fb6
		/* Reach the end */
Packit d14fb6
		if (address + writeSize > totalSize) {
Packit d14fb6
			writeSize = (totalSize - address);
Packit d14fb6
		} else if (((address % KFWUM_PAGE_SIZE)
Packit d14fb6
					+ writeSize) > KFWUM_PAGE_SIZE) {
Packit d14fb6
			/* Reach boundary end */
Packit d14fb6
			writeSize = (KFWUM_PAGE_SIZE - (address % KFWUM_PAGE_SIZE));
Packit d14fb6
		}
Packit d14fb6
		oldWriteSize = writeSize;
Packit d14fb6
		rc = KfwumSaveFirmwareImage(intf, sequenceNumber,
Packit d14fb6
				address, &pBuffer[address], &writeSize);
Packit d14fb6
		if ((rc != 0) && (retry-- != 0)) {
Packit d14fb6
			address = lastAddress;
Packit d14fb6
			rc = 0;
Packit d14fb6
		} else if ( writeSize == 0) {
Packit d14fb6
			rc = (-1);
Packit d14fb6
		} else {
Packit d14fb6
			if (writeSize != oldWriteSize) {
Packit d14fb6
				printf("Adjusting length to %d bytes \n",
Packit d14fb6
						writeSize);
Packit d14fb6
				save_fw_nfo.bufferSize -= (oldWriteSize - writeSize);
Packit d14fb6
			}
Packit d14fb6
			retry = FWUM_MAX_UPLOAD_RETRY;
Packit d14fb6
			lastAddress = address;
Packit d14fb6
			address+= writeSize;
Packit d14fb6
		}
Packit d14fb6
		if (rc == 0) {
Packit d14fb6
			if ((address % 1024) == 0) {
Packit d14fb6
				KfwumShowProgress("Writing Firmware in Flash",
Packit d14fb6
						address, totalSize);
Packit d14fb6
			}
Packit d14fb6
			sequenceNumber++;
Packit d14fb6
		}
Packit d14fb6
	} while ((rc == 0) && (address < totalSize));
Packit d14fb6
	if (rc == 0) {
Packit d14fb6
		KfwumShowProgress("Writing Firmware in Flash",
Packit d14fb6
				100, 100);
Packit d14fb6
	}
Packit d14fb6
	return rc;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
int
Packit d14fb6
KfwumStartFirmwareUpgrade(struct ipmi_intf *intf)
Packit d14fb6
{
Packit d14fb6
	int rc = 0;
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	/* Upgrade type, wait BMC shutdown */
Packit d14fb6
	unsigned char upgType = 0 ;
Packit d14fb6
Packit d14fb6
	memset(&req, 0, sizeof(req));
Packit d14fb6
	req.msg.netfn = IPMI_NETFN_FIRMWARE;
Packit d14fb6
	req.msg.cmd = KFWUM_CMD_ID_START_FIRMWARE_UPDATE;
Packit d14fb6
	req.msg.data = (unsigned char *) &upgType;
Packit d14fb6
	req.msg.data_len = 1;
Packit d14fb6
Packit d14fb6
	rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
	if (rsp == NULL) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Error in FWUM Firmware Start Firmware Upgrade Command");
Packit d14fb6
		rc = (-1);
Packit d14fb6
	} else if (rsp->ccode) {
Packit d14fb6
		if (rsp->ccode == 0xd5) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"No firmware available for upgrade.  Download Firmware first.");
Packit d14fb6
		} else {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"FWUM Firmware Start Firmware Upgrade returned %x",
Packit d14fb6
					rsp->ccode);
Packit d14fb6
		}
Packit d14fb6
		rc = (-1);
Packit d14fb6
	}
Packit d14fb6
	return rc;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
int
Packit d14fb6
KfwumGetTraceLog(struct ipmi_intf *intf)
Packit d14fb6
{
Packit d14fb6
	int rc = 0;
Packit d14fb6
	struct ipmi_rs *rsp;
Packit d14fb6
	struct ipmi_rq req;
Packit d14fb6
	unsigned char chunkIdx;
Packit d14fb6
	unsigned char cmdIdx;
Packit d14fb6
	if (verbose) {
Packit d14fb6
		printf(" Getting Trace Log!\n");
Packit d14fb6
	}
Packit d14fb6
	for (chunkIdx = 0;
Packit d14fb6
			(chunkIdx < TRACE_LOG_CHUNK_COUNT)
Packit d14fb6
			&& (rc == 0);
Packit d14fb6
			chunkIdx++) {
Packit d14fb6
		/* Retreive each log chunk and print it */
Packit d14fb6
		memset(&req, 0, sizeof(req));
Packit d14fb6
		req.msg.netfn = IPMI_NETFN_FIRMWARE;
Packit d14fb6
		req.msg.cmd = KFWUM_CMD_ID_GET_TRACE_LOG;
Packit d14fb6
		req.msg.data = &chunkIdx;
Packit d14fb6
		req.msg.data_len = 1;
Packit d14fb6
Packit d14fb6
		rsp = intf->sendrecv(intf, &req;;
Packit d14fb6
		if (rsp == NULL) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"Error in FWUM Firmware Get Trace Log Command");
Packit d14fb6
			rc = (-1);
Packit d14fb6
			break;
Packit d14fb6
		} else if (rsp->ccode) {
Packit d14fb6
			lprintf(LOG_ERR,
Packit d14fb6
					"FWUM Firmware Get Trace Log returned %x",
Packit d14fb6
					rsp->ccode);
Packit d14fb6
			rc = (-1);
Packit d14fb6
			break;
Packit d14fb6
		}
Packit d14fb6
		for (cmdIdx=0; cmdIdx < TRACE_LOG_CHUNK_SIZE; cmdIdx++) {
Packit d14fb6
			/* Don't diplay commands with an invalid state */
Packit d14fb6
			if ((rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1] != 0)
Packit d14fb6
					&& (rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx] < KFWUM_CMD_ID_STD_MAX_CMD)) {
Packit d14fb6
				printf("  Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
Packit d14fb6
						CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx]],
Packit d14fb6
						CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1]],
Packit d14fb6
						rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 2]);
Packit d14fb6
			} else if ((rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1] != 0)
Packit d14fb6
					&& (rsp->data[TRACE_LOG_ATT_COUNT*cmdIdx] >= KFWUM_CMD_ID_EXTENDED_CMD)) {
Packit d14fb6
				printf("  Cmd ID: %17s -- CmdState: %10s -- CompCode: %2x\n",
Packit d14fb6
						EXT_CMD_ID_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx] - KFWUM_CMD_ID_EXTENDED_CMD],
Packit d14fb6
						CMD_STATE_STRING[rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 1]],
Packit d14fb6
						rsp->data[TRACE_LOG_ATT_COUNT * cmdIdx + 2]);
Packit d14fb6
			}
Packit d14fb6
		}
Packit d14fb6
	}
Packit d14fb6
	printf("\n");
Packit d14fb6
	return rc;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
int
Packit d14fb6
KfwumGetInfoFromFirmware(unsigned char *pBuf, unsigned long bufSize,
Packit d14fb6
		tKFWUM_InFirmwareInfo *pInfo)
Packit d14fb6
{
Packit d14fb6
	unsigned long offset = 0;
Packit d14fb6
	if (bufSize < (IN_FIRMWARE_INFO_OFFSET_LOCATION + IN_FIRMWARE_INFO_SIZE)) {
Packit d14fb6
		return (-1);
Packit d14fb6
	}
Packit d14fb6
	offset = IN_FIRMWARE_INFO_OFFSET_LOCATION;
Packit d14fb6
Packit d14fb6
	/* Now, fill the structure with read informations */
Packit d14fb6
	pInfo->checksum = (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + 0 + IN_FIRMWARE_INFO_OFFSET_CHECKSUM ) << 8;
Packit d14fb6
Packit d14fb6
	pInfo->checksum|= (unsigned short)KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + 1 + IN_FIRMWARE_INFO_OFFSET_CHECKSUM);
Packit d14fb6
Packit d14fb6
	pInfo->sumToRemoveFromChecksum = KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_CHECKSUM);
Packit d14fb6
Packit d14fb6
	pInfo->sumToRemoveFromChecksum+= KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_CHECKSUM + 1);
Packit d14fb6
Packit d14fb6
	pInfo->fileSize = KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 0) << 24;
Packit d14fb6
Packit d14fb6
	pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 1) << 16;
Packit d14fb6
Packit d14fb6
	pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 2) << 8;
Packit d14fb6
Packit d14fb6
	pInfo->fileSize|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_FILE_SIZE + 3);
Packit d14fb6
Packit d14fb6
	pInfo->boardId = KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_BOARD_ID + 0) << 8;
Packit d14fb6
Packit d14fb6
	pInfo->boardId|= KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_BOARD_ID + 1);
Packit d14fb6
Packit d14fb6
	pInfo->deviceId = KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_DEVICE_ID);
Packit d14fb6
Packit d14fb6
	pInfo->tableVers = KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_TABLE_VERSION);
Packit d14fb6
Packit d14fb6
	pInfo->implRev = KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_IMPLEMENT_REV);
Packit d14fb6
Packit d14fb6
	pInfo->versMajor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
				offset
Packit d14fb6
				+ IN_FIRMWARE_INFO_OFFSET_VER_MAJOROR)) & 0x0f;
Packit d14fb6
Packit d14fb6
	pInfo->versMinor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
				offset
Packit d14fb6
				+ IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB) >> 4) & 0x0f;
Packit d14fb6
Packit d14fb6
	pInfo->versSubMinor = (KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
				offset + IN_FIRMWARE_INFO_OFFSET_VER_MINORSUB)) & 0x0f;
Packit d14fb6
Packit d14fb6
	pInfo->sdrRev = KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_SDR_REV);
Packit d14fb6
Packit d14fb6
	pInfo->iana = KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_IANA2) << 16;
Packit d14fb6
Packit d14fb6
	pInfo->iana|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_IANA1) << 8;
Packit d14fb6
Packit d14fb6
	pInfo->iana|= (unsigned long)KWUM_GET_BYTE_AT_OFFSET(pBuf,
Packit d14fb6
			offset + IN_FIRMWARE_INFO_OFFSET_IANA0);
Packit d14fb6
Packit d14fb6
	KfwumFixTableVersionForOldFirmware(pInfo);
Packit d14fb6
	return 0;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
KfwumFixTableVersionForOldFirmware(tKFWUM_InFirmwareInfo * pInfo)
Packit d14fb6
{
Packit d14fb6
	switch(pInfo->boardId) {
Packit d14fb6
	case KFWUM_BOARD_KONTRON_UNKNOWN:
Packit d14fb6
		pInfo->tableVers = 0xff;
Packit d14fb6
		break;
Packit d14fb6
	default:
Packit d14fb6
		/* pInfo->tableVers is already set for
Packit d14fb6
		 * the right version
Packit d14fb6
		 */
Packit d14fb6
		break;
Packit d14fb6
	}
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
/* ipmi_kfwum_checkfwcompat - check whether firmware we're about to upload is
Packit d14fb6
 * compatible with board.
Packit d14fb6
 *
Packit d14fb6
 * @boardInfo:
Packit d14fb6
 * @firmInfo:
Packit d14fb6
 *
Packit d14fb6
 * returns 0 if compatible, otherwise (-1)
Packit d14fb6
 */
Packit d14fb6
int
Packit d14fb6
ipmi_kfwum_checkfwcompat(tKFWUM_BoardInfo boardInfo,
Packit d14fb6
		tKFWUM_InFirmwareInfo firmInfo)
Packit d14fb6
{
Packit d14fb6
	int compatible = 0;
Packit d14fb6
	if (boardInfo.iana != firmInfo.iana) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Board IANA does not match firmware IANA.");
Packit d14fb6
		compatible = (-1);
Packit d14fb6
	}
Packit d14fb6
	if (boardInfo.boardId != firmInfo.boardId) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Board IANA does not match firmware IANA.");
Packit d14fb6
		compatible = (-1);
Packit d14fb6
	}
Packit d14fb6
	if (compatible != 0) {
Packit d14fb6
		lprintf(LOG_ERR,
Packit d14fb6
				"Firmware invalid for target board. Download of upgrade aborted.");
Packit d14fb6
	}
Packit d14fb6
	return compatible;
Packit d14fb6
}
Packit d14fb6
Packit d14fb6
void
Packit d14fb6
printf_kfwum_info(tKFWUM_BoardInfo boardInfo, tKFWUM_InFirmwareInfo firmInfo)
Packit d14fb6
{
Packit d14fb6
	printf(
Packit d14fb6
"Target Board Id            : %u\n", boardInfo.boardId);
Packit d14fb6
	printf(
Packit d14fb6
"Target IANA number         : %u\n", boardInfo.iana);
Packit d14fb6
	printf(
Packit d14fb6
"File Size                  : %lu bytes\n", firmInfo.fileSize);
Packit d14fb6
	printf(
Packit d14fb6
"Firmware Version           : %d.%d%d SDR %d\n", firmInfo.versMajor,
Packit d14fb6
firmInfo.versMinor, firmInfo.versSubMinor, firmInfo.sdrRev);
Packit d14fb6
}