2
* Copyright (C) Jan 2013 Mellanox Technologies Ltd. All rights reserved.
4
* This software is available to you under a choice of one of two
5
* licenses. You may choose to be licensed under the terms of the GNU
6
* General Public License (GPL) Version 2, available from the file
7
* COPYING in the main directory of this source tree, or the
8
* OpenIB.org BSD license below:
10
* Redistribution and use in source and binary forms, with or
11
* without modification, are permitted provided that the following
14
* - Redistributions of source code must retain the above
15
* copyright notice, this list of conditions and the following
18
* - Redistributions in binary form must reproduce the above
19
* copyright notice, this list of conditions and the following
20
* disclaimer in the documentation and/or other materials
21
* provided with the distribution.
23
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38
#include "flint_base.h"
45
#ifndef NO_MFA_SUPPORT
49
#define BAD_CRC_MSG "Bad CRC."
50
extern const char* g_sectNames[];
52
#ifndef NO_MFA_SUPPORT
54
int FwOperations::getFileSignature(const char* fname)
60
if (!(fin = fopen(fname, "r"))) {
61
// abit ugly , need to establish a correct ret val
62
return IMG_SIG_OPEN_FILE_FAILED;
64
if (!fgets(tmpb, sizeof(tmpb), fin)) {
67
if (strlen(tmpb) < 4) {
71
if (!strncmp(tmpb, "MTFW", 4)) {
72
res = IMG_SIG_TYPE_BIN;
74
if (!strncmp(tmpb, "MFAR", 4)) {
75
res = IMG_SIG_TYPE_MFA;
84
int FwOperations::getBufferSignature(u_int8_t* buf, u_int32_t size)
91
if (!strncmp((char*)buf, "MTFW", 4)) {
92
res = IMG_SIG_TYPE_BIN;
94
if (!strncmp((char*)buf, "MFAR", 4)) {
95
res = IMG_SIG_TYPE_MFA;
102
int FwOperations::getMfaImg(char* fileName, char *psid, u_int8_t **imgbuf)
106
int image_type = 1; //FW image
109
return -1; //No psid => no image
111
if ((res = mfa_open_file(&mfa_d, fileName))) {
115
res = mfa_get_image(mfa_d, psid, image_type, (char*)"", imgbuf);
122
int FwOperations::getMfaImg(u_int8_t* mfa_buf, int size, char *psid, u_int8_t **imgbuf)
126
int image_type = 1; //FW image
129
return -1; //No psid => no image
131
if ((res = mfa_open_buf(&mfa_d, mfa_buf, size))) {
135
res = mfa_get_image(mfa_d, psid, image_type, (char*)"", imgbuf);
143
void FwOperations::FwCleanUp()
147
if (_fname != NULL) {
153
void FwOperations::FwInitCom()
155
memset(&_fwImgInfo, 0, sizeof(_fwImgInfo));
160
bool FwOperations::checkBoot2(u_int32_t beg, u_int32_t offs, u_int32_t& next, bool fullRead, const char *pref, VerifyCallBack verifyCallBackFunc)
164
// char *pr = (char *)alloca(strlen(pref) + 512);
165
char pr[strlen(pref) + 512];
166
sprintf(pr, "%s /0x%08x/ (BOOT2)", pref, offs+beg);
168
READ4((*_ioAccess), offs+beg+4, &size, pr);
170
if (size > 1048576 || size < 4) {
171
report_callback(verifyCallBackFunc, "%s /0x%08x/ - unexpected size (0x%x)\n", pr, offs+beg+4, size);
174
_fwImgInfo.bootSize = (size + 4) * 4;
177
sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (BOOT2)", pref, offs+beg,
178
offs+beg+(size+4)*4-1, (size+4)*4);
180
if ((_ioAccess->is_flash() && fullRead == true) || !_ioAccess->is_flash()) {
182
// u_int32_t *buff = (u_int32_t*)alloca((size + 4)*sizeof(u_int32_t));
183
u_int32_t buff[size + 4];
184
READBUF((*_ioAccess), offs+beg, buff, size*4 + 16, pr);
185
// we hold for FS3 an image cache so we selectevely update it in UpdateImgCache() call
186
UpdateImgCache((u_int8_t*)buff, offs+beg, size*4 + 16);
188
TOCPUn(buff, size+4);
189
CRC1n(crc, buff, size+4);
190
CRC1n(_ioAccess->get_image_crc(), buff, size+4);
195
u_int32_t crc_act = buff[size+3];
196
if (crc.get() != crc_act) {
197
report_callback(verifyCallBackFunc, "%s /0x%08x/ - wrong CRC (exp:0x%x, act:0x%x)\n",
198
pr, offs+beg, crc.get(), crc_act);
199
return errmsg(BAD_CRC_MSG);
201
_ioAccess->get_image_crc() << crc_act;
204
report_callback(verifyCallBackFunc, "%s - OK (CRC:0x%04x)\n", pr, (crc_act & 0xffff));
206
report_callback(verifyCallBackFunc, "%s - OK\n", pr);
209
next = offs + size*4 + 16;
214
bool FwOperations::CheckAndPrintCrcRes(char* pr, bool blank_crc, u_int32_t off, u_int32_t crc_act, u_int32_t crc_exp, bool ignore_crc,
215
VerifyCallBack verifyCallBackFunc)
218
if (!blank_crc && crc_exp != crc_act) {
219
report_callback(verifyCallBackFunc, "%s /0x%08x/ - wrong CRC (exp:0x%x, act:0x%x)\n",
220
pr, off, crc_exp, crc_act);
221
return errmsg(BAD_CRC_MSG);
224
// TODO: Print CRC here.
226
report_callback(verifyCallBackFunc, "%s - OK (CRC:0x%04x)\n", pr, crc_act & 0xffff);
229
report_callback(verifyCallBackFunc, "%s - CRC IGNORED\n", pr);
232
report_callback(verifyCallBackFunc, "%s - BLANK CRC (0xffff)\n", pr);
234
report_callback(verifyCallBackFunc, "%s - OK\n", pr);
241
bool FwOperations::FwVerLessThan(u_int16_t r1[3], u_int16_t r2[3]) {
242
for (int i = 0; i < 3 ; i++)
245
else if (r1[i] > r2[i])
248
return false; // equal versions
250
const u_int32_t FwOperations::_cntx_magic_pattern[4] = {
251
0x4D544657, // Ascii of "MTFW"
252
0x8CDFD000, // Random data
257
const u_int32_t FwOperations::_cntx_image_start_pos[FwOperations::CNTX_START_POS_SIZE] = {
267
bool FwOperations::CntxFindMagicPattern (FBase* ioAccess, u_int32_t addr) {
268
if (addr + 16 > ioAccess->get_size()) {
271
for (int i = 0; i < 4 ; i++) {
273
READ4_NOERRMSG((*ioAccess), addr + i * 4, &w);
275
if (w != _cntx_magic_pattern[i]) {
276
//printf("-D- Looking for magic pattern %d addr %06x: Exp=%08x Act=%08x\n", i, addr + i * 4, _cntx_magic_pattern[i], w);
287
// OUT: start_locations: set to the start addresses of the found image markers (in accending order)
288
// OUT: found_images: Number of found images (and number of valid entries in the start_locations array).
289
bool FwOperations::CntxFindAllImageStart (FBase* ioAccess, u_int32_t start_locations[CNTX_START_POS_SIZE], u_int32_t* found_images) {
292
needed_pos_num = CNTX_START_POS_SIZE;
294
if (ioAccess->is_flash()) {
295
if ( (((Flash*)ioAccess)->get_dev_id() == 400) ||
296
(((Flash*)ioAccess)->get_dev_id() == 435) ||
297
(((Flash*)ioAccess)->get_dev_id() == 6100)) {
298
needed_pos_num = OLD_CNTX_START_POS_SIZE;
302
ioAccess->set_address_convertor(0,0);
304
for (int i = 0; i < needed_pos_num; i++) {
305
if (CntxFindMagicPattern(ioAccess, _cntx_image_start_pos[i])) {
306
start_locations[*found_images] = _cntx_image_start_pos[i];
316
// CAN BE IN ANOTHER MODULE
317
bool FwOperations::GetSectData(std::vector<u_int8_t>& file_sect, const u_int32_t *buff, const u_int32_t size) {
320
file_sect.insert(file_sect.end(),
322
(u_int8_t*)buff + size);
329
bool FwOperations::FwAccessCreate(fw_ops_params_t& fwParams, FBase **ioAccessP)
331
// FBase *ioAccess = *ioAccessP;
332
if (fwParams.hndlType == FHT_FW_FILE) {
333
#ifndef NO_MFA_SUPPORT
334
int sig = getFileSignature(fwParams.fileHndl);
335
if (sig == IMG_SIG_OPEN_FILE_FAILED) { //i.e we failed to open file
336
WriteToErrBuff(fwParams.errBuff, strerror(errno), fwParams.errBuffSize);
339
if (sig == IMG_SIG_TYPE_BIN) {
340
*ioAccessP = new FImage;
341
if (!(*ioAccessP)->open(fwParams.fileHndl, false, !fwParams.shortErrors)) {
342
WriteToErrBuff(fwParams.errBuff,(*ioAccessP)->err(), fwParams.errBuffSize);
346
} else if (sig == IMG_SIG_TYPE_MFA) {
349
if ((sz = getMfaImg(fwParams.fileHndl, fwParams.psid, &imgbuf)) < 0) {
350
WriteToErrBuff(fwParams.errBuff,"Failed to get MFA Image.", fwParams.errBuffSize);
353
*ioAccessP = new FImage;
354
if (!((FImage*)(*ioAccessP))->open((u_int32_t*)imgbuf, (u_int32_t)sz, !fwParams.shortErrors)) {
355
mfa_release_image(imgbuf);
356
WriteToErrBuff(fwParams.errBuff,(*ioAccessP)->err(), fwParams.errBuffSize);
360
mfa_release_image(imgbuf);
362
WriteToErrBuff(fwParams.errBuff,"Invalid Image signature.", fwParams.errBuffSize);
363
return false; //Unknown signature
366
*ioAccessP = new FImage;
367
if (!(*ioAccessP)->open(fwParams.fileHndl, false, !fwParams.shortErrors)) {
368
WriteToErrBuff(fwParams.errBuff,(*ioAccessP)->err(), fwParams.errBuffSize);
373
} else if (fwParams.hndlType == FHT_FW_BUFF) {
374
u_int32_t numInfo = fwParams.buffSize;
375
#ifndef NO_MFA_SUPPORT
376
int sig = getBufferSignature((u_int8_t*)fwParams.buffHndl, numInfo);
377
if (sig == IMG_SIG_TYPE_BIN) {
378
*ioAccessP = new FImage;
379
if (!((FImage*)*ioAccessP)->open(fwParams.buffHndl, (u_int32_t)numInfo, !fwParams.shortErrors)) {
380
WriteToErrBuff(fwParams.errBuff,(*ioAccessP)->err(), fwParams.errBuffSize);
384
} else if (sig == IMG_SIG_TYPE_MFA) {
387
if ((sz = getMfaImg((u_int8_t*)fwParams.buffHndl, numInfo, fwParams.psid, &imgbuf)) < 0) {
388
WriteToErrBuff(fwParams.errBuff,"Failed to get MFA Image.", fwParams.errBuffSize);
391
*ioAccessP = new FImage;
392
if (!((FImage*)*ioAccessP)->open((u_int32_t*)imgbuf, (u_int32_t)sz, !fwParams.shortErrors)) {
393
mfa_release_image(imgbuf);
394
WriteToErrBuff(fwParams.errBuff,(*ioAccessP)->err(), fwParams.errBuffSize);
398
mfa_release_image(imgbuf);
400
WriteToErrBuff(fwParams.errBuff,"Invalid Image signature.", fwParams.errBuffSize);
401
return false;//Unknown signature
404
*ioAccessP = new FImage;
405
if (!((FImage*)*ioAccessP)->open(fwParams.buffHndl, numInfo, !fwParams.shortErrors)) {
406
WriteToErrBuff(fwParams.errBuff,(*ioAccessP)->err(), fwParams.errBuffSize);
411
} else if (fwParams.hndlType == FHT_UEFI_DEV) {
412
*ioAccessP = new Flash;
413
if (!((Flash*)*ioAccessP)->open(fwParams.uefiHndl, fwParams.uefiExtra, false, !fwParams.shortErrors)) {
414
WriteToErrBuff(fwParams.errBuff,(*ioAccessP)->err(), fwParams.errBuffSize);
418
} else if (fwParams.hndlType == FHT_MST_DEV) {
419
*ioAccessP = new Flash;
420
if ( !((Flash*)*ioAccessP)->open(fwParams.mstHndl, fwParams.forceLock, fwParams.readOnly, fwParams.numOfBanks,\
421
fwParams.flashParams, fwParams.ignoreCacheRep, !fwParams.shortErrors)) {
422
// TODO: release memory here ?
423
WriteToErrBuff(fwParams.errBuff,(*ioAccessP)->err(), fwParams.errBuffSize);
427
//set no flash verify if needed (default =false)
428
((Flash*)*ioAccessP)->set_no_flash_verify(fwParams.noFlashVerify);
430
WriteToErrBuff(fwParams.errBuff,"Unknown Handle Type.", fwParams.errBuffSize);
436
u_int8_t FwOperations::CheckFwFormat(FBase& f, bool getFwFormatFromImg) {
437
if (f.is_flash() && !getFwFormatFromImg) {
438
if ( ( ((Flash*)&f)->get_dev_id() == 400) ||
439
( ((Flash*)&f)->get_dev_id() == 435) ||
440
( ((Flash*)&f)->get_dev_id() == CX3_HW_ID) ||
441
( ((Flash*)&f)->get_dev_id() == SWITCHX_HW_ID) ||
442
( ((Flash*)&f)->get_dev_id() == 6100) ||
443
( ((Flash*)&f)->get_dev_id() == CX3_PRO_HW_ID)) {
445
} else if ( (((Flash*)&f)->get_dev_id() == CONNECT_IB_HW_ID) ||
446
(((Flash*)&f)->get_dev_id() == SWITCH_IB_HW_ID) ||
447
(((Flash*)&f)->get_dev_id() == CX4_HW_ID)) {
451
u_int32_t found_images;
452
u_int32_t image_start[CNTX_START_POS_SIZE];
454
// Image - check if magic pattern is somewhere in the file:
455
CntxFindAllImageStart(&f, image_start, &found_images);
458
u_int8_t image_version;
459
READ4_NOERRMSG(f, FS3_IND_ADDR, &data);
461
image_version = data >> 24;
462
if (image_version == IMG_VER_FS3) {
465
// TODO: if the img format version is unknown we should fail instead of considering it FS2
473
FwOperations* FwOperations::FwOperationsCreate(void* fwHndl, void *info, char* psid, fw_hndl_type_t hndlType, char* errBuff, int buffSize)
475
fw_ops_params_t fwParams;
476
fwParams.psid = psid;
477
fwParams.hndlType = hndlType;
478
fwParams.errBuff = errBuff;
479
fwParams.errBuffSize = buffSize;
480
fwParams.shortErrors = true;
482
if (hndlType == FHT_FW_FILE) {
483
fwParams.fileHndl = (char*)fwHndl;
484
}else if (hndlType == FHT_FW_BUFF) {
485
fwParams.buffHndl = (u_int32_t*)fwHndl;
486
fwParams.buffSize = *((u_int32_t*)info);
487
}else if (hndlType == FHT_UEFI_DEV) {
488
fwParams.uefiHndl = (uefi_Dev_t*)fwHndl;
489
fwParams.uefiExtra = (f_fw_cmd)info;
490
}else if (hndlType == FHT_MST_DEV) {
491
fwParams.mstHndl = (char*)fwHndl;
492
fwParams.forceLock = false;
493
fwParams.readOnly = false;
494
fwParams.numOfBanks = 4;
495
fwParams.flashParams = (flash_params_t*)NULL;
496
fwParams.ignoreCacheRep = 0;
497
fwParams.noFlashVerify = false;
499
return FwOperationsCreate(fwParams);
502
FwOperations* FwOperations::FwOperationsCreate(fw_ops_params_t& fwParams)
507
bool getFwFormatFromImg = false;
509
if (!FwAccessCreate(fwParams, &ioAccess)) {
510
return (FwOperations*)NULL;
512
if (fwParams.hndlType == FHT_UEFI_DEV) {
513
// IN UEFI we don't have an access to read devID from cr-space so we are reading it from FW image signature
514
getFwFormatFromImg = true;
516
fwFormat = CheckFwFormat(*ioAccess, getFwFormatFromImg);
519
fwops = new Fs2Operations(ioAccess);
523
fwops = new Fs3Operations(ioAccess);
528
WriteToErrBuff(fwParams.errBuff,"invalid Firmware Format (found FS Gen 1)", fwParams.errBuffSize);
529
return (FwOperations*)NULL;
531
fwops->_advErrors = !fwParams.shortErrors;
533
if (fwParams.hndlType == FHT_FW_FILE) {
534
fwops->_fname = strcpy(new char[strlen(fwParams.fileHndl)+ 1], fwParams.fileHndl);
539
u_int32_t FwOperations::CalcImageCRC(u_int32_t* buff, u_int32_t size)
543
CRCn(crc, buff, size);
546
u_int32_t new_crc = crc.get();
550
bool FwOperations::writeImage(ProgressCallBack progressFunc, u_int32_t addr, void *data, int cnt, bool is_phys_addr)
552
u_int8_t *p = (u_int8_t *)data;
553
u_int32_t curr_addr = addr;
554
u_int32_t towrite = cnt;
556
// if (!_ioAccess->is_flash()) {
557
// return errmsg("Internal error: writeImage is supported only on flash.");
562
if (_ioAccess->is_flash()) {
563
trans = (towrite > (int)Flash::TRANS) ? (int)Flash::TRANS : towrite;
565
rc = ((Flash*)_ioAccess)->write_phy(curr_addr, p, trans);
567
rc = ((Flash*)_ioAccess)->write(curr_addr, p, trans);
570
return errmsg("Flash write failed: %s", _ioAccess->err());
574
if (!ModifyImageFile(_fname, curr_addr, p, trans)) {
583
if (progressFunc != NULL) {
584
u_int32_t new_perc = ((cnt - towrite) * 100) / cnt;
586
if (progressFunc((int)new_perc)) {
587
return errmsg("Aborting... recieved interrupt signal");
593
} // Flash::WriteImage
595
bool FwOperations::ModifyImageFile(const char *fimage, u_int32_t addr, void *data, int cnt)
598
u_int8_t * file_data;
600
if (!ReadImageFile(fimage, file_data, file_size, addr + cnt)) {
603
memcpy(&file_data[addr], data, cnt);
605
if (!WriteImageToFile(fimage, file_data, file_size)) {
613
bool FwOperations::WriteImageToFile(const char *file_name, u_int8_t *data, u_int32_t length)
616
if ((fh = fopen(file_name, "wb")) == NULL) {
617
return errmsg("Can not open %s: %s\n", file_name, strerror(errno));
621
if (fwrite(data, 1, length, fh) != length) {
623
return errmsg("Failed to write to %s: %s\n", file_name, strerror(errno));
629
bool FwOperations::CheckMac(u_int64_t mac) {
630
if ((mac >> 40) & 0x1) {
631
return errmsg("Multicast bit (bit 40) is set");
635
return errmsg("More than 48 bits are used");
641
void FwOperations::recalcSectionCrc(u_int8_t *buf, u_int32_t data_size) {
644
for (u_int32_t i = 0; i < data_size; i += 4) {
645
crc << __be32_to_cpu(*(u_int32_t*)(buf + i));
648
*((u_int32_t*)(buf + data_size)) = __cpu_to_be32(crc.get());
651
chip_type_t FwOperations::getChipType() {
653
while (hwDevData[i].name != NULL) {
655
while (hwDevData[i].swDevIds[j] != 0) {
656
if (hwDevData[i].swDevIds[j] == _fwImgInfo.ext_info.dev_type) {
657
return hwDevData[i].chipType;
666
chip_type_t FwOperations::getChipTypeFromHwDevid(u_int32_t hwDevId) {
668
while (hwDevData[i].name != NULL) {
669
if (hwDevData[i].hwDevId == hwDevId) {
670
return hwDevData[i].chipType;
677
// TODO:combine both databases(hwDevData and hwDev2Str) and remove old unsupporded devices i.e tavor arbel sinai
678
const FwOperations::HwDevData FwOperations::hwDevData[] = {
679
{ "InfiniHost", TAVOR_HW_ID, CT_UNKNOWN, 2, {23108, 0}},
680
{ "InfiniHost III Ex", ARBEL_HW_ID, CT_UNKNOWN,2 , {25208, 25218, 0}},
681
{ "InfiniHost III Lx", SINAI_HW_ID, CT_UNKNOWN, 1, {25204, 0}},
682
{ "ConnectX", CX_HW_ID, CT_CONNECTX, 2, {25408, 25418, 26418, 26438,
683
26428, 25448, 26448, 26468,
684
25458, 26458, 26478, 26488,
686
{ "ConnectX3", CX3_HW_ID, CT_CONNECTX, 2, {4099, 4100, 4101, 4102,
687
4103, 4104, 4105, 4106,
688
4107, 4108, 4109, 4110,
690
{ "Connect_IB", CONNECT_IB_HW_ID, CT_CONNECT_IB, 2, {CONNECT_IB_SW_ID, 4114, 4115, 4116,
691
4117, 4118, 4119, 4120,
692
4121, 4122, 4123, 4124, 0}},
693
{ "InfiniScale IV", IS4_HW_ID, CT_IS4, 0, {48436, 48437, 48438, 0}},
694
{ "BridgeX", BRIDGEX_HW_ID, CT_BRIDGEX, 0, {64102, 64112, 64122, 0}},
695
{ "SwitchX", SWITCHX_HW_ID, CT_SWITCHX, 0, {51000, 0}},
696
{ "Switch_IB", SWITCH_IB_HW_ID, CT_SWITCH_IB,0, {52000, 0}},
697
{ "ConnectX4", CX4_HW_ID, CT_CONNECTX, 0, {4115, 0}},
698
{ (char*)NULL , 0, CT_UNKNOWN, 0, {0}},// zero devid terminator
701
const FwOperations::HwDev2Str FwOperations::hwDev2Str[] = {
702
{"ConnectIB", CONNECT_IB_HW_ID, 0x00},
703
{"ConnectX", CX_HW_ID, 0xA0},
704
{"ConnectX-2", CX_HW_ID, 0xB0},
705
{"ConnectX-3 A0", CX3_HW_ID, 0x00},
706
{"ConnectX-3 A1", CX3_HW_ID, 0x01},
707
{"ConnectX-4", CX4_HW_ID, 0x00},
708
{"SwitchX A0", SWITCHX_HW_ID, 0x00},
709
{"SwitchX A1", SWITCHX_HW_ID, 0x01},
710
{"BridgeX", BRIDGEX_HW_ID, 0xA0},
711
{"InfiniScale IV A0", IS4_HW_ID, 0xA0},
712
{"InfiniScale IV A1", IS4_HW_ID, 0xA1},
713
{"InfiniHost A0", TAVOR_HW_ID, 0xA0},
714
{"InfiniHost A1", TAVOR_HW_ID, 0xA1},
715
{"InfiniHost III Lx", SINAI_HW_ID, 0xA0},
716
{"InfiniHost III Ex", ARBEL_HW_ID, 0xA0},
717
{"SwitchIB A0", SWITCH_IB_HW_ID, 0x00},
718
{ (char*)NULL , (u_int32_t)0, (u_int8_t)0x00}, // zero device ID terminator
721
#define ARR_SIZE(arr) sizeof(arr)/sizeof(arr[0])
722
#define MAX_HW_NAME_LEN 100
723
bool FwOperations::HWIdRevToName(u_int32_t hw_id, u_int8_t rev_id, char *hw_name)
726
for (int i = 0; hwDev2Str[i].hwDevId != 0; i++) {
727
const HwDev2Str *hwDev2StrMem = &(hwDev2Str[i]);
729
if (hwDev2StrMem->hwDevId == hw_id && hwDev2StrMem->revId == rev_id) {
730
int len = strlen(hwDev2StrMem->name);
731
if (len >= MAX_HW_NAME_LEN) {
732
return errmsg("Internal error: Length of device name: %d exceeds the maximum allowed size: %d", len, MAX_HW_NAME_LEN - 1);
734
strcpy(hw_name, hwDev2StrMem->name);
738
// When the device or rev is unknown we use the hw ID and rev to display it.
739
sprintf(hw_name, "MT%d-%02X", hw_id, rev_id);
744
// This function gets the HW ID of the target device and the dev ID from
745
// the image. It then matches the 2 IDs and returns an error in case of
746
// missmatch. The match is not 1:1 , since the FW image contains the SW
747
// dev id, and a single hw dev id may match multiple SW dev IDs.
749
bool FwOperations::CheckMatchingHwDevId(u_int32_t hwDevId, u_int32_t rev_id, u_int32_t* supportedHwId, u_int32_t supportedHwIdNum) {
751
char supp_hw_id_list[MAX_NUM_SUPP_HW_LIST_STR] = {'\0'};
752
char supp_hw_id_list_tmp[MAX_NUM_SUPP_HW_LIST_STR];
753
char curr_hw_id_name[MAX_HW_NAME_LEN];
755
for (u_int32_t i = 0; i < supportedHwIdNum; i++) {
756
u_int32_t currSupportedHwId = supportedHwId[i];
757
u_int32_t supp_hw_id = currSupportedHwId & 0xffff;
758
u_int32_t supp_rev_id = (currSupportedHwId >> 16) & 0xff;
759
u_int32_t tmp_size_of_list;
760
char hw_name[MAX_HW_NAME_LEN];
762
if (currSupportedHwId == 0) {
765
// Check if device is supported!
766
if ( supp_hw_id == hwDevId && supp_rev_id == rev_id) {
769
// Append checked to list of supported device in order to print it in the error if we this device is not supported
771
// Get the HW name of current supported HW ID
772
if (!HWIdRevToName(supp_hw_id, supp_rev_id, hw_name)) {
775
// Check if we don't exceed the array size we have
776
tmp_size_of_list = strlen(supp_hw_id_list) + strlen(hw_name) + 2;
777
if (tmp_size_of_list >= MAX_NUM_SUPP_HW_LIST_STR) {
778
return errmsg("Internal error: Size of supported devs list: %d exceeds the maximum allowed size: %d",
779
tmp_size_of_list, MAX_NUM_SUPP_HW_LIST_STR - 1);
782
if (supp_hw_id_list[0] == '\0') {
783
sprintf(supp_hw_id_list, "%s", hw_name);
785
strcpy(supp_hw_id_list_tmp, supp_hw_id_list);
786
sprintf(supp_hw_id_list, "%s, %s", supp_hw_id_list_tmp, hw_name);
789
// If we get here, this FW cannot be burnt in the current device.
790
// Get the Device name
791
if (!HWIdRevToName(hwDevId, rev_id, curr_hw_id_name)) {
795
return errmsg("FW image file cannot be programmed to device %s, it is intended for: %s only",
796
curr_hw_id_name, supp_hw_id_list);
798
bool FwOperations::CheckMatchingDevId(u_int32_t hwDevId, u_int32_t imageDevId) {
800
const HwDevData* devData = (const HwDevData*)NULL;
801
const char* hwDevName = (const char*)NULL;
802
// HACK: InfiniHost III LX may have 2 HW device ids. - Map the second devid to the first.
803
if (hwDevId == 24204) {
807
// First, find the HW device that the SW id matches
808
for (int i = 0; hwDevData[i].hwDevId != 0 ; i++) {
809
if (hwDevData[i].hwDevId == hwDevId) {
810
hwDevName = hwDevData[i].name; // TODO: Check bug if device not found
813
if (devData == NULL) {
814
for (int j = 0; hwDevData[i].swDevIds[j]; j++) {
815
if (hwDevData[i].swDevIds[j] == imageDevId) {
816
devData = &hwDevData[i];
823
if (devData == NULL) {
824
report_warn("Unknown device id (%d) in the given FW image. Skipping HW match check.\n",
827
} else if (devData->hwDevId != hwDevId) {
828
return errmsg("Trying to burn a \"%s\" image on a \"%s\" device.",
836
void FwOperations::FwDebugPrint(char *str)
838
if (_printFunc != NULL) {
843
bool FwOperations::FwSetPrint(PrintCallBack PrintFunc)
845
_printFunc = PrintFunc;
849
bool FwOperations::CheckPSID(FwOperations &imageOps, u_int8_t allow_psid_change)
851
if (!allow_psid_change) {
852
if (strncmp( _fwImgInfo.ext_info.psid, imageOps._fwImgInfo.ext_info.psid, PSID_LEN)) {
853
return errmsg("Image PSID is %s, it cannot be burnt into current device (PSID: %s)",
854
imageOps._fwImgInfo.ext_info.psid, _fwImgInfo.ext_info.psid);
860
bool FwOperations::CheckFwVersion(FwOperations &imageOps, u_int8_t forceVersion)
862
bool updateRequired = true;
864
updateRequired = FwVerLessThan(_fwImgInfo.ext_info.fw_ver, imageOps._fwImgInfo.ext_info.fw_ver);
865
if (!updateRequired) {
866
return errmsg("FW is already updated.");
872
bool FwOperations::FwSwReset() {
873
if (!_ioAccess->is_flash()) {
874
return errmsg("operation supported only for switch devices InfiniScaleIV and SwitchX over an IB interface");
876
if (!((Flash*)_ioAccess)->sw_reset()) {
877
return errmsg("%s", _ioAccess->err());
883
void FwOperations::WriteToErrBuff(char* errBuff, const char* errStr, int size)
886
if (size-4 > (int) strlen(errStr)) {
887
strncpy(errBuff, errStr, size);
889
strncpy(errBuff, errStr, size-4);
890
strcpy(&errBuff[size-4], "...");
896
bool FwOperations::UpdateImgCache(u_int8_t *buff, u_int32_t addr, u_int32_t size)
898
//avoid compiler warrnings
902
//in FS2 we dont have ImgCache, just in FS3 so we define a defult behaviour.
906
bool FwOperations::CntxEthOnly(u_int32_t devid)
908
return(devid == 25448) || // ETH
909
(devid == 26448) || // ETH
910
(devid == 25458) || //
911
(devid == 26458) || //
916
// RomInfo implementation
918
FwOperations::RomInfo::RomInfo(const std::vector<u_int8_t>& romSector, bool resEndi)
920
expRomFound = !romSector.empty();
923
TOCPUn(&romSect[0], romSect.size()/4);
927
expRomWarning = false;
928
expRomErrMsgValid = false;
929
noRomChecksum = false;
930
memset(expRomErrMsg, 0, sizeof(expRomErrMsg));
931
memset(expRomWarningMsg, 0, sizeof(expRomWarningMsg));
932
memset(&romsInfo, 0, (sizeof(rom_info_t)*MAX_ROMS_NUM));
936
bool FwOperations::RomInfo::initRomsInfo(roms_info_t *info)
939
return errmsg("invalid roms_info_t pointer.");
941
info->exp_rom_found = expRomFound;
942
info->num_of_exp_rom = numOfExpRom;
943
info->no_rom_checksum = noRomChecksum;
944
info->exp_rom_com_devid = expRomComDevid;
945
info->exp_rom_warning = expRomWarning;
946
info->exp_rom_err_msg_valid = expRomErrMsgValid;
947
//copy strings and rom_info
948
for (int i=0; i< MAX_ROM_ERR_MSG_LEN; i++) {
949
info->exp_rom_warning_msg[i] = expRomWarningMsg[i];
950
info->exp_rom_err_msg[i] = expRomErrMsg[i];
952
for (int i=0; i< MAX_ROMS_NUM; i++) {
953
//copy rom_info struct
954
info->rom_info[i].exp_rom_product_id = romsInfo[i].exp_rom_product_id; // 0 - invalid.
955
info->rom_info[i].exp_rom_dev_id = romsInfo[i].exp_rom_dev_id;
956
info->rom_info[i].exp_rom_port = romsInfo[i].exp_rom_port;
957
info->rom_info[i].exp_rom_proto = romsInfo[i].exp_rom_proto;
958
info->rom_info[i].exp_rom_num_ver_fields = romsInfo[i].exp_rom_num_ver_fields;
959
for (int j=0; j< 3 ; j++) {
960
info->rom_info[i].exp_rom_ver[j] = romsInfo[i].exp_rom_ver[j];
967
bool FwOperations::RomInfo::ParseInfo()
969
if (!GetExpRomVersion()) {
970
snprintf(expRomErrMsg, MAX_ROM_ERR_MSG_LEN, "%s", err());
971
expRomErrMsgValid = true;
972
//printf("-D-expRomErrMsg: %s \n", expRomErrMsg);
974
//printf("-D- expRomFound: %d \n",expRomFound);
975
//printf("-D- numOfExpRom: %d \n",numOfExpRom);
976
//printf("-D- noRomChecksum: %d \n",noRomChecksum);
977
//printf("-D- expRomComDevid: %d \n",expRomComDevid);
978
//printf("-D- expRomWarning: %d \n",expRomWarning);
979
//printf("-D- expRomErrMsgValid: %d \n",expRomErrMsgValid);
985
bool FwOperations::RomInfo::GetExpRomVersion()
987
char magicString[MAGIC_LEN] = {"mlxsignX"};
988
u_int32_t magicLen = strlen(magicString);
989
bool magicFound = false;
991
u_int32_t romChecksumRange;
993
// We do this HACK in order not to have mlxsign: word in our code so if mlxfwops will be part
994
// of rom, no mlxsign: string will appear
995
magicString[magicLen - 1] = ':';
997
if (romSect.empty()) {
998
return errmsg("Expansion Rom section not found.");
1000
// When checking the version of the expansion rom, only the first image has
1001
// to be checked. This is because the second image the uefi image does not
1002
// have to comply with checksumming to 0. To do this you have to read byte
1003
// 2 (third) of the image and multiply by 512 to get the size of the x86
1007
if (romSect.size() < 4) {
1008
return errmsg("ROM size (0x%x) is too small",
1009
(u_int32_t) romSect.size());
1012
// restore endianess is done in the constructor if needed.
1013
/* // FOR WE DON'T CHECKSUM UNTIL WE DECIDED REGARDING THE NEW FORMAT.
1015
// We will look for the magic string in whole ROM instead of the first part of it.
1016
romChecksumRange = romSect.size();
1018
for (u_int32_t i = 0; i < romChecksumRange; i++) {
1019
for (u_int32_t j = 0; j < magicLen; j++) {
1020
if (romSect[i + j] != magicString[j]) {
1022
} else if (j == magicLen - 1) {
1029
// Get the ROM info after the mlxsign
1031
rom_info_t *currRom;
1033
if (numOfExpRom == MAX_ROMS_NUM) {
1034
expRomWarning = true;
1035
snprintf(expRomWarningMsg,
1036
MAX_ROM_ERR_MSG_LEN,
1037
"Number of exp ROMs exceeds the maximum allowed number (%d)",
1039
// Here we want to warn regarding this issue without checksum.
1043
currRom = &(romsInfo[numOfExpRom]);
1044
verOffset = i + magicLen;
1045
rc = GetExpRomVerForOneRom(verOffset);
1050
// Get the device ID and check if it mismatches with other ROMs
1051
if (expRomComDevid != MISS_MATCH_DEV_ID) { // When the DevId is already mismatched, no end to any check
1052
if (currRom->exp_rom_dev_id != EXP_ROM_GEN_DEVID) { // When we have a device ID on the ROM
1053
if (expRomComDevid == EXP_ROM_GEN_DEVID) { // Update the common DevId at the first time we find ID
1054
expRomComDevid = currRom->exp_rom_dev_id;
1055
} else { // Check if we have the same IDs, if yes, continue
1056
if (currRom->exp_rom_dev_id != expRomComDevid) { // There is a mismatch between ROMs
1057
expRomComDevid = MISS_MATCH_DEV_ID;
1058
expRomWarning = true;
1059
snprintf(expRomWarningMsg,
1060
MAX_ROM_ERR_MSG_LEN,
1061
"The device IDs of the ROMs mismatched.");
1067
magicFound = false; // Clean the magic_found to start search for another magic string
1068
i += (ROM_INFO_SIZE - 1); // Increase the index to point to the end of the ROM info.
1073
// TODO: ADD CHECKSUM CHECK
1075
return errmsg("Cannot get ROM version. Signature not found.");
1079
if (!noRomChecksum) { // No need for checksum on some ROMs like uEFI
1080
u_int8_t romChecksum = 0;
1081
romChecksumRange = romSect[2] * 512;
1082
if (romChecksumRange > romSect.size()) {
1084
"ROM size field (0x%2x) is larger than actual ROM size (0x%x)",
1085
romChecksumRange, (u_int32_t) romSect.size());
1086
} else if (romChecksumRange == 0) {
1088
"ROM size field is 0. Unknown ROM format or corrupted ROM.");
1091
for (u_int32_t i = 0; i < romChecksumRange; i++) {
1092
romChecksum += romSect[i];
1095
if (romChecksum != 0) {
1096
expRomWarning = true;
1099
MAX_ROM_ERR_MSG_LEN,
1100
"Bad ROM Checksum (0x%02x), ROM info may not be displayed correctly.",
1108
bool FwOperations::RomInfo::GetExpRomVerForOneRom(u_int32_t verOffset)
1114
rom_info_t *romInfo;
1116
if (numOfExpRom == MAX_ROMS_NUM) {
1117
expRomWarning = true;
1118
snprintf(expRomWarningMsg,
1119
MAX_ROM_ERR_MSG_LEN,
1120
"Number of exp ROMs exceeds the maximum allowed number: %d",
1124
romInfo = &(romsInfo[numOfExpRom]);
1126
// Following mlxsign:
1127
// 31:24 0 Compatible with UEFI
1128
// 23:16 ProductID Product ID:
1129
// 0x1 - CLP implementation for Sinai (MT25408)
1130
// 0x2 - CLP implementation for Hermon DDR (MT25418)
1131
// 0x3 - CLP implementation for Hermon QDR (MT26428)
1132
// 0x4 - CLP implementation for Hermon ETHERNET (MT25448)
1135
// 0x12 - CLP with device ID and Version
1136
// 0x21 - FCODE - IBM's ROM version format, the same as PXE
1137
// (0xf) - extended format(see code or rom version format document)
1139
// 15:0 Major version If ProductID < 0x10 or == 0x12 this field is subversion
1140
// number, otherwise It's product major version.
1142
// 31:16 Minor version Product minor version*. Not valid if
1143
// roductID < 0x10 or == 0x12.
1144
// 15:0 SubMinor version Product sub minor version*. Not valid if
1145
// ProductID < 0x10 or == 0x12.
1147
// 31:16 Device ID The PCI Device ID (ex. 0x634A for Hermon
1148
// DDR). Not valid if ProductID < 0x10.
1149
// 15:12 Port Number Port number: 0 - Port independent, 1 - Port 1, 2 - Port 2
1151
// 0:7 Protocol type: 0=IB 1=ETH 2=VPI
1153
// Get expansion rom product ID
1154
tmp = __le32_to_cpu(*((u_int32_t*) &romSect[verOffset]));
1155
romInfo->exp_rom_product_id = tmp >> 16;
1156
romInfo->exp_rom_ver[0] = tmp & 0xffff;
1158
if (romInfo->exp_rom_product_id < 0xF || romInfo->exp_rom_product_id == 0x12) {
1159
romInfo->exp_rom_num_ver_fields = 1;//For CLPs
1160
} else if (romInfo->exp_rom_product_id == 0xF) {
1161
romInfo->exp_rom_num_ver_fields = 0;
1163
romInfo->exp_rom_num_ver_fields = 3;
1166
if (romInfo->exp_rom_product_id == 0x11 || romInfo->exp_rom_product_id == 0x21) {
1167
noRomChecksum = true;
1170
if (romInfo->exp_rom_product_id >= 0x10) {
1171
offs8 = __le32_to_cpu(*((u_int32_t*) &romSect[verOffset + 8]));
1172
romInfo->exp_rom_dev_id = offs8 >> 16;
1173
//0x12 is CLP we have only 1 version field and no porty
1174
if (romInfo->exp_rom_product_id != 0x12){
1175
offs4 = __le32_to_cpu(*((u_int32_t*) &romSect[verOffset + 4]));
1176
romInfo->exp_rom_ver[1] = offs4 >> 16;
1177
romInfo->exp_rom_ver[2] = offs4 & 0xffff;
1179
romInfo->exp_rom_port = (offs8 >> 12) & 0xf;
1180
romInfo->exp_rom_proto = offs8 & 0xff;
1182
} else if (romInfo->exp_rom_product_id == 0xf) {
1183
// get string length
1184
u_int32_ba tmp_ba = *((u_int32_t*) &romSect[verOffset + 0xc]);
1185
u_int32_t str_len = u_int32_t(tmp_ba.range(15, 8));
1186
u_int32_t sign_length = u_int32_t(tmp_ba.range(7, 0));
1187
u_int32_t dws_num = ((str_len + 3) / 4) + 4;
1189
if (sign_length < dws_num) {
1191
"The Signature length (%d) and the ROM version string length (%d) are not coordinated",
1192
sign_length, str_len);
1196
char free_str[FREE_STR_MAX_LEN];
1197
strncpy(free_str,(char*) &romSect[verOffset + 0x10], str_len);
1198
free_str[str_len] = '\0';
1199
if (sscanf((char*) free_str, "%d", &svnv) == 1) {
1200
romInfo->exp_rom_ver[0] = svnv;
1203
tmp_ba = __le32_to_cpu(*((u_int32_t*) &romSect[0x18]));
1204
u_int32_t dev_id_off = u_int32_t(tmp_ba.range(15, 0)) + 4;
1206
if (dev_id_off >= romSect.size()) {
1208
"The device ID offset %#x is out of range. ROM size: %#x",
1209
dev_id_off, (u_int32_t) romSect.size());
1213
tmp_ba = __le32_to_cpu(*((u_int32_t*) &romSect[dev_id_off]));
1214
romInfo->exp_rom_dev_id = u_int32_t(tmp_ba.range(31, 16));
1215
u_int32_t vendor_id = u_int32_t(tmp_ba.range(15, 0));
1217
if (vendor_id != MELLANOX_VENDOR_ID) {
1218
expRomWarning = true;
1219
snprintf(expRomWarningMsg,
1220
MAX_ROM_ERR_MSG_LEN,
1221
"The Exp-ROM PCI vendor ID: %#x does not match the expected value: %#x.",
1222
vendor_id, MELLANOX_VENDOR_ID);
1229
bool FwOperations::ReadImageFile(const char *fimage, u_int8_t *&file_data, int &file_size, int min_size)
1233
if ((fh = fopen(fimage, "rb")) == NULL) {
1234
return errmsg("Can not open %s: %s\n", fimage, strerror(errno));
1237
if (fseek(fh, 0, SEEK_END) < 0) {
1239
return errmsg("Failed to get size of the file \"%s\": %s\n", fimage, strerror(errno));
1242
int read_file_size = ftell(fh);
1243
if (read_file_size < 0) {
1245
return errmsg("Failed to get size of the file \"%s\": %s\n", fimage, strerror(errno));
1249
if (min_size > read_file_size) {
1250
file_size = min_size;
1252
file_size = read_file_size;
1255
file_data = new u_int8_t[file_size];
1256
if (fread(file_data, 1, read_file_size, fh) != (size_t)read_file_size) {
1259
return errmsg("Failed to read from %s: %s\n", fimage, strerror(errno));
1265
void FwOperations::SetDevFlags(chip_type_t chipType, u_int32_t devType, fw_img_type_t fwType, bool &ibDev, bool ðDev) {
1267
if (chipType == CT_IS4) {
1270
} else if (chipType == CT_SWITCHX) {
1274
ibDev = (fwType == FIT_FS3) || !CntxEthOnly(devType);
1275
ethDev = chipType == CT_CONNECTX;
1278
if ((!ibDev && !ethDev) || chipType == CT_UNKNOWN) {
1279
// Unknown device id - for forward compat - assume that ConnectX is MP and
1280
// prev HCAs are IB only (these flags are for printing only - no real harm can be done).
1281
// TODO: FS2 does not mean ConnectX now.
1283
if (fwType == FIT_FS2) {
1291
bool FwOperations::IsFwSupportingRomModify(u_int16_t fw_ver[3])
1293
u_int16_t supported_fw[3] = {MAJOR_MOD_ROM_FW, MINOR_MOD_ROM_FW, SUBMINOR_MOD_ROM_FW};
1294
return !FwVerLessThan(fw_ver, supported_fw);
1297
bool FwOperations::checkMatchingExpRomDevId(const fw_info_t& info)
1300
if ((info.fw_info.roms_info.num_of_exp_rom > 0) && (info.fw_info.dev_type)
1301
&& (info.fw_info.roms_info.exp_rom_com_devid != EXP_ROM_GEN_DEVID) \
1302
&& (info.fw_info.roms_info.exp_rom_com_devid != MISS_MATCH_DEV_ID)
1303
&& (info.fw_info.dev_type != info.fw_info.roms_info.exp_rom_com_devid)) {
1307
return checkMatchingExpRomDevId(info.fw_info.dev_type, info.fw_info.roms_info);
1311
bool FwOperations::checkMatchingExpRomDevId(u_int16_t dev_type, roms_info_t roms_info)
1313
if ((roms_info.num_of_exp_rom > 0) && (dev_type)
1314
&& (roms_info.exp_rom_com_devid != EXP_ROM_GEN_DEVID) \
1315
&& (roms_info.exp_rom_com_devid != MISS_MATCH_DEV_ID)
1316
&& (dev_type != roms_info.exp_rom_com_devid)) {
1323
bool FwOperations::FwWriteBlock(u_int32_t addr, std::vector<u_int8_t> dataVec, ProgressCallBack progressFunc)
1325
if (dataVec.empty()) {
1326
return errmsg("no data to write.");
1328
// make sure we work on device
1329
if (!_ioAccess->is_flash()) {
1330
return errmsg("no flash detected.(command is only supported on flash)");
1333
//check if flash is big enough
1334
if ((addr + dataVec.size()) > ((Flash*)_ioAccess)->get_size()) {
1335
return errmsg("Writing %#x bytes from address %#x is out of flash limits (%#x bytes)\n",
1336
(unsigned int)(dataVec.size()), (unsigned int)addr, (unsigned int)_ioAccess->get_size());
1339
if (!writeImage(progressFunc, addr, &dataVec[0], (int)dataVec.size())) {
1346
bool FwOperations::FwBurnData(u_int32_t *data, u_int32_t dataSize, ProgressCallBack progressFunc) {
1347
FwOperations* newImgOps;
1348
fwOpsParams imgOpsParams;
1349
char errBuff[1024] = {0};
1351
imgOpsParams.psid = NULL;
1352
imgOpsParams.buffHndl = data;
1353
imgOpsParams.buffSize = dataSize;
1354
imgOpsParams.errBuff = errBuff;
1355
imgOpsParams.errBuffSize = 1024;
1356
imgOpsParams.hndlType = FHT_FW_BUFF;
1358
newImgOps = FwOperationsCreate(imgOpsParams);
1359
if (newImgOps == NULL) {
1360
return errmsg("Internal error: Failed to create modified image: %s", errBuff);
1362
if (!newImgOps->FwVerify(NULL)) {
1363
errmsg("Internal error: Modified image failed to verify: %s", newImgOps->err());
1364
newImgOps->FwCleanUp();
1369
ExtBurnParams burnParams = ExtBurnParams();
1370
burnParams.ignoreVersionCheck = true;
1371
burnParams.progressFunc = progressFunc;
1372
burnParams.useImagePs = true;
1373
burnParams.useImageGuids = true;
1374
burnParams.burnRomOptions = ExtBurnParams::BRO_ONLY_FROM_IMG;
1376
if (!FwBurnAdvanced(newImgOps, burnParams)) {
1377
newImgOps->FwCleanUp();
1379
return errmsg("Failed to re-burn image after modify: %s", err());
1381
newImgOps->FwCleanUp();
1387
bool FwOperations::getRomsInfo(FBase* io, roms_info_t& romsInfo)
1389
std::vector<u_int8_t> romSector;
1391
romSector.resize(io->get_size());
1392
if (!io->read(0, &romSector[0], io->get_size())) {
1395
RomInfo info(romSector, false);
1397
info.initRomsInfo(&romsInfo);
1401
const char* FwOperations::expRomType2Str(u_int16_t type)
1413
return "CLP "; // hack as 0xf isnt always CLP (its type is defined in the free string inside the ROM)
1423
return (const char*)NULL;
1425
return (const char*)NULL;