~ubuntu-branches/ubuntu/utopic/mstflint/utopic-updates

« back to all changes in this revision

Viewing changes to .pc/uninitialized-variables-O3.patch/mlxfwops/lib/fw_ops.cpp

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2015-07-15 10:21:50 UTC
  • Revision ID: package-import@ubuntu.com-20150715102150-ywh5chiwl6lzq25k
Tags: 3.7.0-1ubuntu2
debian/patches/uninitialized-variables-O3.patch: Steal patch
from vivid/wily to fix build failure with -O3 on ppc64el.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) Jan 2013 Mellanox Technologies Ltd. All rights reserved.
 
3
 * 
 
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:
 
9
 * 
 
10
 *     Redistribution and use in source and binary forms, with or
 
11
 *     without modification, are permitted provided that the following
 
12
 *     conditions are met:
 
13
 * 
 
14
 *      - Redistributions of source code must retain the above
 
15
 *        copyright notice, this list of conditions and the following
 
16
 *        disclaimer.
 
17
 * 
 
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.
 
22
 * 
 
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
 
30
 * SOFTWARE.
 
31
 */
 
32
 
 
33
 
 
34
#include <stdlib.h>
 
35
#include <string.h>
 
36
#include <errno.h>
 
37
 
 
38
#include "flint_base.h"
 
39
#include "flint_io.h"
 
40
#include "fw_ops.h"
 
41
#include "fs3_ops.h"
 
42
#include "fs2_ops.h"
 
43
 
 
44
 
 
45
#ifndef NO_MFA_SUPPORT
 
46
#include <mfa.h>
 
47
#endif
 
48
 
 
49
#define BAD_CRC_MSG "Bad CRC."
 
50
extern const char* g_sectNames[];
 
51
 
 
52
#ifndef NO_MFA_SUPPORT
 
53
 
 
54
int FwOperations::getFileSignature(const char* fname)
 
55
{
 
56
    FILE* fin;
 
57
    char tmpb[16];
 
58
    int res = 0;
 
59
 
 
60
    if (!(fin = fopen(fname, "r"))) {
 
61
        // abit ugly , need to establish a correct ret val
 
62
        return IMG_SIG_OPEN_FILE_FAILED;
 
63
    }
 
64
    if (!fgets(tmpb, sizeof(tmpb), fin)) {
 
65
        goto clean_up;
 
66
    }
 
67
    if (strlen(tmpb) < 4) {
 
68
        goto clean_up;
 
69
    }
 
70
 
 
71
    if (!strncmp(tmpb, "MTFW", 4)) {
 
72
        res = IMG_SIG_TYPE_BIN;
 
73
    }
 
74
    if (!strncmp(tmpb, "MFAR", 4)) {
 
75
        res = IMG_SIG_TYPE_MFA;
 
76
    }
 
77
 
 
78
clean_up:
 
79
    fclose(fin);
 
80
    return res;
 
81
}
 
82
 
 
83
 
 
84
int FwOperations::getBufferSignature(u_int8_t* buf, u_int32_t size)
 
85
{
 
86
    int res = 0;
 
87
 
 
88
    if (size < 4) {
 
89
        return 0;
 
90
    }
 
91
    if (!strncmp((char*)buf, "MTFW", 4)) {
 
92
        res = IMG_SIG_TYPE_BIN;
 
93
    }
 
94
    if (!strncmp((char*)buf, "MFAR", 4)) {
 
95
        res = IMG_SIG_TYPE_MFA;
 
96
    }
 
97
 
 
98
    return res;
 
99
}
 
100
 
 
101
 
 
102
int FwOperations::getMfaImg(char* fileName, char *psid, u_int8_t **imgbuf)
 
103
{
 
104
    int res;
 
105
    mfa_desc* mfa_d;
 
106
    int image_type = 1; //FW image
 
107
 
 
108
    if (psid == NULL) {
 
109
        return -1; //No psid => no image
 
110
    }
 
111
    if ((res = mfa_open_file(&mfa_d, fileName))) {
 
112
        return -1;
 
113
    }
 
114
 
 
115
    res = mfa_get_image(mfa_d, psid, image_type, (char*)"", imgbuf);
 
116
 
 
117
    mfa_close(mfa_d);
 
118
    return res;
 
119
}
 
120
 
 
121
 
 
122
int FwOperations::getMfaImg(u_int8_t* mfa_buf, int size, char *psid, u_int8_t **imgbuf)
 
123
{
 
124
    int res;
 
125
    mfa_desc* mfa_d;
 
126
    int image_type = 1; //FW image
 
127
 
 
128
    if (psid == NULL) {
 
129
        return -1; //No psid => no image
 
130
    }
 
131
    if ((res = mfa_open_buf(&mfa_d, mfa_buf, size))) {
 
132
        return -1;
 
133
    }
 
134
 
 
135
    res = mfa_get_image(mfa_d, psid, image_type, (char*)"", imgbuf);
 
136
 
 
137
    mfa_close(mfa_d);
 
138
    return res;
 
139
}
 
140
#endif
 
141
 
 
142
 
 
143
void FwOperations::FwCleanUp()
 
144
{
 
145
    _ioAccess->close();
 
146
    delete _ioAccess;
 
147
    if (_fname != NULL) {
 
148
        delete[] _fname;
 
149
    }
 
150
}
 
151
 
 
152
 
 
153
void FwOperations::FwInitCom()
 
154
{
 
155
    memset(&_fwImgInfo, 0, sizeof(_fwImgInfo));
 
156
}
 
157
 
 
158
 
 
159
 
 
160
bool FwOperations::checkBoot2(u_int32_t beg, u_int32_t offs, u_int32_t& next, bool fullRead, const char *pref, VerifyCallBack verifyCallBackFunc)
 
161
{
 
162
    u_int32_t    size;
 
163
 
 
164
    // char         *pr = (char *)alloca(strlen(pref) + 512);
 
165
    char pr[strlen(pref) + 512];
 
166
    sprintf(pr, "%s /0x%08x/ (BOOT2)", pref, offs+beg);
 
167
    // Size
 
168
    READ4((*_ioAccess), offs+beg+4, &size, pr);
 
169
    TOCPU1(size);
 
170
    if (size > 1048576 || size < 4) {
 
171
        report_callback(verifyCallBackFunc, "%s /0x%08x/ - unexpected size (0x%x)\n", pr, offs+beg+4, size);
 
172
        return false;
 
173
    }
 
174
    _fwImgInfo.bootSize = (size + 4) * 4;
 
175
 
 
176
 
 
177
    sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (BOOT2)", pref, offs+beg,
 
178
            offs+beg+(size+4)*4-1, (size+4)*4);
 
179
 
 
180
    if ((_ioAccess->is_flash() && fullRead == true) || !_ioAccess->is_flash()) {
 
181
        Crc16        crc;
 
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);
 
187
 
 
188
        TOCPUn(buff, size+4);
 
189
        CRC1n(crc, buff, size+4);
 
190
        CRC1n(_ioAccess->get_image_crc(), buff, size+4);
 
191
 
 
192
 
 
193
        crc.finish();
 
194
 
 
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);
 
200
        }
 
201
        _ioAccess->get_image_crc() << crc_act;
 
202
        // TODO: Print CRC
 
203
        if (0) {
 
204
            report_callback(verifyCallBackFunc, "%s - OK (CRC:0x%04x)\n", pr, (crc_act & 0xffff));
 
205
        } else {
 
206
            report_callback(verifyCallBackFunc, "%s - OK\n", pr);
 
207
        }
 
208
    }
 
209
    next = offs + size*4 + 16;
 
210
    return true;
 
211
} // checkBoot2
 
212
 
 
213
 
 
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)
 
216
{
 
217
 
 
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);
 
222
    }
 
223
    // if (_print_crc) {
 
224
    // TODO: Print CRC here.
 
225
    if (0) {
 
226
        report_callback(verifyCallBackFunc, "%s - OK (CRC:0x%04x)\n", pr, crc_act & 0xffff);
 
227
    } else {
 
228
        if (ignore_crc) {
 
229
            report_callback(verifyCallBackFunc, "%s - CRC IGNORED\n", pr);
 
230
        } else {
 
231
            if (blank_crc) {
 
232
                report_callback(verifyCallBackFunc, "%s - BLANK CRC (0xffff)\n", pr);
 
233
            } else {
 
234
                report_callback(verifyCallBackFunc, "%s - OK\n", pr);
 
235
            }
 
236
        }
 
237
    }
 
238
    return true;
 
239
}
 
240
 
 
241
bool FwOperations::FwVerLessThan(u_int16_t r1[3], u_int16_t r2[3]) {
 
242
    for (int i = 0; i < 3 ; i++)
 
243
        if (r1[i] < r2[i])
 
244
            return true;
 
245
        else if (r1[i] > r2[i])
 
246
            return false;
 
247
 
 
248
    return false; // equal versions
 
249
}
 
250
const u_int32_t FwOperations::_cntx_magic_pattern[4] = {
 
251
    0x4D544657,   // Ascii of "MTFW"
 
252
    0x8CDFD000,   // Random data
 
253
    0xDEAD9270,
 
254
    0x4154BEEF
 
255
};
 
256
 
 
257
const u_int32_t FwOperations::_cntx_image_start_pos[FwOperations::CNTX_START_POS_SIZE] = {
 
258
    0,
 
259
    0x10000,
 
260
    0x20000,
 
261
    0x40000,
 
262
    0x80000,
 
263
    0x100000,
 
264
    0x200000
 
265
};
 
266
 
 
267
bool FwOperations::CntxFindMagicPattern (FBase* ioAccess, u_int32_t addr) {
 
268
    if (addr + 16 > ioAccess->get_size()) {
 
269
        return false;
 
270
    }
 
271
    for (int i = 0; i < 4 ; i++) {
 
272
        u_int32_t w;
 
273
        READ4_NOERRMSG((*ioAccess), addr + i * 4, &w);
 
274
        TOCPU1(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);
 
277
            return false;
 
278
        }
 
279
    }
 
280
 
 
281
    return true;
 
282
}
 
283
 
 
284
 
 
285
 
 
286
// FindAllImageStart
 
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) {
 
290
    int needed_pos_num;
 
291
 
 
292
    needed_pos_num = CNTX_START_POS_SIZE;
 
293
 
 
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;
 
299
        }
 
300
    }
 
301
 
 
302
    ioAccess->set_address_convertor(0,0);
 
303
    *found_images = 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];
 
307
            (*found_images)++;
 
308
        }
 
309
    }
 
310
 
 
311
    return true;
 
312
}
 
313
 
 
314
 
 
315
 
 
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) {
 
318
 
 
319
    file_sect.clear();
 
320
    file_sect.insert(file_sect.end(),
 
321
                     (u_int8_t*)buff,
 
322
                     (u_int8_t*)buff + size);
 
323
 
 
324
 
 
325
    return true;
 
326
}
 
327
 
 
328
 
 
329
bool FwOperations::FwAccessCreate(fw_ops_params_t& fwParams, FBase **ioAccessP)
 
330
{
 
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);
 
337
            return false;
 
338
        }
 
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);
 
343
                delete *ioAccessP;
 
344
                return false;
 
345
            }
 
346
        } else if (sig == IMG_SIG_TYPE_MFA) {
 
347
            u_int8_t* imgbuf;
 
348
            int sz;
 
349
            if ((sz = getMfaImg(fwParams.fileHndl, fwParams.psid, &imgbuf)) < 0) {
 
350
                WriteToErrBuff(fwParams.errBuff,"Failed to get MFA Image.", fwParams.errBuffSize);
 
351
                return false;
 
352
            }
 
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);
 
357
                delete *ioAccessP;
 
358
                return false;
 
359
            }
 
360
            mfa_release_image(imgbuf);
 
361
        } else {
 
362
            WriteToErrBuff(fwParams.errBuff,"Invalid Image signature.", fwParams.errBuffSize);
 
363
            return false; //Unknown signature
 
364
        }
 
365
#else
 
366
        *ioAccessP = new FImage;
 
367
        if (!(*ioAccessP)->open(fwParams.fileHndl, false, !fwParams.shortErrors)) {
 
368
            WriteToErrBuff(fwParams.errBuff,(*ioAccessP)->err(), fwParams.errBuffSize);
 
369
            delete *ioAccessP;
 
370
            return false;
 
371
        }
 
372
#endif
 
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);
 
381
                delete *ioAccessP;
 
382
                return false;
 
383
            }
 
384
        } else if (sig == IMG_SIG_TYPE_MFA) {
 
385
            u_int8_t* imgbuf;
 
386
            int sz;
 
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);
 
389
                return false;
 
390
            }
 
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);
 
395
                delete *ioAccessP;
 
396
                return false;
 
397
            }
 
398
            mfa_release_image(imgbuf);
 
399
        } else {
 
400
            WriteToErrBuff(fwParams.errBuff,"Invalid Image signature.", fwParams.errBuffSize);
 
401
            return false;//Unknown signature
 
402
        }
 
403
#else
 
404
        *ioAccessP = new FImage;
 
405
        if (!((FImage*)*ioAccessP)->open(fwParams.buffHndl, numInfo, !fwParams.shortErrors)) {
 
406
            WriteToErrBuff(fwParams.errBuff,(*ioAccessP)->err(), fwParams.errBuffSize);
 
407
            delete *ioAccessP;
 
408
            return false;
 
409
        }
 
410
#endif
 
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);
 
415
            delete *ioAccessP;
 
416
            return false;
 
417
        }
 
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);
 
424
            delete *ioAccessP;
 
425
            return false;
 
426
        }
 
427
        //set no flash verify if needed (default =false)
 
428
        ((Flash*)*ioAccessP)->set_no_flash_verify(fwParams.noFlashVerify);
 
429
     } else {
 
430
         WriteToErrBuff(fwParams.errBuff,"Unknown Handle Type.", fwParams.errBuffSize);
 
431
         return false;
 
432
     }
 
433
    return true;
 
434
}
 
435
 
 
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)) {
 
444
            return FS_FS2_GEN;
 
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)) {
 
448
            return FS_FS3_GEN;
 
449
        }
 
450
    } else {
 
451
        u_int32_t found_images;
 
452
        u_int32_t image_start[CNTX_START_POS_SIZE];
 
453
 
 
454
        // Image - check if magic pattern is somewhere in the file:
 
455
        CntxFindAllImageStart(&f, image_start, &found_images);
 
456
        if (found_images) {
 
457
            u_int32_t data;
 
458
            u_int8_t image_version;
 
459
            READ4_NOERRMSG(f, FS3_IND_ADDR, &data);
 
460
            TOCPU1(data);
 
461
            image_version = data >> 24;
 
462
            if (image_version == IMG_VER_FS3) {
 
463
                return FS_FS3_GEN;
 
464
            } else {
 
465
                // TODO: if the img format version is unknown we should fail instead of considering it FS2
 
466
                return FS_FS2_GEN;
 
467
            }
 
468
        }
 
469
    }
 
470
    return FS_OLD_GEN;
 
471
}
 
472
 
 
473
FwOperations* FwOperations::FwOperationsCreate(void* fwHndl, void *info, char* psid, fw_hndl_type_t hndlType, char* errBuff, int buffSize)
 
474
{
 
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;
 
481
 
 
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;
 
498
    }
 
499
    return FwOperationsCreate(fwParams);
 
500
}
 
501
 
 
502
FwOperations* FwOperations::FwOperationsCreate(fw_ops_params_t& fwParams)
 
503
{
 
504
    FwOperations* fwops;
 
505
    u_int8_t fwFormat;
 
506
    FBase *ioAccess;
 
507
    bool getFwFormatFromImg = false;
 
508
 
 
509
    if (!FwAccessCreate(fwParams, &ioAccess)) {
 
510
        return (FwOperations*)NULL;
 
511
    }
 
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;
 
515
    }
 
516
    fwFormat = CheckFwFormat(*ioAccess, getFwFormatFromImg);
 
517
    switch (fwFormat) {
 
518
        case FS_FS2_GEN: {
 
519
            fwops = new Fs2Operations(ioAccess);
 
520
            break;
 
521
        }
 
522
        case FS_FS3_GEN: {
 
523
            fwops = new Fs3Operations(ioAccess);
 
524
            break;
 
525
        }
 
526
        default:
 
527
            delete ioAccess;
 
528
            WriteToErrBuff(fwParams.errBuff,"invalid Firmware Format (found FS Gen 1)", fwParams.errBuffSize);
 
529
            return (FwOperations*)NULL;
 
530
    }
 
531
    fwops->_advErrors = !fwParams.shortErrors;
 
532
    fwops->FwInit();
 
533
    if (fwParams.hndlType == FHT_FW_FILE) {
 
534
        fwops->_fname = strcpy(new char[strlen(fwParams.fileHndl)+ 1], fwParams.fileHndl);
 
535
    }
 
536
    return fwops;
 
537
}
 
538
 
 
539
u_int32_t FwOperations::CalcImageCRC(u_int32_t* buff, u_int32_t size)
 
540
{
 
541
    Crc16 crc;
 
542
    TOCPUn(buff, size);
 
543
    CRCn(crc, buff, size);
 
544
    CPUTOn(buff, size);
 
545
    crc.finish();
 
546
    u_int32_t new_crc = crc.get();
 
547
    return new_crc;
 
548
}
 
549
 
 
550
bool FwOperations::writeImage(ProgressCallBack progressFunc, u_int32_t addr, void *data, int cnt, bool is_phys_addr)
 
551
{
 
552
    u_int8_t   *p = (u_int8_t *)data;
 
553
    u_int32_t  curr_addr = addr;
 
554
    u_int32_t  towrite = cnt;
 
555
    bool rc;
 
556
//    if (!_ioAccess->is_flash()) {
 
557
 //       return errmsg("Internal error: writeImage is supported only on flash.");
 
558
   // }
 
559
    while (towrite) {
 
560
        // Write
 
561
        int trans;
 
562
        if (_ioAccess->is_flash()) {
 
563
            trans = (towrite > (int)Flash::TRANS) ? (int)Flash::TRANS : towrite;
 
564
            if (is_phys_addr) {
 
565
                rc = ((Flash*)_ioAccess)->write_phy(curr_addr, p, trans);
 
566
            } else {
 
567
                rc = ((Flash*)_ioAccess)->write(curr_addr, p, trans);
 
568
            }
 
569
            if (!rc) {
 
570
                return errmsg("Flash write failed: %s", _ioAccess->err());
 
571
            }
 
572
        } else {
 
573
            trans = towrite;
 
574
            if (!ModifyImageFile(_fname, curr_addr, p, trans)) {
 
575
                return false;
 
576
            }
 
577
        }
 
578
        p += trans;
 
579
        curr_addr += trans;
 
580
        towrite -= trans;
 
581
 
 
582
        // Report
 
583
        if (progressFunc != NULL) {
 
584
            u_int32_t new_perc = ((cnt - towrite) * 100) / cnt;
 
585
 
 
586
                    if (progressFunc((int)new_perc)) {
 
587
                        return errmsg("Aborting... recieved interrupt signal");
 
588
                    }
 
589
            }
 
590
        }
 
591
 
 
592
    return true;
 
593
} //  Flash::WriteImage
 
594
 
 
595
bool FwOperations::ModifyImageFile(const char *fimage, u_int32_t addr, void *data, int cnt)
 
596
{
 
597
    int file_size;
 
598
    u_int8_t * file_data;
 
599
 
 
600
    if (!ReadImageFile(fimage, file_data, file_size, addr + cnt)) {
 
601
        return false;
 
602
    }
 
603
    memcpy(&file_data[addr], data, cnt);
 
604
 
 
605
    if (!WriteImageToFile(fimage, file_data, file_size)) {
 
606
        delete[] file_data;
 
607
        return false;
 
608
    }
 
609
    delete[] file_data;
 
610
    return true;
 
611
}
 
612
 
 
613
bool FwOperations::WriteImageToFile(const char *file_name, u_int8_t *data, u_int32_t length)
 
614
{
 
615
    FILE* fh;
 
616
    if ((fh = fopen(file_name, "wb")) == NULL) {
 
617
        return errmsg("Can not open %s: %s\n", file_name, strerror(errno));
 
618
    }
 
619
 
 
620
    // Write output
 
621
    if (fwrite(data, 1, length, fh) != length) {
 
622
        fclose(fh);
 
623
        return errmsg("Failed to write to %s: %s\n", file_name, strerror(errno));
 
624
    }
 
625
    fclose(fh);
 
626
    return true;
 
627
}
 
628
 
 
629
bool FwOperations::CheckMac(u_int64_t mac) {
 
630
    if ((mac >> 40) & 0x1) {
 
631
        return errmsg("Multicast bit (bit 40) is set");
 
632
    }
 
633
 
 
634
    if (mac >> 48) {
 
635
        return errmsg("More than 48 bits are used");
 
636
    }
 
637
 
 
638
    return true;
 
639
}
 
640
 
 
641
void FwOperations::recalcSectionCrc(u_int8_t *buf, u_int32_t data_size) {
 
642
 
 
643
    Crc16              crc;
 
644
    for (u_int32_t i = 0; i < data_size; i += 4) {
 
645
        crc << __be32_to_cpu(*(u_int32_t*)(buf + i));
 
646
    }
 
647
    crc.finish();
 
648
    *((u_int32_t*)(buf + data_size)) = __cpu_to_be32(crc.get());
 
649
}
 
650
 
 
651
chip_type_t FwOperations::getChipType() {
 
652
    int i = 0;
 
653
    while (hwDevData[i].name != NULL) {
 
654
        int j = 0;
 
655
        while (hwDevData[i].swDevIds[j] != 0) {
 
656
            if (hwDevData[i].swDevIds[j] == _fwImgInfo.ext_info.dev_type) {
 
657
                    return hwDevData[i].chipType;
 
658
                }
 
659
                j++;
 
660
            }
 
661
            i++;
 
662
        }
 
663
    return CT_UNKNOWN;
 
664
}
 
665
 
 
666
chip_type_t FwOperations::getChipTypeFromHwDevid(u_int32_t hwDevId) {
 
667
    int i = 0;
 
668
    while (hwDevData[i].name != NULL) {
 
669
        if (hwDevData[i].hwDevId == hwDevId) {
 
670
            return hwDevData[i].chipType;
 
671
        }
 
672
            i++;
 
673
        }
 
674
    return CT_UNKNOWN;
 
675
}
 
676
 
 
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,
 
685
                                         4097, 4098, 0}},
 
686
    { "ConnectX3",        CX3_HW_ID, CT_CONNECTX, 2,  {4099, 4100, 4101, 4102,
 
687
                                         4103, 4104, 4105, 4106,
 
688
                                         4107, 4108, 4109, 4110,
 
689
                                         4111, 4112, 0}},
 
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
 
699
};
 
700
 
 
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
 
719
};
 
720
 
 
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)
 
724
{
 
725
 
 
726
    for (int i = 0;  hwDev2Str[i].hwDevId != 0; i++) {
 
727
        const HwDev2Str *hwDev2StrMem = &(hwDev2Str[i]);
 
728
 
 
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);
 
733
            }
 
734
            strcpy(hw_name, hwDev2StrMem->name);
 
735
            return true;
 
736
        }
 
737
    }
 
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);
 
740
    return true;
 
741
}
 
742
 
 
743
 
 
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.
 
748
//
 
749
bool FwOperations::CheckMatchingHwDevId(u_int32_t hwDevId, u_int32_t rev_id, u_int32_t* supportedHwId, u_int32_t supportedHwIdNum) {
 
750
 
 
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];
 
754
 
 
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];
 
761
 
 
762
        if (currSupportedHwId == 0) {
 
763
            break;
 
764
        }
 
765
        // Check if device is supported!
 
766
        if ( supp_hw_id == hwDevId && supp_rev_id == rev_id) {
 
767
            return true;
 
768
        }
 
769
        // Append checked to list of supported device in order to print it in the error if we this device is not supported
 
770
 
 
771
        // Get the HW name of current supported HW ID
 
772
        if (!HWIdRevToName(supp_hw_id, supp_rev_id, hw_name)) {
 
773
            return false;
 
774
        }
 
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);
 
780
        }
 
781
 
 
782
        if (supp_hw_id_list[0] == '\0') {
 
783
            sprintf(supp_hw_id_list, "%s", hw_name);
 
784
        } else {
 
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);
 
787
        }
 
788
    }
 
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)) {
 
792
        return false;
 
793
    }
 
794
 
 
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);
 
797
}
 
798
bool FwOperations::CheckMatchingDevId(u_int32_t hwDevId, u_int32_t imageDevId) {
 
799
 
 
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) {
 
804
        hwDevId = 25204;
 
805
    }
 
806
 
 
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
 
811
        }
 
812
 
 
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];
 
817
                    break;
 
818
                }
 
819
            }
 
820
        }
 
821
    }
 
822
 
 
823
    if (devData == NULL) {
 
824
        report_warn("Unknown device id (%d) in the given FW image. Skipping HW match check.\n",
 
825
               imageDevId);
 
826
        return true;
 
827
    } else if (devData->hwDevId != hwDevId) {
 
828
        return errmsg("Trying to burn a \"%s\" image on a \"%s\" device.",
 
829
                      devData->name,
 
830
                      hwDevName);
 
831
    }
 
832
 
 
833
    return true;
 
834
}
 
835
 
 
836
void FwOperations::FwDebugPrint(char *str)
 
837
{
 
838
    if (_printFunc != NULL) {
 
839
        _printFunc(str);
 
840
    }
 
841
}
 
842
 
 
843
bool FwOperations::FwSetPrint(PrintCallBack PrintFunc)
 
844
{
 
845
    _printFunc = PrintFunc;
 
846
    return true;
 
847
}
 
848
 
 
849
bool FwOperations::CheckPSID(FwOperations &imageOps, u_int8_t allow_psid_change)
 
850
{
 
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);
 
855
        }
 
856
    }
 
857
    return true;
 
858
}
 
859
 
 
860
bool FwOperations::CheckFwVersion(FwOperations &imageOps, u_int8_t forceVersion)
 
861
{
 
862
    bool updateRequired = true;
 
863
    if (!forceVersion) {
 
864
        updateRequired = FwVerLessThan(_fwImgInfo.ext_info.fw_ver, imageOps._fwImgInfo.ext_info.fw_ver);
 
865
        if (!updateRequired) {
 
866
            return errmsg("FW is already updated.");
 
867
        }
 
868
    }
 
869
    return true;
 
870
}
 
871
 
 
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");
 
875
    }
 
876
    if (!((Flash*)_ioAccess)->sw_reset()) {
 
877
        return errmsg("%s",  _ioAccess->err());
 
878
    }
 
879
    return true;
 
880
}
 
881
 
 
882
 
 
883
void FwOperations::WriteToErrBuff(char* errBuff, const char* errStr, int size)
 
884
{
 
885
    if (size>0) {
 
886
        if (size-4 > (int) strlen(errStr)) {
 
887
            strncpy(errBuff, errStr, size);
 
888
        } else {
 
889
            strncpy(errBuff, errStr, size-4);
 
890
            strcpy(&errBuff[size-4], "...");
 
891
        }
 
892
    }
 
893
    return;
 
894
}
 
895
 
 
896
bool FwOperations::UpdateImgCache(u_int8_t *buff, u_int32_t addr, u_int32_t size)
 
897
{
 
898
    //avoid compiler warrnings
 
899
    (void)buff;
 
900
    (void)addr;
 
901
    (void)size;
 
902
    //in FS2 we dont have ImgCache, just in FS3 so we define a defult behaviour.
 
903
    return true;
 
904
}
 
905
 
 
906
bool FwOperations::CntxEthOnly(u_int32_t devid)
 
907
{
 
908
    return(devid == 25448) || // ETH
 
909
            (devid == 26448) || // ETH
 
910
            (devid == 25458) || //
 
911
            (devid == 26458) || //
 
912
            (devid == 26468) ||
 
913
            (devid == 26478);
 
914
}
 
915
 
 
916
// RomInfo implementation
 
917
 
 
918
FwOperations::RomInfo::RomInfo(const std::vector<u_int8_t>& romSector, bool resEndi)
 
919
{
 
920
    expRomFound = !romSector.empty();
 
921
    romSect = romSector;
 
922
    if (resEndi) {
 
923
        TOCPUn(&romSect[0], romSect.size()/4);
 
924
    }
 
925
    numOfExpRom = 0;
 
926
    expRomComDevid = 0;
 
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));
 
933
}
 
934
 
 
935
 
 
936
bool FwOperations::RomInfo::initRomsInfo(roms_info_t *info)
 
937
{
 
938
    if (info == NULL) {
 
939
        return errmsg("invalid roms_info_t pointer.");
 
940
    }
 
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];
 
951
    }
 
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];
 
961
        }
 
962
    }
 
963
 
 
964
    return true;
 
965
}
 
966
 
 
967
bool FwOperations::RomInfo::ParseInfo()
 
968
{
 
969
    if (!GetExpRomVersion()) {
 
970
        snprintf(expRomErrMsg, MAX_ROM_ERR_MSG_LEN, "%s",  err());
 
971
        expRomErrMsgValid = true;
 
972
        //printf("-D-expRomErrMsg: %s \n", expRomErrMsg);
 
973
    }
 
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);
 
980
    return true;
 
981
}
 
982
 
 
983
#define MAGIC_LEN 32
 
984
 
 
985
bool FwOperations::RomInfo::GetExpRomVersion()
 
986
{
 
987
    char magicString[MAGIC_LEN] = {"mlxsignX"};
 
988
    u_int32_t magicLen = strlen(magicString);
 
989
    bool magicFound = false;
 
990
    u_int32_t verOffset;
 
991
    u_int32_t romChecksumRange;
 
992
 
 
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] = ':';
 
996
 
 
997
    if (romSect.empty()) {
 
998
        return errmsg("Expansion Rom section not found.");
 
999
    }
 
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
 
1004
    // image.
 
1005
 
 
1006
    // Checksum:
 
1007
    if (romSect.size() < 4) {
 
1008
        return errmsg("ROM size (0x%x) is too small",
 
1009
                (u_int32_t) romSect.size());
 
1010
    }
 
1011
 
 
1012
    // restore endianess is done in the constructor if needed.
 
1013
    /*  // FOR WE DON'T CHECKSUM UNTIL WE DECIDED REGARDING THE NEW FORMAT.
 
1014
     */
 
1015
    // We will look for the magic string in whole ROM instead of the first part of it.
 
1016
    romChecksumRange = romSect.size();
 
1017
 
 
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]) {
 
1021
                break;
 
1022
            } else if (j == magicLen - 1) {
 
1023
                magicFound = true;
 
1024
            }
 
1025
        }
 
1026
 
 
1027
 
 
1028
        if (magicFound) {
 
1029
            // Get the ROM info after the mlxsign
 
1030
            bool rc;
 
1031
            rom_info_t *currRom;
 
1032
 
 
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)",
 
1038
                        MAX_ROMS_NUM);
 
1039
                // Here we want to warn regarding this issue without checksum.
 
1040
                return true;
 
1041
            }
 
1042
 
 
1043
            currRom = &(romsInfo[numOfExpRom]);
 
1044
            verOffset = i + magicLen;
 
1045
            rc = GetExpRomVerForOneRom(verOffset);
 
1046
            if (rc != true) {
 
1047
                return rc;
 
1048
            }
 
1049
 
 
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.");
 
1062
                        }
 
1063
                    }
 
1064
                }
 
1065
            }
 
1066
 
 
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.
 
1069
            numOfExpRom++;
 
1070
        }
 
1071
    }
 
1072
 
 
1073
    // TODO: ADD CHECKSUM CHECK
 
1074
    if (!numOfExpRom) {
 
1075
        return errmsg("Cannot get ROM version. Signature not found.");
 
1076
 
 
1077
    }
 
1078
 
 
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()) {
 
1083
             return errmsg(
 
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) {
 
1087
             return errmsg(
 
1088
                     "ROM size field is 0. Unknown ROM format or corrupted ROM.");
 
1089
         }
 
1090
 
 
1091
         for (u_int32_t i = 0; i < romChecksumRange; i++) {
 
1092
             romChecksum += romSect[i];
 
1093
         }
 
1094
 
 
1095
         if (romChecksum != 0) {
 
1096
             expRomWarning = true;
 
1097
             snprintf(
 
1098
                     expRomWarningMsg,
 
1099
                     MAX_ROM_ERR_MSG_LEN,
 
1100
                     "Bad ROM Checksum (0x%02x), ROM info may not be displayed correctly.",
 
1101
                     romChecksum);
 
1102
         }
 
1103
     }
 
1104
 
 
1105
    return true;
 
1106
}
 
1107
 
 
1108
bool FwOperations::RomInfo::GetExpRomVerForOneRom(u_int32_t verOffset)
 
1109
{
 
1110
 
 
1111
    u_int32_t tmp;
 
1112
    u_int32_t offs4;
 
1113
    u_int32_t offs8;
 
1114
    rom_info_t *romInfo;
 
1115
 
 
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",
 
1121
                MAX_ROMS_NUM);
 
1122
        return true;
 
1123
    }
 
1124
    romInfo = &(romsInfo[numOfExpRom]);
 
1125
 
 
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)
 
1133
    //                          0X10 - PXE
 
1134
    //                                                  0x11 - UEFI
 
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)
 
1138
    //
 
1139
    // 15:0 Major version   If ProductID < 0x10 or == 0x12 this field is subversion
 
1140
    //                          number, otherwise It's product major version.
 
1141
    //
 
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.
 
1146
    //
 
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
 
1150
    //  8:11    Reserved
 
1151
    //  0:7     Protocol type: 0=IB 1=ETH 2=VPI
 
1152
 
 
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;
 
1157
 
 
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;
 
1162
    } else { // >= 0x10
 
1163
        romInfo->exp_rom_num_ver_fields = 3;
 
1164
    }
 
1165
 
 
1166
    if (romInfo->exp_rom_product_id == 0x11 || romInfo->exp_rom_product_id == 0x21) {
 
1167
        noRomChecksum = true;
 
1168
    }
 
1169
 
 
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;
 
1178
 
 
1179
                romInfo->exp_rom_port = (offs8 >> 12) & 0xf;
 
1180
                romInfo->exp_rom_proto = offs8 & 0xff;
 
1181
        }
 
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;
 
1188
 
 
1189
        if (sign_length < dws_num) {
 
1190
            return errmsg(
 
1191
                    "The Signature length (%d) and the ROM version string length (%d) are not coordinated",
 
1192
                    sign_length, str_len);
 
1193
        }
 
1194
 
 
1195
        int svnv;
 
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;
 
1201
        }
 
1202
 
 
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;
 
1205
 
 
1206
        if (dev_id_off >= romSect.size()) {
 
1207
            return errmsg(
 
1208
                    "The device ID offset %#x is out of range. ROM size: %#x",
 
1209
                    dev_id_off, (u_int32_t) romSect.size());
 
1210
        }
 
1211
 
 
1212
        // get devid
 
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));
 
1216
 
 
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);
 
1223
        }
 
1224
 
 
1225
    }
 
1226
    return true;
 
1227
}
 
1228
 
 
1229
bool FwOperations::ReadImageFile(const char *fimage, u_int8_t *&file_data, int &file_size, int min_size)
 
1230
{
 
1231
    FILE* fh;
 
1232
 
 
1233
    if ((fh = fopen(fimage, "rb")) == NULL) {
 
1234
        return errmsg("Can not open %s: %s\n", fimage, strerror(errno));
 
1235
    }
 
1236
 
 
1237
    if (fseek(fh, 0, SEEK_END) < 0) {
 
1238
        fclose(fh);
 
1239
        return errmsg("Failed to get size of the file \"%s\": %s\n", fimage, strerror(errno));
 
1240
    }
 
1241
 
 
1242
    int read_file_size = ftell(fh);
 
1243
    if (read_file_size < 0) {
 
1244
        fclose(fh);
 
1245
        return errmsg("Failed to get size of the file \"%s\": %s\n", fimage, strerror(errno));
 
1246
    }
 
1247
    rewind(fh);
 
1248
 
 
1249
    if (min_size > read_file_size) {
 
1250
        file_size = min_size;
 
1251
    } else {
 
1252
        file_size = read_file_size;
 
1253
    }
 
1254
 
 
1255
    file_data = new u_int8_t[file_size];
 
1256
    if (fread(file_data, 1, read_file_size, fh) != (size_t)read_file_size) {
 
1257
        delete[] file_data;
 
1258
        fclose(fh);
 
1259
        return errmsg("Failed to read from %s: %s\n", fimage, strerror(errno));
 
1260
    }
 
1261
    fclose(fh);
 
1262
    return true;
 
1263
}
 
1264
 
 
1265
void FwOperations::SetDevFlags(chip_type_t chipType, u_int32_t devType, fw_img_type_t fwType, bool &ibDev, bool &ethDev) {
 
1266
 
 
1267
    if (chipType == CT_IS4) {
 
1268
        ibDev =  true;
 
1269
        ethDev = false;
 
1270
    } else if (chipType == CT_SWITCHX) {
 
1271
        ibDev = true;
 
1272
        ethDev = true;
 
1273
    } else {
 
1274
        ibDev  = (fwType == FIT_FS3) || !CntxEthOnly(devType);
 
1275
        ethDev = chipType == CT_CONNECTX;
 
1276
    }
 
1277
 
 
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.
 
1282
        ibDev = true;
 
1283
        if (fwType == FIT_FS2) {
 
1284
            ethDev = true;
 
1285
        } else {
 
1286
            ethDev = false;
 
1287
        }
 
1288
    }
 
1289
}
 
1290
 
 
1291
bool FwOperations::IsFwSupportingRomModify(u_int16_t fw_ver[3])
 
1292
{
 
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);
 
1295
}
 
1296
 
 
1297
bool FwOperations::checkMatchingExpRomDevId(const fw_info_t& info)
 
1298
{
 
1299
    /*
 
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)) {
 
1304
        return false;
 
1305
    }
 
1306
    return true; */
 
1307
    return checkMatchingExpRomDevId(info.fw_info.dev_type, info.fw_info.roms_info);
 
1308
}
 
1309
 
 
1310
 
 
1311
bool FwOperations::checkMatchingExpRomDevId(u_int16_t dev_type, roms_info_t roms_info)
 
1312
{
 
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)) {
 
1317
        return false;
 
1318
    }
 
1319
    return true;
 
1320
}
 
1321
 
 
1322
 
 
1323
bool FwOperations::FwWriteBlock(u_int32_t addr, std::vector<u_int8_t> dataVec, ProgressCallBack progressFunc)
 
1324
{
 
1325
    if (dataVec.empty()) {
 
1326
        return errmsg("no data to write.");
 
1327
    }
 
1328
    // make sure we work on device
 
1329
    if (!_ioAccess->is_flash()) {
 
1330
        return errmsg("no flash detected.(command is only supported on flash)");
 
1331
    }
 
1332
 
 
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());
 
1337
    }
 
1338
 
 
1339
    if (!writeImage(progressFunc, addr, &dataVec[0], (int)dataVec.size())) {
 
1340
        return false;
 
1341
    }
 
1342
    return true;
 
1343
};
 
1344
 
 
1345
 
 
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};
 
1350
 
 
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;
 
1357
 
 
1358
    newImgOps = FwOperationsCreate(imgOpsParams);
 
1359
    if (newImgOps == NULL) {
 
1360
        return errmsg("Internal error: Failed to create modified image: %s", errBuff);
 
1361
    }
 
1362
    if (!newImgOps->FwVerify(NULL)) {
 
1363
        errmsg("Internal error: Modified image failed to verify: %s", newImgOps->err());
 
1364
        newImgOps->FwCleanUp();
 
1365
        delete newImgOps;
 
1366
        return false;
 
1367
    }
 
1368
 
 
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;
 
1375
 
 
1376
    if (!FwBurnAdvanced(newImgOps, burnParams)) {
 
1377
        newImgOps->FwCleanUp();
 
1378
        delete newImgOps;
 
1379
        return errmsg("Failed to re-burn image after modify: %s", err());
 
1380
    }
 
1381
    newImgOps->FwCleanUp();
 
1382
    delete newImgOps;
 
1383
    return true;
 
1384
}
 
1385
 
 
1386
 
 
1387
bool FwOperations::getRomsInfo(FBase* io, roms_info_t& romsInfo)
 
1388
{
 
1389
    std::vector<u_int8_t> romSector;
 
1390
    romSector.clear();
 
1391
    romSector.resize(io->get_size());
 
1392
    if (!io->read(0, &romSector[0], io->get_size())) {
 
1393
        return false;
 
1394
    }
 
1395
    RomInfo info(romSector, false);
 
1396
    info.ParseInfo();
 
1397
    info.initRomsInfo(&romsInfo);
 
1398
    return true;
 
1399
}
 
1400
 
 
1401
const char* FwOperations::expRomType2Str(u_int16_t type)
 
1402
{
 
1403
        switch (type) {
 
1404
                case 0x1:
 
1405
                    return "CLP1 ";
 
1406
                case 0x2:
 
1407
                        return "CLP2 ";
 
1408
                case 0x3:
 
1409
                        return "CLP3 ";
 
1410
                case 0x4:
 
1411
                        return "CLP4 ";
 
1412
                case 0xf:
 
1413
                        return "CLP "; // hack as 0xf isnt always CLP (its type is defined in the free string inside the ROM)
 
1414
                case 0x10:
 
1415
                        return "PXE  ";
 
1416
                case 0x11:
 
1417
                        return "UEFI ";
 
1418
                case 0x12:
 
1419
                        return "CLP ";
 
1420
                case 0x21:
 
1421
                        return "FCODE ";
 
1422
                default:
 
1423
                    return (const char*)NULL;
 
1424
                }
 
1425
        return (const char*)NULL;
 
1426
}