Blame IbaTools/opasw/opaswfwverify/opaswfwverify.c

Packit 857059
/* BEGIN_ICS_COPYRIGHT7 ****************************************
Packit 857059
Packit 857059
Copyright (c) 2015-2017, Intel Corporation
Packit 857059
Packit 857059
Redistribution and use in source and binary forms, with or without
Packit 857059
modification, are permitted provided that the following conditions are met:
Packit 857059
Packit 857059
    * Redistributions of source code must retain the above copyright notice,
Packit 857059
      this list of conditions and the following disclaimer.
Packit 857059
    * Redistributions in binary form must reproduce the above copyright
Packit 857059
      notice, this list of conditions and the following disclaimer in the
Packit 857059
      documentation and/or other materials provided with the distribution.
Packit 857059
    * Neither the name of Intel Corporation nor the names of its contributors
Packit 857059
      may be used to endorse or promote products derived from this software
Packit 857059
      without specific prior written permission.
Packit 857059
Packit 857059
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 857059
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 857059
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit 857059
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
Packit 857059
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 857059
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
Packit 857059
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Packit 857059
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
Packit 857059
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 857059
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 857059
Packit 857059
** END_ICS_COPYRIGHT7   ****************************************/
Packit 857059
Packit 857059
/* [ICS VERSION STRING: unknown] */
Packit 857059
Packit 857059
#include <stdio.h>
Packit 857059
#include <string.h>
Packit 857059
#include <getopt.h>
Packit 857059
#include <limits.h>
Packit 857059
#include <dirent.h>
Packit 857059
#include <errno.h>
Packit 857059
Packit 857059
/* work around conflicting names */
Packit 857059
Packit 857059
#include "iba/ib_types.h"
Packit 857059
#include "iba/ib_sm_priv.h"
Packit 857059
#include "iba/ib_helper.h"
Packit 857059
#include "opamgt_sa_priv.h"
Packit 857059
#include <iba/ibt.h>
Packit 857059
#include "opaswcommon.h"
Packit 857059
#include "zlib.h"
Packit 857059
Packit 857059
#define FW_RESP_WAIT_TIME		2000
Packit 857059
Packit 857059
#define NEED_TO_RETRY(madStatus)	((madStatus == VM_MAD_STATUS_NACK) || (madStatus == VM_MAD_STATUS_BUS_BUSY) || (madStatus == VM_MAD_STATUS_BUS_HUNG) || (madStatus == VM_MAD_STATUS_LOST_ARB) || (madStatus == VM_MAD_STATUS_TIMEOUT))
Packit 857059
Packit 857059
// globals
Packit 857059
Packit 857059
int						g_debugMode = 0;
Packit 857059
int						g_verbose = 0;
Packit 857059
int						g_quiet = 0;
Packit 857059
int						g_gotHfi = 0;
Packit 857059
int						g_gotPort = 0;
Packit 857059
int						g_gotSecondary = 0;
Packit 857059
int						g_fileParam = 0;
Packit 857059
int						g_dirParam = 0;
Packit 857059
int32					g_sleepParam = 0;
Packit 857059
int32					g_usleepParam = 0;
Packit 857059
int32					g_dataLenParam = 0;
Packit 857059
int32					g_respTimeout = FW_RESP_WAIT_TIME;
Packit 857059
int						g_compareEEPROMs = 0;
Packit 857059
Packit 857059
typedef uint8_t bool_t;
Packit 857059
Packit 857059
#define LIST_FILE_SUPPORTED 0
Packit 857059
Packit 857059
static void usage(char *app_name)
Packit 857059
{
Packit 857059
	fprintf(stderr, "usage: %s -t target\n", app_name);
Packit 857059
#if LIST_FILE_SUPPORTED
Packit 857059
	fprintf(stderr, " [-l list_file]");
Packit 857059
#endif
Packit 857059
	fprintf(stderr, " [-v|-q] [-h hfi] [-o port] [-m module] [-F]");
Packit 857059
	fprintf(stderr, "\n");
Packit 857059
	fprintf(stderr, "   -t - target for which to verify fw\n");
Packit 857059
#if LIST_FILE_SUPPORTED
Packit 857059
	fprintf(stderr, "   -l - file that holds a list of targets to update\n");
Packit 857059
#endif
Packit 857059
	fprintf(stderr, "   -v - verbose output\n");
Packit 857059
	fprintf(stderr, "   -q - no output\n");
Packit 857059
	fprintf(stderr, "   -h - hfi, numbered 1..n, 0= -o port will be a\n");
Packit 857059
	fprintf(stderr, "        system wide port num (default is 0)\n");
Packit 857059
	fprintf(stderr, "   -o - port, numbered 1..n, 0=1st active (default\n");
Packit 857059
	fprintf(stderr, "        is 1st active)\n");
Packit 857059
	fprintf(stderr, "   -F - do secondary EEPROM (default is primary)\n");
Packit 857059
	fprintf(stderr, "\n");
Packit 857059
	fprintf(stderr, "The -h and -o options permit a variety of selections:\n");
Packit 857059
	fprintf(stderr, "    -h 0       - 1st active port in system (this is the default)\n");
Packit 857059
	fprintf(stderr, "    -h 0 -o 0  - 1st active port in system\n");
Packit 857059
	fprintf(stderr, "    -h x       - 1st active port on HFI x\n");
Packit 857059
	fprintf(stderr, "    -h x -o 0  - 1st active port on HFI x\n");
Packit 857059
	fprintf(stderr, "    -h 0 -o y  - port y within system (irrespective of which ports are active)\n");
Packit 857059
	fprintf(stderr, "    -h x -o y  - HFI x, port y\n");
Packit 857059
Packit 857059
#if 0 /* non-documented options */
Packit 857059
	fprintf(stderr, "   -s - delay in seconds between requests\n");
Packit 857059
	fprintf(stderr, "   -u - delay in microseconds between requests\n");
Packit 857059
	fprintf(stderr, "   -T - response timeout in microseconds\n");
Packit 857059
	fprintf(stderr, "   -z - read data length in bytes\n");
Packit 857059
	fprintf(stderr, "   -C - compare primary and secondary EEPROM, verify same\n");
Packit 857059
#endif
Packit 857059
Packit 857059
	exit(2);
Packit 857059
}
Packit 857059
Packit 857059
int main(int argc, char *argv[])
Packit 857059
{
Packit 857059
	char				*cmdName;
Packit 857059
	char				*opts="CDFvqt:l:h:o:m:s:u:T:z:";
Packit 857059
	char				*fwBuffer = NULL;
Packit 857059
	char				*imageDesc = "primary";
Packit 857059
	char				parameter[100];
Packit 857059
	char				*p;
Packit 857059
	uint8				initialBuffer[32];
Packit 857059
	uint8				*data = NULL;
Packit 857059
	int					fwSize = 0;;
Packit 857059
	int					bufferSize;
Packit 857059
	EUI64				destPortGuid = -1;
Packit 857059
	int					c;
Packit 857059
	uint8				hfi = 0;
Packit 857059
	uint8				port = 0;
Packit 857059
	IB_PATH_RECORD		path;
Packit 857059
	uint16				sessionID=(uint16)-1;
Packit 857059
	uint32				locationDescriptor;
Packit 857059
	uint32				dataLen = 0;
Packit 857059
	uint32				dataOffset;
Packit 857059
	uint32				*u;
Packit 857059
	uint32				crcEEPROM;
Packit 857059
	uint32				crc;
Packit 857059
	VENDOR_MAD			mad;
Packit 857059
	FSTATUS				status = FSUCCESS;
Packit 857059
	struct              omgt_port *omgt_port_session = NULL;
Packit 857059
Packit 857059
	// determine how we've been invoked
Packit 857059
	cmdName = strrchr(argv[0], '/');			// Find last '/' in path
Packit 857059
	if (cmdName != NULL) {
Packit 857059
		cmdName++;								// Skip over last '/'
Packit 857059
	} else {
Packit 857059
		cmdName = argv[0];
Packit 857059
	}
Packit 857059
Packit 857059
	// parse options and parameters
Packit 857059
	while (-1 != (c = getopt(argc, argv, opts))) {
Packit 857059
		switch (c) {
Packit 857059
			case 'D':
Packit 857059
				g_debugMode = 1;
Packit 857059
				break;
Packit 857059
Packit 857059
			case 't':
Packit 857059
				errno = 0;
Packit 857059
				strncpy(parameter, optarg, sizeof(parameter)-1);
Packit 857059
				parameter[sizeof(parameter)-1] = 0;
Packit 857059
				if ((p = strchr(parameter, ',')) != NULL) {
Packit 857059
					*p = '\0';
Packit 857059
				}
Packit 857059
				if (FSUCCESS != StringToUint64(&destPortGuid, parameter, NULL, 0, TRUE)) {
Packit 857059
					fprintf(stderr, "%s: Error: Invalid GUID: %s\n", cmdName, optarg);
Packit 857059
					usage(cmdName);
Packit 857059
				}
Packit 857059
				break;
Packit 857059
Packit 857059
			case 'l':
Packit 857059
#if !LIST_FILE_SUPPORTED
Packit 857059
				fprintf(stderr, "Error: l option is not supported at this time\n");
Packit 857059
				exit(1);
Packit 857059
#endif
Packit 857059
				break;
Packit 857059
Packit 857059
			case 'v':
Packit 857059
				g_verbose = 1;
Packit 857059
				break;
Packit 857059
Packit 857059
			case 'q':
Packit 857059
				g_quiet = 1;
Packit 857059
				break;
Packit 857059
Packit 857059
			case 'h':
Packit 857059
				if (FSUCCESS != StringToUint8(&hfi, optarg, NULL, 0, TRUE)) {
Packit 857059
					fprintf(stderr, "%s: Error: Invalid HFI Number: %s\n", cmdName, optarg);
Packit 857059
					usage(cmdName);
Packit 857059
				}
Packit 857059
				g_gotHfi = 1;
Packit 857059
				break;
Packit 857059
Packit 857059
			case 'o':
Packit 857059
				if (FSUCCESS != StringToUint8(&port, optarg, NULL, 0, TRUE)) {
Packit 857059
					fprintf(stderr, "%s: Error: Invalid Port Number: %s\n", cmdName, optarg);
Packit 857059
					usage(cmdName);
Packit 857059
				}
Packit 857059
				g_gotPort = 1;
Packit 857059
				break;
Packit 857059
Packit 857059
			case 's':
Packit 857059
				if (FSUCCESS != StringToInt32(&g_sleepParam, optarg, NULL, 0, TRUE)
Packit 857059
					|| g_sleepParam < 0) {
Packit 857059
					fprintf(stderr, "%s: Error: Invalid delay value: %s\n", cmdName, optarg);
Packit 857059
					usage(cmdName);
Packit 857059
				}
Packit 857059
				break;
Packit 857059
Packit 857059
			case 'u':
Packit 857059
				if (FSUCCESS != StringToInt32(&g_usleepParam, optarg, NULL, 0, TRUE)
Packit 857059
					|| g_usleepParam < 0) {
Packit 857059
					fprintf(stderr, "%s: Error: Invalid delay value: %s\n", cmdName, optarg);
Packit 857059
					usage(cmdName);
Packit 857059
				}
Packit 857059
				break;
Packit 857059
Packit 857059
			case 'z':
Packit 857059
				if (FSUCCESS != StringToInt32(&g_dataLenParam, optarg, NULL, 0, TRUE)
Packit 857059
					|| g_dataLenParam < 0) {
Packit 857059
					fprintf(stderr, "%s: Error: Invalid data length value: %s\n", cmdName, optarg);
Packit 857059
					usage(cmdName);
Packit 857059
				}
Packit 857059
				break;
Packit 857059
Packit 857059
			case 'T':
Packit 857059
				if (FSUCCESS != StringToInt32(&g_respTimeout, optarg, NULL, 0, TRUE)
Packit 857059
					|| g_respTimeout < 0) {
Packit 857059
					fprintf(stderr, "%s: Error: Invalid delay value: %s\n", cmdName, optarg);
Packit 857059
					usage(cmdName);
Packit 857059
				}
Packit 857059
				break;
Packit 857059
Packit 857059
			case 'F':
Packit 857059
				g_gotSecondary = 1;
Packit 857059
				imageDesc = "secondary";
Packit 857059
				break;
Packit 857059
Packit 857059
			case 'C':
Packit 857059
				g_compareEEPROMs = 1;
Packit 857059
				break;
Packit 857059
Packit 857059
			default:
Packit 857059
				usage(cmdName);
Packit 857059
				break;
Packit 857059
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
	// user has requested display of help
Packit 857059
	if (argc == 1) {
Packit 857059
		usage(cmdName);
Packit 857059
	}
Packit 857059
Packit 857059
	if (-1 == destPortGuid) {
Packit 857059
		fprintf(stderr, "%s: Error: Must specify a target GUID\n", cmdName);
Packit 857059
		exit(1);
Packit 857059
	}
Packit 857059
Packit 857059
	if (g_quiet && (g_debugMode || g_verbose)) {
Packit 857059
		fprintf(stderr, "%s: Error: Can not specify both -q and -D|-v\n", cmdName);
Packit 857059
		exit(1);
Packit 857059
	}
Packit 857059
Packit 857059
	if (g_sleepParam && g_usleepParam) {
Packit 857059
		fprintf(stderr, "%s: Error: Can not specify both -s and -u\n", cmdName);
Packit 857059
		exit(1);
Packit 857059
	}
Packit 857059
Packit 857059
Packit 857059
	// read the file into the buffer
Packit 857059
Packit 857059
	// Get the path
Packit 857059
Packit 857059
	struct omgt_params params = {.debug_file = g_debugMode ? stderr : NULL};
Packit 857059
	status = omgt_open_port_by_num(&omgt_port_session, hfi, port, &params);
Packit 857059
	if (status != 0) {
Packit 857059
		fprintf(stderr, "%s: Error: Unable to open fabric interface.\n", cmdName);
Packit 857059
		exit(1);
Packit 857059
	}
Packit 857059
Packit 857059
	if (getDestPath(omgt_port_session, destPortGuid, cmdName, &path) != FSUCCESS) {
Packit 857059
		fprintf(stderr, "%s: Error: Failed to get destination path\n", cmdName);
Packit 857059
		status = FERROR;
Packit 857059
		goto err_exit;
Packit 857059
	}
Packit 857059
Packit 857059
	// Send a ClassPortInfo to see if the switch is responding
Packit 857059
Packit 857059
	status = sendClassPortInfoMad(omgt_port_session, &path, &mad;;
Packit 857059
	if (status != FSUCCESS) {
Packit 857059
		fprintf(stderr, "%s: Error: Failed to send/rcv ClassPortInfo\n", cmdName);
Packit 857059
		goto err_exit;
Packit 857059
	}
Packit 857059
Packit 857059
	// Get a session ID
Packit 857059
Packit 857059
	sessionID = getSessionID(omgt_port_session, &path);
Packit 857059
	if (sessionID == (uint16)-1) {
Packit 857059
		fprintf(stderr, "%s: Error: Failed to obtain sessionID\n", cmdName);
Packit 857059
		status = FERROR;
Packit 857059
		goto err_exit;
Packit 857059
	}
Packit 857059
Packit 857059
	locationDescriptor = g_gotSecondary ? STL_PRR_SEC_EEPROM1_ADDR :
Packit 857059
						 STL_PRR_PRI_EEPROM1_ADDR;
Packit 857059
	dataOffset = 4;
Packit 857059
Packit 857059
	if (g_compareEEPROMs) {
Packit 857059
		uint8 primaryBuf[STL_MAX_EEPROM_SIZE];
Packit 857059
		uint8 secondaryBuf[STL_MAX_EEPROM_SIZE];
Packit 857059
		uint32 crc1, crc2;
Packit 857059
		int currentEEPROM;
Packit 857059
		
Packit 857059
		for (currentEEPROM = 0; currentEEPROM < STL_EEPROM_COUNT; currentEEPROM++) {
Packit 857059
Packit 857059
			status = opaswEepromRW(omgt_port_session, &path, sessionID, (void *)&mad, g_respTimeout, 
Packit 857059
								   STL_MAX_EEPROM_SIZE, currentEEPROM * STL_MAX_EEPROM_SIZE, 
Packit 857059
								   (uint8 *)primaryBuf, FALSE, FALSE);
Packit 857059
Packit 857059
			status = opaswEepromRW(omgt_port_session, &path, sessionID, (void *)&mad, g_respTimeout, 
Packit 857059
								   STL_MAX_EEPROM_SIZE, currentEEPROM * STL_MAX_EEPROM_SIZE, 
Packit 857059
								   (uint8 *)secondaryBuf, FALSE, TRUE);
Packit 857059
Packit 857059
			crc1 = crc32(0, (uint8 *)primaryBuf, STL_MAX_EEPROM_SIZE);
Packit 857059
			crc2 = crc32(0, (uint8 *)secondaryBuf, STL_MAX_EEPROM_SIZE);
Packit 857059
			if (crc1 != crc2) {
Packit 857059
				printf("EEPROM #%u CRC mismatch\n", currentEEPROM+1);
Packit 857059
			} else {
Packit 857059
				printf("EEPROM #%u CRC match\n", currentEEPROM+1);
Packit 857059
			}
Packit 857059
		
Packit 857059
		}
Packit 857059
Packit 857059
		/* yes, we are exiting with success via the error path */
Packit 857059
		goto err_exit;
Packit 857059
	}
Packit 857059
Packit 857059
	// first, read 16 bytes to access the firmware size
Packit 857059
Packit 857059
	status = sendI2CAccessMad(omgt_port_session, &path, sessionID, &mad, 
Packit 857059
							  NOJUMBOMAD, MMTHD_GET, g_respTimeout, locationDescriptor, 16, 
Packit 857059
							  dataOffset + CSS_HEADER_SIZE + 4, initialBuffer);
Packit 857059
	if (status == FSUCCESS) {
Packit 857059
		fwSize = ntoh32(*(uint32 *)&initialBuffer[0]) * 4;
Packit 857059
		if (fwSize < 0) {
Packit 857059
			fprintf(stderr, "%s: Error: Invalid firmware length: %d\n", cmdName, fwSize);
Packit 857059
			status = FERROR;
Packit 857059
			goto err_exit;
Packit 857059
		} else {
Packit 857059
			bufferSize = fwSize + CSS_HEADER_SIZE + 1024 + OPASW_BUFFER_PAD;
Packit 857059
			fwBuffer = malloc(bufferSize);
Packit 857059
			if (fwBuffer) {
Packit 857059
				memset(fwBuffer, 0, sizeof(bufferSize));
Packit 857059
				data = (uint8 *)fwBuffer;
Packit 857059
			} else {
Packit 857059
				fprintf(stderr, "%s: Error: Failed to allocate memory of length: %d\n", cmdName, fwSize);
Packit 857059
				status = FERROR;
Packit 857059
				goto err_exit;
Packit 857059
			}
Packit 857059
		}
Packit 857059
	} else goto err_exit;
Packit 857059
Packit 857059
	dataLen = fwSize + CSS_HEADER_SIZE;
Packit 857059
	data = (uint8 *)fwBuffer;
Packit 857059
	dataOffset = 0;
Packit 857059
Packit 857059
	status = opaswEepromRW(omgt_port_session, &path, sessionID, &mad, g_respTimeout, 
Packit 857059
						   dataLen + 4, dataOffset, data, FALSE, g_gotSecondary);
Packit 857059
	if (!g_quiet && (status == FSUCCESS)) {
Packit 857059
		printf("\n");
Packit 857059
		fflush(stdout);
Packit 857059
	}
Packit 857059
	if (status == FSUCCESS) {
Packit 857059
		u = (uint32 *)&fwBuffer[fwSize + CSS_HEADER_SIZE];
Packit 857059
		crcEEPROM = *u;
Packit 857059
		crc = crc32(0, (uint8 *)&fwBuffer[CSS_HEADER_SIZE + 4], fwSize - 4);
Packit 857059
		if (crcEEPROM != crc) {
Packit 857059
			printf("%s: invalid %s image found\n", cmdName, imageDesc);
Packit 857059
			fprintf(stderr, "CRC mismatch: 0x%08x : 0x%08x\n", ntoh32(crc), ntoh32(crcEEPROM));
Packit 857059
			status = FERROR;
Packit 857059
		} else {
Packit 857059
			if (g_verbose)
Packit 857059
				fprintf(stderr, "CRC match: 0x%08x : 0x%08x\n", ntoh32(crc), ntoh32(crcEEPROM));
Packit 857059
			printf("%s: valid %s image found\n", cmdName, imageDesc);
Packit 857059
		}
Packit 857059
	}
Packit 857059
Packit 857059
err_exit:
Packit 857059
	if (sessionID != (uint16)-1)
Packit 857059
		releaseSession(omgt_port_session, &path, sessionID);
Packit 857059
Packit 857059
	omgt_close_port(omgt_port_session);
Packit 857059
Packit 857059
	if (status == FSUCCESS) {
Packit 857059
		printf("opaswfwverify completed\n");
Packit 857059
		exit(0);
Packit 857059
	} else
Packit 857059
		exit(1);
Packit 857059
Packit 857059
}