~ubuntu-branches/ubuntu/trusty/mstflint/trusty-updates

« back to all changes in this revision

Viewing changes to flint.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Benoit Mortier
  • Date: 2010-03-30 00:19:00 UTC
  • Revision ID: james.westby@ubuntu.com-20100330001900-a4oyvb4ioi6w6gvh
Tags: upstream-1.4-OFED-1.4.2
ImportĀ upstreamĀ versionĀ 1.4-OFED-1.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * flint.cpp - FLash INTerface
 
4
 *
 
5
 * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved.
 
6
 *
 
7
 * This software is available to you under a choice of one of two
 
8
 * licenses.  You may choose to be licensed under the terms of the GNU
 
9
 * General Public License (GPL) Version 2, available from the file
 
10
 * COPYING in the main directory of this source tree, or the
 
11
 * OpenIB.org BSD license below:
 
12
 *
 
13
 *     Redistribution and use in source and binary forms, with or
 
14
 *     without modification, are permitted provided that the following
 
15
 *     conditions are met:
 
16
 *
 
17
 *      - Redistributions of source code must retain the above
 
18
 *        copyright notice, this list of conditions and the following
 
19
 *        disclaimer.
 
20
 *
 
21
 *      - Redistributions in binary form must reproduce the above
 
22
 *        copyright notice, this list of conditions and the following
 
23
 *        disclaimer in the documentation and/or other materials
 
24
 *        provided with the distribution.
 
25
 *
 
26
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
27
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
28
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
29
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 
30
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 
31
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
32
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
33
 * SOFTWARE.
 
34
 *
 
35
 *  Version: $Id: flint.cpp 4624 2008-08-26 08:32:49Z orenk $
 
36
 *
 
37
 */
 
38
 
 
39
 
 
40
#include <ctype.h>
 
41
#include <stdarg.h>
 
42
#include <stdio.h>
 
43
#include <string.h>
 
44
#include <stdlib.h>
 
45
#include <errno.h>
 
46
#include <malloc.h>
 
47
#include <sys/types.h>
 
48
#include <sys/stat.h>
 
49
#include <fcntl.h>
 
50
#include <assert.h>
 
51
 
 
52
#ifndef NO_ZLIB
 
53
#include <zlib.h>
 
54
#endif
 
55
 
 
56
#include <signal.h>
 
57
 
 
58
#ifndef __WIN__
 
59
 
 
60
//
 
61
// GCC Compiler
 
62
//
 
63
 
 
64
 
 
65
#if defined __DJGPP__
 
66
//
 
67
// DJGPP - GCC PORT TO MS DOS
 
68
//
 
69
 
 
70
#include <mtcr.h> // This contains the u_* types definitions
 
71
 
 
72
#include <netinet/in.h>
 
73
#include <unistd.h>
 
74
 
 
75
#define bswap_32(x) ntohl(x)
 
76
 
 
77
// djgpp stdio does not define vsnprintf. I simply call vsprintf (and pray ...)
 
78
#define vsnprintf(buf, len, format, args) (vsprintf(buf, format, args))
 
79
 
 
80
#else // Linux GCC
 
81
 
 
82
#include <byteswap.h>
 
83
#include <endian.h>
 
84
#include <alloca.h>
 
85
#include <netinet/in.h>
 
86
#include <unistd.h>
 
87
 
 
88
#endif // __DJGPP__
 
89
 
 
90
#else // __WIN__
 
91
 
 
92
//
 
93
// Windows (Under DDK)
 
94
//
 
95
 
 
96
#include <io.h>
 
97
#include <Winsock2.h>
 
98
#include <mtcr.h>
 
99
// Sleep adaptor
 
100
#define usleep(x) Sleep((x)/1000)
 
101
#define sleep(x)  Sleep((x)*1000)
 
102
 
 
103
#define vsnprintf      _vsnprintf
 
104
#define strtoull       _strtoui64
 
105
#define isatty         _isatty
 
106
 
 
107
#define COMP_CDECL     __cdecl
 
108
 
 
109
#define __LITTLE_ENDIAN 1234
 
110
#define __BIG_ENDIAN 4321
 
111
#define __BYTE_ORDER __LITTLE_ENDIAN
 
112
 
 
113
 
 
114
#if __BYTE_ORDER == __LITTLE_ENDIAN
 
115
#define bswap_32(x) ntohl(x)
 
116
#else
 
117
#error windows is assumed to run a on little endian architecture
 
118
#endif
 
119
 
 
120
#endif // __WIN__
 
121
 
 
122
#include <memory>
 
123
#include <vector>
 
124
 
 
125
#include <mflash.h>
 
126
 
 
127
 
 
128
#ifndef DEV_MST_EXAMPLE1
 
129
    #define DEV_MST_EXAMPLE1 "/dev/mst/mt25418_pci_cr0"
 
130
#endif
 
131
 
 
132
#ifndef DEV_MST_EXAMPLE2
 
133
    #define DEV_MST_EXAMPLE2 "/dev/mst/mt25418_pciconf0"
 
134
#endif
 
135
 
 
136
#ifndef FLINT_NAME
 
137
    #ifdef __GNUC__
 
138
        #define FLINT_NAME "%1$s"
 
139
    #else
 
140
        #define FLINT_NAME "./flint"
 
141
    #endif
 
142
#endif
 
143
 
 
144
namespace std {}; using namespace std;
 
145
 
 
146
#ifdef VERSION_ID
 
147
//char* _versionID = VERSION_ID ;
 
148
#define __VFSTR(x)                      #x
 
149
#define _VFSTR(x)                       __VFSTR(x)
 
150
const char* _versionID = _VFSTR( VERSION_ID ) ;
 
151
#else
 
152
const char* _versionID = "ofed_1.4";
 
153
#endif
 
154
 
 
155
const char* _svnID     = "$Revision: 4624 $";
 
156
 
 
157
#ifndef __be32_to_cpu
 
158
    #define __be32_to_cpu(x) ntohl(x)
 
159
    #ifndef bswap_32
 
160
        #define bswap_32(x) (htonl(x))
 
161
    #endif
 
162
#endif
 
163
#ifndef __cpu_to_be32
 
164
    #define __cpu_to_be32(x) htonl(x)
 
165
#endif
 
166
 
 
167
#if __BYTE_ORDER == __LITTLE_ENDIAN
 
168
    #ifndef __cpu_to_le32
 
169
        #define  __cpu_to_le32(x) (x)
 
170
    #endif
 
171
    #ifndef __le32_to_cpu
 
172
        #define  __le32_to_cpu(x) (x)
 
173
    #endif
 
174
#elif __BYTE_ORDER == __BIG_ENDIAN
 
175
    #ifndef __cpu_to_le32
 
176
        #define  __cpu_to_le32(x) bswap_32(x)
 
177
    #endif
 
178
    #ifndef __le32_to_cpu
 
179
        #define  __le32_to_cpu(x) bswap_32(x)
 
180
    #endif
 
181
#else
 
182
    #ifndef __cpu_to_le32
 
183
        #define  __cpu_to_le32(x) bswap_32(__cpu_to_be32(x))
 
184
    #endif
 
185
    #ifndef __le32_to_cpu
 
186
        #define  __le32_to_cpu(x) __be32_to_cpu(bswap_32(x))
 
187
    #endif
 
188
#endif
 
189
 
 
190
 
 
191
////////////////////////////////////////////////////////////////////////
 
192
//                                                                    //
 
193
// ****************************************************************** //
 
194
//                     Miscellaneous global stuff                     //
 
195
// ****************************************************************** //
 
196
//                                                                    //
 
197
////////////////////////////////////////////////////////////////////////
 
198
typedef struct guid {
 
199
    u_int32_t h;
 
200
    u_int32_t l;
 
201
} guid_t;
 
202
 
 
203
static inline void be_guid_to_cpu(guid_t* to, guid_t* from) {
 
204
    to->h=__be32_to_cpu(from->h);
 
205
    to->l=__be32_to_cpu(from->l);
 
206
}
 
207
 
 
208
static inline void cpu_to_be_guid(guid_t* to, guid_t* from) {
 
209
    to->h=__cpu_to_be32(from->h);
 
210
    to->l=__cpu_to_be32(from->l);
 
211
}
 
212
 
 
213
#define GUID_FORMAT "%8.8x%8.8x"
 
214
#define MAC_FORMAT  "%4.4x%8.8x"
 
215
#define TOCPU1(s) s = __be32_to_cpu(s)
 
216
#define TOCPU(s) do {                                              \
 
217
    u_int32_t *p = (u_int32_t *)(s);                               \
 
218
    for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t); ii++,p++) \
 
219
        *p = __be32_to_cpu(*p);                                    \
 
220
    } while(0)
 
221
#define TOCPUn(s, n) do {                                          \
 
222
    u_int32_t *p = (u_int32_t *)(s);                               \
 
223
    for (u_int32_t ii=0; ii<(n); ii++,p++)                         \
 
224
        *p = __be32_to_cpu(*p);                                    \
 
225
    } while(0)
 
226
#define TOCPUBY(s) do {                                            \
 
227
    u_int32_t *p = (u_int32_t *)(&s);                              \
 
228
    for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t); ii++,p++) \
 
229
        *p = __be32_to_cpu(*p);                                    \
 
230
    } while(0)
 
231
#define TOCPUBY64(s) do {                                          \
 
232
    guid_t *p = s;                              \
 
233
    for (unsigned ii=0; ii<sizeof(s)/sizeof(guid_t); ii++,p++) \
 
234
        be_guid_to_cpu(p,p);                                   \
 
235
    } while(0)
 
236
#define CRC(c, s) do {                                             \
 
237
    u_int32_t *p = (u_int32_t *)(s);                               \
 
238
    for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t); ii++)     \
 
239
        c << *p++;                                                 \
 
240
    } while(0)
 
241
#define CRCn(c, s, n) do {                                         \
 
242
    u_int32_t *p = (u_int32_t *)(s);                               \
 
243
    for (u_int32_t ii=0; ii<(n); ii++)                             \
 
244
        c << *p++;                                                 \
 
245
    } while(0)
 
246
#define CRCBY(c, s) do {                                           \
 
247
    u_int32_t *p = (u_int32_t *)(&s);                              \
 
248
    for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t); ii++)     \
 
249
        c << *p++;                                                 \
 
250
    } while(0)
 
251
#define CRC1(c, s) do {                                            \
 
252
    u_int32_t *p = (u_int32_t *)(s);                               \
 
253
    for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t) - 1; ii++) \
 
254
        c << *p++;                                                 \
 
255
    } while(0)
 
256
#define CRC1n(c, s, n) do {                                        \
 
257
    u_int32_t *p = (u_int32_t *)(s);                               \
 
258
    for (u_int32_t ii=0; ii<(n) - 1; ii++)                         \
 
259
        c << *p++;                                                 \
 
260
    } while(0)
 
261
#define CRC1BY(c, s) do {                                          \
 
262
    u_int32_t *p = (u_int32_t *)(&s);                              \
 
263
    for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t) - 1; ii++) \
 
264
        c << *p++;                                                 \
 
265
    } while(0)
 
266
#define CHECKB2(f,b,o,n,p) do { if (!checkBoot2(f,b,o,n,p)) return false; } while (0)
 
267
#define CHECKGN(f,b,o,n,p) do { if (!checkGen(f,b,o,n,p)) return false; } while (0)
 
268
#define CHECKLS(f,o,s,p) do { if (!checkList(f,o,s,p)) return false; } while(0)
 
269
#define READ4(f,o,d,p) do { if (!f.read(o,d)) {  \
 
270
    return errmsg("%s - read error (%s)\n", p, f.err()); }} while (0)
 
271
#define READBUF(f,o,d,l,p) do { if (!f.read(o,d,l)) { \
 
272
    return errmsg("%s - read error (%s)\n", p, f.err()); }} while (0)
 
273
 
 
274
 
 
275
class ErrMsg
 
276
{
 
277
public:
 
278
    ErrMsg() : _err(0)       {                           }
 
279
    ~ErrMsg()                { err_clear();              }
 
280
    const char *err() const  { return _err;              }
 
281
    void       err_clear()   { delete [] _err; _err = 0; }
 
282
 
 
283
protected:
 
284
 
 
285
    char *vprint(const char *format, va_list args)
 
286
    {
 
287
        const int INIT_VAL = 1024;
 
288
        int       max_str, max_buf = INIT_VAL;
 
289
        char      *out_buf;
 
290
 
 
291
        while (1)
 
292
        {
 
293
            out_buf = new char[max_buf];
 
294
            max_str = max_buf - 1;
 
295
 
 
296
            if (vsnprintf(out_buf, max_str, format, args) < max_str)
 
297
                return out_buf;
 
298
            delete [] out_buf;
 
299
            max_buf *= 2;
 
300
        }
 
301
    }
 
302
 
 
303
 
 
304
    bool errmsg(const char *format, ...)
 
305
#ifdef __GNUC__
 
306
        __attribute__ ((format (printf, 2, 3)))
 
307
#endif
 
308
    ;
 
309
 
 
310
private:
 
311
 
 
312
    char       *_err;
 
313
};
 
314
 
 
315
 
 
316
bool ErrMsg::errmsg(const char *format, ...) {
 
317
    va_list   args;
 
318
 
 
319
    char* prev_err = _err;
 
320
 
 
321
    va_start(args, format);
 
322
    _err = vprint(format, args);
 
323
    va_end(args);
 
324
 
 
325
    delete[] prev_err;
 
326
 
 
327
    return false;
 
328
}
 
329
 
 
330
 
 
331
enum {
 
332
    SIGNATURE          = 0x5a445a44,
 
333
    MELLANOX_VENDOR_ID = 0x15b3
 
334
};
 
335
struct PS {
 
336
    u_int32_t fi_addr;
 
337
    u_int32_t fi_size;
 
338
    u_int32_t signature;
 
339
    u_int32_t fw_reserved[5];
 
340
    u_int32_t vsd[52];
 
341
    u_int32_t psid[4];
 
342
    u_int32_t branch_to;
 
343
    u_int32_t crc016;
 
344
};
 
345
 
 
346
enum {
 
347
    H_FIRST     =  1,
 
348
    H_DDR       =  1,
 
349
    H_CNF       =  2,
 
350
    H_JMP       =  3,
 
351
    H_EMT       =  4,
 
352
    H_ROM       =  5,
 
353
    H_GUID      =  6,
 
354
    H_BOARD_ID  =  7,
 
355
    H_USER_DATA =  8,
 
356
    H_FW_CONF   =  9,
 
357
    H_IMG_INFO  = 10,
 
358
    H_DDRZ      = 11,
 
359
    H_LAST
 
360
};
 
361
 
 
362
const char* g_sectNames[] = {
 
363
    "UNKNOWN (0 - Reserved)",
 
364
    "DDR"             ,
 
365
    "Configuration"   ,
 
366
    "Jump addresses"  ,
 
367
    "EMT Service"     ,
 
368
    "ROM"             ,
 
369
    "GUID"            ,
 
370
    "BOARD ID"        ,
 
371
    "User Data"       ,
 
372
    "FW Configuration",
 
373
    "Image Info"      ,
 
374
    "DDRZ"
 
375
};
 
376
 
 
377
 
 
378
struct GPH {
 
379
    u_int32_t type;
 
380
    u_int32_t size;
 
381
    u_int32_t param;
 
382
    u_int32_t next;
 
383
};
 
384
 
 
385
#define MAX_SECTION_SIZE 0x400000
 
386
 
 
387
const u_int32_t BOARD_ID_BSN_LEN=64;
 
388
const u_int32_t BOARD_ID_BID_LEN=32;
 
389
const u_int32_t BOARD_ID_PID=7;
 
390
 
 
391
struct BOARD_ID {
 
392
    char      bsn[BOARD_ID_BSN_LEN];
 
393
    char      bid[BOARD_ID_BID_LEN];
 
394
};
 
395
 
 
396
int  const VSD_LEN  = 208;
 
397
int  const PSID_LEN = 16;
 
398
int  const PRODUCT_VER_LEN = 16;
 
399
 
 
400
//
 
401
// TODO: Remove the below globals to class members.
 
402
//
 
403
bool _print_crc = false;
 
404
bool _silent = false;
 
405
bool _assume_yes = false;
 
406
bool _assume_no = false;
 
407
bool _no_erase = false;
 
408
bool _no_burn = false;
 
409
 
 
410
bool _unlock_bypass = false;
 
411
 
 
412
bool _byte_write = false;
 
413
 
 
414
 
 
415
void report(const char *format, ...)
 
416
#ifdef __GNUC__
 
417
__attribute__ ((format (printf, 1, 2)))
 
418
#endif
 
419
;
 
420
void report(const char *format, ...)
 
421
{
 
422
    va_list  args;
 
423
 
 
424
    if (!_silent) {
 
425
        va_start(args, format);
 
426
        vprintf(format, args);
 
427
        va_end(args);
 
428
    }
 
429
} // report
 
430
 
 
431
void report_erase(const char *format, ...)
 
432
{
 
433
    va_list  args;
 
434
    char buf[256];
 
435
    int i;
 
436
    int len;
 
437
 
 
438
    if (_silent)
 
439
        return;
 
440
 
 
441
    va_start(args, format);
 
442
    vsnprintf(buf, sizeof buf, format, args);
 
443
    va_end(args);
 
444
 
 
445
    len = strlen(buf);
 
446
    for(i=0; i < len; ++i)
 
447
        printf("\b");
 
448
} // report_erase
 
449
 
 
450
 
 
451
////////////////////////////////////////////////////////////////////////
 
452
//                                                                    //
 
453
// ****************************************************************** //
 
454
//                        CRC16 CALCULATION                           //
 
455
// ****************************************************************** //
 
456
//                                                                    //
 
457
////////////////////////////////////////////////////////////////////////
 
458
class Crc16 {
 
459
public:
 
460
    Crc16(bool d = false) : _debug(d) { clear();}
 
461
    u_int16_t      get()              { return _crc;}
 
462
    void           clear()            { _crc = 0xffff;}
 
463
    void           operator<<(u_int32_t val) { add(val);}
 
464
    void           add(u_int32_t val);
 
465
    void           finish();
 
466
private:
 
467
    u_int16_t      _crc;
 
468
    bool           _debug;
 
469
};
 
470
 
 
471
////////////////////////////////////////////////////////////////////////
 
472
void Crc16::add(u_int32_t o)
 
473
{
 
474
    if (_debug)
 
475
        printf("Crc16::add(%08x)\n", o);
 
476
    for (int i=0; i<32; i++) {
 
477
        if (_crc & 0x8000)
 
478
            _crc = (u_int16_t) ((((_crc<<1) | (o>>31)) ^  0x100b) & 0xffff);
 
479
        else
 
480
            _crc= (u_int16_t) (((_crc<<1) | (o>>31)) & 0xffff);
 
481
        o = (o<<1) & 0xffffffff;
 
482
    }
 
483
} // Crc16::add
 
484
 
 
485
 
 
486
////////////////////////////////////////////////////////////////////////
 
487
void Crc16::finish()
 
488
{
 
489
    for (int i=0; i<16; i++) {
 
490
        if (_crc & 0x8000)
 
491
            _crc=((_crc<<1)  ^  0x100b) & 0xffff;
 
492
        else
 
493
            _crc=(_crc<<1) & 0xffff;
 
494
    }
 
495
 
 
496
    // Revert 16 low bits
 
497
    _crc = _crc ^ 0xffff;
 
498
 
 
499
} // Crc16::finish
 
500
 
 
501
 
 
502
//////////////////////////////////////////////////////////////////////
 
503
//
 
504
//  class u_int32_ba (bit access):
 
505
//  A uint wrapper which allows easy access to bit/range of bits.
 
506
//
 
507
//  Usage example:
 
508
//     u_int32_ba a;
 
509
//     Read_Word( Table.reg ,&a);
 
510
//     int upper_byte = a.range(31,24);
 
511
//     if (a[15])
 
512
//        cout << " Bit 15 is 1 \n";
 
513
//     else
 
514
//        cout << " Bit 15 is 0 \n";
 
515
//
 
516
//     u_int32_ba b;
 
517
//     b.range(15,12) = 0xa;
 
518
//     b[31]          = 1;     // b == 0x8000a000
 
519
//     Write_Word( Table.reg ,b);
 
520
//
 
521
//////////////////////////////////////////////////////////////////////
 
522
 
 
523
 
 
524
class u_int32_ba {
 
525
public:
 
526
    u_int32_ba(u_int32_t i = 0) :
 
527
    _bits(i),
 
528
    _rbits(_bits),
 
529
    _sptr1(0),
 
530
    _eptr(31)    {}
 
531
 
 
532
    u_int32_ba  operator[](u_int32_t idx) {return range((u_int8_t)idx,(u_int8_t)idx);}
 
533
    u_int32_ba& operator= (u_int32_t i)   {_rbits = ((i << _sptr1) & mask()) | (_rbits & ~mask()); return *this;}
 
534
    u_int32_t*  operator& ()              {return &_bits;}
 
535
    operator    u_int32_t ()              {return((mask() & _rbits) >> _sptr1);}
 
536
 
 
537
    u_int32_ba  range     (u_int8_t eptr,
 
538
                           u_int8_t sptr) {return u_int32_ba(*this,eptr,sptr);}
 
539
 
 
540
private:
 
541
    u_int32_ba(u_int32_ba& other, u_int8_t eptr, u_int8_t sptr) :
 
542
    _bits(other._bits),
 
543
    _rbits(other._bits),
 
544
    _sptr1(sptr),
 
545
    _eptr(eptr) {}
 
546
 
 
547
    u_int32_t  mask       () {
 
548
        u_int32_t s_msk = (u_int32_t)-1; // start mask
 
549
        u_int32_t e_msk = (u_int32_t)-1; // end mask
 
550
 
 
551
        s_msk = (s_msk << _sptr1);
 
552
        e_msk = (_eptr >= (sizeof(_bits)*8-1)) ? e_msk : ~(e_msk << (_eptr+1));
 
553
 
 
554
        return(s_msk & e_msk);
 
555
    };
 
556
 
 
557
    u_int32_t  _bits;
 
558
    u_int32_t& _rbits;
 
559
 
 
560
    u_int8_t   _sptr1;
 
561
    u_int8_t   _eptr;
 
562
};
 
563
 
 
564
//////////////////////////////////////////////////////////////////////
 
565
//
 
566
//  class Aligner:
 
567
//  A utillity class for accessing an addr/size region
 
568
//  in a specific alignment.
 
569
//  If a 0 alignment is given, infinity (no alignment requirements)
 
570
//  is assumed - This is to support single flow for the caller.
 
571
//
 
572
//////////////////////////////////////////////////////////////////////
 
573
 
 
574
class Aligner {
 
575
public:
 
576
    Aligner(u_int32_t log2_alignment_size) :
 
577
        _log2_alignment_size(log2_alignment_size),
 
578
        _alignment_size(1 << log2_alignment_size),
 
579
        _alignment_mask(_alignment_size - 1)
 
580
    {
 
581
        if (_log2_alignment_size == 0) {
 
582
            _log2_alignment_size = 31;
 
583
            _alignment_size      = 1 << _log2_alignment_size;
 
584
            _alignment_mask      = _alignment_size - 1;
 
585
        }
 
586
    }
 
587
 
 
588
    void Init        (u_int32_t  addr, u_int32_t  size) {
 
589
        _curr_addr = addr;
 
590
        _curr_size = size;
 
591
    }
 
592
 
 
593
    bool GetNextChunk(u_int32_t& chunk_addr, u_int32_t& chunk_size) {
 
594
        if (_curr_size == 0) {
 
595
            return false;
 
596
        }
 
597
 
 
598
        chunk_addr = _curr_addr;
 
599
 
 
600
        if ( (_curr_addr               >> _log2_alignment_size) !=
 
601
            ((_curr_addr + _curr_size) >> _log2_alignment_size)) {
 
602
            // Next chunk crosses alignment boundary
 
603
            chunk_size = _alignment_size - (_curr_addr & _alignment_mask);
 
604
        } else {
 
605
            chunk_size = _curr_size;
 
606
        }
 
607
 
 
608
        _curr_addr += chunk_size;
 
609
        _curr_size -= chunk_size;
 
610
 
 
611
        return true;
 
612
    }
 
613
 
 
614
private:
 
615
    u_int32_t _curr_addr;
 
616
    u_int32_t _curr_size;
 
617
    u_int32_t _log2_alignment_size;
 
618
    u_int32_t _alignment_size;
 
619
    u_int32_t _alignment_mask;
 
620
};
 
621
 
 
622
 
 
623
 
 
624
 
 
625
////////////////////////////////////////////////////////////////////////
 
626
//                                                                    //
 
627
// ****************************************************************** //
 
628
//                        FLASH ACCESS                                //
 
629
// ****************************************************************** //
 
630
//                                                                    //
 
631
////////////////////////////////////////////////////////////////////////
 
632
 
 
633
// Common base class for Flash and for FImage
 
634
 
 
635
 
 
636
class FBase : public ErrMsg{
 
637
public:
 
638
    FBase(bool is_flash) :
 
639
        _log2_chunk_size(0),
 
640
        _is_flash(is_flash) {}
 
641
    virtual ~FBase()  {}
 
642
 
 
643
    virtual bool open(const char *, bool)                  {return false;}
 
644
    virtual void close()                                   = 0;
 
645
    virtual bool read(u_int32_t addr, u_int32_t *data)     = 0;
 
646
    virtual bool read(u_int32_t addr, void *data, int len,
 
647
                      bool verbose=false)                  = 0;
 
648
 
 
649
    virtual u_int32_t get_sector_size()                    = 0;
 
650
    virtual u_int32_t get_size()                           = 0;
 
651
 
 
652
    virtual u_int32_t get_dev_id()                         = 0;
 
653
 
 
654
    bool              is_flash() {return _is_flash;};
 
655
 
 
656
    virtual void set_address_convertor(u_int32_t log2_chunk_size, bool is_image_in_odd_chunks) {
 
657
        _log2_chunk_size = log2_chunk_size;
 
658
        _is_image_in_odd_chunks = is_image_in_odd_chunks;
 
659
    }
 
660
 
 
661
    enum {
 
662
        MAX_FLASH = 4*1048576
 
663
    };
 
664
 
 
665
protected:
 
666
 
 
667
    // Address translation functions for ConnectX.
 
668
    // Translate between contiguous "logical" addresses
 
669
 
 
670
    // If Failsafe zebra mapping is enabled:
 
671
 
 
672
    // Result is concatenation of:
 
673
    // The lower log2_chunk_size bits of the cons_addr
 
674
    // The is_image_in_odd_chunk bit
 
675
    // The remaining upper bits of the cons_addr
 
676
 
 
677
    u_int32_t cont2phys(u_int32_t cont_addr) {
 
678
        u_int32_t result;
 
679
        if (_log2_chunk_size) {
 
680
            result  = (cont_addr       & (0xffffffff >> (32 - _log2_chunk_size))) |
 
681
                      (_is_image_in_odd_chunks       << _log2_chunk_size)         |
 
682
                     ((cont_addr << 1) & (0xffffffff << (_log2_chunk_size + 1)));
 
683
        } else {
 
684
            result = cont_addr;
 
685
        }
 
686
        return result;
 
687
    }
 
688
 
 
689
    u_int32_t phys2cont(u_int32_t phys_addr) {
 
690
        u_int32_t result;
 
691
        if (_log2_chunk_size) {
 
692
            result =  (phys_addr       & (0xffffffff >> (32 - _log2_chunk_size)))  |
 
693
                     ((phys_addr >> 1) & (0xffffffff << (     _log2_chunk_size)));
 
694
        } else {
 
695
            result = phys_addr;
 
696
        }
 
697
        return result;
 
698
    }
 
699
 
 
700
    bool       _is_image_in_odd_chunks;
 
701
    u_int32_t  _log2_chunk_size;
 
702
 
 
703
    const bool _is_flash;
 
704
 
 
705
};
 
706
 
 
707
// Flash image (RO)
 
708
class FImage : public FBase {
 
709
public:
 
710
    FImage() :  FBase(false), _buf(0) {}
 
711
    virtual ~FImage() { close();}
 
712
 
 
713
    u_int32_t    *getBuf()      { return _buf;}
 
714
    u_int32_t    getBufLength() { return _len;}
 
715
    virtual bool open(const char *fname, bool read_only = false);
 
716
    virtual void close();
 
717
    virtual bool read(u_int32_t addr, u_int32_t *data);
 
718
    virtual bool read(u_int32_t addr, void *data, int len, bool verbose=false);
 
719
 
 
720
    virtual u_int32_t get_sector_size();
 
721
    virtual u_int32_t get_size()     { return  getBufLength();}
 
722
    virtual u_int32_t get_dev_id()   { return  0;}
 
723
 
 
724
private:
 
725
    u_int32_t *_buf;
 
726
    u_int32_t _len;
 
727
};
 
728
 
 
729
//
 
730
// Flash access (R/W)
 
731
//
 
732
class Flash : public FBase {
 
733
public:
 
734
    Flash() :
 
735
        FBase(true),
 
736
        _mfl(0),
 
737
        _curr_sector(0xffffffff),
 
738
        _port_num(0)
 
739
     {}
 
740
 
 
741
    virtual ~Flash()  { close();};
 
742
 
 
743
    // FBase Interface
 
744
 
 
745
    virtual bool open          (const char *device,
 
746
                                bool force_lock = false,
 
747
                                bool read_only  = false);
 
748
 
 
749
    virtual void close         ();
 
750
 
 
751
    virtual bool read          (u_int32_t addr,
 
752
                                u_int32_t *data);
 
753
 
 
754
    virtual bool read          (u_int32_t addr,
 
755
                                void*     data,
 
756
                                int       len,
 
757
                                bool      verbose = false);
 
758
 
 
759
    bool         cr_write      (u_int32_t addr,
 
760
                                u_int32_t data) {return mf_cr_write(_mfl, addr, data) == MFE_OK;}
 
761
 
 
762
    //
 
763
    // Flash Interface
 
764
    //
 
765
 
 
766
    u_int32_t get_sector_size        ()  {return _attr.sector_size; }
 
767
    u_int32_t get_size               ()  {return _attr.size;}
 
768
 
 
769
    u_int32_t get_dev_id             ()  {return _attr.hw_dev_id;}
 
770
 
 
771
    u_int32_t get_port_num           ()  {return _port_num;}
 
772
 
 
773
    bool sw_reset();
 
774
 
 
775
    // Write and Erase functions are performed by the Command Set
 
776
 
 
777
    virtual bool erase_sector  (u_int32_t addr);
 
778
 
 
779
    virtual bool write         (u_int32_t addr,
 
780
                                void*     data,
 
781
                                int       cnt,
 
782
                                bool      noerase = false);
 
783
 
 
784
    virtual bool write         (u_int32_t addr,
 
785
                                u_int32_t data);
 
786
 
 
787
    bool         print_attr();
 
788
    bool         print_attr_old_format();
 
789
 
 
790
    enum {
 
791
        TRANS = 4096
 
792
    };
 
793
 
 
794
    static bool _byte_mode;
 
795
 
 
796
#ifndef _MSC_VER
 
797
protected:
 
798
#endif
 
799
 
 
800
    mflash*    _mfl;
 
801
    flash_attr _attr;
 
802
 
 
803
    u_int32_t  _curr_sector;
 
804
    u_int32_t  _port_num;
 
805
};
 
806
 
 
807
 
 
808
////////////////////////////////////////////////////////////////////////
 
809
//
 
810
// FImage Class Implementation
 
811
//
 
812
////////////////////////////////////////////////////////////////////////
 
813
 
 
814
bool FImage::open(const char *fname, bool read_only)
 
815
{
 
816
    int                fsize;
 
817
    int                r_cnt;
 
818
    FILE              *fh;
 
819
 
 
820
    read_only = true;  // FImage can be opened only for read
 
821
 
 
822
    fh = fopen(fname, "rb");
 
823
 
 
824
    if (!fh) {
 
825
        return errmsg("Can not open file \"%s\" - %s\n", fname, strerror(errno));
 
826
    }
 
827
 
 
828
    // Get the file size:
 
829
    if (fseek(fh, 0, SEEK_END) < 0) {
 
830
        return errmsg("Can not get file size for \"%s\" - %s\n", fname, strerror(errno));
 
831
    }
 
832
 
 
833
    fsize = ftell(fh);
 
834
    if (fsize < 0) {
 
835
        return errmsg("Can not get file size for \"%s\" - %s\n", fname, strerror(errno));
 
836
    }
 
837
    rewind(fh);
 
838
 
 
839
    //printf("-D- %s size is %d\n", fname, fsize);
 
840
    if (fsize & 0x3) {
 
841
        return errmsg("Image size should be 4-bytes aligned. Make sure file %s is in the right format (binary image)",
 
842
                      fname);
 
843
    }
 
844
 
 
845
    _buf = new u_int32_t[fsize/4];
 
846
    if ((r_cnt = fread(_buf, 1, fsize, fh)) != fsize) {
 
847
        if (r_cnt < 0)
 
848
            return errmsg("Read error on file \"%s\" - %s\n",fname, strerror(errno));
 
849
        else
 
850
            return errmsg("Read error on file \"%s\" - read only %d bytes (from %ld)\n",
 
851
                          fname, r_cnt, (unsigned long)fsize);
 
852
    }
 
853
 
 
854
    _len = fsize;
 
855
    fclose(fh);
 
856
 
 
857
    return true;
 
858
} // FImage::open
 
859
 
 
860
////////////////////////////////////////////////////////////////////////
 
861
void FImage::close()
 
862
{
 
863
    delete [] _buf;
 
864
    _buf = 0;
 
865
} // FImage::close
 
866
 
 
867
////////////////////////////////////////////////////////////////////////
 
868
bool FImage::read(u_int32_t addr, u_int32_t *data)
 
869
{
 
870
    return read(addr, data, 4);
 
871
} // FImage::read
 
872
 
 
873
////////////////////////////////////////////////////////////////////////
 
874
bool FImage::read(u_int32_t addr, void *data, int len, bool)
 
875
{
 
876
 
 
877
    if (addr & 0x3) {
 
878
        return errmsg("Address should be 4-bytes aligned.");
 
879
    }
 
880
    if (len & 0x3) {
 
881
        return errmsg("Length should be 4-bytes aligned.");
 
882
    }
 
883
    if (!_buf) {
 
884
        return errmsg("read() when not opened");
 
885
    }
 
886
 
 
887
    if (cont2phys(addr + len) > _len) {
 
888
        return errmsg("Reading 0x%x bytes from %saddress 0x%x is out of image limits (0x%x bytes)",
 
889
                      len,
 
890
                      _log2_chunk_size ? "physical " : "",
 
891
                      addr,
 
892
                      _len);
 
893
    }
 
894
 
 
895
    u_int32_t chunk_addr;
 
896
    u_int32_t chunk_size;
 
897
    Aligner align(_log2_chunk_size);
 
898
    align.Init (addr, len);
 
899
    while (align.GetNextChunk(chunk_addr, chunk_size)) {
 
900
        u_int32_t phys_addr = cont2phys(chunk_addr);
 
901
 
 
902
        memcpy((u_int8_t*)data + (chunk_addr - addr),
 
903
               (u_int8_t*)_buf +  phys_addr,
 
904
                chunk_size);
 
905
    }
 
906
 
 
907
    return true;
 
908
} // FImage::read
 
909
 
 
910
////////////////////////////////////////////////////////////////////////
 
911
u_int32_t FImage::get_sector_size()
 
912
{
 
913
    u_int32_t log2_sector_sz_ptr;
 
914
    u_int32_t log2_sector_sz;
 
915
    u_int32_t signature;
 
916
 
 
917
    read(0x24, &signature);
 
918
    TOCPU1(signature);
 
919
    if (signature == SIGNATURE) {
 
920
        // full image:
 
921
        read(0x14, &log2_sector_sz_ptr);
 
922
        TOCPU1(log2_sector_sz_ptr);
 
923
        log2_sector_sz_ptr &= 0xffff;
 
924
 
 
925
        read(0x30 + log2_sector_sz_ptr, &log2_sector_sz);
 
926
        TOCPU1(log2_sector_sz);
 
927
        log2_sector_sz &= 0xffff;
 
928
 
 
929
        return(1 << log2_sector_sz);
 
930
 
 
931
    } else {
 
932
        return 0;
 
933
    }
 
934
}
 
935
 
 
936
 
 
937
 
 
938
////////////////////////////////////////////////////////////////////////
 
939
//
 
940
// Flash Class Implementation
 
941
//
 
942
////////////////////////////////////////////////////////////////////////
 
943
 
 
944
 
 
945
bool Flash::_byte_mode = false;
 
946
 
 
947
////////////////////////////////////////////////////////////////////////
 
948
bool Flash::open(const char *device, bool force_lock, bool read_only)
 
949
{
 
950
    // Open device
 
951
    int rc;
 
952
    read_only = false;
 
953
 
 
954
    rc = mf_open(&_mfl, device);
 
955
 
 
956
    if ((rc == MFE_SEM_LOCKED) && force_lock) {
 
957
        report("Warning: Taking flash lock even though semaphore is set.\n");
 
958
        rc = mf_open_ignore_lock(_mfl);
 
959
    }
 
960
 
 
961
    if (rc == MFE_SEM_LOCKED) {
 
962
        return errmsg("Can not obtain Flash semaphore (63). You can run \"flint -clear_semaphore -d <device>\" to force semaphore unlock. See help for details.");
 
963
    } else
 
964
        if (rc != MFE_OK) {
 
965
        return errmsg("%s %s", errno == 0 ? "" : strerror(errno), mf_err2str(rc));
 
966
    }
 
967
 
 
968
    rc = mf_get_attr(_mfl, &_attr);
 
969
    if (rc != MFE_OK) {
 
970
        return errmsg("Failed getting flash attributes for device %s: %s", device,  mf_err2str(rc));
 
971
    }
 
972
 
 
973
    if (_attr.hw_dev_id == 435) {
 
974
        _port_num = 0;
 
975
    }
 
976
    else if (_attr.hw_dev_id == 25204 || _attr.hw_dev_id == 24204) {
 
977
        _port_num = 1;
 
978
    } else {
 
979
        _port_num = 2;
 
980
    }
 
981
 
 
982
    if (_byte_mode) {
 
983
        rc = mf_set_opt(_mfl, MFO_AMD_BYTE_MODE, 1);
 
984
        if (rc != MFE_OK) {
 
985
            return errmsg("Failed setting byte mode fore device %s: %s", device,  mf_err2str(rc));
 
986
        }
 
987
    }
 
988
 
 
989
    return true;
 
990
} // Flash::open
 
991
 
 
992
////////////////////////////////////////////////////////////////////////
 
993
void Flash::close()
 
994
{
 
995
    if (!_mfl)
 
996
        return;
 
997
 
 
998
    mf_close(_mfl);
 
999
    _mfl = 0;
 
1000
} // Flash::close
 
1001
 
 
1002
 
 
1003
bool Flash::read(u_int32_t addr,
 
1004
                 u_int32_t *data) {
 
1005
    int rc;
 
1006
 
 
1007
    u_int32_t phys_addr = cont2phys(addr);
 
1008
    rc = mf_read(_mfl, phys_addr, 4, (u_int8_t*)data);
 
1009
    if (rc != MFE_OK) {
 
1010
        return errmsg("Flash read failed at address %s%x : %s",
 
1011
                      _log2_chunk_size ? "physical " : "",
 
1012
                      addr,
 
1013
                      mf_err2str(rc));
 
1014
    }
 
1015
 
 
1016
    return true;
 
1017
}
 
1018
 
 
1019
////////////////////////////////////////////////////////////////////////
 
1020
bool Flash::read(u_int32_t addr, void *data, int len, bool verbose)
 
1021
{
 
1022
    int rc;
 
1023
    u_int32_t  perc = 0xffffffff;
 
1024
 
 
1025
    if (addr & 0x3) {
 
1026
        return errmsg("Address should be 4-bytes aligned.");
 
1027
    }
 
1028
    if (len & 0x3) {
 
1029
        return errmsg("Length should be 4-bytes aligned.");
 
1030
    }
 
1031
 
 
1032
    // Report
 
1033
    if (verbose) {
 
1034
        printf("000%%");
 
1035
        fflush(stdout);
 
1036
    }
 
1037
 
 
1038
    // Much better perf for read in a single chunk. need to work on progress report though.
 
1039
    bool read_in_single_chunk = true;
 
1040
 
 
1041
    if (read_in_single_chunk) {
 
1042
        u_int32_t chunk_addr;
 
1043
        u_int32_t chunk_size;
 
1044
 
 
1045
        Aligner align(_log2_chunk_size);
 
1046
        align.Init (addr, len);
 
1047
        while (align.GetNextChunk(chunk_addr, chunk_size)) {
 
1048
            u_int32_t phys_addr = cont2phys(chunk_addr);
 
1049
 
 
1050
            rc = mf_read(_mfl, phys_addr, chunk_size, ((u_int8_t*)data) + chunk_addr - addr);
 
1051
            if (rc != MFE_OK) {
 
1052
                return errmsg("Flash read failed at address %s%x : %s",
 
1053
                              _log2_chunk_size ? "physical " : "",
 
1054
                              chunk_addr,
 
1055
                              mf_err2str(rc));
 
1056
            }
 
1057
        }
 
1058
 
 
1059
    } else {
 
1060
        u_int32_t *p = (u_int32_t *)data;
 
1061
        for (int i=0; i<len/4; i++) {
 
1062
            if (!read(addr, p++))
 
1063
                return false;
 
1064
 
 
1065
            addr += 4;
 
1066
 
 
1067
            // Report
 
1068
            if (verbose) {
 
1069
                u_int32_t new_perc = (i * 100) / len;
 
1070
                if (new_perc != perc) {
 
1071
                    printf("\b\b\b\b%03d%%", new_perc);
 
1072
                    fflush(stdout);
 
1073
                    perc = new_perc;
 
1074
                }
 
1075
            }
 
1076
        }
 
1077
    }
 
1078
    // Report
 
1079
    if (verbose) {
 
1080
        printf("\b\b\b\b100%%");
 
1081
        fflush(stdout);
 
1082
    }
 
1083
 
 
1084
    return true;
 
1085
} // Flash::read
 
1086
 
 
1087
 
 
1088
////////////////////////////////////////////////////////////////////////
 
1089
bool Flash::write  (u_int32_t addr,
 
1090
                    void*     data,
 
1091
                    int       cnt,
 
1092
                    bool      noerase)
 
1093
{
 
1094
 
 
1095
    // FIX:
 
1096
    noerase = _no_erase || noerase;
 
1097
 
 
1098
    if (!_mfl) {
 
1099
        return errmsg("Not opened");
 
1100
    }
 
1101
    if (addr & 0x3) {
 
1102
        return errmsg("Address should be 4-bytes aligned.");
 
1103
    }
 
1104
 
 
1105
 
 
1106
    if (cont2phys(addr + cnt) > get_size()) {
 
1107
        return errmsg(
 
1108
            "Trying to write %d bytes to address 0x%x, which exceeds max image size (0x%x - half of total flash size).",
 
1109
            cnt,
 
1110
            addr,
 
1111
            get_size() / 2);
 
1112
    }
 
1113
 
 
1114
    u_int8_t         *p = (u_int8_t *)data;
 
1115
    u_int32_t sect_size = get_sector_size();
 
1116
 
 
1117
    u_int32_t chunk_addr;
 
1118
    u_int32_t chunk_size;
 
1119
 
 
1120
    u_int32_t first_set;
 
1121
    for (first_set = 0; ((sect_size >> first_set) & 1) == 0; first_set++ )
 
1122
        ;
 
1123
 
 
1124
    Aligner align(first_set);
 
1125
    align.Init (addr, cnt);
 
1126
    while (align.GetNextChunk(chunk_addr, chunk_size)) {
 
1127
        // Write / Erase in sector_size alligned chunks
 
1128
        int rc;
 
1129
 
 
1130
        if (!noerase) {
 
1131
            u_int32_t sector = (chunk_addr / sect_size) * sect_size;
 
1132
            if (sector != _curr_sector) {
 
1133
                _curr_sector = sector;
 
1134
                if (!erase_sector(_curr_sector))
 
1135
                    return false;
 
1136
            }
 
1137
        }
 
1138
 
 
1139
        if (_no_burn)
 
1140
            continue;
 
1141
 
 
1142
        // Actual write:
 
1143
        u_int32_t phys_addr = cont2phys(chunk_addr);
 
1144
        rc = mf_write(_mfl, phys_addr, chunk_size, p);
 
1145
        if (rc != MFE_OK) {
 
1146
            return errmsg("Flash write of %d bytes to address %s0x%x failed: %s",
 
1147
                          chunk_size,
 
1148
                          _log2_chunk_size ? "physical " : "",
 
1149
                          chunk_addr,
 
1150
                          mf_err2str(rc));
 
1151
        }
 
1152
 
 
1153
        // Loop advance
 
1154
        p    += chunk_size;
 
1155
    }
 
1156
 
 
1157
    return true;
 
1158
}
 
1159
 
 
1160
 
 
1161
////////////////////////////////////////////////////////////////////////
 
1162
bool Flash::write(u_int32_t addr, u_int32_t data)
 
1163
{
 
1164
    if (!_mfl) {
 
1165
        return errmsg("Not opened");
 
1166
    }
 
1167
    if (addr & 0x3) {
 
1168
        return errmsg("Address should be 4-bytes aligned.");
 
1169
    }
 
1170
 
 
1171
    u_int32_t word;
 
1172
 
 
1173
    u_int32_t sector_size = _attr.sector_size;
 
1174
    u_int32_t sector_mask = ~(sector_size - 1);
 
1175
 
 
1176
    u_int32_t sector = addr & sector_mask;
 
1177
    u_int32_t word_in_sector = (addr & ~sector_mask)/sizeof(u_int32_t);
 
1178
 
 
1179
    if (!read(addr, &word))
 
1180
        return false;
 
1181
    if (word == data)
 
1182
        return true;   // already there
 
1183
 
 
1184
    vector<u_int32_t> buff(sector_size/sizeof(u_int32_t));
 
1185
    if (!read(sector, &buff[0] , sector_size))
 
1186
        return false;
 
1187
    buff[word_in_sector] = data;
 
1188
    return write(sector, &buff[0], sector_size);
 
1189
} // Flash::write
 
1190
 
 
1191
 
 
1192
bool Flash::erase_sector  (u_int32_t addr) {
 
1193
    int rc;
 
1194
 
 
1195
    u_int32_t phys_addr = cont2phys(addr);
 
1196
    rc = mf_erase_sector(_mfl, phys_addr);
 
1197
    if (rc != MFE_OK) {
 
1198
        return errmsg("Flash erase of address 0x%x failed: %s",
 
1199
                      phys_addr,
 
1200
                      mf_err2str(rc));
 
1201
    }
 
1202
 
 
1203
    return true;
 
1204
}
 
1205
 
 
1206
bool Flash::sw_reset() {
 
1207
    if (_attr.hw_dev_id != 435) {
 
1208
        return errmsg("operation supported only for InfiniScale4 switch over IB interface");
 
1209
    }
 
1210
    int rc = mf_sw_reset(_mfl);
 
1211
    if (rc != MFE_OK) {
 
1212
        return errmsg("%s %s", errno == 0 ? "" : strerror(errno), mf_err2str(rc));
 
1213
    }
 
1214
    return true;
 
1215
}
 
1216
 
 
1217
 
 
1218
 
 
1219
bool Flash::print_attr() {
 
1220
    printf("Flash attributes:\n");
 
1221
    printf("  HwDevId          %d\n",     _attr.hw_dev_id);
 
1222
    printf("  TotalSize        0x%x\n",   _attr.size);
 
1223
    printf("  Banks            0x%x\n",   _attr.size/_attr.bank_size );
 
1224
    printf("  SectorSize       0x%x\n",   _attr.sector_size );
 
1225
    printf("  WriteBlockSize   0x%x\n",   _attr.block_write);
 
1226
    printf("  CmdSet           0x%x\n",   _attr.command_set);
 
1227
 
 
1228
    return true;
 
1229
}
 
1230
 
 
1231
bool Flash::print_attr_old_format() {
 
1232
    // Needed for some old tools which parce the size section of the CFI query in oder flint versions:
 
1233
 
 
1234
    int i;
 
1235
    printf("\n----Sector Organization Parameters-------------------\n\n");
 
1236
 
 
1237
    printf("%-50s ", "Device size:");
 
1238
    printf("[%8li] bytes, or [%2i] Mbit\n",
 
1239
           (long int)_attr.size,
 
1240
           (int) (_attr.size/((long)0x20000)));
 
1241
 
 
1242
    printf("%-50s ", "Number of erase block regions:");
 
1243
    printf("%d\n", _attr.num_erase_blocks);
 
1244
 
 
1245
    for (i = 0; i < _attr.num_erase_blocks; i++) {
 
1246
        printf("  Size:[%8lx] bytes, Mask [%08x], [Number:[%4i]\n",
 
1247
               _attr.erase_block[i].sector_size,
 
1248
               _attr.erase_block[i].sector_mask,
 
1249
               _attr.erase_block[i].num_sectors);
 
1250
    }
 
1251
    return true;
 
1252
}
 
1253
 
 
1254
////////////////////////////////////////////////////////////////////////
 
1255
 
 
1256
 
 
1257
 
 
1258
////////////////////////////////////////////////////////////////////////
 
1259
//
 
1260
// Burn Operations functions
 
1261
//
 
1262
////////////////////////////////////////////////////////////////////////
 
1263
 
 
1264
class Operations : public ErrMsg {
 
1265
public:
 
1266
    Operations() :
 
1267
        _last_image_addr(0),
 
1268
        _num_ports(2),
 
1269
        _allow_skip_is(false),
 
1270
        _is_cntx(false),
 
1271
        _cntx_striped_image(false),
 
1272
        _burn_blank_guids(false),
 
1273
        _quick_query(false){}
 
1274
 
 
1275
    enum {
 
1276
        GUIDS = 4,
 
1277
        MACS  = 2,
 
1278
        MAX_GUIDS = 6
 
1279
    };
 
1280
 
 
1281
    enum ImageInfoTags {
 
1282
        II_IiFormatRevision   = 0,
 
1283
        II_FwVersion          = 1,
 
1284
        II_FwBuildTime        = 2,
 
1285
        II_DeviceType         = 3,
 
1286
        II_PSID               = 4,
 
1287
        II_VSD                = 5,
 
1288
        II_SuppurtedPsids     = 6,
 
1289
        II_ProductVer         = 7,
 
1290
        II_VsdVendorId        = 8,
 
1291
        II_IsGa               = 9,
 
1292
        II_Last               = 10,  // Mark the end of used tag ids
 
1293
        II_End                = 0xff
 
1294
    };
 
1295
 
 
1296
    struct ImageInfo;
 
1297
 
 
1298
    // Burn operations:
 
1299
    bool write_image     (Flash& f, u_int32_t addr, void *data, int cnt, bool need_report);
 
1300
    bool WriteSignature  (Flash& f, u_int32_t image_idx, u_int32_t sig);
 
1301
    bool repair          (Flash& f, const int from, const int to, bool need_report);
 
1302
    bool FailSafeBurn    (Flash& f, FImage& fim, bool need_report, bool single_image_burn);
 
1303
    bool CntxFailSafeBurn(Flash&     f,
 
1304
                          FImage&    fim,
 
1305
                          bool       need_report,
 
1306
                          ImageInfo* flash_info,
 
1307
                          ImageInfo* image_info,
 
1308
                          bool       allow_nofs = false);
 
1309
 
 
1310
    bool CheckMatchingDevId(u_int32_t hwDevId, u_int32_t imageDevId);
 
1311
 
 
1312
    // Image operations:
 
1313
    bool Verify          (FBase& f, ImageInfo* info = NULL, bool both_images = false);
 
1314
    bool VerifyCntx      (FBase& f, ImageInfo* info = NULL, bool both_images = false, bool only_get_start = false);
 
1315
 
 
1316
    bool LoadAsExpRom    (FBase& f);
 
1317
 
 
1318
    bool DumpConf        (const char* conf_file = NULL);
 
1319
    bool GetExpRomVersion(ImageInfo* info);
 
1320
 
 
1321
    bool DisplayExpRomInfo(ImageInfo* info);
 
1322
    bool DisplayImageInfo (ImageInfo* info);
 
1323
 
 
1324
    bool QueryAll        (FBase& f, ImageInfo* info) {return (IsCntx() ||
 
1325
                                                              (QueryIs(f, info) &&
 
1326
                                                              (!info->isFailsafe || QueryPs(f, info)))) &&
 
1327
                                                             QueryImage(f, info);}
 
1328
 
 
1329
    bool getBSN          (char *s, guid_t *guid);
 
1330
    bool getGUID         (const char *s, guid_t *guid);
 
1331
 
 
1332
    bool patchVSD        (FImage& f,
 
1333
                          Operations::ImageInfo* info,
 
1334
                          const char *user_vsd,
 
1335
                          const char *user_psid,
 
1336
                          const char *curr_vsd,
 
1337
                          const char *curr_psid,
 
1338
                          const char *image_psid);
 
1339
 
 
1340
    // Misc operations
 
1341
    void SetDevFlags(u_int16_t devType, bool& ib_dev, bool& eth_dev);
 
1342
    bool CheckGuidsFlags(u_int16_t devType,
 
1343
                         bool ib_dev,
 
1344
                         bool guids_specified,
 
1345
                         bool eth_dev,
 
1346
                         bool macs_specified);
 
1347
 
 
1348
    bool patchGUIDs      (FImage&    f,
 
1349
                          ImageInfo* info,
 
1350
                          bool       patch_guids,
 
1351
                          bool       patch_macs,
 
1352
                          bool       user_guids,
 
1353
                          bool       user_macs,
 
1354
                          guid_t     new_guids[MAX_GUIDS],
 
1355
                          guid_t     old_guids[MAX_GUIDS],
 
1356
                          u_int32_t num_of_old_guids,
 
1357
                          bool       interactive);
 
1358
 
 
1359
    bool printGUIDs(const char* msg, guid_t guids[MAX_GUIDS], bool print_guids, bool print_macs, bool old_guid_fmt);
 
1360
 
 
1361
    void SetNumPorts     (u_int32_t num_ports) {_num_ports = num_ports;}
 
1362
    void SetAllowSkipIs  (bool asis)           {_allow_skip_is = asis;}
 
1363
 
 
1364
    void SetBurnBlankGuids(bool b) {_burn_blank_guids = b;}
 
1365
    bool GetBurnBlankGuids()       {return _burn_blank_guids;}
 
1366
    void SetQuickQuery(bool b)     {_quick_query = b;}
 
1367
    bool GetQuickQuery()           {return _quick_query;}
 
1368
 
 
1369
    // ConnectX methods
 
1370
    void SetCntxMode     (bool cntx_mode)      {_is_cntx = cntx_mode;}
 
1371
    void SetCntxStripedImage(bool si)          {_cntx_striped_image = si;}
 
1372
    bool IsCntx          ()                    {return _is_cntx;}
 
1373
    bool CheckMac        (u_int64_t mac);
 
1374
 
 
1375
    bool CheckIsCntx     (FBase& f);
 
1376
 
 
1377
    bool CntxIsIb        (u_int32_t devid)     {return (devid == 25408) || // IB SDR
 
1378
                                                       (devid == 25418) || // IB DDR
 
1379
                                                       (devid == 25428) || // IB QDR
 
1380
                                                       (devid == 26418) || // IB DDR
 
1381
                                                       (devid == 26428);   // IB QDR
 
1382
    }
 
1383
 
 
1384
    bool CntxIsEth       (u_int32_t devid)     {return (devid == 25448) || // ETH
 
1385
                                                       (devid == 26448) || // ETH
 
1386
                                                       (devid == 25458) || //
 
1387
                                                       (devid == 26458) || //
 
1388
                                                        CntxIsIb(devid);   // From FW 2.5.0, CntX ib devices also support ETH
 
1389
    }
 
1390
 
 
1391
    bool IsIs4           (u_int32_t devid)     {
 
1392
                                                return (devid == 435) ||
 
1393
                                                       (devid == 48436) ||
 
1394
                                                       (devid == 48437) ||
 
1395
                                                       (devid == 48438);
 
1396
    }
 
1397
 
 
1398
    bool CntxIsMp        (u_int32_t devid)     {return CntxIsIb(devid) && CntxIsEth(devid);}
 
1399
 
 
1400
    bool ask_user        ();
 
1401
 
 
1402
    // _last_image_addr is set by the Verify() op
 
1403
    u_int32_t            _last_image_addr;
 
1404
 
 
1405
    //
 
1406
    // ImageInfo struct: Everything you wanted to know about the FW image (and was afraid to ask).
 
1407
    // This struct includes both user's info (psid, dev rev , fwver ...) and tools internal
 
1408
    // info (images locations, guid ptr ...).
 
1409
    //
 
1410
    struct ImageInfo {
 
1411
        ImageInfo() :
 
1412
            invSectOk(false),
 
1413
            psOk(false),
 
1414
            imageOk(false)
 
1415
        {
 
1416
            memset(allImgStart,    0, sizeof(allImgStart));
 
1417
            memset(guids      , 0xff, sizeof(guids));
 
1418
 
 
1419
            psid[0] = '\0';
 
1420
            vsd[0]  = '\0';
 
1421
            for (int i=0; i < II_Last; i++ )
 
1422
                infoOffs[i] = 0;
 
1423
 
 
1424
            expRomFound = false;
 
1425
        }
 
1426
 
 
1427
        // *Ok : The exit status of the specific query.
 
1428
        // Note - invSectOk = true doesnt mean that invariant sector exists, it
 
1429
        //        only means that the query was OK (and isFailsafe may be false).
 
1430
 
 
1431
        bool         invSectOk;
 
1432
        bool         psOk;
 
1433
        bool         imageOk;
 
1434
 
 
1435
        u_int32_t    allImgStart[2];
 
1436
 
 
1437
        bool         isFailsafe;
 
1438
 
 
1439
        // ConnectX:
 
1440
        // For an image file where the image is marked as FW but actually contiguous, this bit would be cleared.
 
1441
        bool         actuallyFailsafe;
 
1442
        u_int32_t    cntxLog2ChunkSize;
 
1443
 
 
1444
        bool         validImage[2];
 
1445
        u_int32_t    psStart;
 
1446
        u_int32_t    imgStart;
 
1447
 
 
1448
        // For ConnectX, guids 4:5 are the cards MAC addresses (if applicable)
 
1449
        guid_t       guids[MAX_GUIDS];
 
1450
        u_int32_t    guidPtr;
 
1451
        u_int32_t    guidNum;
 
1452
        bool         blankGuids;
 
1453
 
 
1454
        u_int32_t    infoSectPtr;
 
1455
 
 
1456
        u_int16_t    vsdVendorId;
 
1457
        char         vsd[VSD_LEN+1];
 
1458
        char         psid[PSID_LEN+1];
 
1459
        char         productVer[17];
 
1460
 
 
1461
        bool         isGa;
 
1462
 
 
1463
        u_int8_t     isVer;
 
1464
        u_int16_t    fwVer[3];        // = {major_ver, minor_ver , sum_minor_ver}
 
1465
        u_int16_t    fwTime[6];  // = {year, month, day, hour, minute, second}
 
1466
 
 
1467
        u_int16_t    devType;
 
1468
        u_int8_t     devRev;
 
1469
 
 
1470
        u_int32_t    infoOffs[II_Last];  // Offset of the tag data inside the info section data.
 
1471
                                         // Can not be 0 (because of tag header) - 0 means not found.
 
1472
        bool         expRomFound;
 
1473
        bool         expRomValidVersion;
 
1474
        u_int16_t    expRomProductId;    // 0 - invalid.
 
1475
        u_int16_t    expRomVer[3];
 
1476
        u_int16_t    expRomDevId;
 
1477
        u_int8_t     expRomPort;
 
1478
 
 
1479
        bool         magicPatternFound;
 
1480
    };
 
1481
 
 
1482
    enum {MAX_SW_DEVICES_PER_HW=16};
 
1483
 
 
1484
    struct HwDevData {
 
1485
        const char*      name;
 
1486
        u_int32_t        hwDevId;
 
1487
        int              portNum;
 
1488
        // Zero terminated list of SW device ids
 
1489
        const u_int32_t  swDevIds[MAX_SW_DEVICES_PER_HW];
 
1490
    };
 
1491
 
 
1492
    bool FwVerLessThan(u_int16_t r1[3], u_int16_t r2[3]) {
 
1493
        int i;
 
1494
        for (i = 0; i < 3 ; i++)
 
1495
            if      (r1[i] < r2[i])
 
1496
                return true;
 
1497
            else if (r1[i] > r2[i])
 
1498
                return false;
 
1499
 
 
1500
        return false; // equal versions
 
1501
    }
 
1502
 
 
1503
    enum {CNTX_START_POS_SIZE = 6};
 
1504
 
 
1505
    static const u_int32_t _cntx_image_start_pos[CNTX_START_POS_SIZE];
 
1506
 
 
1507
    static const u_int32_t _cntx_magic_pattern[4];
 
1508
 
 
1509
    void patchGUIDsSection      (u_int32_t *buf, u_int32_t ind,
 
1510
                                 guid_t guids[GUIDS], int nguids);
 
1511
private:
 
1512
 
 
1513
    bool FailSafe_burn_image   (Flash&       f,
 
1514
                                void         *data,
 
1515
                                int          ps_addr,
 
1516
                                const char*  image_name,
 
1517
                                int          image_addr,
 
1518
                                int          image_size,
 
1519
                                bool         need_report);
 
1520
 
 
1521
    bool CheckInvariantSector   (Flash& f, u_int32_t *data32, int sect_size);
 
1522
 
 
1523
    bool FailSafe_burn_internal (Flash& f, void *data, int cnt, bool need_report);
 
1524
 
 
1525
    bool checkBoot2             (FBase& f, u_int32_t beg, u_int32_t offs,
 
1526
                                 u_int32_t& next, const char *pref);
 
1527
 
 
1528
    bool checkGen               (FBase& f, u_int32_t beg,
 
1529
                                 u_int32_t offs, u_int32_t& next, const char *pref);
 
1530
 
 
1531
    bool checkPS                (FBase& f, u_int32_t offs, u_int32_t& next, const char *pref);
 
1532
 
 
1533
    bool checkList              (FBase& f, u_int32_t offs, u_int32_t fw_start, const char *pref);
 
1534
 
 
1535
    bool extractGUIDptr         (u_int32_t sign, u_int32_t *buf, int buf_len,
 
1536
                                 char *pref, u_int32_t *ind, int *nguids);
 
1537
 
 
1538
 
 
1539
    void recalcSectionCrc       (u_int8_t *buf, u_int32_t data_size);
 
1540
 
 
1541
    u_int32_t BSN_subfield      (const char *s, int beg, int len);
 
1542
 
 
1543
    void PatchPs                (u_int8_t*      rawPs,
 
1544
                                 const char     vsd[VSD_LEN],
 
1545
                                 const char     psid[PSID_LEN]   = NULL,
 
1546
                                 u_int32_t      imageAddr        = 0);
 
1547
 
 
1548
    void PatchInfoSect          (u_int8_t*      rawSect,
 
1549
                                 u_int32_t      vsdOffs,
 
1550
                                 const char*    vsd);
 
1551
 
 
1552
    bool QueryIs                (FBase& f,  ImageInfo* info);
 
1553
    bool QueryPs                (FBase& f,  ImageInfo* info);
 
1554
    bool QueryImage             (FBase& f,  ImageInfo* info);
 
1555
 
 
1556
    bool CntxFindMagicPattern   (FBase& f,  u_int32_t addr);
 
1557
    bool CntxFindAllImageStart  (FBase& f,  u_int32_t start_locations[CNTX_START_POS_SIZE], u_int32_t* found_images);
 
1558
    bool CntxGetFsData          (FBase& f,  u_int32_t img_addr, bool& fs_en, u_int32_t& log2chunk_size);
 
1559
 
 
1560
    bool ParseInfoSect          (u_int8_t* buff, u_int32_t byteSize, ImageInfo *info);
 
1561
 
 
1562
    u_int32_t _num_ports;
 
1563
    bool      _allow_skip_is;
 
1564
    bool      _is_cntx;
 
1565
    bool      _cntx_striped_image;
 
1566
 
 
1567
    bool      _burn_blank_guids;
 
1568
    bool      _quick_query;
 
1569
 
 
1570
    static const HwDevData hwDevData[];
 
1571
 
 
1572
    std::vector<u_int8_t>  _fw_conf_sect;
 
1573
    std::vector<u_int8_t>  _rom_sect;
 
1574
};
 
1575
 
 
1576
 
 
1577
const u_int32_t Operations::_cntx_magic_pattern[4] = {
 
1578
    0x4D544657,   // Ascii of "MTFW"
 
1579
    0x8CDFD000,   // Random data
 
1580
    0xDEAD9270,
 
1581
    0x4154BEEF
 
1582
};
 
1583
 
 
1584
const u_int32_t Operations::_cntx_image_start_pos[Operations::CNTX_START_POS_SIZE] = {
 
1585
           0,
 
1586
     0x10000,
 
1587
     0x20000,
 
1588
     0x40000,
 
1589
     0x80000,
 
1590
    0x100000
 
1591
};
 
1592
 
 
1593
const Operations::HwDevData Operations::hwDevData[] = {
 
1594
    { "InfiniHost"       , 23108 , 2, {23108, 0}},
 
1595
    { "InfiniHost III Ex", 25208 , 2, {25208, 25218, 0}},
 
1596
    { "InfiniHost III Lx", 25204 , 1, {25204, 0}},
 
1597
    { "ConnectX"         ,   400 , 2, {25408, 25418, 26418,
 
1598
                                       26428, 25448, 26448,
 
1599
                                       25458, 26458, 0}},
 
1600
    { "InfiniScale IV"   ,   435 , 0, {48436, 48437, 48438, 0}},
 
1601
    { NULL               ,     0 , 0, {0}},// zero devid terminator
 
1602
};
 
1603
 
 
1604
//
 
1605
// Asks user a yes/no question.
 
1606
// Returns true if user chose Y, false if user chose N.
 
1607
//
 
1608
 
 
1609
bool Operations::ask_user() {
 
1610
    printf("\n Do you want to continue ? (y/n) [n] : ");
 
1611
    if (_assume_yes)
 
1612
        printf("y\n");
 
1613
    else {
 
1614
        char ansbuff[32];
 
1615
        ansbuff[0] = '\0';
 
1616
        if (_assume_no) {
 
1617
            printf("n\n");
 
1618
            return errmsg("-no flag is set");
 
1619
        }
 
1620
 
 
1621
        if (!isatty(0)) {
 
1622
            return errmsg("Not on tty - Can not interact. assuming \"no\"");
 
1623
        }
 
1624
        fflush(stdout);
 
1625
        fgets(ansbuff, 30, stdin);
 
1626
 
 
1627
        if (  strcmp(ansbuff, "y\n") &&
 
1628
              strcmp(ansbuff, "Y\n") &&
 
1629
              strcmp(ansbuff, "yes\n") &&
 
1630
              strcmp(ansbuff, "Yes\n") &&
 
1631
              strcmp(ansbuff, "YES\n"))
 
1632
            return errmsg("Aborted by user");
 
1633
    }
 
1634
    return true;
 
1635
}
 
1636
 
 
1637
bool Operations::write_image(Flash& f, u_int32_t addr, void *data, int cnt, bool need_report)
 
1638
{
 
1639
    u_int8_t   *p = (u_int8_t *)data;
 
1640
    u_int32_t  curr_addr = addr;
 
1641
    u_int32_t  towrite = cnt;
 
1642
    u_int32_t  perc = 0xffffffff;
 
1643
 
 
1644
    //f.curr_sector = 0xffffffff;  // Erase sector first time
 
1645
    if (need_report) {
 
1646
        printf("000%%");
 
1647
        fflush(stdout);
 
1648
    }
 
1649
 
 
1650
 
 
1651
    while (towrite) {
 
1652
        // Write
 
1653
        int trans = (towrite > (int)Flash::TRANS) ? (int)Flash::TRANS : towrite;
 
1654
        if (!f.write(curr_addr, p, trans))
 
1655
            return errmsg("Flash write failed: %s", f.err());
 
1656
        p += trans;
 
1657
        curr_addr += trans;
 
1658
        towrite -= trans;
 
1659
 
 
1660
        // Report
 
1661
        if (need_report) {
 
1662
            u_int32_t new_perc = ((cnt - towrite) * 100) / cnt;
 
1663
            if (new_perc != perc) {
 
1664
                printf("\b\b\b\b%03d%%", new_perc);
 
1665
                fflush(stdout);
 
1666
                perc = new_perc;
 
1667
            }
 
1668
        }
 
1669
    }
 
1670
 
 
1671
    if (need_report) {
 
1672
        printf("\b\b\b\b100%%");
 
1673
        fflush(stdout);
 
1674
    }
 
1675
 
 
1676
    return true;
 
1677
} //  Flash::write_image
 
1678
 
 
1679
 
 
1680
////////////////////////////////////////////////////////////////////////
 
1681
bool Operations::WriteSignature(Flash& f, u_int32_t image_idx, u_int32_t sig) {
 
1682
    u_int32_t sect_size = f.get_sector_size();
 
1683
 
 
1684
    if (!f.write( sect_size * (image_idx + 1)  + 8, &sig, 4, true))
 
1685
        return false;
 
1686
 
 
1687
    return true;
 
1688
}
 
1689
 
 
1690
 
 
1691
////////////////////////////////////////////////////////////////////////
 
1692
bool Operations::repair(Flash& f, const int from, const int to, bool need_report)
 
1693
{
 
1694
 
 
1695
    u_int32_t sect_size = f.get_sector_size();
 
1696
 
 
1697
    report("Repairing: Copy %s image to %s     -", from ? "secondary" : "primary" ,
 
1698
           to ? "secondary" : "primary");
 
1699
 
 
1700
 
 
1701
    // Read valid pointer sector
 
1702
    u_int32_t sect[sizeof(PS)/4];
 
1703
    report("\b READ %s ", from ? "SPS" : "PPS");
 
1704
    if (!f.read(from ? sect_size*2 : sect_size, sect, sizeof(sect) , need_report)) {
 
1705
        report("FAILED\n\n");
 
1706
        return false;
 
1707
    }
 
1708
    report_erase(" READ %s 100%", from ? "SPS" : "PPS");
 
1709
 
 
1710
    u_int32_t im_ptr = sect[0];
 
1711
    u_int32_t sig    = sect[2];
 
1712
 
 
1713
    TOCPU1(im_ptr);
 
1714
    TOCPU1(sig);
 
1715
 
 
1716
    // Make sure ps ik ok:
 
1717
    if (sig != SIGNATURE) {
 
1718
        return errmsg("Can not copy image. Pointer sector %d signature is bad (%08x).", from, sig);
 
1719
    }
 
1720
 
 
1721
    // Valid image size in bytes
 
1722
    u_int32_t im_size_b;
 
1723
    if (!f.read(sect_size * (from+1) + 4, &im_size_b)) {
 
1724
        report("FAILED\n\n");
 
1725
        return false;
 
1726
    }
 
1727
    TOCPU1(im_size_b);
 
1728
 
 
1729
    // Valid image size in sectors
 
1730
    u_int32_t im_size_s = (im_size_b + sect_size - 1) / sect_size;
 
1731
 
 
1732
    // Address to copy valid image
 
1733
    u_int32_t write_to = (!to) ? sect_size * 3 : sect_size * (3 + im_size_s);
 
1734
 
 
1735
    // f.read valid image
 
1736
    report(" READ FW ");
 
1737
    fflush(stdout);
 
1738
    char *buf = new char[im_size_b];
 
1739
    if (!f.read(im_ptr, buf, im_size_b, need_report)) {
 
1740
        report("FAILED\n\n");
 
1741
        delete [] buf;
 
1742
        return false;
 
1743
    }
 
1744
    report_erase(" READ FW 100%");
 
1745
 
 
1746
    // Copy it to right place
 
1747
    report("\b WRITE FW ");
 
1748
    fflush(stdout);
 
1749
    if (!write_image(f, write_to, buf, im_size_b, need_report)) {
 
1750
        report("FAILED\n\n");
 
1751
        delete [] buf;
 
1752
        return false;
 
1753
    }
 
1754
    delete [] buf;
 
1755
    report_erase(" WRITE FW 100%");
 
1756
 
 
1757
    // Set new image address
 
1758
    // ++++++
 
1759
    sect[0] = __be32_to_cpu(write_to);
 
1760
 
 
1761
    // Calculate new CRC
 
1762
    // ++++++
 
1763
    Crc16 crc;
 
1764
 
 
1765
    for (u_int32_t i = 0; i < (sizeof(sect)/4 - 1) ; i++) {
 
1766
        crc << __be32_to_cpu(sect[i]);
 
1767
    }
 
1768
    crc.finish();
 
1769
 
 
1770
    sect[sizeof(sect)/4 - 1] = __be32_to_cpu(crc.get());
 
1771
 
 
1772
    // Corrupt signature
 
1773
    u_int32_t valid_signature = sect[2];
 
1774
    sect[2] = 0xffffffff;
 
1775
 
 
1776
    // Write it to invalid sector
 
1777
    report("\b WRITE %s ", to ? "SPS" : "PPS");
 
1778
    if (!write_image(f, to ? sect_size*2 : sect_size, sect, sizeof(sect), need_report)) {
 
1779
        report("FAILED\n\n");
 
1780
        return false;
 
1781
    }
 
1782
    report_erase(" WRITE %s 100%", to ? "SPS" : "PPS");
 
1783
 
 
1784
    // Validate signature
 
1785
    report("\b SIGNATURE     ");
 
1786
    if (!WriteSignature(f, to, valid_signature)) {
 
1787
        report("FAILED\n\n");
 
1788
        return false;
 
1789
    }
 
1790
 
 
1791
    report_erase(" SIGNATURE     ");
 
1792
    report(" OK       \n");
 
1793
    return true;
 
1794
} // Flash::repair
 
1795
 
 
1796
 
 
1797
 
 
1798
 
 
1799
 
 
1800
////////////////////////////////////////////////////////////////////////
 
1801
bool Operations::FailSafe_burn_image(Flash&       f,
 
1802
                         void         *data,
 
1803
                         int          ps_addr,
 
1804
                         const char*  image_name,
 
1805
                         int          image_addr,
 
1806
                         int          image_size,
 
1807
                         bool         need_report) {
 
1808
 
 
1809
    u_int8_t* data8 = (u_int8_t*) data;
 
1810
    u_int32_t sect_size = f.get_sector_size();
 
1811
 
 
1812
    report("Burning %-6s FW image without signatures  - ", image_name);
 
1813
    fflush(stdout);
 
1814
 
 
1815
    // Invalidate signature
 
1816
    u_int32_t zeros = 0;
 
1817
    if (!f.write(ps_addr + 8, &zeros, 4, true)) {
 
1818
        report("FAILED (Invalidating signature)\n\n");
 
1819
        return false;
 
1820
    }
 
1821
 
 
1822
    // Burn image (from new offset)
 
1823
 
 
1824
    // Both burnt images are taken from the first image in the file - both images in file are identical.
 
1825
    // (future binary releases may contain a single image).
 
1826
    if (!write_image(f, image_addr, data8 + sect_size * 3, image_size, need_report)) {
 
1827
        report("FAILED\n\n");
 
1828
        return false;
 
1829
    }
 
1830
    report("\b\b\b\bOK  \n");
 
1831
    report("Restoring %-6s signature                  - ", image_name);
 
1832
    fflush(stdout);
 
1833
 
 
1834
    // Burn PS
 
1835
    if (!write_image(f, ps_addr, data8 + ps_addr, sect_size, false)) {
 
1836
        report("FAILED\n\n");
 
1837
        return false;
 
1838
    }
 
1839
 
 
1840
    // Validate signature
 
1841
    u_int32_t sig = SIGNATURE;
 
1842
    TOCPU1(sig);
 
1843
    if (!f.write(ps_addr + 8, &sig, 4, true)) {
 
1844
        report("FAILED\n\n");
 
1845
        return false;
 
1846
    }
 
1847
 
 
1848
    report("OK  \n");
 
1849
 
 
1850
    return true;
 
1851
}
 
1852
 
 
1853
 
 
1854
////////////////////////////////////////////////////////////////////////
 
1855
bool Operations::FailSafe_burn_internal(Flash& f, void *data, int cnt, bool need_report)
 
1856
{
 
1857
    u_int32_t *data32 = (u_int32_t *)data;
 
1858
 
 
1859
    u_int32_t sect_size = f.get_sector_size();
 
1860
 
 
1861
    // Extract Primary/Secondary image pointers and lengths
 
1862
    u_int32_t prim_ptr = data32[sect_size / 4];
 
1863
    u_int32_t prim_len = data32[sect_size / 4 + 1];
 
1864
    u_int32_t scnd_ptr = data32[(sect_size * 2) / 4];
 
1865
    u_int32_t scnd_len = data32[(sect_size * 2) / 4 + 1];
 
1866
    TOCPU1(prim_ptr);
 
1867
    TOCPU1(prim_len);
 
1868
    TOCPU1(scnd_ptr);
 
1869
    TOCPU1(scnd_len);
 
1870
    if ((cnt < (int)(prim_ptr + prim_len)) || (cnt < (int)(scnd_ptr + scnd_len))) {
 
1871
        return errmsg("Invalid image: too small.");
 
1872
    }
 
1873
    if (prim_len != scnd_len) {
 
1874
        return errmsg("Invalid image: two FW images should have the same size.");
 
1875
    }
 
1876
 
 
1877
    // Image size from flash
 
1878
    u_int32_t old_im_size;
 
1879
    if (!f.read(sect_size + 4, &old_im_size)) {
 
1880
        report("FAILED\n\n");
 
1881
        return false;
 
1882
    }
 
1883
    TOCPU1(old_im_size);
 
1884
 
 
1885
    u_int32_t prim_order;
 
1886
    u_int32_t scnd_order;
 
1887
 
 
1888
    u_int32_t ps_addr[2];
 
1889
    u_int32_t image_addr[2];
 
1890
    const char* image_name[2];
 
1891
 
 
1892
 
 
1893
    if (prim_len > old_im_size) {
 
1894
        scnd_order = 0;
 
1895
        prim_order = 1;
 
1896
    } else {
 
1897
        prim_order = 0;
 
1898
        scnd_order = 1;
 
1899
    }
 
1900
 
 
1901
    image_name[scnd_order] = "Secondary";
 
1902
    image_addr[scnd_order] = scnd_ptr;
 
1903
    ps_addr   [scnd_order] = sect_size * 2;
 
1904
 
 
1905
    image_name[prim_order] = "Primary";
 
1906
    image_addr[prim_order] = prim_ptr;
 
1907
    ps_addr   [prim_order] = sect_size;
 
1908
 
 
1909
 
 
1910
    for (int i = 0 ; i < 2 ; i++) {
 
1911
        if (!FailSafe_burn_image(f, data, ps_addr[i], image_name[i], image_addr[i], prim_len, need_report)) {
 
1912
            return false;
 
1913
        }
 
1914
    }
 
1915
 
 
1916
    return true;
 
1917
}
 
1918
 
 
1919
bool Operations::CheckInvariantSector(Flash& f, u_int32_t *data32, int sect_size) {
 
1920
    int i;
 
1921
 
 
1922
    report("\nRead and verify Invariant Sector            - ");
 
1923
    fflush(stdout);
 
1924
 
 
1925
    // Once more check signature - the Inv.Sector signature should be OK
 
1926
    u_int32_t signature;
 
1927
    if (!f.read(0x24, &signature)) {
 
1928
        report("FAILED\n\n");
 
1929
        return false;
 
1930
    }
 
1931
    TOCPU1(signature);
 
1932
    if (signature != SIGNATURE) {
 
1933
        report("FAILED\n\n");
 
1934
        return errmsg("Flash has wrong signature in Invariant Sector (Expected %08x, got %08x).", SIGNATURE, signature);
 
1935
    }
 
1936
 
 
1937
    // Now check Invariant sector contents
 
1938
    vector<u_int32_t> buf1(sect_size/4);
 
1939
 
 
1940
    if (!f.read(0, &buf1[0] , sect_size)) {
 
1941
        report("FAILED\n\n");
 
1942
        return false;
 
1943
    }
 
1944
 
 
1945
    int first_diff = -1;
 
1946
 
 
1947
    for (i=0; i < sect_size/4; i++) {
 
1948
        if (buf1[i] != data32[i]  &&  (data32[i] != 0 || buf1[i] != 0xffffffff)) {
 
1949
            if (first_diff == -1)
 
1950
                first_diff = i;
 
1951
        }
 
1952
    }
 
1953
 
 
1954
    // Check if a diff was found:
 
1955
    if (first_diff != -1) {
 
1956
            report("DIFF DETECTED\n\n");
 
1957
            printf(" Invariant sector mismatch. Address 0x%x "
 
1958
                   " in image: 0x%08x, while on flash: 0x%08x\n\n",
 
1959
                   first_diff*4 , data32[first_diff], buf1[first_diff]);
 
1960
 
 
1961
            printf(" The invariant sector can not be burnt in a failsafe manner.\n");
 
1962
 
 
1963
        if (_allow_skip_is) {
 
1964
            printf(" You can continue the FW update without burning the invariant sector.\n"
 
1965
                   " See FW release notes for details on invariant sector updates.\n\n");
 
1966
 
 
1967
            return ask_user();
 
1968
 
 
1969
        } else {
 
1970
            // Continue with burn
 
1971
            printf(" You can perform the FW update without burning the invariant sector by\n"
 
1972
                   " by specifying the -skip_is flag.\n"
 
1973
                   " See FW release notes for details on invariant sector updates.\n\n");
 
1974
 
 
1975
            return errmsg("Invariant sector mismatch");
 
1976
        }
 
1977
    }
 
1978
 
 
1979
    report("OK\n");
 
1980
    return true;
 
1981
 
 
1982
}
 
1983
 
 
1984
////////////////////////////////////////////////////////////////////////
 
1985
bool Operations::FailSafeBurn(Flash& f, FImage& fim, bool need_report, bool single_image_burn)
 
1986
{
 
1987
    u_int32_t *data32 = fim.getBuf();
 
1988
    u_int8_t  *data8  = (u_int8_t *) data32;
 
1989
    void*      data   = data8;
 
1990
    int        size   = fim.getBufLength();
 
1991
 
 
1992
    u_int32_t i;
 
1993
 
 
1994
    u_int32_t sect_size     = f.get_sector_size();
 
1995
    u_int32_t img_sect_size = fim.get_sector_size();
 
1996
 
 
1997
    // Check that the flash sector size is well defined in the image
 
1998
    if (img_sect_size && (img_sect_size != sect_size)) {
 
1999
        return errmsg("Flash sector size(0x%x) differs from sector size defined in the image (0x%x).\n"
 
2000
                      "This means that the given FW file is not configured to work with the burnt HCA board type.\n",
 
2001
                      sect_size,
 
2002
                      img_sect_size);
 
2003
    }
 
2004
 
 
2005
    if (size < (int)sect_size * 3) {
 
2006
        report("FAILED\n\n");
 
2007
        return errmsg("Image is too small.");
 
2008
    }
 
2009
 
 
2010
    if (!CheckInvariantSector(f, data32, sect_size)) {
 
2011
        return false;
 
2012
    }
 
2013
 
 
2014
    // Check signatures in image
 
2015
    u_int32_t actual_signature = data32[sect_size/4 + 2];
 
2016
 
 
2017
    u_int32_t signature_for_compare = actual_signature;
 
2018
 
 
2019
    TOCPU1(signature_for_compare);
 
2020
    if (signature_for_compare != SIGNATURE) {
 
2021
        return errmsg("Bad image file given: signature in PPS is 0x%08x (should be 0x%08x)",
 
2022
                      signature_for_compare, SIGNATURE);
 
2023
    }
 
2024
    signature_for_compare = data32[(sect_size * 2)/4 + 2];
 
2025
    TOCPU1(signature_for_compare);
 
2026
    if (signature_for_compare != SIGNATURE) {
 
2027
        return errmsg("Bad image file given: signature in SPS is 0x%08x (should be 0x%08x)",
 
2028
                      signature_for_compare, SIGNATURE);
 
2029
    }
 
2030
 
 
2031
    // Corrupt signatures in image
 
2032
    data32[sect_size/4 + 2] = 0xffffffff;
 
2033
    data32[(sect_size * 2)/4 + 2] = 0xffffffff;
 
2034
 
 
2035
    bool       cur_image_ok[2] = {false, false};
 
2036
    u_int32_t  cur_image_addr[2];
 
2037
    u_int32_t  cur_image_size[2];
 
2038
 
 
2039
    // Check signatures on flash
 
2040
    report("Read and verify PPS/SPS on flash            - ");
 
2041
    for (i = 0 ; i < 2 ; i++) {
 
2042
        if (!f.read(sect_size * (i+1) + 8, &signature_for_compare)) {
 
2043
 
 
2044
        }
 
2045
        TOCPU1(signature_for_compare);
 
2046
        if (signature_for_compare == SIGNATURE) {
 
2047
            cur_image_ok[i] = true;
 
2048
 
 
2049
            if (!f.read(sect_size * (i+1)    , &cur_image_addr[i]) ||
 
2050
                !f.read(sect_size * (i+1) + 4, &cur_image_size[i])) {
 
2051
                 report("FAILED\n\n");
 
2052
                 return false;
 
2053
            }
 
2054
 
 
2055
            TOCPU1(cur_image_addr[i]);
 
2056
            TOCPU1(cur_image_size[i]);
 
2057
        }
 
2058
    }
 
2059
 
 
2060
    if (!cur_image_ok[0] && !cur_image_ok[1]) {
 
2061
        //
 
2062
        // Both images are invalid on flash
 
2063
        // --------------------------------
 
2064
        //
 
2065
        printf("\nBoth images (primary and secondary) are invalid on flash.\n");
 
2066
        printf("The burning can not be failsafe, but it is harmless for host.\n");
 
2067
        if(!ask_user()) {
 
2068
            return false;
 
2069
        }
 
2070
 
 
2071
        // Burn all image
 
2072
        report("Burn FW image without signatures - ");
 
2073
        fflush(stdout);
 
2074
        if (!write_image(f, sect_size, data8 + sect_size, size - sect_size, need_report)) {
 
2075
            report("FAILED\n\n");
 
2076
            return false;
 
2077
        }
 
2078
        report("\b\b\b\bOK  \n");
 
2079
 
 
2080
        // Restore signatures
 
2081
        report("Restore right signatures         - ");
 
2082
        fflush(stdout);
 
2083
        if (!WriteSignature(f, 0, actual_signature)) {
 
2084
            report("FAILED (PPS Signature)\n\n");
 
2085
            return false;
 
2086
        }
 
2087
        if (!WriteSignature(f, 1, actual_signature)) {
 
2088
            report("FAILED (SPS Signature)\n\n");
 
2089
            return false;
 
2090
        }
 
2091
        report("OK\n");
 
2092
        return true;
 
2093
    } else {
 
2094
        report("OK\n");
 
2095
    }
 
2096
 
 
2097
    if (single_image_burn == false) {
 
2098
 
 
2099
        if (cur_image_ok[0] == false || cur_image_ok[1] == false) {
 
2100
            int image_from;
 
2101
            int image_to;
 
2102
 
 
2103
            assert (cur_image_ok[1] || cur_image_ok[0]);
 
2104
 
 
2105
            if (cur_image_ok[1]) {
 
2106
                image_from = 1;
 
2107
                image_to   = 0;
 
2108
            } else {
 
2109
                image_from = 0;
 
2110
                image_to   = 1;
 
2111
            }
 
2112
 
 
2113
            report("Reparable Error Detected.\n");
 
2114
            if (!repair(f, image_from, image_to, need_report))
 
2115
                    return false;
 
2116
        }
 
2117
 
 
2118
        //
 
2119
        // Both images are valid on flash
 
2120
        //
 
2121
        return FailSafe_burn_internal(f, data, size, need_report);
 
2122
 
 
2123
    } else {
 
2124
 
 
2125
        //
 
2126
        // Single image burn:
 
2127
        //
 
2128
 
 
2129
        // Extract Primary/Secondary image pointers and lengths
 
2130
        u_int32_t frst_new_image_addr = data32[sect_size / 4];
 
2131
        u_int32_t frst_new_image_size = data32[sect_size / 4 + 1];
 
2132
        TOCPU1(frst_new_image_addr);
 
2133
        TOCPU1(frst_new_image_size);
 
2134
 
 
2135
        if (!cur_image_ok[0] && cur_image_ok[1]) {
 
2136
            // Second image is valid on flash.
 
2137
            // If the new image can fit in the first image gap, it would be
 
2138
            //   burnt as first image.
 
2139
            // Otherwise (new image too big), image on flash is copied from second to
 
2140
            //   first image, and new image would be written as second.
 
2141
 
 
2142
            if (frst_new_image_addr + frst_new_image_size > cur_image_addr[1]) {
 
2143
                // New image is too large - can not get in between first image start
 
2144
                // and current (second) image - move current image to be first.
 
2145
                if (!repair(f, 1, 0, need_report))
 
2146
                    return false;
 
2147
 
 
2148
                // Now 2 images are valid
 
2149
                cur_image_ok[0] = true;
 
2150
            } else {
 
2151
                if (!FailSafe_burn_image(f, data, sect_size, "first", sect_size * 3, frst_new_image_size, need_report))
 
2152
                    return false;
 
2153
 
 
2154
                if (!WriteSignature(f, 1, 0))
 
2155
                    return false;
 
2156
 
 
2157
                return true;
 
2158
            }
 
2159
        }
 
2160
 
 
2161
        if (cur_image_ok[0] && cur_image_ok[1]) {
 
2162
            // Invalidate second image
 
2163
            if (!WriteSignature(f, 1, 0)) {
 
2164
                report("FAILED\n");
 
2165
                return false;
 
2166
            }
 
2167
 
 
2168
            cur_image_ok[1] = false;
 
2169
        }
 
2170
 
 
2171
        if (cur_image_ok[0] && !cur_image_ok[1]) {
 
2172
            u_int32_t new_image_size_sect = ((frst_new_image_size - 1) / sect_size) + 1 ;
 
2173
 
 
2174
            // First image is valid on flash.
 
2175
            // If the new image is smaller than current image, it would
 
2176
            // overwrite the end of current image. In this case, move the current image
 
2177
            // to the second position and burn in first.
 
2178
            //
 
2179
            // TODO: STOP THIS MOVEMENT BULLSHI%@#&! !!! : Reproduce PS in flint with the correct addr. Locate second image in middle of flash.
 
2180
 
 
2181
            if ( (3 + new_image_size_sect) * sect_size < cur_image_addr[0] + cur_image_size[0]) {
 
2182
                // New image overwrites end of cur image
 
2183
                // move current image to be second.
 
2184
                if (!repair(f, 0, 1, need_report))
 
2185
                    return false;
 
2186
 
 
2187
                // Now 2 images are valid
 
2188
                cur_image_ok[1] = true;
 
2189
 
 
2190
                // Burn new image as firse
 
2191
                if (!FailSafe_burn_image(f, data, sect_size, "first",
 
2192
                                         sect_size * 3, frst_new_image_size, need_report))
 
2193
                    return false;
 
2194
 
 
2195
                if (!WriteSignature(f, 1, 0))
 
2196
                    return false;
 
2197
 
 
2198
                return true;
 
2199
 
 
2200
            } else {
 
2201
                if (!FailSafe_burn_image(f, data, sect_size * 2, "second",
 
2202
                                     sect_size * (3 + new_image_size_sect) , frst_new_image_size, need_report))
 
2203
                    return false;
 
2204
 
 
2205
                // Invalidate first image
 
2206
                if (!WriteSignature(f, 0, 0))
 
2207
                    return false;
 
2208
 
 
2209
                return true;
 
2210
 
 
2211
            }
 
2212
        } else {
 
2213
            report("Bad flash state: Valid images = (%d,%d).\n", cur_image_ok[0], cur_image_ok[1] );
 
2214
            return false;
 
2215
        }
 
2216
 
 
2217
    }
 
2218
 
 
2219
    return true;
 
2220
}
 
2221
 
 
2222
bool Operations::CntxFailSafeBurn(Flash&    f,
 
2223
                                  FImage&   fim,
 
2224
                                  bool      need_report,
 
2225
                                  Operations::ImageInfo* flash_info,
 
2226
                                  Operations::ImageInfo* image_info,
 
2227
                                  bool      allow_nofs) {
 
2228
 
 
2229
    // TODO: See getBuf effect on zebra image.
 
2230
    u_int8_t  *data8      = (u_int8_t *) fim.getBuf();
 
2231
    int        image_size = fim.getBufLength();
 
2232
    u_int32_t  zeroes     = 0;
 
2233
 
 
2234
    bool is_curr_image_in_odd_chunks;
 
2235
 
 
2236
    if (!allow_nofs) {
 
2237
        if (!image_info->isFailsafe) {
 
2238
            return errmsg("The given image is not a failsae image");
 
2239
        }
 
2240
 
 
2241
        if (flash_info->cntxLog2ChunkSize != image_info->cntxLog2ChunkSize) {
 
2242
            return errmsg("Failsafe chunk sizes in flash (0x%x) and in image (0x%x) are not the same.",
 
2243
                          1 << flash_info->cntxLog2ChunkSize,
 
2244
                          1 << image_info->cntxLog2ChunkSize);
 
2245
        }
 
2246
    }
 
2247
 
 
2248
    u_int32_t new_image_start;
 
2249
 
 
2250
    if (flash_info->imgStart != 0) {
 
2251
        is_curr_image_in_odd_chunks = 1;
 
2252
        new_image_start = 0;
 
2253
    } else {
 
2254
        is_curr_image_in_odd_chunks = 0;
 
2255
        new_image_start = (1 << image_info->cntxLog2ChunkSize);
 
2256
    }
 
2257
 
 
2258
    //printf("-I- Chunk=%x . Cur image start=%x burning from %x, flash_log2_chunk_size=%d\n",
 
2259
    //       1 << flash_info->cntxLog2ChunkSize,
 
2260
    //       flash_info->imgStart,
 
2261
    //       new_image_start,
 
2262
    //       flash_info->cntxLog2ChunkSize);
 
2263
 
 
2264
    if (image_info->isFailsafe) {
 
2265
        f.set_address_convertor(image_info->cntxLog2ChunkSize, !is_curr_image_in_odd_chunks);
 
2266
    } else {
 
2267
        f.set_address_convertor(0,0);
 
2268
        new_image_start = 0;
 
2269
    }
 
2270
 
 
2271
    // Go ahead and burn!
 
2272
    const char* image_name = new_image_start == 0 ? "first" : "second";
 
2273
    report("\nBurning %-6s FW image without signatures  - ", image_name);
 
2274
 
 
2275
    fflush(stdout);
 
2276
 
 
2277
    if (!write_image(f, 16 , data8 + 16, image_size - 16, need_report)) {
 
2278
        report("FAILED\n\n");
 
2279
        return false;
 
2280
    }
 
2281
    report("\b\b\b\bOK  \n");
 
2282
 
 
2283
    report("Restoring %-6s signature                  -     ", image_name);
 
2284
 
 
2285
    fflush(stdout);
 
2286
 
 
2287
    // Write new signature
 
2288
    if (!f.write(0, data8, 16, true)) {
 
2289
        report("FAILED\n\n");
 
2290
        return false;
 
2291
    }
 
2292
 
 
2293
    // Write new image start address to crspace (for SW reset)
 
2294
    f.cr_write(0xf0000, (new_image_start << 8) | 0x06);
 
2295
 
 
2296
    if (image_info->isFailsafe) {
 
2297
        if (allow_nofs) {
 
2298
            // When burning in nofs, remnant of older image with different chunk size
 
2299
            // may reside on the flash -
 
2300
            // Invalidate all images marking on flash except the one we've just burnt
 
2301
 
 
2302
            u_int32_t cntx_image_start[CNTX_START_POS_SIZE];
 
2303
            u_int32_t cntx_image_num;
 
2304
            u_int32_t i;
 
2305
 
 
2306
            CntxFindAllImageStart(f, cntx_image_start, &cntx_image_num);
 
2307
            // Address convertor is disabled now - use phys addresses
 
2308
            for (i = 0; i < cntx_image_num; i++) {
 
2309
                if (cntx_image_start[i] != new_image_start) {
 
2310
                    if (!f.write(cntx_image_start[i], &zeroes, sizeof(zeroes), true)) {
 
2311
                        report("FAILED\n\n");
 
2312
                        return false;
 
2313
                    }
 
2314
                }
 
2315
            }
 
2316
        } else {
 
2317
            // invalidate previous signature
 
2318
            f.set_address_convertor(image_info->cntxLog2ChunkSize, is_curr_image_in_odd_chunks);
 
2319
            if (!f.write(0, &zeroes, sizeof(zeroes), true)) {
 
2320
                report("FAILED\n\n");
 
2321
                return false;
 
2322
            }
 
2323
        }
 
2324
    }
 
2325
    report("\b\b\b\bOK  \n");
 
2326
 
 
2327
    if (allow_nofs && image_info->isFailsafe) {
 
2328
 
 
2329
    }
 
2330
 
 
2331
    return true;
 
2332
}
 
2333
 
 
2334
 
 
2335
 
 
2336
 
 
2337
////////////////////////////////////////////////////////////////////////
 
2338
//                                                                    //
 
2339
// ****************************************************************** //
 
2340
//                        VERIFY FLASH                                //
 
2341
// ****************************************************************** //
 
2342
//                                                                    //
 
2343
////////////////////////////////////////////////////////////////////////
 
2344
 
 
2345
 
 
2346
//
 
2347
// Cntx image verification flow:
 
2348
//
 
2349
// The "zebra"failsafe scheme presents few problems:
 
2350
// - Need to search for a valid image in the flash.
 
2351
// - handle no image / more than a single valid image cases
 
2352
// - check image actual start location(s) vs. fs_zebra_size field in the image.
 
2353
// - Image file is not striped though its fs_zebra_size sais it is - need to allow that
 
2354
//   when checking a file.
 
2355
//
 
2356
// Verification flow:
 
2357
//
 
2358
// 1. Find image start addresses.
 
2359
//    if num of start_addr not in [1,2] - Error - corrupted flash
 
2360
// 2. for each start_addr:
 
2361
//      Check that its fs_zebra_size is identical to other images (if exists)
 
2362
//      For Flash:
 
2363
//          Set address translation according to the fs_zebra_size.
 
2364
//      For File:
 
2365
//          *GUESS* if image is contiguous or striped. This can be according
 
2366
//          to the file size vs. image size field in the image.
 
2367
//          Set address translation according to the fs_zebra_size or to 0.
 
2368
//      verify - same as previous projects nofs image, with the aditional start
 
2369
//
 
2370
 
 
2371
 
 
2372
bool Operations::CntxFindMagicPattern       (FBase& f,  u_int32_t addr) {
 
2373
    int i;
 
2374
    if (addr + 16 > f.get_size()) {
 
2375
        return false;
 
2376
    }
 
2377
    for (i = 0; i < 4 ; i++) {
 
2378
        u_int32_t w;
 
2379
        READ4(f, addr + i * 4, &w, "Magic Pattern" );
 
2380
        TOCPU1(w);
 
2381
        if (w != _cntx_magic_pattern[i]) {
 
2382
            //printf("-D- Looking for magic pattern %d addr %06x: Exp=%08x Act=%08x\n", i, addr + i * 4, _cntx_magic_pattern[i], w);
 
2383
            return false;
 
2384
        }
 
2385
    }
 
2386
 
 
2387
    return true;
 
2388
}
 
2389
 
 
2390
// FindAllImageStart
 
2391
// OUT: start_locations: set to the start addresses of the found image markers (in accending order)
 
2392
// OUT: found_images:    Number of found images (and number of valid entries in the start_locations array).
 
2393
bool Operations::CntxFindAllImageStart       (FBase& f,  u_int32_t start_locations[CNTX_START_POS_SIZE], u_int32_t* found_images) {
 
2394
    int i;
 
2395
    f.set_address_convertor(0,0);
 
2396
 
 
2397
    *found_images = 0;
 
2398
    for (i = 0; i < CNTX_START_POS_SIZE; i++) {
 
2399
        if (CntxFindMagicPattern(f, _cntx_image_start_pos[i])) {
 
2400
            start_locations[*found_images] = _cntx_image_start_pos[i];
 
2401
            (*found_images)++;
 
2402
        }
 
2403
    }
 
2404
 
 
2405
    return true;
 
2406
}
 
2407
 
 
2408
bool Operations::checkBoot2(FBase& f, u_int32_t beg, u_int32_t offs,
 
2409
                u_int32_t& next, const char *pref)
 
2410
{
 
2411
    u_int32_t    size;
 
2412
 
 
2413
    char         *pr = (char *)alloca(strlen(pref) + 512);
 
2414
 
 
2415
    sprintf(pr, "%s /0x%08x/ (BOOT2)", pref, offs+beg);
 
2416
 
 
2417
    // Size
 
2418
    READ4(f, offs+beg+4, &size, pr);
 
2419
    TOCPU1(size);
 
2420
    if (size > 1048576 || size < 4) {
 
2421
        report("%s /0x%08x/ - unexpected size (0x%x)\n", pr, offs+beg+4, size);
 
2422
        return false;
 
2423
    }
 
2424
 
 
2425
    sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (BOOT2)", pref, offs+beg,
 
2426
            offs+beg+(size+4)*4-1, (size+4)*4);
 
2427
 
 
2428
    Crc16        crc;
 
2429
    u_int32_t    *buff = (u_int32_t*)alloca((size + 4)*sizeof(u_int32_t));
 
2430
 
 
2431
    READBUF(f, offs+beg, buff, size*4 + 16, pr);
 
2432
    TOCPUn(buff, size+4);
 
2433
    CRC1n(crc, buff, size+4);
 
2434
    crc.finish();
 
2435
    u_int32_t crc_act = buff[size+3];
 
2436
    if (crc.get() != crc_act) {
 
2437
        report("%s /0x%08x/ - wrong CRC (exp:0x%x, act:0x%x)\n",
 
2438
               pr, offs+beg, crc.get(), crc_act);
 
2439
        return errmsg("Bad CRC");
 
2440
    }
 
2441
 
 
2442
    if (_print_crc)
 
2443
        report("%s - OK (CRC:0x%04x)\n", pr, crc_act&0xffff);
 
2444
    else
 
2445
        report("%s - OK\n", pr);
 
2446
    next = offs + size*4 + 16;
 
2447
    return true;
 
2448
} // checkBoot2
 
2449
 
 
2450
static int part_cnt;
 
2451
 
 
2452
////////////////////////////////////////////////////////////////////////
 
2453
bool Operations::checkGen(FBase& f, u_int32_t beg,
 
2454
              u_int32_t offs, u_int32_t& next, const char *pref)
 
2455
{
 
2456
    char         *pr = (char *)alloca(strlen(pref) + 100);
 
2457
 
 
2458
    char         unknown_sect_name[128];
 
2459
    const char*  sect_name;
 
2460
 
 
2461
    u_int32_t    size=0;
 
2462
    GPH          gph;
 
2463
 
 
2464
    // GPH
 
2465
    sprintf(pr, "%s /0x%08x/ (GeneralHeader)", pref, offs+beg);
 
2466
    READBUF(f, offs+beg, &gph, sizeof(GPH), pr);
 
2467
    TOCPUBY(gph);
 
2468
 
 
2469
    // Body
 
2470
    part_cnt++;
 
2471
 
 
2472
    // May be BOOT3?
 
2473
    if (gph.type < H_FIRST  ||  gph.type >= H_LAST) {
 
2474
        if (part_cnt > 2) {
 
2475
            //report("%s /0x%x/ - Invalid partition type (%d)\n",
 
2476
            //       pref, offs+beg, gph.type);
 
2477
            //return false;
 
2478
        } else
 
2479
            return checkBoot2(f, beg, offs, next, pref);
 
2480
    }
 
2481
 
 
2482
    // All partitions here
 
2483
    offs += beg;
 
2484
 
 
2485
    if (gph.type < H_FIRST  ||  gph.type >= H_LAST) {
 
2486
        // For forward compatibility, try analyzing even if section type is uncknown
 
2487
        // Assuming the size is in DW, like all other sections (except emt service).
 
2488
        // If this assumption is wrong, CRC calc would fail - no harm done.
 
2489
        sprintf(unknown_sect_name, "UNKNOWN (%d)" , gph.type);
 
2490
        sect_name = unknown_sect_name;
 
2491
        size = gph.size * 4;
 
2492
    } else {
 
2493
        if (gph.type == H_EMT) {
 
2494
            size = (gph.size + 3) / 4 * 4;
 
2495
        } else {
 
2496
            size = gph.size * 4;
 
2497
        }
 
2498
        sect_name = g_sectNames[gph.type];
 
2499
    }
 
2500
 
 
2501
    sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (%s)",
 
2502
                pref, offs, offs+size+(u_int32_t)sizeof(gph)+3,
 
2503
                size+(u_int32_t)sizeof(gph)+4, sect_name);
 
2504
 
 
2505
    if (size > MAX_SECTION_SIZE) {
 
2506
        report("%s - size too big (0x%x)\n",
 
2507
               pr, size);
 
2508
        return false;
 
2509
    }
 
2510
 
 
2511
    // CRC
 
2512
    Crc16        crc;
 
2513
    std::vector<u_int8_t> buffv(size);
 
2514
    u_int32_t *buff = (u_int32_t*)(&(buffv[0]));
 
2515
 
 
2516
    READBUF(f, offs+sizeof(gph), buff, size, pr);
 
2517
 
 
2518
    TOCPUn(buff,size/4);
 
2519
    CRCBY(crc, gph);
 
2520
    CRCn(crc, buff, size/4);
 
2521
    crc.finish();
 
2522
    u_int32_t crc_act;
 
2523
    READ4(f, offs+sizeof(gph)+size, &crc_act, pr);
 
2524
    TOCPU1(crc_act);
 
2525
    bool blank_crc = false;
 
2526
    if (gph.type == H_GUID && crc_act == 0xffff) {
 
2527
        blank_crc = true;
 
2528
    } else if (crc.get() != crc_act) {
 
2529
        report("%s /0x%08x/ - wrong CRC (exp:0x%x, act:0x%x)\n",
 
2530
               pr, offs, crc.get(), crc_act);
 
2531
        return errmsg("Bad CRC");
 
2532
    }
 
2533
 
 
2534
    if (_print_crc)
 
2535
        report("%s - OK (CRC:0x%04x)\n", pr, crc_act&0xffff);
 
2536
    else
 
2537
        if (blank_crc) {
 
2538
            report("%s - BLANK CRC (0xffff)\n", pr);
 
2539
        } else {
 
2540
            report("%s - OK\n", pr);
 
2541
        }
 
2542
    next = gph.next;
 
2543
 
 
2544
    if (gph.type == H_FW_CONF) {
 
2545
        _fw_conf_sect.clear();
 
2546
        _fw_conf_sect.insert(_fw_conf_sect.end(),
 
2547
                         vector<u_int8_t>::iterator((u_int8_t*)buff),
 
2548
                         vector<u_int8_t>::iterator((u_int8_t*)buff + size));
 
2549
 
 
2550
    }
 
2551
 
 
2552
    if (gph.type == H_ROM && _rom_sect.empty()) {
 
2553
        _rom_sect.clear();
 
2554
        _rom_sect.insert(_rom_sect.end(),
 
2555
                         vector<u_int8_t>::iterator((u_int8_t*)buff),
 
2556
                         vector<u_int8_t>::iterator((u_int8_t*)buff + size));
 
2557
    }
 
2558
 
 
2559
    // mark last read addr
 
2560
    _last_image_addr = offs + size +sizeof(gph) + 4;  // the 4 is for the trailing crc
 
2561
 
 
2562
    return true;
 
2563
} // checkGen
 
2564
 
 
2565
////////////////////////////////////////////////////////////////////////
 
2566
bool Operations::checkPS(FBase& f, u_int32_t offs, u_int32_t& next, const char *pref)
 
2567
{
 
2568
    Crc16 crc;
 
2569
    PS    ps;
 
2570
    f.read(offs, &ps, sizeof(ps));
 
2571
    TOCPUBY(ps);
 
2572
 
 
2573
    // Signature
 
2574
    if (ps.signature != SIGNATURE) {
 
2575
        report("%s Pointer Sector /0x%08x/ - invalid signature (%08x)\n",
 
2576
               pref, offs, ps.signature);
 
2577
        return false;
 
2578
    }
 
2579
 
 
2580
    // CRC
 
2581
    CRC1BY(crc, ps);
 
2582
    crc.finish();
 
2583
    if (crc.get() != ps.crc016) {
 
2584
        report("%s Pointer Sector /0x%08x/ - wrong CRC (exp:0x%x, act:0x%x)\n",
 
2585
               pref, offs, ps.crc016, crc.get());
 
2586
        return errmsg("Bad CRC");
 
2587
    }
 
2588
 
 
2589
    next = ps.fi_addr;
 
2590
    if (_print_crc)
 
2591
        report("%s Image /0x%08x-0x%08x (0x%06x)/ (Pointer Sector)- OK (CRC:0x%04x)\n", pref, offs,
 
2592
               offs+(u_int32_t)sizeof(ps)-1, (u_int32_t)sizeof(ps), ps.crc016&0xffff);
 
2593
    else
 
2594
        report("%s Image /0x%08x-0x%08x (0x%06x)/ (Pointer Sector)- OK\n", pref, offs,
 
2595
               offs+(u_int32_t)sizeof(ps)-1, (u_int32_t)sizeof(ps));
 
2596
    return true;
 
2597
} // checkPS
 
2598
 
 
2599
////////////////////////////////////////////////////////////////////////
 
2600
bool Operations::checkList(FBase& f, u_int32_t offs, u_int32_t fw_start, const char *pref)
 
2601
{
 
2602
    u_int32_t next_ptr;
 
2603
 
 
2604
    CHECKB2(f, offs, fw_start, next_ptr, pref);
 
2605
    part_cnt = 1;
 
2606
    while (next_ptr && next_ptr != 0xff000000)
 
2607
        CHECKGN(f, offs, next_ptr, next_ptr, pref);
 
2608
 
 
2609
    return true;
 
2610
} // checkList
 
2611
 
 
2612
////////////////////////////////////////////////////////////////////////
 
2613
 
 
2614
bool Operations::CheckIsCntx(FBase& f) {
 
2615
    if (f.is_flash()) {
 
2616
        return ( ((Flash*)&f)->get_dev_id() == 400) ||
 
2617
               ( ((Flash*)&f)->get_dev_id() == 435);
 
2618
 
 
2619
    } else {
 
2620
        u_int32_t found_images;
 
2621
        u_int32_t image_start[CNTX_START_POS_SIZE];
 
2622
 
 
2623
        // Image - check if magic pattern is somewhere in the file:
 
2624
        CntxFindAllImageStart(f, image_start, &found_images);
 
2625
        return found_images > 0;
 
2626
    }
 
2627
}
 
2628
 
 
2629
bool Operations::CheckMac(u_int64_t mac) {
 
2630
    if ((mac >> 40) & 0x1) {
 
2631
        return errmsg("Multicast bit (bit 40) is set");
 
2632
    }
 
2633
 
 
2634
    if (mac >> 48) {
 
2635
        return errmsg("More than 48 bits are used");
 
2636
    }
 
2637
 
 
2638
    return true;
 
2639
}
 
2640
 
 
2641
 
 
2642
bool Operations::CntxGetFsData(FBase& f, u_int32_t img_addr, bool& fs_en, u_int32_t& log2chunk_size) {
 
2643
    u_int32_t fs_info_word;
 
2644
    u_int8_t  checksum;
 
2645
 
 
2646
    f.read(img_addr + 0x28, &fs_info_word);
 
2647
    TOCPU1(fs_info_word);
 
2648
 
 
2649
    // printf("-D- fs_info_word=%08x\n", fs_info_word);
 
2650
 
 
2651
    checksum = ((fs_info_word      ) & 0xff) +
 
2652
               ((fs_info_word >>  8) & 0xff) +
 
2653
               ((fs_info_word >> 16) & 0xff) +
 
2654
               ((fs_info_word >> 24) & 0xff);
 
2655
 
 
2656
    if (checksum != 0) {
 
2657
        return errmsg("Corrupted chunk size checksum");
 
2658
    }
 
2659
 
 
2660
    fs_en = (fs_info_word & 0x8) != 0;
 
2661
 
 
2662
    if (fs_en) {
 
2663
        log2chunk_size = (fs_info_word & 0x7) + 16;
 
2664
    } else {
 
2665
        log2chunk_size = 0;
 
2666
    }
 
2667
 
 
2668
    return true;
 
2669
}
 
2670
 
 
2671
 
 
2672
// This function gets the HW ID of the target device and the dev ID from
 
2673
// the image. It then matches the 2 IDs and returns an error in case of
 
2674
// missmatch. The match is not 1:1 , since the FW image contains the SW
 
2675
// dev id, and a single hw dev id may match multiple SW dev IDs.
 
2676
//
 
2677
 
 
2678
bool Operations::CheckMatchingDevId(u_int32_t hwDevId, u_int32_t imageDevId) {
 
2679
    int i, j;
 
2680
    const HwDevData* devData = NULL;
 
2681
    const char* hwDevName;
 
2682
    // HACK: InfiniHost III LX may have 2 HW device ids. - Map the second devid to the first.
 
2683
    if (hwDevId == 24204) {
 
2684
        hwDevId = 25204;
 
2685
    }
 
2686
 
 
2687
    // First, find the HW device that the SW id matches
 
2688
    for (i = 0; hwDevData[i].hwDevId != 0 ; i++) {
 
2689
        if (hwDevData[i].hwDevId == hwDevId) {
 
2690
            hwDevName = hwDevData[i].name;
 
2691
        }
 
2692
 
 
2693
        if (devData == NULL) {
 
2694
            for (j = 0; hwDevData[i].swDevIds[j]; j++) {
 
2695
                if (hwDevData[i].swDevIds[j] == imageDevId) {
 
2696
                    devData = &hwDevData[i];
 
2697
                    break;
 
2698
                }
 
2699
            }
 
2700
        }
 
2701
    }
 
2702
 
 
2703
    if (devData == NULL) {
 
2704
        printf("-W- Unknown device id (%d) in the given FW image. Skipping HW match check.\n",
 
2705
               imageDevId);
 
2706
        return true;
 
2707
    } else if (devData->hwDevId != hwDevId) {
 
2708
        return errmsg("Trying to burn a \"%s\" image on a \"%s\" device.",
 
2709
                      devData->name,
 
2710
                      hwDevName);
 
2711
    }
 
2712
 
 
2713
    return true;
 
2714
}
 
2715
 
 
2716
bool Operations::VerifyCntx(FBase& f, Operations::ImageInfo* info, bool both_images, bool only_get_start) {
 
2717
    u_int32_t cntx_image_start[CNTX_START_POS_SIZE];
 
2718
    u_int32_t cntx_image_num;
 
2719
    u_int32_t i;
 
2720
    bool      ret = true;
 
2721
 
 
2722
    // Look for image in "physical addresses
 
2723
    CntxFindAllImageStart(f, cntx_image_start, &cntx_image_num);
 
2724
 
 
2725
    if (cntx_image_num == 0) {
 
2726
        return errmsg("No valid image found");
 
2727
    } else if (cntx_image_num > 2) {
 
2728
                // This check may be redundant - Maybe ignore if more than 2 images found
 
2729
                return errmsg("More than 2 image start locations found at addresses %x, %x and %x. Image may be corrupted.",
 
2730
                              cntx_image_start[0],
 
2731
                              cntx_image_start[1],
 
2732
                              cntx_image_start[2]);
 
2733
    }
 
2734
 
 
2735
    if (!both_images) {
 
2736
        // Check only the first image. This is enough to ensure that the device is bootable.
 
2737
        cntx_image_num = 1;
 
2738
    }
 
2739
 
 
2740
    bool info_set = false;
 
2741
 
 
2742
    // Verify the images:
 
2743
    for (i = 0; i < cntx_image_num; i++ ) {
 
2744
        bool      fs_en;
 
2745
        u_int32_t log2chunk_size;
 
2746
 
 
2747
        f.set_address_convertor(0,0);
 
2748
        if (!CntxGetFsData(f, cntx_image_start[i], fs_en, log2chunk_size)) {
 
2749
            report("\n    Can't read failsafe info word: %s\n", err());
 
2750
 
 
2751
            return (i > 0);
 
2752
        }
 
2753
 
 
2754
        // If fw not enabled, image must start at addr 0
 
2755
        if (!fs_en && cntx_image_start[i] != 0) {
 
2756
            return errmsg("ConnectX Non Failsafe image must start at address 0. Found non-fs image at address %x",
 
2757
                          cntx_image_start[i]);
 
2758
        }
 
2759
 
 
2760
        if (fs_en) {
 
2761
            report("\n     ConnectX failsafe image. Start address: %x. Chunk size %x:\n\n", cntx_image_start[i], 1 << log2chunk_size);
 
2762
            report("     NOTE: The addresses below are contiguous logical addresses. Physical addresses on\n"
 
2763
                   "           flash may be different, based on the image start address and chunk size\n\n");
 
2764
        } else {
 
2765
            report("\n     ConnectX non failsafe image:\n\n");
 
2766
        }
 
2767
 
 
2768
        if (fs_en && cntx_image_start[i] != 0 && cntx_image_start[i] != (u_int32_t)(1 << log2chunk_size)) {
 
2769
            return errmsg("ConnectX Failsafe image must start at address 0 or at chunk size. Found a failsafe image at address %x",
 
2770
                          cntx_image_start[i]);
 
2771
        }
 
2772
 
 
2773
        if (info && !info_set) {
 
2774
            info->imgStart          = cntx_image_start[i];
 
2775
            info->isFailsafe        = fs_en;
 
2776
            info->actuallyFailsafe  = true;
 
2777
            info->cntxLog2ChunkSize = log2chunk_size;
 
2778
        }
 
2779
 
 
2780
        if (f.is_flash()) {
 
2781
            // In flash, image layout must match the FS Data
 
2782
            if (info && !info_set) {
 
2783
                info->actuallyFailsafe    = true;
 
2784
                info_set = true;
 
2785
            }
 
2786
 
 
2787
            if (fs_en) {
 
2788
                f.set_address_convertor(log2chunk_size, cntx_image_start[i] != 0);
 
2789
            }
 
2790
        } else {
 
2791
            // In an image file there are 2 cases:
 
2792
            // 1. Image generated by mlxburn
 
2793
            //    The image in the file is contiguous (though it is marked as FS) - no need to set address convertion.
 
2794
            // 2. The image was raw read from flash. In this case it would be in "zebra" format.
 
2795
            //
 
2796
            // So - I try both cases, and see which verify() succeeds.
 
2797
            //
 
2798
            // Heuristics that may come in handy:
 
2799
            // If the image does not start at addr 0, it's not an mlxburn image.
 
2800
            // If there is more than a single valid image, it's not an mlxburn image.
 
2801
            // If the file size matches the image size, it is an mlxburn image.
 
2802
            //
 
2803
            // For now, get the "striped" indication from user.
 
2804
 
 
2805
            if (_cntx_striped_image) {
 
2806
                f.set_address_convertor(log2chunk_size, cntx_image_start[i] != 0);
 
2807
            } else {
 
2808
                f.set_address_convertor(0,0); //disable conversion
 
2809
            }
 
2810
            if (info && !info_set) {
 
2811
                info->actuallyFailsafe    = _cntx_striped_image;
 
2812
                info_set = true;
 
2813
            }
 
2814
        }
 
2815
 
 
2816
        bool imgStat = true;
 
2817
 
 
2818
        if (!only_get_start) {
 
2819
            imgStat = checkList(f, 0, 0x38, "    ");
 
2820
        }
 
2821
        if (i == 0) {
 
2822
            ret = ret && imgStat;
 
2823
        }
 
2824
    }
 
2825
    return ret;
 
2826
}
 
2827
 
 
2828
bool Operations::Verify(FBase& f, Operations::ImageInfo* info, bool both_images)
 
2829
{
 
2830
    u_int32_t prim_ptr, scnd_ptr;
 
2831
    u_int32_t signature;
 
2832
 
 
2833
    bool      ret = true;
 
2834
 
 
2835
    if (IsCntx()) {
 
2836
        return VerifyCntx(f, info, both_images);
 
2837
    }
 
2838
 
 
2839
    READ4(f, 0x24, &signature, "Signature");
 
2840
    TOCPU1(signature);
 
2841
    if (signature == SIGNATURE) {
 
2842
        // Full image
 
2843
 
 
2844
        bool psStat[2];
 
2845
 
 
2846
        report("\nFailsafe image:\n\n");
 
2847
        CHECKB2(f, 0, 0x28, prim_ptr, "Invariant      ");
 
2848
        report("\n");
 
2849
        psStat[0] = checkPS(f, f.get_sector_size(), prim_ptr, "Primary  ");
 
2850
        if (psStat[0]) {
 
2851
            ret &= checkList(f, prim_ptr, 0x28, "               ");
 
2852
        }
 
2853
        report("\n");
 
2854
 
 
2855
        if (psStat[0] && !both_images) {
 
2856
            return ret;
 
2857
        }
 
2858
 
 
2859
        psStat[1] = checkPS(f, f.get_sector_size() * 2, scnd_ptr, "Secondary");
 
2860
        bool scndStat;
 
2861
        if (psStat[1]) {
 
2862
            scndStat = checkList(f, scnd_ptr, 0x28, "               ");
 
2863
            if (!psStat[0]) {
 
2864
                // If the first image is valid, the HCA would boot OK even if the secondary image is messed up -
 
2865
                // consider this status only if the first image is not valid.
 
2866
                ret &= scndStat;
 
2867
            }
 
2868
        }
 
2869
 
 
2870
        if (psStat[0] == false && psStat[1] == false) {
 
2871
            ret = false;
 
2872
        }
 
2873
    } else {
 
2874
 
 
2875
        report("\nShort image:\n");
 
2876
        CHECKLS(f, 0, 0x28, "    ");
 
2877
    }
 
2878
 
 
2879
    return ret;
 
2880
} // Verify
 
2881
 
 
2882
bool Operations::GetExpRomVersion(ImageInfo* info) {
 
2883
    const char* magic_string = "mlxsign:";
 
2884
    u_int32_t   magic_len    = strlen(magic_string);
 
2885
    u_int32_t   i;
 
2886
    bool        magic_found  = false;
 
2887
    u_int32_t   ver_offset;
 
2888
    u_int8_t    rom_checksum = 0;
 
2889
    u_int32_t   rom_checksum_range;
 
2890
 
 
2891
    info->expRomValidVersion = false;
 
2892
    if (_rom_sect.empty()) {
 
2893
        return errmsg("Expansion Rom section not found.");
 
2894
    }
 
2895
 
 
2896
    // When checking the version of the expansion rom, only the first image has
 
2897
    // to be checked. This is because the second image  the uefi image does not
 
2898
    // have to comply with checksumming to 0. To do this you have to read  byte
 
2899
    // 2 (third) of the image  and multiply by 512 to get the size of the x86
 
2900
    // image.
 
2901
 
 
2902
    // Checksum:
 
2903
    if (_rom_sect.size() < 4) {
 
2904
        return errmsg("ROM size (0x%x) is too small", (u_int32_t)_rom_sect.size());
 
2905
    }
 
2906
 
 
2907
    // restore endianess.
 
2908
    TOCPUn(&(_rom_sect[0]), _rom_sect.size()/4);
 
2909
 
 
2910
    rom_checksum_range = _rom_sect[2] * 512 ;
 
2911
    if (rom_checksum_range > _rom_sect.size()) {
 
2912
       return errmsg("ROM size field (0x%2x) is larger than actual ROM size (0x%x)",
 
2913
                     rom_checksum_range ,
 
2914
                     (u_int32_t)_rom_sect.size());
 
2915
    } else if (rom_checksum_range == 0) {
 
2916
       return errmsg("ROM size field is 0. Unknown ROM format or corrupted ROM.");
 
2917
    }
 
2918
 
 
2919
    for (i = 0; i < rom_checksum_range; i++) {
 
2920
        rom_checksum += _rom_sect[i];
 
2921
    }
 
2922
 
 
2923
    if (rom_checksum != 0) {
 
2924
        return errmsg("Bad ROM Checksum (0x%02x)", rom_checksum);
 
2925
    }
 
2926
 
 
2927
    for (i = 0 ; i < rom_checksum_range; i++) {
 
2928
        for (u_int32_t j = 0; j < magic_len; j++) {
 
2929
            if (_rom_sect[i+j] != magic_string[j]) {
 
2930
                break;
 
2931
            } else if (j == magic_len - 1) {
 
2932
                magic_found = true;
 
2933
            }
 
2934
        }
 
2935
 
 
2936
        if (magic_found) {
 
2937
            break;
 
2938
        }
 
2939
    }
 
2940
 
 
2941
    if (magic_found) {
 
2942
        ver_offset = i + magic_len;
 
2943
    } else {
 
2944
        return errmsg("Mellanox version string (%s) not found in ROM section.", magic_string);
 
2945
    }
 
2946
 
 
2947
    // Following mlxsign:
 
2948
    // 31:24    0        Compatible with UEFI
 
2949
    // 23:16    ProductID       Product ID:
 
2950
    //                          1 - CLP implementation for Sinai (MT25408)
 
2951
    //                          2 - CLP implementation for Hermon DDR (MT25418)
 
2952
    //                          0X10 - PXE
 
2953
    // 15:0     Major version   If ProductID < 0x10 this field is subversion
 
2954
    //                          number, otherwise It's product major version.
 
2955
    //
 
2956
    // 31:16    Minor version   Product minor version*. Not valid if
 
2957
    //                          roductID < 0x10.
 
2958
    // 15:0     SubMinor version        Product sub minor version*. Not valid if
 
2959
    //                                  ProductID < 0x10.
 
2960
    //
 
2961
    // 31:16    Device ID       The PCI Device ID (ex. 0x634A for Hermon
 
2962
    //                          DDR). Not valid if ProductID < 0x10.
 
2963
    // 15:12    Port Number     Port number: 0 - Port independent, 1 - Port 1, 2 - Port 2
 
2964
    // 11:0     Reserved
 
2965
 
 
2966
    u_int32_t tmp;
 
2967
 
 
2968
    tmp = __le32_to_cpu(*((u_int32_t*) &_rom_sect[ver_offset]));
 
2969
    info->expRomProductId = tmp >> 16;
 
2970
    info->expRomVer[0]    = tmp & 0xffff;
 
2971
 
 
2972
    if (info->expRomProductId >= 0x10) {
 
2973
        tmp = __le32_to_cpu(*((u_int32_t*) &_rom_sect[ver_offset + 4]));
 
2974
        info->expRomVer[1] = tmp >> 16;
 
2975
        info->expRomVer[2] = tmp  & 0xffff;
 
2976
 
 
2977
        tmp = __le32_to_cpu(*((u_int32_t*) &_rom_sect[ver_offset + 8]));
 
2978
        info->expRomDevId  = tmp >> 16;
 
2979
        info->expRomPort   = (tmp >> 12) & 0xf;
 
2980
    }
 
2981
    info->expRomValidVersion = true;
 
2982
    return true;
 
2983
}
 
2984
 
 
2985
bool Operations::LoadAsExpRom (FBase& f) {
 
2986
    _rom_sect.clear();
 
2987
    _rom_sect.resize(f.get_size());
 
2988
    if (!f.read(0, &_rom_sect[0], f.get_size()))
 
2989
        return errmsg(f.err());
 
2990
 
 
2991
    TOCPUn(&_rom_sect[0], _rom_sect.size()/4);
 
2992
 
 
2993
    return true;
 
2994
}
 
2995
 
 
2996
bool Operations::DumpConf        (const char* conf_file) {
 
2997
#ifndef NO_ZLIB
 
2998
 
 
2999
    FILE* out;
 
3000
    if (conf_file == NULL) {
 
3001
        out = stdout;
 
3002
    } else {
 
3003
        out = fopen(conf_file, "w");
 
3004
 
 
3005
        if (out == NULL) {
 
3006
            return errmsg("Can not open file %s for write: %s.", conf_file, strerror(errno));
 
3007
        }
 
3008
    }
 
3009
 
 
3010
    if (_fw_conf_sect.empty()) {
 
3011
        return errmsg("FW configuration section not found in the given image.");
 
3012
    }
 
3013
 
 
3014
    // restore endianess.
 
3015
    TOCPUn(&(_fw_conf_sect[0]), _fw_conf_sect.size()/4);
 
3016
 
 
3017
    // uncompress:
 
3018
    uLongf destLen = _fw_conf_sect.size();
 
3019
    destLen *= 10;
 
3020
    vector<u_int8_t> dest(destLen);
 
3021
 
 
3022
    int rc = uncompress((Bytef *)&(dest[0]), &destLen,
 
3023
                        (const Bytef *)&(_fw_conf_sect[0]), _fw_conf_sect.size());
 
3024
 
 
3025
    if (rc != Z_OK)
 
3026
    {
 
3027
        return errmsg("Failed uncompressing FW configuration section. uncompress returnes %d", rc);
 
3028
    }
 
3029
 
 
3030
    dest.resize(destLen);
 
3031
    dest[destLen] = 0;  // Terminating NULL
 
3032
    fprintf(out, "%s", (char*)&(dest[0]));
 
3033
 
 
3034
    if (conf_file != NULL) {
 
3035
        fclose(out);
 
3036
    }
 
3037
 
 
3038
    return true;
 
3039
#else
 
3040
    return errmsg("Executable was compiled with \"dump configuration\" option disabled.");
 
3041
#endif
 
3042
 
 
3043
} // DumpConf
 
3044
 
 
3045
 
 
3046
 
 
3047
////////////////////////////////////////////////////////////////////////
 
3048
//                                                                    //
 
3049
// ****************************************************************** //
 
3050
//                       GUIDs TREATMENT                              //
 
3051
// ****************************************************************** //
 
3052
//                                                                    //
 
3053
////////////////////////////////////////////////////////////////////////
 
3054
#define GETGUID(s, g) do { if (!ops.getGUID(s,g)) return 1; } while (0)
 
3055
#define GETBSN(s, g)  do { if (!ops.getBSN(s,g)) return 1; } while (0)
 
3056
 
 
3057
#define BSN_RET do {                                            \
 
3058
    printf("Invalid BSN. Should be MTxxxxx[-]R[xx]ddmmyy-nnn[-cc]\n"); \
 
3059
    return false;                                               \
 
3060
} while(0)
 
3061
#define BSN_RET1(s) do {                                             \
 
3062
    printf("Valid BSN format is: MTxxxxx[-]R[xx]ddmmyy-nnn[-cc]\n%s.\n",s); \
 
3063
    return false;                                                    \
 
3064
} while(0)
 
3065
u_int32_t Operations::BSN_subfield(const char *s, int beg, int len)
 
3066
{
 
3067
    char buf[64];
 
3068
    strncpy(buf, &s[beg], len);
 
3069
    buf[len] = '\0';
 
3070
    return strtoul(&buf[0], 0, 10);
 
3071
}
 
3072
bool Operations::getBSN(char *s, guid_t *guid)
 
3073
{
 
3074
    const u_int64_t COMPANY_ID = 0x0002c9;
 
3075
    const u_int64_t  TYPE      = 1;
 
3076
    bool cc_present = false;
 
3077
    char *p;
 
3078
    int  date_offs = 0;
 
3079
    int  i;
 
3080
 
 
3081
    // Convert to lowercase
 
3082
    for (p = s; *p; p++)
 
3083
        *p = (char)tolower(*p);
 
3084
 
 
3085
    // Check validity
 
3086
    p = s;
 
3087
    if (strncmp(p, "mt", 2))     // MT
 
3088
        BSN_RET;
 
3089
    p += 2;
 
3090
    for (i=0; i<5; i++)
 
3091
        if (!isdigit(*p++))      // xxxxx
 
3092
            BSN_RET;
 
3093
    if (*p == '-') {               // - /optional/
 
3094
        p++;
 
3095
        date_offs++;
 
3096
    }
 
3097
    if (*p < 'a' || *p > 'z')    // R
 
3098
        BSN_RET;
 
3099
    p++;
 
3100
 
 
3101
    // Count how many digits after R
 
3102
    char *q = p;
 
3103
    int  ndigits=0;
 
3104
    while (isdigit(*q++))
 
3105
        ndigits++;
 
3106
 
 
3107
    switch (ndigits) {
 
3108
    case 6:
 
3109
        p += 6;                  // skip ddmmyy
 
3110
        break;
 
3111
    case 8:
 
3112
        p += 8;                  // skip xxddmmyy
 
3113
        date_offs += 2;
 
3114
        break;
 
3115
    default:
 
3116
        BSN_RET;
 
3117
    }
 
3118
 
 
3119
    if (*p++ != '-')             // -
 
3120
        BSN_RET;
 
3121
    for (i=0; i<3; i++)          // nnn
 
3122
        if (!isdigit(*p++))
 
3123
            BSN_RET;
 
3124
    if (*p) {
 
3125
        cc_present = true;
 
3126
        if (*p++ != '-')         // -
 
3127
            BSN_RET;
 
3128
        for (i=0; i<2; i++)      // cc
 
3129
            if (!isdigit(*p++))
 
3130
                BSN_RET;
 
3131
    }
 
3132
 
 
3133
    u_int32_t dd = BSN_subfield(s, 8+date_offs, 2);
 
3134
    if (dd > 31)
 
3135
        BSN_RET1("Day (dd) should not exceed 31");
 
3136
    if (!dd)
 
3137
        BSN_RET1("Day (dd) can not be zero");
 
3138
    u_int32_t mm = BSN_subfield(s, 10+date_offs, 2);
 
3139
    if (mm > 12)
 
3140
        BSN_RET1("Months (mm) should not exceed 12");
 
3141
    if (!mm)
 
3142
        BSN_RET1("Months (mm) can not be zero");
 
3143
    u_int32_t yy = BSN_subfield(s, 12+date_offs, 2);
 
3144
    if (yy > 99)
 
3145
        BSN_RET1("Year (yy) should not exceed 99");
 
3146
    if (!yy)
 
3147
        BSN_RET1("Year (yy) can not be zero");
 
3148
    u_int32_t num = BSN_subfield(s, 15+date_offs, 3);
 
3149
    if (num > 999)
 
3150
        BSN_RET1("Number (num) should not exceed 999");
 
3151
    if (!num)
 
3152
        BSN_RET1("Number (num) can not be zero");
 
3153
    int cc = 1;
 
3154
    if (cc_present) {
 
3155
        cc = BSN_subfield(s, 19+date_offs, 2);
 
3156
        if (cc > 14)
 
3157
            BSN_RET1("Chip number (cc) should not exceed 14");
 
3158
        if (!cc)
 
3159
            BSN_RET1("Chip number (cc) can not be zero");
 
3160
    }
 
3161
    u_int64_t id = ((((yy*12+mm-1)*31+ dd-1) * 1000) + num-1) * 112;
 
3162
    id += (cc-1)*8;
 
3163
 
 
3164
    u_int64_t g = (COMPANY_ID << 40) | (TYPE << 32) | id;
 
3165
    guid->h = (u_int32_t)(g>>32);
 
3166
    guid->l = (u_int32_t)g;
 
3167
    return true;
 
3168
}
 
3169
 
 
3170
bool Operations::getGUID(const char *s, guid_t *guid)
 
3171
{
 
3172
    char* endp;
 
3173
    u_int64_t g;
 
3174
 
 
3175
    g = strtoull(s, &endp, 16);
 
3176
    if (*endp || (g == 0xffffffffffffffffULL && errno == ERANGE)) {
 
3177
        printf("Invalid GUID syntax (%s) %s \n",
 
3178
               s,
 
3179
               errno ? strerror(errno) : "" );
 
3180
        return false;
 
3181
    }
 
3182
    guid->h = (u_int32_t)(g >> 32);
 
3183
    guid->l = (u_int32_t)(g & 0xffffffff);
 
3184
    return true;
 
3185
} // getGUID
 
3186
 
 
3187
////////////////////////////////////////////////////////////////////////
 
3188
bool Operations::extractGUIDptr(u_int32_t sign, u_int32_t *buf, int buf_len,
 
3189
                    char *pref, u_int32_t *ind, int *nguids)
 
3190
{
 
3191
    u_int32_t offs = 0;
 
3192
 
 
3193
    if (IsCntx()) {
 
3194
        offs = 16;
 
3195
    }
 
3196
 
 
3197
    // Check signature
 
3198
    if (sign) {
 
3199
        u_int32_t signature = buf[(sign + 8)/4];
 
3200
        TOCPU1(signature);
 
3201
        if (signature != SIGNATURE) {
 
3202
            printf("%s pointer section not valid\n", pref);
 
3203
            return false;
 
3204
        }
 
3205
        offs = buf[sign/4];
 
3206
        TOCPU1(offs);
 
3207
    }
 
3208
 
 
3209
    // Get GUID ptr
 
3210
    *ind = buf[(offs+0x24)/4];
 
3211
    TOCPU1(*ind);
 
3212
    if (!IsCntx()) {
 
3213
        *ind += offs;
 
3214
    }
 
3215
    if (*ind >= (u_int32_t)buf_len) {
 
3216
        printf("%s image - illegal GUID pointer (%08x)\n", pref, *ind);
 
3217
        return false;
 
3218
    }
 
3219
    *nguids = buf[*ind/4 - 3];
 
3220
    TOCPU1(*nguids);
 
3221
    *nguids /= 2;
 
3222
 
 
3223
    // More sanity check
 
3224
    if (IsCntx() ? (*nguids > MAX_GUIDS) : (*nguids > GUIDS)) {
 
3225
        printf("%s image - illegal number of GUIDs (0x%x)\n", pref, *nguids);
 
3226
        return false;
 
3227
    }
 
3228
 
 
3229
    return true;
 
3230
} // extractGUIDptr
 
3231
 
 
3232
 
 
3233
 
 
3234
////////////////////////////////////////////////////////////////////////
 
3235
 
 
3236
//
 
3237
// This function calculates CRC over the geven buf/size, and stores
 
3238
// the crc in the dwors after the data.
 
3239
// Caller should make sure CRC word memory is really there.
 
3240
void Operations::recalcSectionCrc(u_int8_t *buf, u_int32_t data_size) {
 
3241
    Crc16              crc;
 
3242
    u_int32_t          i;
 
3243
 
 
3244
    for (i = 0; i < data_size; i += 4) {
 
3245
        crc << __be32_to_cpu(*(u_int32_t*)(buf + i));
 
3246
    }
 
3247
    crc.finish();
 
3248
    *(u_int32_t*)(buf + data_size) = __cpu_to_be32(crc.get());
 
3249
}
 
3250
 
 
3251
////////////////////////////////////////////////////////////////////////
 
3252
void Operations::patchGUIDsSection(u_int32_t *buf, u_int32_t ind,
 
3253
                       guid_t guids[MAX_GUIDS], int nguids)
 
3254
{
 
3255
    u_int32_t       i;
 
3256
    u_int32_t       new_buf[MAX_GUIDS*2];
 
3257
 
 
3258
    // Form new GUID section
 
3259
    for (i=0; i<(u_int32_t)nguids; i++) {
 
3260
        new_buf[i*2] = guids[i].h;
 
3261
        new_buf[i*2+1] = guids[i].l;
 
3262
    }
 
3263
 
 
3264
    // Patch GUIDs
 
3265
    for (i=0; i<sizeof(new_buf)/sizeof(u_int32_t); ++i) {
 
3266
        new_buf[i] = _burn_blank_guids ? 0xffffffff : __cpu_to_be32(new_buf[i]);
 
3267
    }
 
3268
    memcpy(&buf[ind/4], &new_buf[0], nguids * 2 * sizeof(u_int32_t));
 
3269
 
 
3270
    // Insert new CRC
 
3271
    if (_burn_blank_guids) {
 
3272
        buf[ind/4 + nguids*2] =  __cpu_to_be32(0xffff);
 
3273
    } else {
 
3274
        recalcSectionCrc((u_int8_t*)buf + ind - sizeof(GPH), sizeof(GPH) + nguids * 8);
 
3275
    }
 
3276
} // patchGUIDsSection
 
3277
 
 
3278
 
 
3279
 
 
3280
 
 
3281
//
 
3282
// PatchInfoSect() :
 
3283
// This func assumes it gets a pointer (rawSect) to a valid info sect.
 
3284
// It patches the it with the given data, recalculated CRC ,
 
3285
// and copies it back to the geven data
 
3286
//
 
3287
 
 
3288
void Operations::PatchInfoSect(u_int8_t*      rawSect,
 
3289
                               u_int32_t      vsdOffs,
 
3290
                               const char*    vsd) {
 
3291
 
 
3292
    u_int32_t  vsdSize  = __be32_to_cpu(*((u_int32_t*)(rawSect + sizeof(GPH) + vsdOffs - 4))) & 0xffffff;
 
3293
    u_int32_t  infoSize = __be32_to_cpu(*((u_int32_t*)(rawSect + 4)));
 
3294
 
 
3295
    // byte size;
 
3296
    infoSize *= 4;
 
3297
 
 
3298
    //printf("-D- vsdOffs=%x, vsdSize=%x, infoSize=%x\n", vsdOffs,vsdSize, infoSize );
 
3299
    if (vsd) {
 
3300
        u_int32_t len = strlen(vsd);
 
3301
 
 
3302
        if (len > vsdSize) {
 
3303
            report("Warning: The given VSD length is too large (%d chars). Truncating to %d chars.\n", len, vsdSize);
 
3304
            len = vsdSize;
 
3305
        }
 
3306
 
 
3307
        memset(rawSect + sizeof(GPH) + vsdOffs,  0,   vsdSize );
 
3308
        memcpy(rawSect + sizeof(GPH) + vsdOffs,  vsd, len);
 
3309
    }
 
3310
 
 
3311
    recalcSectionCrc(rawSect, sizeof(GPH) + infoSize);
 
3312
}
 
3313
 
 
3314
 
 
3315
//
 
3316
// PatchPs() :
 
3317
// This func assumes it gets a pointer (rawPs) to a valid PS.
 
3318
// It patches the PS with the given data, recalculated CRC ,
 
3319
// and copies it back to the rawPs.
 
3320
//
 
3321
 
 
3322
void Operations::PatchPs(u_int8_t*      rawPs,
 
3323
                         const char*    vsd,
 
3324
                         const char*    psid,
 
3325
                         u_int32_t      imageAddr) {
 
3326
 
 
3327
    PS         *ps = (PS*)rawPs;
 
3328
 
 
3329
    u_int32_t fix_start = 0;
 
3330
    u_int32_t fix_end   = 0;
 
3331
 
 
3332
    if (vsd) {
 
3333
        u_int32_t len = strlen(vsd);
 
3334
 
 
3335
        memset(&ps->vsd[0],  0,   VSD_LEN );
 
3336
        memcpy(&ps->vsd[0],  vsd, len);
 
3337
 
 
3338
        fix_end += VSD_LEN;
 
3339
    } else {
 
3340
        fix_start +=VSD_LEN;
 
3341
    }
 
3342
    if (psid) {
 
3343
        u_int32_t len = strlen(psid);
 
3344
 
 
3345
        memset(&ps->psid[0],  0,    PSID_LEN );
 
3346
        memcpy(&ps->psid[0],  psid, len );
 
3347
        fix_end += PSID_LEN;
 
3348
    }
 
3349
 
 
3350
    //VSD is kept on flash byte-swapped.
 
3351
    //recode it back before patching
 
3352
    u_int32_t *qp;
 
3353
 
 
3354
    qp = (u_int32_t *)&ps->vsd[0];
 
3355
    for (u_int32_t i=fix_start; i<fix_end/4; i++) {
 
3356
        *qp = bswap_32(*qp);
 
3357
        qp++;
 
3358
    }
 
3359
 
 
3360
    if (imageAddr) {
 
3361
        ps->fi_addr = __cpu_to_be32(imageAddr);
 
3362
    }
 
3363
 
 
3364
    recalcSectionCrc((u_int8_t *)ps, sizeof(PS) - 4);
 
3365
}
 
3366
 
 
3367
 
 
3368
////////////////////////////////////////////////////////////////////////
 
3369
//Note that vsd1 is a string of bytes.
 
3370
bool Operations::patchVSD(FImage& f,
 
3371
                          Operations::ImageInfo* info,
 
3372
                          const char *user_vsd,
 
3373
                          const char *user_psid,
 
3374
                          const char *curr_vsd,
 
3375
                          const char *curr_psid,
 
3376
                          const char *image_psid)
 
3377
{
 
3378
    const char* vsd_to_use  = curr_vsd ? curr_vsd : "";
 
3379
    const char* psid_to_use = image_psid;
 
3380
 
 
3381
    // TODO: Should not give the user_psid param. Do not allow for on-the-fly PSID changes.
 
3382
 
 
3383
    curr_psid = NULL;
 
3384
    // Form new VSD
 
3385
 
 
3386
    if (user_psid) {
 
3387
        // New psid is explicitly given - take it from user
 
3388
        printf("\n    You are about to replace current PSID in the image file - \"%s\" with a different PSID - \"%s\".\n"
 
3389
               "    Note: It is highly recommended not to change the image PSID.\n", user_psid, image_psid);
 
3390
 
 
3391
        if (! ask_user())
 
3392
            return false;
 
3393
 
 
3394
        psid_to_use = user_psid;
 
3395
    }
 
3396
 
 
3397
    if (user_vsd) {
 
3398
        vsd_to_use = user_vsd;
 
3399
    }
 
3400
 
 
3401
    if (IsCntx() && info->infoOffs[II_VSD]) {
 
3402
        PatchInfoSect((u_int8_t*)f.getBuf() + info->infoSectPtr - sizeof(GPH),
 
3403
                      info->infoOffs[II_VSD],
 
3404
                      vsd_to_use);
 
3405
    } else {
 
3406
        PatchPs((u_int8_t*)f.getBuf() + f.get_sector_size(),     vsd_to_use, psid_to_use);
 
3407
        PatchPs((u_int8_t*)f.getBuf() + f.get_sector_size() * 2, vsd_to_use, psid_to_use);
 
3408
    }
 
3409
 
 
3410
    return true;
 
3411
} // pathVSD
 
3412
 
 
3413
 
 
3414
bool Operations::printGUIDs(const char* msg, guid_t guids[MAX_GUIDS], bool print_guids, bool print_macs, bool old_guid_fmt) {
 
3415
    const char* g_m;
 
3416
 
 
3417
    if        ( print_guids &&  print_macs) {
 
3418
        g_m = "GUIDs/MACs";
 
3419
    } else if (!print_guids &&  print_macs) {
 
3420
        g_m = "MACs";
 
3421
    } else if ( print_guids && !print_macs) {
 
3422
        g_m = "GUIDs";
 
3423
    } else {
 
3424
        return errmsg("Internal error: Operations::PrintGuids() with both guid and mac turned off");
 
3425
    }
 
3426
 
 
3427
    printf("%s %s:\n", msg, g_m);
 
3428
    if (print_guids) {
 
3429
        printf("        Node  GUID:     " GUID_FORMAT "\n", guids[0].h, guids[0].l);
 
3430
        if (_num_ports > 0)
 
3431
            printf("        Port1 GUID:     " GUID_FORMAT "\n", guids[1].h, guids[1].l);
 
3432
        if (_num_ports > 1)
 
3433
            printf("        Port2 GUID:     " GUID_FORMAT "\n", guids[2].h, guids[2].l);
 
3434
        if (!old_guid_fmt)
 
3435
            printf("        Sys.Image GUID: " GUID_FORMAT "\n", guids[3].h, guids[3].l);
 
3436
    }
 
3437
 
 
3438
    if (print_macs) {
 
3439
        printf("        Port1 MAC:      " MAC_FORMAT "\n", guids[4].h, guids[4].l);
 
3440
        printf("        Port2 MAC:      " MAC_FORMAT "\n", guids[5].h, guids[5].l);
 
3441
    }
 
3442
    return true;
 
3443
}
 
3444
 
 
3445
void Operations::SetDevFlags(u_int16_t devType, bool& ib_dev, bool& eth_dev) {
 
3446
 
 
3447
    if (IsIs4(devType)) {
 
3448
        ib_dev = true;
 
3449
        eth_dev = false;
 
3450
    } else {
 
3451
        ib_dev  = !IsCntx() || CntxIsIb(devType);
 
3452
        eth_dev = IsCntx()  && CntxIsEth(devType);
 
3453
    }
 
3454
 
 
3455
    if (!ib_dev && !eth_dev) {
 
3456
        // Unknown device id - for forward compat - assume that ConnectX is MP and
 
3457
        // prev HCAs are IB only (these flags are for printing only - no real harm can be done).
 
3458
        ib_dev = true;
 
3459
        if (IsCntx()) {
 
3460
            eth_dev = true;
 
3461
        } else {
 
3462
            eth_dev = false;
 
3463
        }
 
3464
    }
 
3465
}
 
3466
 
 
3467
bool Operations::CheckGuidsFlags (u_int16_t devType,
 
3468
                                  bool ib_dev,
 
3469
                                  bool guids_specified,
 
3470
                                  bool eth_dev,
 
3471
                                  bool macs_specified) {
 
3472
    // Patch GUIDS
 
3473
    if  (guids_specified || macs_specified) {
 
3474
        if (!IsCntx() && macs_specified) {
 
3475
            return errmsg("-mac flag is not applicable for IB MT%d device.\n",
 
3476
                          devType);
 
3477
        } else if (ib_dev  && !guids_specified) {
 
3478
            return errmsg("Use -guid(s) flag for IB MT%d device.\n",
 
3479
                          devType);
 
3480
        } else if (eth_dev && !macs_specified) {
 
3481
            return errmsg("*** ERROR *** Use -mac(s) flag for ETH MT%d device.\n",
 
3482
                   devType);
 
3483
        }
 
3484
    }
 
3485
    return true;
 
3486
}
 
3487
 
 
3488
////////////////////////////////////////////////////////////////////////
 
3489
bool Operations::patchGUIDs (FImage&   f,
 
3490
                             ImageInfo* info,
 
3491
                             bool      patch_guids,
 
3492
                             bool      patch_macs,
 
3493
                             bool      user_guids,
 
3494
                             bool      user_macs,
 
3495
                             guid_t    new_guids[MAX_GUIDS],
 
3496
                             guid_t    old_guids[MAX_GUIDS],
 
3497
                             u_int32_t num_of_old_guids,
 
3498
                             bool      interactive)
 
3499
{
 
3500
    guid_t*         used_guids = old_guids ? old_guids : new_guids;
 
3501
    u_int32_t       *buf = f.getBuf();
 
3502
    int i;
 
3503
 
 
3504
    bool old_guids_fmt = info->guidNum < GUIDS;
 
3505
 
 
3506
    // Print old GUIDs and get confirmation
 
3507
    if (new_guids) {
 
3508
        if (old_guids_fmt)
 
3509
            printf("    Old image!!!! Only %d GUIDs may be set.\n", info->guidNum);
 
3510
            // if only guids or only macs are specified by user, keep the other
 
3511
            // as currently set of flash. This is in order to simplify transitions between
 
3512
            // burning IB and ETH FW.
 
3513
 
 
3514
        if (old_guids && !user_guids) {
 
3515
            for (i = 0; i < GUIDS; i++) {
 
3516
                new_guids[i] = old_guids[i];
 
3517
            }
 
3518
        }
 
3519
 
 
3520
        if (old_guids && !user_macs) {
 
3521
            for (i = GUIDS; i < MAX_GUIDS; i++) {
 
3522
                new_guids[i] = old_guids[i];
 
3523
            }
 
3524
        }
 
3525
 
 
3526
        used_guids = new_guids;
 
3527
    }
 
3528
 
 
3529
    if (patch_macs) {
 
3530
 
 
3531
        // To ease upgrade from 4 GUIDS format to 4+2 format, or to move from IB to ETH,
 
3532
        // if macs are not
 
3533
        // explicitly set in flash, they are derived from the GUIDs according to
 
3534
        // Mellanox methodology - 48 bit MAC == 64 bit GUID without the middle 16 bits.
 
3535
 
 
3536
        if (old_guids && ((num_of_old_guids == 4) ||
 
3537
                          (num_of_old_guids == 6 &&
 
3538
                            (old_guids[GUIDS  ].h & 0xffff)     == 0xffff     &&
 
3539
                            (old_guids[GUIDS  ].l & 0xffffffff) == 0xffffffff &&
 
3540
                            (old_guids[GUIDS+1].h & 0xffff)     == 0xffff     &&
 
3541
                            (old_guids[GUIDS+1].l & 0xffffffff) == 0xffffffff))) {
 
3542
            for (i = 0 ; i < MACS; i++) {
 
3543
                u_int64_t mac  =  old_guids[i+1].h >> 8;
 
3544
                mac <<= 24;
 
3545
                mac |= (old_guids[i+1].l & 0xffffff);
 
3546
 
 
3547
                old_guids[GUIDS+i].h = u_int32_t(mac >> 32);
 
3548
                old_guids[GUIDS+i].l = u_int32_t(mac  & 0xffffffff);
 
3549
 
 
3550
                // printf("-D- Guid " GUID_FORMAT " to MAC "MAC_FORMAT"\n", old_guids[i+1].h, old_guids[i+1].l, old_guids[i+GUIDS].h,old_guids[i+GUIDS].l  );
 
3551
            }
 
3552
        }
 
3553
 
 
3554
        guid_t* macs = &used_guids[4];
 
3555
        int i;
 
3556
 
 
3557
        for (i = 0 ; i < Operations::MACS ; i++) {
 
3558
            u_int64_t mac = (((u_int64_t)macs[i].h) << 32) | macs[i].l;
 
3559
            if (!_burn_blank_guids && !CheckMac(mac)) {
 
3560
                printf("*** ERROR *** Bad mac (" MAC_FORMAT ") %s: %s. Please re-burn with a valid -mac flag value.\n",
 
3561
                       macs[i].h,
 
3562
                       macs[i].l,
 
3563
                       user_macs ? "given" : "found on flash",
 
3564
                       err());
 
3565
                return false;
 
3566
            }
 
3567
        }
 
3568
    }
 
3569
 
 
3570
    if (new_guids && old_guids) {
 
3571
        printGUIDs("    Current settings of",
 
3572
                   old_guids,
 
3573
                   patch_guids,
 
3574
                   patch_macs,
 
3575
                   old_guids_fmt);
 
3576
        printf("\n");
 
3577
    }
 
3578
 
 
3579
    if (interactive) {
 
3580
        printGUIDs("    You are about to burn the image with the following",
 
3581
                   used_guids,
 
3582
                   patch_guids,
 
3583
                   patch_macs,
 
3584
                   old_guids_fmt);
 
3585
 
 
3586
        if (!ask_user())
 
3587
            return false;
 
3588
    }
 
3589
 
 
3590
    // Path GUIDs section
 
3591
    if (info->guidPtr) {
 
3592
        patchGUIDsSection(buf, info->imgStart + info->guidPtr, used_guids, info->guidNum);
 
3593
 
 
3594
        if (info->allImgStart[1]) {
 
3595
            // For no ConnectX HCAs, patch also the secondary image (if found). This is applicable
 
3596
            // only for nofs burn, where both images are burnt as is.
 
3597
            patchGUIDsSection(buf, info->allImgStart[1] + info->guidPtr, used_guids, info->guidNum);
 
3598
        }
 
3599
    }
 
3600
 
 
3601
    return true;
 
3602
} // patchGUIDs
 
3603
 
 
3604
 
 
3605
////////////////////////////////////////////////////////////////////////
 
3606
//                                                                    //
 
3607
// ****************************************************************** //
 
3608
//                  Revision info and board ID                        //
 
3609
// ****************************************************************** //
 
3610
//                                                                    //
 
3611
////////////////////////////////////////////////////////////////////////
 
3612
 
 
3613
bool Operations::QueryIs (FBase& f,
 
3614
                          Operations::ImageInfo* info) {
 
3615
    u_int32_t signature;
 
3616
 
 
3617
    READ4(f, 0x24, &signature, "Signature");
 
3618
    TOCPU1(signature);
 
3619
    if (signature == SIGNATURE) {
 
3620
        // Full image
 
3621
        info->isFailsafe = true;
 
3622
 
 
3623
        // FW ID
 
3624
        u_int32_t fw_id;
 
3625
 
 
3626
        READ4(f, 0x10, &fw_id, "FW ID");
 
3627
        TOCPU1(fw_id);
 
3628
 
 
3629
        info->isVer   = ( fw_id >> 8) && 0xff;
 
3630
        info->devRev  = fw_id >> 24;
 
3631
 
 
3632
    } else {
 
3633
        info->isFailsafe = false;
 
3634
        info->imgStart   = 0;
 
3635
    }
 
3636
 
 
3637
    info->invSectOk = true;
 
3638
    return true;
 
3639
}
 
3640
 
 
3641
bool Operations::QueryPs (FBase& f,
 
3642
                          Operations::ImageInfo* info) {
 
3643
 
 
3644
    if (!info->isFailsafe) {
 
3645
        return errmsg("Internal Error: Tried to query PS when image is not failsafe");
 
3646
    }
 
3647
 
 
3648
    u_int32_t prim_ptr, scnd_ptr;
 
3649
    u_int32_t sectSize = f.get_sector_size();
 
3650
 
 
3651
    bool currSielent = _silent;
 
3652
    _silent = true;
 
3653
 
 
3654
    if (checkPS(f, sectSize, prim_ptr, "Primary  ")) {
 
3655
        info->allImgStart[0] = prim_ptr;
 
3656
        info->imgStart = prim_ptr;
 
3657
        info->psStart  = sectSize;
 
3658
    }
 
3659
    if (checkPS(f, sectSize * 2, scnd_ptr, "Secondary")) {
 
3660
        info->allImgStart[1] = scnd_ptr;
 
3661
        if (info->allImgStart[0] == 0) {
 
3662
            info->imgStart = scnd_ptr;
 
3663
            info->psStart  = sectSize * 2;
 
3664
        }
 
3665
    }
 
3666
 
 
3667
    if (info->allImgStart[0] == 0 && info->allImgStart[1] == 0)  {
 
3668
        return errmsg("No valid image found.");
 
3669
    }
 
3670
 
 
3671
    char       vsd[VSD_LEN+PSID_LEN+1];   // +1  => Leave a space for \0 when psid size == 16 .
 
3672
 
 
3673
    memset(vsd, 0, sizeof(vsd));
 
3674
    READBUF(f, info->psStart + 0x20, vsd, VSD_LEN+PSID_LEN , "Vendor Specific Data (Board ID)");
 
3675
    u_int32_t* vsd_dwp = (u_int32_t*)vsd;
 
3676
 
 
3677
    for (u_int32_t i=0; i < sizeof(vsd)/sizeof(u_int32_t); i++)
 
3678
         vsd_dwp[i] = bswap_32(vsd_dwp[i]);
 
3679
 
 
3680
    memcpy(info->vsd,  vsd,           VSD_LEN);
 
3681
    memcpy(info->psid, vsd + VSD_LEN, PSID_LEN);
 
3682
 
 
3683
    info->vsd [sizeof(info->vsd)  - 1] = '\0';
 
3684
    info->psid[sizeof(info->psid) - 1] = '\0';
 
3685
 
 
3686
    _silent = currSielent;
 
3687
 
 
3688
    info->psOk = true;
 
3689
 
 
3690
    return true;
 
3691
}
 
3692
 
 
3693
 
 
3694
bool Operations::QueryImage (FBase& f,
 
3695
                             Operations::ImageInfo* info) {
 
3696
 
 
3697
    u_int32_t guid_ptr, nguids;
 
3698
    guid_t guids[MAX_GUIDS];
 
3699
 
 
3700
    // FW ID
 
3701
    u_int32_t fw_id;
 
3702
    u_int32_t fw_id_offs;
 
3703
    u_int32_t im_start = info->imgStart;
 
3704
 
 
3705
    if (IsCntx()) {
 
3706
        if (info->isFailsafe && info->actuallyFailsafe) {
 
3707
            f.set_address_convertor(info->cntxLog2ChunkSize, im_start != 0);
 
3708
        } else {
 
3709
            f.set_address_convertor(0,0);
 
3710
        }
 
3711
 
 
3712
        im_start = 0; // offset is done by address convertor
 
3713
        info->magicPatternFound = true;
 
3714
        fw_id_offs = 0x20;
 
3715
    } else {
 
3716
        info->magicPatternFound = false;
 
3717
        fw_id_offs = 0x10;
 
3718
    }
 
3719
 
 
3720
    READ4(f, im_start + fw_id_offs, &fw_id, "FW ID");
 
3721
    TOCPU1(fw_id);
 
3722
 
 
3723
    info->devRev  = fw_id >> 24;
 
3724
    // Read GUIDs
 
3725
    READ4(f, im_start + fw_id_offs + 0x14 , &guid_ptr, "GUID PTR");
 
3726
    TOCPU1(guid_ptr);
 
3727
    info->guidPtr = guid_ptr;
 
3728
 
 
3729
    guid_ptr += im_start;
 
3730
    if (guid_ptr >= f.get_size()) {
 
3731
        return errmsg("Failed to read GUIDs - Illegal GUID pointer (%08x). Probably image is corrupted", guid_ptr);
 
3732
    }
 
3733
    READ4(f, guid_ptr - 3*sizeof(u_int32_t), &nguids, "Number of GUIDs");
 
3734
    TOCPU1(nguids);
 
3735
    nguids /= 2;
 
3736
    if (nguids > MAX_GUIDS) {
 
3737
        report("Failed to read GUIDs - Illegal Number of GUIDs (%d)\n", nguids);
 
3738
        return false;
 
3739
    }
 
3740
    READBUF(f, guid_ptr, guids, nguids * sizeof(u_int64_t), "GUIDS");
 
3741
    TOCPUBY64(guids);
 
3742
 
 
3743
    u_int32_t guids_crc;
 
3744
    READ4(f, guid_ptr + nguids * sizeof(u_int64_t), &guids_crc, "GUIDS CRC");
 
3745
    guids_crc = __be32_to_cpu(guids_crc);
 
3746
 
 
3747
    info->blankGuids = true;
 
3748
 
 
3749
    if ((guids_crc & 0xffff) != 0xffff ) {
 
3750
       info->blankGuids = false;
 
3751
    }
 
3752
 
 
3753
    info->guidNum = nguids;
 
3754
    for (u_int32_t i = 0 ; i < nguids ; i++) {
 
3755
        info->guids[i] = guids[i];
 
3756
        if (guids[i].h != 0xffffffff || guids[i].l != 0xffffffff) {
 
3757
            info->blankGuids = false;
 
3758
        }
 
3759
    }
 
3760
 
 
3761
    // Expansion Rom version:
 
3762
    if (_rom_sect.empty()) {
 
3763
        info->expRomFound = false;
 
3764
    } else {
 
3765
        info->expRomFound = true;
 
3766
        if (!GetExpRomVersion(info)) {
 
3767
            report("\nWarning: Failed to get ROM Version: %s\n\n", err());
 
3768
            info->expRomValidVersion = false;
 
3769
        }
 
3770
    }
 
3771
 
 
3772
    // Read Info:
 
3773
    u_int32_ba info_ptr_ba;
 
3774
    u_int32_t  info_ptr;
 
3775
    u_int32_t  info_size;
 
3776
    u_int8_t   info_ptr_cs = 0;
 
3777
    READ4(f, im_start + fw_id_offs + 0xC, &info_ptr, "INFO PTR");
 
3778
    TOCPU1(info_ptr);
 
3779
 
 
3780
    // Verify info_ptr checksum (should be 0)
 
3781
    info_ptr_ba = info_ptr;
 
3782
    for (u_int32_t i = 0; i < 4 ; i++) {
 
3783
        info_ptr_cs += (u_int8_t)info_ptr_ba.range(i*8+7, i*8);
 
3784
    }
 
3785
 
 
3786
    if (info_ptr_cs) {
 
3787
        return errmsg("Failed to read Info Section - Bad checksum for Info section pointer (%08x). Probably the image is corrupted.", info_ptr);
 
3788
    }
 
3789
 
 
3790
    info_ptr = info_ptr_ba.range(23,0);
 
3791
    if (info_ptr_cs == 0 && info_ptr != 0) {
 
3792
        info->infoSectPtr = info_ptr;
 
3793
 
 
3794
        info_ptr += im_start;
 
3795
        if (info_ptr >= f.get_size()) {
 
3796
            return errmsg("Failed to read Info Section - Info section pointer (%08x) too large. Probably the image is corrupted.", info_ptr);
 
3797
        }
 
3798
        READ4(f, info_ptr - 3*sizeof(u_int32_t), &info_size, "Info section size");
 
3799
        TOCPU1(info_size);
 
3800
 
 
3801
        // byte size;
 
3802
        info_size *= 4;
 
3803
 
 
3804
        u_int8_t* info_buff = (u_int8_t*)alloca(info_size);
 
3805
        READBUF(f, info_ptr, info_buff, info_size, "Info Section");
 
3806
 
 
3807
        if (!ParseInfoSect(info_buff, info_size,  info)) {
 
3808
            return false;
 
3809
        }
 
3810
    }
 
3811
 
 
3812
    info->imageOk = true;
 
3813
    return true;
 
3814
}
 
3815
 
 
3816
 
 
3817
bool Operations::ParseInfoSect(u_int8_t* buff, u_int32_t byteSize, Operations::ImageInfo *info) {
 
3818
 
 
3819
    u_int32_t *p = (u_int32_t*)buff;
 
3820
    u_int32_t offs = 0;
 
3821
    u_int32_t tagNum = 0;
 
3822
    bool endFound = false;
 
3823
 
 
3824
    while (!endFound && offs < byteSize) {
 
3825
        u_int32_t tagSize = __be32_to_cpu(*p) & 0xffffff;
 
3826
        u_int32_t tagId   = __be32_to_cpu(*p) >> 24;
 
3827
 
 
3828
        if (offs + tagSize > byteSize) {
 
3829
            return errmsg("Info section corrupted: Tag %d (TagId %d, size %d) exceeds Info section size (%d bytes) ",
 
3830
                          tagNum, tagId, tagSize, byteSize);
 
3831
        }
 
3832
 
 
3833
        u_int32_t   tmp;
 
3834
        const char* str;
 
3835
 
 
3836
        switch (tagId) {
 
3837
        case II_FwVersion:
 
3838
            info->fwVer[0] = u_int16_t(__be32_to_cpu(*(p+1)) >> 16);
 
3839
            tmp = __be32_to_cpu(*(p+2));
 
3840
            info->fwVer[1] = tmp >> 16;
 
3841
            info->fwVer[2] = tmp & 0xffff;
 
3842
            break;
 
3843
 
 
3844
        case II_DeviceType:
 
3845
            tmp = __be32_to_cpu(*(p+1));
 
3846
            info->devType = tmp & 0xffff;
 
3847
            //info->devRev  = (tmp >> 16) & 0xff;
 
3848
            break;
 
3849
 
 
3850
        case II_VsdVendorId:
 
3851
            tmp = __be32_to_cpu(*(p+1));
 
3852
            info->vsdVendorId = tmp & 0xffff;
 
3853
            break;
 
3854
 
 
3855
        case II_IsGa:
 
3856
            tmp = __be32_to_cpu(*(p+1));
 
3857
            info->isGa = tmp ? true : false;;
 
3858
            break;
 
3859
 
 
3860
        case II_PSID:
 
3861
            // set psid only if not previosly found in PS
 
3862
            if (!info->psOk) {
 
3863
                str = (const char*)p;
 
3864
                str += 4;
 
3865
 
 
3866
                for (int i = 0 ; i < PSID_LEN ; i++) {
 
3867
                    info->psid[i] = str[i];
 
3868
                }
 
3869
                info->psid[PSID_LEN] = '\0';
 
3870
            }
 
3871
            break;
 
3872
 
 
3873
        case II_VSD:
 
3874
            // set psid only if not previosly found in PS
 
3875
            if (!info->psOk) {
 
3876
                str = (const char*)p;
 
3877
                str += 4;
 
3878
 
 
3879
                for (int i = 0 ; i < VSD_LEN ; i++) {
 
3880
                    info->vsd[i] = str[i];
 
3881
                }
 
3882
                info->vsd[VSD_LEN] = '\0';
 
3883
            }
 
3884
            break;
 
3885
 
 
3886
        case II_ProductVer:
 
3887
 
 
3888
            str = (const char*)p;
 
3889
            str += 4;
 
3890
 
 
3891
            for (int i = 0 ; i < PRODUCT_VER_LEN ; i++) {
 
3892
                info->productVer[i] = str[i];
 
3893
            }
 
3894
            info->productVer[PRODUCT_VER_LEN] = '\0';
 
3895
            break;
 
3896
 
 
3897
        case II_End:
 
3898
            endFound = true;
 
3899
            break;
 
3900
 
 
3901
        //default:
 
3902
            //printf("-D- Found tag ID %d of size %d - ignoring.\n", tagId, tagSize);
 
3903
        }
 
3904
 
 
3905
        if (tagId < II_Last) {
 
3906
            info->infoOffs[tagId] = offs + 4;
 
3907
        }
 
3908
 
 
3909
        p    += tagSize/4 + 1;
 
3910
        offs += tagSize + 4;
 
3911
        tagNum++;
 
3912
    }
 
3913
 
 
3914
    if (offs != byteSize) {
 
3915
        if (endFound) {
 
3916
            return errmsg("Info section corrupted: Section data size is %x bytes, "
 
3917
                          "but end tag found after %x bytes.", byteSize, offs);
 
3918
        } else {
 
3919
            return errmsg("Info section corrupted: Section data size is %x bytes, "
 
3920
                          "but end tag not found before section end.", byteSize);
 
3921
        }
 
3922
    }
 
3923
 
 
3924
    return true;
 
3925
}
 
3926
 
 
3927
bool Operations::DisplayExpRomInfo(Operations::ImageInfo* info) {
 
3928
    report("Rom Info:        ");
 
3929
    if (info->expRomValidVersion) {
 
3930
        report("type=");
 
3931
        switch (info->expRomProductId) {
 
3932
        case 1   : report("CLP1 "); break;
 
3933
        case 2   : report("CLP2 "); break;
 
3934
        case 0x10: report("GPXE "); break;
 
3935
        default:   report("0x%x ", info->expRomProductId);
 
3936
        }
 
3937
 
 
3938
        report("version=%d", info->expRomVer[0]);
 
3939
 
 
3940
        if (info->expRomProductId >= 0x10) {
 
3941
            report(".%d.%d devid=%d",
 
3942
                   info->expRomVer[1],
 
3943
                   info->expRomVer[2],
 
3944
                   info->expRomDevId);
 
3945
 
 
3946
            if (info->expRomPort) {
 
3947
                // Do not display if 0 - port independant
 
3948
                report(" port=%d", info->expRomPort);
 
3949
            }
 
3950
        }
 
3951
        report("\n");
 
3952
    } else {
 
3953
        report("N/A\n");
 
3954
    }
 
3955
    return true;
 
3956
}
 
3957
 
 
3958
bool Operations::DisplayImageInfo(Operations::ImageInfo* info) {
 
3959
    report("Image type:      %s\n", info->magicPatternFound ? (CntxIsEth(info->devType) ? "ConnectX" : "FS2") :
 
3960
                                    info->isFailsafe        ? "Failsafe" :
 
3961
                                                              "Short");
 
3962
 
 
3963
    if (info->infoOffs[II_FwVersion]) {
 
3964
        report("FW Version:      %d.%d.%d\n", info->fwVer[0], info->fwVer[1], info->fwVer[2]);
 
3965
    }
 
3966
 
 
3967
    if (info->infoOffs[II_ProductVer] && strlen(info->productVer)) {
 
3968
        report("Product Version: %s\n", info->productVer);
 
3969
    }
 
3970
 
 
3971
    if (info->expRomFound) {
 
3972
        DisplayExpRomInfo(info);
 
3973
    }
 
3974
 
 
3975
    if (info->isFailsafe && !IsCntx()) {
 
3976
        report("I.S. Version:    %d\n", info->isVer );
 
3977
    }
 
3978
 
 
3979
    if (info->infoOffs[II_DeviceType]) {
 
3980
        report("Device ID:       %d\n", info->devType);
 
3981
        if (info->devType == 25204 || info->devType == 24204) {
 
3982
            _num_ports = 1;
 
3983
        } else if (IsIs4(info->devType)) {
 
3984
            _num_ports = 0;
 
3985
        }
 
3986
    }
 
3987
 
 
3988
    report("Chip Revision:   %X\n", info->devRev);
 
3989
 
 
3990
    // GUIDS:
 
3991
    // TODO: Handle case where devtype not found.
 
3992
    bool ib_dev;
 
3993
    bool eth_dev;
 
3994
    SetDevFlags(info->devType, ib_dev, eth_dev);
 
3995
 
 
3996
    const char* mac_indent = "";
 
3997
    if (ib_dev) {
 
3998
        //report("GUID Des:        Node             Port1            ");
 
3999
        report("Description:     Node             ");
 
4000
        if (_num_ports > 0)
 
4001
            report("Port1            ");
 
4002
        if (_num_ports > 1)
 
4003
            report("Port2            ");
 
4004
        report( "Sys image\n");
 
4005
 
 
4006
        report("GUIDs:           ");
 
4007
        for (u_int32_t i=0; i < GUIDS; i++) {
 
4008
            if ((i == 1 && _num_ports < 1) ||
 
4009
                (i == 2 && _num_ports < 2)) {
 
4010
                continue;
 
4011
            }
 
4012
            report(GUID_FORMAT " ", info->guids[i].h, info->guids[i].l);
 
4013
        }
 
4014
        mac_indent = "                 ";
 
4015
    }
 
4016
 
 
4017
    // MACS:
 
4018
    if (eth_dev) {
 
4019
        if (info->guidNum == MAX_GUIDS) {
 
4020
            if (!ib_dev)
 
4021
                report("Description:%s     Port1            Port2\n", mac_indent);
 
4022
            else
 
4023
                printf("\n");
 
4024
 
 
4025
            report("MACs:    %s        ", mac_indent);
 
4026
            for (u_int32_t i=GUIDS; i < MAX_GUIDS; i++) {
 
4027
                report(MAC_FORMAT "     ", info->guids[i].h, info->guids[i].l);
 
4028
            }
 
4029
 
 
4030
            for (u_int32_t i=GUIDS; i < MAX_GUIDS; i++) {
 
4031
                u_int64_t mac = (((u_int64_t)info->guids[i].h) << 32) | info->guids[GUIDS + i].l;
 
4032
                if (!info->blankGuids && !CheckMac(mac)) {
 
4033
                    if (i==GUIDS) printf("\n\n");
 
4034
                    printf("Warning: Bad mac address (" MAC_FORMAT "): %s\n", info->guids[i].h, info->guids[i].l, err());
 
4035
                }
 
4036
            }
 
4037
        } else {
 
4038
            printf("\nWarning: Can not get MAC addrerss: Expecting %d entries in guid section, got %d. Probably an old FW image. Please update.\n",
 
4039
                   MAX_GUIDS,
 
4040
                   info->guidNum);
 
4041
        }
 
4042
    }
 
4043
 
 
4044
    // VSD, PSID
 
4045
    if (!info->infoOffs[II_VsdVendorId] || info->vsdVendorId == MELLANOX_VENDOR_ID) {
 
4046
        report("\nBoard ID:        %s", info->vsd);
 
4047
        if (info->psid[0])
 
4048
            report(" (%s)\n", info->psid);
 
4049
        else
 
4050
            report("\n");
 
4051
 
 
4052
        report("VSD:             %s\n", info->vsd);
 
4053
        report("PSID:            %s\n", info->psid);
 
4054
    } else {
 
4055
        report("\n\nWarning: Not a Mellanox FW image (vendor_id = 0x%04x). VSD and PSID are not displayed.\n\n", info->vsdVendorId);
 
4056
    }
 
4057
 
 
4058
    if (info->infoOffs[II_IsGa]) {
 
4059
        if (!info->isGa) {
 
4060
            report("BOARD GA:        no\n");
 
4061
        }
 
4062
    }
 
4063
 
 
4064
    if (info->blankGuids) {
 
4065
        report("\nWarning: GUIDs%s values and their CRC are not set.\n",
 
4066
               IsCntx() ? "/MACs" : "");
 
4067
    }
 
4068
    return true;
 
4069
}
 
4070
 
 
4071
////////////////////////////////////////////////////////////////////////
 
4072
//                                                                    //
 
4073
// ****************************************************************** //
 
4074
//                           MAIN                                     //
 
4075
// ****************************************************************** //
 
4076
//                                                                    //
 
4077
////////////////////////////////////////////////////////////////////////
 
4078
// sed -e 's/"/\\"/g' < flint.txt | perl -pe 's/^(.*)$/"$1\\n"/'
 
4079
void usage(const char *sname, bool full = false)
 
4080
{
 
4081
    const char *descr =
 
4082
    "\n"
 
4083
    "               FLINT - FLash INTerface\n"
 
4084
    "\n"
 
4085
    "FW (firmware) burning and flash memory operations tool for\n"
 
4086
    "Mellanox Infiniband HCAs and Ethernet NIC cards.\n"
 
4087
    "\n"
 
4088
    "Usage:\n"
 
4089
    "------\n"
 
4090
    "\n"
 
4091
    "    " FLINT_NAME " [switches...] <command> [parameters...]\n"
 
4092
    "\n"
 
4093
    "\n"
 
4094
    "Switches summary:\n"
 
4095
    "-----------------\n"
 
4096
//    "    -bsn <BSN>         - Mellanox Board Serial Number (BSN).\n"
 
4097
//    "                         Valid BSN format is:\n"
 
4098
//    "                                 MTxxxxx[-]R[xx]ddmmyy-nnn[-cc]\n"
 
4099
//    "                         Commands affected: burn\n"
 
4100
//    "\n"
 
4101
//    "    -crc               - Print out each section CRC.\n"
 
4102
//    "                         Commands affected: verify\n"
 
4103
    "\n"
 
4104
    "    -d[evice] <device> - Device flash is connected to.\n"
 
4105
    "                         Commands affected: all\n"
 
4106
    "\n"
 
4107
    "    -guid <GUID>       - GUID base value. 4 GUIDs\n"
 
4108
    "                         are automatically assigned to the\n"
 
4109
    "                         following values:\n"
 
4110
    "\n"
 
4111
    "                         guid   -> node GUID\n"
 
4112
    "                         guid+1 -> port1\n"
 
4113
    "                         guid+2 -> port2\n"
 
4114
    "                         guid+3 -> system image GUID.\n"
 
4115
    "\n"
 
4116
    "                         Note: port2 guid will be assigned even for a"
 
4117
    "                         single port HCA - The HCA ignores this value.\n"
 
4118
    "\n"
 
4119
    "                         Commands affected: burn, sg\n"
 
4120
    "\n"
 
4121
    "    -guids <GUIDs...>  - 4 GUIDs must be specified here.\n"
 
4122
    "                         The specified GUIDs are assigned\n"
 
4123
    "                         the following values, repectively:\n"
 
4124
    "                         node, port1, port2 and system image GUID.\n"
 
4125
    "\n"
 
4126
    "                         Note: port2 guid must be specified even for a\n"
 
4127
    "                         single port HCA - The HCA ignores this value.\n"
 
4128
    "                         It can be set to 0x0.\n"
 
4129
    "\n"
 
4130
    "                         Commands affected: burn, sg\n"
 
4131
    "\n"
 
4132
    "    -mac <MAC>         - MAC address base value. 2 MACs\n"
 
4133
    "                         are automatically assigned to the\n"
 
4134
    "                         following values:\n"
 
4135
    "\n"
 
4136
    "                         mac    -> port1\n"
 
4137
    "                         mac+1  -> port2\n"
 
4138
    "\n"
 
4139
    "                         Commands affected: burn, sg\n"
 
4140
    "\n"
 
4141
    "    -macs <MACs...>    - 2 MACs must be specified here.\n"
 
4142
    "                         The specified MACs are assigned\n"
 
4143
    "                         to port1, port2, repectively.\n"
 
4144
    "\n"
 
4145
    "                         Commands affected: burn, sg\n"
 
4146
    "                         Note: -mac/-macs flags are applicable only for Mellanox\n"
 
4147
    "                               Technologies ethernet products.\n"
 
4148
    "\n"
 
4149
    "    -blank_guids       - Burn the image with blank GUIDs and MACs (where\n"
 
4150
    "                         applicable). These values can be set later using\n"
 
4151
    "                         the \"sg\" command (see details below).\n"
 
4152
    "\n"
 
4153
    "                         Commands affected: burn\n"
 
4154
    "\n"
 
4155
    "    -clear_semaphore   - Force clear the flash semaphore on the device.\n"
 
4156
    "                         No command is allowed when this flag is used.\n"
 
4157
    "                         NOTE: May result in system instability or flash\n"
 
4158
    "                               corruption if the device or another\n"
 
4159
    "                               application is currently using the flash.\n"
 
4160
    "                               Exercise caution.\n"
 
4161
    "\n"
 
4162
    "    -h[elp]            - Prints this message and exits\n"
 
4163
    "    -hh                - Prints extended command help\n"
 
4164
    "\n"
 
4165
    "    -i[mage] <image>   - Binary image file.\n"
 
4166
    "                         Commands affected: burn, verify\n"
 
4167
    "\n"
 
4168
    "    -qq                - Run a quick query. When specified, flint will not perform full\n"
 
4169
    "                         image integrity checks during the query operation. This may shorten\n"
 
4170
    "                         execution time when running over slow interfaces (e.g., I2C, MTUSB-1).\n"
 
4171
    "                         Commands affected: burn, query\n"
 
4172
    "\n"
 
4173
    "    -nofs              - Burn image in a non failsafe manner.\n"
 
4174
    "\n"
 
4175
    "    -skip_is           - Allow burning the FW image without updating the invariant sector,\n"
 
4176
    "                         to ensure failsafe burning even when an invariant sector difference is detected.\n"
 
4177
    "                         See the specific FW release notes for more details.\n"
 
4178
    "\n"
 
4179
    "    -byte_mode         - Shift address when accessing flash internal registers. May\n"
 
4180
    "                         be required for burn/write commands when accessing certain\n"
 
4181
    "                         flash types.\n"
 
4182
    "\n"
 
4183
#if 0
 
4184
    "    -unlock            - Use unlock bypass feature of the flash for quicker burn.\n"
 
4185
    "                         Commands affected: burn\n"
 
4186
    "\n"
 
4187
#endif
 
4188
    "    -s[ilent]          - Do not print burn progress flyer.\n"
 
4189
    "                         Commands affected: burn\n"
 
4190
    "\n"
 
4191
    "    -y[es]             - Non interactive mode - assume answer\n"
 
4192
    "                         \"yes\" to all questions.\n"
 
4193
    "                         Commands affected: all\n"
 
4194
    "\n"
 
4195
    "    -no                - Non interactive mode - assume answer\n"
 
4196
    "                         \"no\" to all questions.\n"
 
4197
    "                         Commands affected: all\n"
 
4198
    "\n"
 
4199
    "    -vsd  <string>     - Write this string, of up to 208 characters, to VSD when burn.\n"
 
4200
    "\n"
 
4201
    "    -use_image_ps      - Burn vsd as appears in the given image - do not keep existing VSD on flash.\n"
 
4202
    "                         Commands affected: burn\n"
 
4203
    "\n"
 
4204
    "    -dual_image        - Make the burn process burn two images on flash (previously default algorithm). Current\n"
 
4205
    "                         default failsafe burn process burns a single image (in alternating locations).\n"
 
4206
    "                         Commands affected: burn\n"
 
4207
    "\n"
 
4208
    "    -v                 - Version info.\n"
 
4209
    "\n"
 
4210
    "Commands summary (use -hh flag for full commands description):\n"
 
4211
    "-----------------\n"
 
4212
    "  b[urn]              - Burn flash\n"
 
4213
    "  q[uery]             - Query misc. flash/firmware characteristics\n"
 
4214
    "  v[erify]            - Verify entire flash\n"
 
4215
    "  bb                  - Burn Block - Burns the given image as is. \n"
 
4216
    "                        No checks are done.\n"
 
4217
    "  sg                  - Set Guids\n"
 
4218
    "  ri       <out-file> - Read the fw image on the flash.\n"
 
4219
    "  dc       [out-file] - Dump Configuration: print fw configuration file\n"
 
4220
    "                        for the given image.\n"
 
4221
    "  e[rase]  <addr>     - Erase sector\n"
 
4222
    "  rw       <addr>     - Read one dword from flash\n"
 
4223
    "  ww       <addr> < data> \n"
 
4224
    "                      - Write one dword to flash\n"
 
4225
    "  wwne     <addr>     - Write one dword to flash without sector erase\n"
 
4226
    "  wbne     <addr> <size> <data ...> \n"
 
4227
    "                      - Write a data block to flash without sector erase\n"
 
4228
    "  rb       <addr> <size> [out-file]\n"
 
4229
    "                      - Read  a data block from flash\n"
 
4230
    "  swreset             - SW reset the target InfniScale IV device. This command\n"
 
4231
    "                        is supported only in the In-Band access method.\n"
 
4232
    "\n"
 
4233
    "  Return values:\n"
 
4234
    "  0 - Successful completion\n"
 
4235
    "  1 - An error has occurred\n"
 
4236
    "  7 - For burn command - FW already updated - burn was aborted.\n"
 
4237
    "\n";
 
4238
 
 
4239
    const char* full_descr =
 
4240
    "\n"
 
4241
    "Command descriptions:\n"
 
4242
    "----------------------------\n"
 
4243
    "\n"
 
4244
    "* Burn flash\n"
 
4245
    "  Burns entire flash from raw binary image.\n"
 
4246
    "\n"
 
4247
    "    Command:\n"
 
4248
    "        b[urn]\n"
 
4249
    "    Parameters:\n"
 
4250
    "        None\n"
 
4251
    "    Examples:\n"
 
4252
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " -i image1.bin burn\n"
 
4253
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE2 " -guid 0x2c9000100d050 -i image1.bin b\n"
 
4254
    "\n"
 
4255
    "\n"
 
4256
    "* Burn Block\n"
 
4257
    "  Burns entire flash from raw binary image as is. No checks are done on the flash or\n"
 
4258
    "  on the given image file. No fields (such as VSD or Guids) are read from flash. \n"
 
4259
    "\n"
 
4260
    "    Command:\n"
 
4261
    "        bb\n"
 
4262
    "    Parameters:\n"
 
4263
    "        None\n"
 
4264
    "    Examples:\n"
 
4265
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " -i image1.bin bb\n"
 
4266
    "\n"
 
4267
    "\n"
 
4268
    "* sg\n"
 
4269
    "  Set GUIDs/MACs in the given device.\n"
 
4270
    "  Use -guid(s) and -mac(s) flags to set the desired values.\n"
 
4271
    "  This command is applicable only for images with blank (0xff)\n"
 
4272
    "  GUIDs/MACs values and crc, I.E., that were burnt or generated\n"
 
4273
    "  using -blank_guids flag.\n"
 
4274
    "  The sg command  is used in production to apply GUIDs/MACs values\n"
 
4275
    "  to cards that were pre-burnt with blank guids. It is not meant for\n"
 
4276
    "  use in field\n"
 
4277
    "\n"
 
4278
    "    Command:\n"
 
4279
    "        sg\n"
 
4280
 
 
4281
    "    Parameters:\n"
 
4282
    "        None\n"
 
4283
    "    Examples:\n"
 
4284
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " -guid 0x0002c9000100d050 sg\n"
 
4285
    "\n"
 
4286
    "\n"
 
4287
    "* Erase sector.\n"
 
4288
    "  Erases a sector that contains specified address.\n"
 
4289
    "\n"
 
4290
    "    Command:\n"
 
4291
    "        e[rase]\n"
 
4292
    "    Parameters:\n"
 
4293
    "        addr - address of word in sector that you want\n"
 
4294
    "                   to erase.\n"
 
4295
    "    Example:\n"
 
4296
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " erase 0x10000\n"
 
4297
    "\n"
 
4298
    "\n"
 
4299
    "* Query miscellaneous FW and flash parameters\n"
 
4300
    "\n"
 
4301
    "    Command:\n"
 
4302
    "        q[uery]\n"
 
4303
    "    Parameters:\n"
 
4304
    "        None\n"
 
4305
    "    Example:\n"
 
4306
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " query\n"
 
4307
    "\n"
 
4308
    "\n"
 
4309
    "* Query flash device parameters (Common Flash Interface)\n"
 
4310
    "\n"
 
4311
    "    Command:\n"
 
4312
    "        cfi\n"
 
4313
    "    Parameters:\n"
 
4314
    "        None\n"
 
4315
    "    Example:\n"
 
4316
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " cfi\n"
 
4317
    "\n"
 
4318
    "\n"
 
4319
    "* Read one dword from flash.\n"
 
4320
    "\n"
 
4321
    "    Command:\n"
 
4322
    "        rw\n"
 
4323
    "    Parameters:\n"
 
4324
    "        addr - address of word to read\n"
 
4325
    "    Example:\n"
 
4326
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rw 0x20\n"
 
4327
    "\n"
 
4328
    "\n"
 
4329
    "* Verify entire flash.\n"
 
4330
    "\n"
 
4331
    "    Command:\n"
 
4332
    "        v[erify]\n"
 
4333
    "    Parameters:\n"
 
4334
    "        None\n"
 
4335
    "    Example:\n"
 
4336
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " v\n"
 
4337
    "\n"
 
4338
    "\n"
 
4339
    "* Write one dword to flash.\n"
 
4340
    "  Note that the utility will read an entire flash sector,\n"
 
4341
    "  modify one word and write the sector back. This may take\n"
 
4342
    "  a few seconds.\n"
 
4343
    "\n"
 
4344
    "    Command:\n"
 
4345
    "        ww\n"
 
4346
    "    Parameters:\n"
 
4347
    "        addr - address of word\n"
 
4348
    "        data - value of word\n"
 
4349
    "    Example:\n"
 
4350
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " ww 0x10008 0x5a445a44\n"
 
4351
    "\n"
 
4352
    "\n"
 
4353
    "* Write one dword to flash without sector erase.\n"
 
4354
    "  Note that the result of operation is undefined and depends\n"
 
4355
    "  on flash type. Usually \"bitwise AND\" (&) between specified\n"
 
4356
    "  word and previous flash contents will be written to\n"
 
4357
    "  specified address.\n"
 
4358
    "\n"
 
4359
    "    Command:\n"
 
4360
    "        wwne\n"
 
4361
    "    Parameters:\n"
 
4362
    "        addr - address of word\n"
 
4363
    "        data - value of word\n"
 
4364
    "    Example:\n"
 
4365
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " wwne 0x10008 0x5a445a44\n"
 
4366
    "\n"
 
4367
    "* Read a data block from the flash and write it to a file or to screen.\n"
 
4368
    "\n"
 
4369
    "    Command:\n"
 
4370
    "        rb\n"
 
4371
    "    Parameters:\n"
 
4372
    "        addr - address of block\n"
 
4373
    "        size - size of data to read in bytes\n"
 
4374
    "        file - filename to write the block (raw binary). If not given, the data\n"
 
4375
    "               is printed to screen\n"
 
4376
    "    Example:\n"
 
4377
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rb 0x10000 100 file.bin\n"
 
4378
    "\n"
 
4379
    "* Read the FW image from flash and write it to a file.\n"
 
4380
    "\n"
 
4381
    "    Command:\n"
 
4382
    "        ri\n"
 
4383
    "    Parameters:\n"
 
4384
    "        file - filename to write the image to (raw binary).\n"
 
4385
    "    Example:\n"
 
4386
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " ri file.bin\n"
 
4387
    "\n"
 
4388
    "* Write a block of data to the flash without erasing.\n"
 
4389
    "\n"
 
4390
    "    Command:\n"
 
4391
    "        wbne\n"
 
4392
    "    Parameters:\n"
 
4393
    "        addr - address of block\n"
 
4394
    "        size - size of data to write in bytes\n"
 
4395
    "        data - data to write - space seperated dwords\n"
 
4396
    "    Example:\n"
 
4397
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " wbne 0x10000 12 0x30000 0x76800 0x5a445a44\n"
 
4398
    "\n"
 
4399
    "* Print (to screen or to a file) the FW configuration text file used by the image generation process.\n"
 
4400
    "  This command would fail if the image does not contain a FW configuration section. Existence of this\n"
 
4401
    "  section depends on the version of the image generation tool.\n"
 
4402
    "\n"
 
4403
    "    Command:\n"
 
4404
    "        dc\n"
 
4405
    "    Parameters:\n"
 
4406
    "        file - (optional) filename to write the dumped configuration to. If not given, the data\n"
 
4407
    "               is printed to screen\n"
 
4408
    "    Example:\n"
 
4409
    "        " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " dc\n"
 
4410
    "\n";
 
4411
 
 
4412
    printf(descr, sname);
 
4413
 
 
4414
    if (full) {
 
4415
        printf(full_descr, sname);
 
4416
    }
 
4417
}
 
4418
 
 
4419
 
 
4420
//
 
4421
// Signal handlers
 
4422
//
 
4423
 
 
4424
Flash* g_flash = NULL;
 
4425
 
 
4426
#ifdef _WIN32
 
4427
HANDLE g_hMainTread = GetCurrentThread();
 
4428
#endif
 
4429
 
 
4430
 
 
4431
 
 
4432
int g_signals_for_termination[] = {
 
4433
    SIGINT,
 
4434
#ifndef _WIN32
 
4435
    SIGHUP,
 
4436
#endif
 
4437
    SIGTERM
 
4438
};
 
4439
 
 
4440
 
 
4441
 
 
4442
void TerminationHandler (int signum)
 
4443
{
 
4444
    static volatile sig_atomic_t fatal_error_in_progress = 0;
 
4445
 
 
4446
#ifdef _WIN32
 
4447
    if (signum == 0) {
 
4448
 
 
4449
        report ("\nWarning: Got SIGINT. Raising SIGTERM\n");
 
4450
        raise(SIGTERM);
 
4451
        return;
 
4452
    }
 
4453
 
 
4454
    report ("\nWarning: This program can not be interrupted.Please wait for its termination.\n");
 
4455
    signal(signum, TerminationHandler);
 
4456
    return;
 
4457
#endif
 
4458
 
 
4459
 
 
4460
    if (fatal_error_in_progress)
 
4461
        raise (signum);
 
4462
    fatal_error_in_progress = 1;
 
4463
 
 
4464
    signal (signum, SIG_DFL);
 
4465
 
 
4466
    if (g_flash != NULL) {
 
4467
        report("\n Received signal %d. Cleaning up ...", signum);
 
4468
        fflush(stdout);
 
4469
        sleep(1); // let erase sector end
 
4470
        //g_flash->wait_ready("Process termination");
 
4471
 
 
4472
        g_flash->close();
 
4473
        report(" Done.\n");
 
4474
    }
 
4475
    raise(signum);
 
4476
}
 
4477
 
 
4478
//
 
4479
// Commands database and parsing methods
 
4480
//
 
4481
enum CommandInput {
 
4482
    CI_NONE         = 0x01,
 
4483
    CI_IMG_ONLY     = 0x02,
 
4484
    CI_DEV_ONLY     = 0x04,
 
4485
    CI_IMG_OR_DEV   = 0x06,
 
4486
    CI_IMG_AND_DEV  = 0x08
 
4487
};
 
4488
 
 
4489
enum CommandType {
 
4490
    CMD_UNKNOWN,
 
4491
    CMD_BURN,
 
4492
    CMD_SET_GUIDS,
 
4493
    CMD_BURN_BLOCK,
 
4494
    CMD_QUERY,
 
4495
    CMD_QUERY_ROM,
 
4496
    CMD_QUERY_FORCE,
 
4497
    CMD_VERIFY,
 
4498
    CMD_READ_WORD,
 
4499
    CMD_READ_BLOCK,
 
4500
    CMD_WRITE_WORD,
 
4501
    CMD_WRITE_WORD_NE,
 
4502
    CMD_WRITE_BLOCK,
 
4503
    CMD_WRITE_BLOCK_NE,
 
4504
    CMD_ERASE_SECT,
 
4505
    CMD_DUMP_CONF,
 
4506
    CMD_READ_IMAGE,
 
4507
    CMD_CFI,
 
4508
    CMD_CLEAR_SEM,
 
4509
    CMD_SWRESET
 
4510
};
 
4511
 
 
4512
struct CommandInfo {
 
4513
    CommandType  cmd;
 
4514
    const char*  cmdName;
 
4515
    bool         requireExactMatch;
 
4516
    int          maxArgs;
 
4517
    CommandInput requiredInput;
 
4518
    const char*  cmdDescription;
 
4519
 
 
4520
};
 
4521
 
 
4522
CommandInfo const g_commands[] = {
 
4523
    { CMD_BURN           , "burn"  ,false , 0 , CI_IMG_AND_DEV , ""},
 
4524
    { CMD_BURN_BLOCK     , "bb"    ,true  , 0 , CI_IMG_AND_DEV , ""},
 
4525
    { CMD_SET_GUIDS      , "sg"    ,true  , 0 , CI_DEV_ONLY    , ""},
 
4526
    { CMD_QUERY_FORCE    , "qf"    ,true  , 0 , CI_IMG_OR_DEV  , ""},
 
4527
    { CMD_QUERY          , "query" ,false , 0 , CI_IMG_OR_DEV  , ""},
 
4528
    { CMD_QUERY_ROM      , "qrom"  ,true  , 0 , CI_IMG_ONLY    , ""},
 
4529
    { CMD_VERIFY         , "verify",false , 0 , CI_IMG_OR_DEV  , ""},
 
4530
    { CMD_READ_WORD      , "rw"    ,true  , 1 , CI_DEV_ONLY    , ""},
 
4531
    { CMD_READ_BLOCK     , "rb"    ,true  , 3 , CI_IMG_OR_DEV  , ""},
 
4532
    { CMD_WRITE_WORD     , "ww"    ,true  , 2 , CI_DEV_ONLY    , ""},
 
4533
    { CMD_WRITE_WORD_NE  , "wwne"  ,true  , 2 , CI_DEV_ONLY    , ""},
 
4534
    { CMD_WRITE_BLOCK    , "wb"    ,true  , 2 , CI_DEV_ONLY    , ""},
 
4535
    { CMD_WRITE_BLOCK_NE , "wbne"  ,true  ,-1 , CI_DEV_ONLY    , ""},
 
4536
    { CMD_ERASE_SECT     , "erase" ,false , 1 , CI_DEV_ONLY    , ""},
 
4537
    { CMD_DUMP_CONF      , "dc"    ,true  , 1 , CI_IMG_OR_DEV  , ""},
 
4538
    { CMD_READ_IMAGE     , "ri"    ,true  , 1 , CI_DEV_ONLY    , ""},
 
4539
    { CMD_CLEAR_SEM      , "clear_semaphore"    ,true  , 0 , CI_DEV_ONLY    , ""},
 
4540
    { CMD_SWRESET        , "swreset",true , 0 , CI_DEV_ONLY    , ""},
 
4541
    { CMD_CFI            , "cfi"   ,true  , 0 , CI_DEV_ONLY    , ""}
 
4542
};
 
4543
 
 
4544
#define numbel(x) (sizeof(x)/sizeof((x)[0]))
 
4545
 
 
4546
 
 
4547
const CommandInfo* GetCommandInfo(CommandType cmd) {
 
4548
    for (u_int32_t i = 0 ; i < numbel(g_commands); i++ ) {
 
4549
        if (cmd == g_commands[i].cmd) {
 
4550
            return &g_commands[i];
 
4551
        }
 
4552
    }
 
4553
 
 
4554
    return NULL;
 
4555
}
 
4556
 
 
4557
CommandType ParseCommand(const char* cmd) {
 
4558
    u_int32_t cmdLenGiven = strlen(cmd);
 
4559
 
 
4560
    for (u_int32_t i = 0 ; i < numbel(g_commands); i++ ) {
 
4561
        if (g_commands[i].requireExactMatch ) {
 
4562
            if (!strcmp(cmd, g_commands[i].cmdName)) {
 
4563
                return g_commands[i].cmd;
 
4564
            }
 
4565
        } else {
 
4566
            // Match if given cmd maches the beginning of the checked cmd
 
4567
            if (!strncmp(cmd, g_commands[i].cmdName, cmdLenGiven )) {
 
4568
                return g_commands[i].cmd;
 
4569
            }
 
4570
        }
 
4571
    }
 
4572
    return CMD_UNKNOWN;
 
4573
}
 
4574
 
 
4575
 
 
4576
bool CheckCommandInputs(const char* dev,
 
4577
                        const char* img,
 
4578
                        CommandType cmd) {
 
4579
 
 
4580
    const CommandInfo* cmdInfo = GetCommandInfo(cmd);
 
4581
 
 
4582
    if (!cmdInfo) {
 
4583
        printf("*** INTERNAL ERROR *** Unknown command given to CheckCommandInputs() (%d)\n", cmd);
 
4584
        return false;
 
4585
    }
 
4586
 
 
4587
    const char* inputDesStr [] = {
 
4588
        NULL,
 
4589
        "neither a device nor an image file",       // CI_NONE
 
4590
        "an image file",                            // CI_IMG_ONLY,
 
4591
        NULL,
 
4592
        "a device",                                 // CI_DEV_ONLY,
 
4593
        NULL,
 
4594
        "either an image file or a device",         // CI_IMG_OR_DEV,
 
4595
        NULL,
 
4596
        "both an image file and a device"           // CI_IMG_AND_DEV
 
4597
    };
 
4598
 
 
4599
    CommandInput given;
 
4600
 
 
4601
    if        ( dev && img) {
 
4602
        given = CI_IMG_AND_DEV;
 
4603
    } else if (!dev && img) {
 
4604
        given = CI_IMG_ONLY;
 
4605
    } else if (dev && !img) {
 
4606
        given = CI_DEV_ONLY;
 
4607
    } else {
 
4608
        given = CI_NONE;
 
4609
    }
 
4610
 
 
4611
    if ((given & cmdInfo->requiredInput) == 0) {
 
4612
        printf("*** ERROR *** Command \"%s\" requires %s to be specified",
 
4613
               cmdInfo->cmdName,
 
4614
               inputDesStr[cmdInfo->requiredInput]);
 
4615
 
 
4616
        if (given != CI_NONE) {
 
4617
            printf(", but %s %s given.\n",
 
4618
                   inputDesStr[given],
 
4619
                   given == CI_IMG_AND_DEV ? "are" : "is");
 
4620
        } else {
 
4621
            printf(".\n");
 
4622
        }
 
4623
 
 
4624
        return false;
 
4625
    }
 
4626
 
 
4627
    return true;
 
4628
}
 
4629
 
 
4630
bool CheckMaxCmdArguments(CommandType cmd, int numArgs) {
 
4631
    const CommandInfo* cmdInfo = GetCommandInfo(cmd);
 
4632
    if (!cmdInfo) {
 
4633
        printf("*** INTERNAL ERROR *** Unknown command given to CheckMaxCmdArguments (%d)\n", cmd);
 
4634
        return false;
 
4635
    }
 
4636
 
 
4637
    if (cmdInfo->maxArgs >= 0 && numArgs > cmdInfo->maxArgs) {
 
4638
        printf("*** ERROR *** Command \"%s\" requires %d arguments, but %d arguments were given\n",
 
4639
               cmdInfo->cmdName,
 
4640
               cmdInfo->maxArgs,
 
4641
               numArgs);
 
4642
        return false;
 
4643
    }
 
4644
    return true;
 
4645
}
 
4646
 
 
4647
////////////////////////////////////////////////////////////////////////
 
4648
//
 
4649
 
 
4650
// Return values:
 
4651
#define RC_FW_ALREADY_UPDATED 7
 
4652
 
 
4653
#define NEXTS(s) do {                                        \
 
4654
    if (++i >= ac)                                           \
 
4655
    {                                                        \
 
4656
        printf("Missed parameter after \"%s\" switch\n", s); \
 
4657
        return 1;                                            \
 
4658
    }} while(0)
 
4659
#define NEXTC(p, s) do {                                           \
 
4660
    if (++i >= ac)                                                 \
 
4661
    {                                                              \
 
4662
        printf("Missed %s parameter after \"%s\" command\n", p,s); \
 
4663
        return 1;                                                  \
 
4664
    }} while(0)
 
4665
 
 
4666
#define SETERR(args) do { printf("*** ERROR *** "); printf args; printf("\n"); return 1; } while(0)
 
4667
 
 
4668
 
 
4669
int main(int ac, char *av[])
 
4670
{
 
4671
 
 
4672
    char         *image_fname=0, *device=0;
 
4673
    bool         clear_semaphore  = false;
 
4674
    bool         silent           = false;
 
4675
    bool         guids_specified  = false;
 
4676
    bool         macs_specified   = false;
 
4677
    bool         burn_failsafe    = true;
 
4678
    bool         use_image_ps     = false;
 
4679
    bool         use_image_guids  = false;
 
4680
    bool         single_image_burn = true;
 
4681
    bool         checkMatchingDevId = true;
 
4682
 
 
4683
    const char*  cmdStr           = NULL;
 
4684
 
 
4685
    char         *user_vsd=0;
 
4686
    char         *user_psid=0;
 
4687
    guid_t       user_guids[Operations::MAX_GUIDS];
 
4688
    int          rc = 0;
 
4689
 
 
4690
    CommandType cmd = CMD_UNKNOWN;
 
4691
 
 
4692
    auto_ptr<Flash>       f;
 
4693
    FImage                fim;
 
4694
 
 
4695
    Operations            ops;
 
4696
 
 
4697
    FBase*      fbase     = NULL;
 
4698
    const char* cmdTarget = NULL;
 
4699
    const char* cmdAccess = NULL;
 
4700
 
 
4701
    bool        cntx_image  = false;
 
4702
    bool        cntx_device = false;
 
4703
    //
 
4704
    // Map termination signal handlers
 
4705
    //
 
4706
    int i;
 
4707
    for (i = 0 ; i < (int)(sizeof(g_signals_for_termination)/sizeof(g_signals_for_termination[0])) ; i++ ) {
 
4708
        signal (g_signals_for_termination[i], TerminationHandler);
 
4709
    }
 
4710
 
 
4711
    if (ac < 2) {
 
4712
        usage(av[0]);
 
4713
        rc =  1; goto done;
 
4714
    }
 
4715
 
 
4716
    // Init with FFs - for ConnectX if only MAC or GUID is specified
 
4717
    memset(user_guids, 0xff, sizeof(user_guids));
 
4718
 
 
4719
    // Go thru command line options
 
4720
    for (i=1; i < ac; i++) {
 
4721
        //
 
4722
        // Switches
 
4723
        // --------
 
4724
        //
 
4725
        if (*av[i] == '-') {
 
4726
            int switchLen = strlen(av[i]);
 
4727
 
 
4728
            if (!strcmp(av[i], "-dual_image"))
 
4729
                single_image_burn = false;
 
4730
 
 
4731
            else if (!strcmp(av[i], "-clear_semaphore")) {
 
4732
                clear_semaphore = true;
 
4733
            }
 
4734
 
 
4735
            else if (!strncmp(av[i], "-device", switchLen)) {
 
4736
                NEXTS("-device");
 
4737
                device = av[i];
 
4738
 
 
4739
            } else if (!strcmp(av[i], "-v") || !strcmp(av[i], "-vv")) {
 
4740
                printf("%s: %s .",
 
4741
                       av[0],
 
4742
                       _versionID);
 
4743
 
 
4744
                if (!strcmp(av[i], "-vv")) {
 
4745
                    printf(" SVN %s", _svnID + 1);
 
4746
                }
 
4747
 
 
4748
                printf("\n");
 
4749
                rc =  0; goto done;
 
4750
 
 
4751
            } else if (!strcmp(av[i], "-unlock")) {
 
4752
                _unlock_bypass = true;
 
4753
            } else if (!strcmp(av[i], "-noerase"))
 
4754
                _no_erase = true;
 
4755
            else if (!strcmp(av[i], "-noburn"))
 
4756
                _no_burn = true;
 
4757
            else if (!strcmp(av[i], "-crc"))
 
4758
                _print_crc = true;
 
4759
            else if (!strcmp(av[i], "-bytewrite")) {
 
4760
                if (device) {
 
4761
                    printf("\"-bytewrite\" should be specifies before \"-device\" switch in the command line.\n");
 
4762
                    rc =  1; goto done;
 
4763
                }
 
4764
                _byte_write = true;
 
4765
            } else if (!strcmp(av[i], "-vsd")) {
 
4766
                NEXTS("-vsd");
 
4767
                user_vsd = av[i];
 
4768
            }
 
4769
            // -vsd1 is an alias to -vsd, for backward compatibility. Can be removed in the future.
 
4770
            else if (!strcmp(av[i], "-vsd1")) {
 
4771
                printf("-W- Flag \"%s\" is deprecated. It will be removed in the next version. Use \"-vsd\" flag for the same result.\n", av[i]);
 
4772
                NEXTS("-vsd1");
 
4773
                user_vsd = av[i];
 
4774
            } else if (!strcmp(av[i], "-psid")) {
 
4775
                printf("-W- Flag \"%s\" is deprecated. It will be removed in the next version.\n", av[i]);
 
4776
                NEXTS("-psid");
 
4777
                user_psid = av[i];
 
4778
            }
 
4779
            // -vsd2 is an alias to psid, for backward compatibility. Can be removed in the future.
 
4780
            else if (!strcmp(av[i], "-vsd2")) {
 
4781
                printf("-W- Flag \"%s\" is deprecated. It will be removed in the next version.\n", av[i]);
 
4782
                NEXTS("-vsd2");
 
4783
                user_psid = av[i];
 
4784
            } else if (!strcmp(av[i], "-bsn")) {
 
4785
                printf("-W- Flag \"%s\" is deprecated. It will be removed in the next version.\n", av[i]);
 
4786
 
 
4787
                NEXTS("-bsn");
 
4788
                GETBSN(av[i], &user_guids[0]);
 
4789
                for (int i=1; i<Operations::GUIDS; i++) {
 
4790
                    u_int64_t g=user_guids[0].h;
 
4791
                    g=(g<<32) | user_guids[0].l;
 
4792
                    g += i;
 
4793
                    user_guids[i].h = (u_int32_t)(g>>32);
 
4794
                    user_guids[i].l = (u_int32_t)g;
 
4795
                }
 
4796
                guids_specified = true;
 
4797
            } else if (!strncmp(av[i], "-image", switchLen)) {
 
4798
                NEXTS("-image");
 
4799
                image_fname = av[i];
 
4800
            } else if (!strcmp(av[i], "-guid")) {
 
4801
                NEXTS("-guid");
 
4802
                GETGUID(av[i], &user_guids[0]);
 
4803
                for (int i=1; i<Operations::GUIDS; i++) {
 
4804
                    u_int64_t g=user_guids[0].h;
 
4805
                    g=(g<<32) | user_guids[0].l;
 
4806
                    g += i;
 
4807
                    user_guids[i].h = (u_int32_t)(g>>32);
 
4808
                    user_guids[i].l = (u_int32_t)g;
 
4809
                }
 
4810
                guids_specified = true;
 
4811
            } else if (!strcmp(av[i], "-guids")) {
 
4812
                if (i + 4 >= ac) {
 
4813
                    printf("Exactly four GUIDs must be specified.\n");
 
4814
                    rc =  1; goto done;
 
4815
                }
 
4816
                i++;
 
4817
                for (int j=0; j<Operations::GUIDS; j++) {
 
4818
                    GETGUID(av[i+j], &user_guids[j]);
 
4819
                }
 
4820
                i += 3;
 
4821
                guids_specified = true;
 
4822
 
 
4823
            } else if (!strcmp(av[i], "-mac")) {
 
4824
                NEXTS("-mac");
 
4825
                GETGUID(av[i], &user_guids[Operations::GUIDS]);
 
4826
                for (int i=1; i < Operations::MACS ; i++) {
 
4827
                    u_int64_t g=user_guids[Operations::GUIDS].h;
 
4828
                    g=(g<<32) | user_guids[Operations::GUIDS].l;
 
4829
                    g += i;
 
4830
                    user_guids[Operations::GUIDS + i].h = (u_int32_t)(g>>32);
 
4831
                    user_guids[Operations::GUIDS + i].l = (u_int32_t)g;
 
4832
                }
 
4833
                macs_specified = true;
 
4834
            } else if (!strcmp(av[i], "-macs")) {
 
4835
                if (i + 2 >= ac) {
 
4836
                    printf("Exactly two MACs must be specified.\n");
 
4837
                    rc =  1; goto done;
 
4838
                }
 
4839
                i++;
 
4840
                for (int j=0; j<Operations::MACS; j++) {
 
4841
                    GETGUID(av[i+j], &user_guids[Operations::GUIDS+j]);
 
4842
                }
 
4843
                i += 1;
 
4844
                macs_specified = true;
 
4845
            } else if (!strncmp(av[i], "-silent", switchLen))
 
4846
                silent = true;
 
4847
            else if (!strcmp(av[i], "-use_image_ps"))
 
4848
                use_image_ps = true;
 
4849
            else if (!strcmp(av[i], "-use_image_guids"))
 
4850
                use_image_guids = true;
 
4851
            else if (!strcmp(av[i], "-no_devid_check"))
 
4852
                checkMatchingDevId = false;
 
4853
            else if (!strncmp(av[i], "-nofs", 5))
 
4854
                burn_failsafe = false;
 
4855
            else if (!strcmp(av[i], "-skip_is"))
 
4856
                ops.SetAllowSkipIs(true);
 
4857
            else if (!strcmp(av[i], "-striped_image"))
 
4858
                ops.SetCntxStripedImage(true);
 
4859
            else if (!strcmp(av[i], "-blank_guids"))
 
4860
                ops.SetBurnBlankGuids(true);
 
4861
            else if (!strcmp(av[i], "-qq"))
 
4862
                ops.SetQuickQuery(true);
 
4863
            else if (!strncmp(av[i], "-yes", switchLen))
 
4864
                _assume_yes = true;
 
4865
            else if (!strcmp(av[i], "-no"))
 
4866
                _assume_no = true;
 
4867
            else if (!strcmp(av[i], "-byte_mode"))
 
4868
                Flash::_byte_mode = true;
 
4869
 
 
4870
 
 
4871
            else if (!strncmp(av[i], "-hh", 3) ||  !strncmp(av[i], "--hh", 4)) {
 
4872
                usage(av[0], true);
 
4873
                rc =  0; goto done;
 
4874
            } else if (!strncmp(av[i], "-help", switchLen) ||  !strncmp(av[i], "--h", 3)) {
 
4875
                usage(av[0]);
 
4876
                rc =  0; goto done;
 
4877
            } else {
 
4878
                printf("*** ERROR *** Invalid switch \"%s\" is specified.\n", av[i]);
 
4879
                rc =  1; goto done;
 
4880
            }
 
4881
        }  else {
 
4882
            // command
 
4883
            cmdStr = av[i];
 
4884
            break;
 
4885
        }
 
4886
    }
 
4887
 
 
4888
    if (_assume_yes && _assume_no) {
 
4889
        printf("*** ERROR *** -yes and -no options can not be specified together.\n");
 
4890
        rc =  1; goto done;
 
4891
    }
 
4892
 
 
4893
    if (ops.GetBurnBlankGuids() && (guids_specified || macs_specified)) {
 
4894
        const char* flag = "-guid(s)";
 
4895
 
 
4896
        if (macs_specified && !guids_specified) {
 
4897
            flag = "-mac(s)";
 
4898
        }
 
4899
 
 
4900
        printf("*** ERROR *** -blank_guids and %s options can not be specified together.\n", flag);
 
4901
        rc =  1; goto done;
 
4902
    }
 
4903
 
 
4904
    //
 
4905
    // Commands
 
4906
    // --------
 
4907
    //
 
4908
 
 
4909
    if (clear_semaphore) {
 
4910
        if (cmdStr) {
 
4911
            printf("*** ERROR *** No command is allowed when -clear_semaphore flag is given.\n");
 
4912
            rc =  1; goto done;
 
4913
        } else {
 
4914
            cmdStr = "clear_semaphore";
 
4915
        }
 
4916
    }
 
4917
 
 
4918
    if (!cmdStr) {
 
4919
        printf("*** ERROR *** No command given. See help for details.\n");
 
4920
        rc =  1; goto done;
 
4921
    }
 
4922
 
 
4923
    //
 
4924
    // Check and parse command
 
4925
    //
 
4926
    cmd = ParseCommand(cmdStr);
 
4927
 
 
4928
    if (cmd == CMD_UNKNOWN) {
 
4929
        printf("*** ERROR *** Invalid command \"%s\".\n", av[i]);
 
4930
        rc =  1; goto done;
 
4931
    }
 
4932
 
 
4933
    if (cmd == CMD_CLEAR_SEM) {
 
4934
        clear_semaphore = true;
 
4935
    }
 
4936
 
 
4937
    if (!CheckCommandInputs(device, image_fname, cmd)) {
 
4938
        rc = 1; goto done;
 
4939
    }
 
4940
 
 
4941
    if (!CheckMaxCmdArguments(cmd, ac - i - 1 )) {
 
4942
        rc = 1; goto done;
 
4943
    }
 
4944
 
 
4945
    if (device) {
 
4946
        // Open the device
 
4947
        auto_ptr<Flash>       tmp(new Flash);
 
4948
        f = tmp;
 
4949
 
 
4950
        if (f.get() == NULL) {
 
4951
            printf("*** ERROR *** Memory allocation failed\n");
 
4952
            rc =  1; goto done;
 
4953
        }
 
4954
 
 
4955
        g_flash = f.get();
 
4956
        if (!f->open(device, clear_semaphore)) {
 
4957
            printf("*** ERROR *** Can not open %s: %s\n", device, f->err());
 
4958
            rc =  1; goto done;
 
4959
        }
 
4960
 
 
4961
        ops.SetNumPorts(f->get_port_num());
 
4962
 
 
4963
        cmdTarget = "Flash";
 
4964
        cmdAccess = device;
 
4965
        fbase     = f.get();
 
4966
 
 
4967
        // Connectx Mode:
 
4968
        cntx_device = ops.CheckIsCntx(*fbase);
 
4969
    }
 
4970
 
 
4971
    if (image_fname) {
 
4972
        if (!fim.open(image_fname)) {
 
4973
            printf("*** ERROR *** Image file open failed: %s\n", fim.err());
 
4974
            rc =  1; goto done;
 
4975
        }
 
4976
 
 
4977
        cmdTarget = "Image file";
 
4978
        cmdAccess = image_fname;
 
4979
        fbase     = &fim;
 
4980
 
 
4981
        // Connectx Mode:
 
4982
        cntx_image = ops.CheckIsCntx(fim);
 
4983
    }
 
4984
 
 
4985
    ops.SetCntxMode(cntx_image || cntx_device);
 
4986
 
 
4987
    switch (cmd) {
 
4988
    case CMD_BURN:
 
4989
    case CMD_BURN_BLOCK:
 
4990
    {
 
4991
 
 
4992
        //
 
4993
        // BURN
 
4994
        //
 
4995
        Operations::ImageInfo fileInfo;
 
4996
        Operations::ImageInfo flashInfo;
 
4997
        bool burn_block = (cmd == CMD_BURN_BLOCK);
 
4998
 
 
4999
        if (!burn_block) {
 
5000
            if (cntx_image != cntx_device) {
 
5001
                printf("*** ERROR *** The given device %s a FS2 image type, but the given image file %s a FS2 FW image\n",
 
5002
                       cntx_device ? "requires" : "does not require",
 
5003
                       cntx_image  ? "contains" : "does not contain");
 
5004
                rc =  1; goto done;
 
5005
            }
 
5006
 
 
5007
            // Make checks and replace vsd/guids.
 
5008
            bool old_silent = _silent;
 
5009
            _silent = true;
 
5010
            if (!ops.Verify(fim, &fileInfo) || !ops.QueryAll(fim, &fileInfo)) {
 
5011
                printf("*** ERROR *** %s: Not a valid image file (%s)\n", image_fname, ops.err());
 
5012
                rc =  1; goto done;
 
5013
            }
 
5014
 
 
5015
            if (checkMatchingDevId && fileInfo.infoOffs[Operations::II_DeviceType]) {
 
5016
                if (!ops.CheckMatchingDevId(f->get_dev_id(),
 
5017
                                            fileInfo.devType)) {
 
5018
                    printf("*** ERROR *** Device/Image mismatch: %s\n",
 
5019
                           ops.err());
 
5020
                    rc =  1; goto done;
 
5021
                }
 
5022
            }
 
5023
 
 
5024
 
 
5025
            // Get GUID and VSD info from flash
 
5026
 
 
5027
            bool read_guids = true;
 
5028
            bool read_ps    = true;
 
5029
 
 
5030
            // Flash query (unlike image file query) does not have to
 
5031
            // pass. E.G. blank flash and the user supplies the needed data (guids, vsd).
 
5032
 
 
5033
            bool flash_query_res= true;
 
5034
            if (ops.GetQuickQuery()) {
 
5035
                printf("\n*** WARNING *** Running quick query - Skipping full image integrity checks.\n");
 
5036
                if (ops.IsCntx()) {
 
5037
                    flash_query_res = ops.VerifyCntx(*f, &flashInfo, false, true);
 
5038
                }
 
5039
 
 
5040
                if (flash_query_res) {
 
5041
                    flash_query_res = ops.QueryAll(*f, &flashInfo);
 
5042
                }
 
5043
            } else {
 
5044
                flash_query_res = ops.Verify(*f, &flashInfo) && ops.QueryAll(*f, &flashInfo);
 
5045
            }
 
5046
 
 
5047
            bool ib_dev;
 
5048
            bool eth_dev;
 
5049
 
 
5050
            ops.SetDevFlags(fileInfo.devType, ib_dev,eth_dev);
 
5051
 
 
5052
            if ((user_vsd && user_psid) || use_image_ps)
 
5053
                read_ps = false;
 
5054
 
 
5055
            if (ops.GetBurnBlankGuids() ||
 
5056
                (guids_specified && ib_dev) ||
 
5057
                (macs_specified && eth_dev))
 
5058
                read_guids = false;
 
5059
 
 
5060
            if (read_guids && !flash_query_res) {
 
5061
                const char* missing_info;
 
5062
                const char* missing_flags;
 
5063
 
 
5064
                if (ib_dev && eth_dev) {
 
5065
                    missing_info  = "GUIDs / MACs";
 
5066
                    missing_flags = "-guid(s) / -mac(s)";
 
5067
                } else if (ib_dev) {
 
5068
                    missing_info  = "GUIDs";
 
5069
                    missing_flags = "-guid(s)";
 
5070
                } else {
 
5071
                    missing_info  = "MACs";
 
5072
                    missing_flags = "-mac(s)";
 
5073
                }
 
5074
 
 
5075
                if (read_guids && !flashInfo.imageOk) {
 
5076
                    printf("\n");
 
5077
                    printf("*** ERROR *** Can not extract %s info from flash. "
 
5078
                           "Please specify %s (using command line flags %s ). \n", missing_info, missing_info, missing_flags);
 
5079
                }
 
5080
 
 
5081
                if (burn_failsafe) {
 
5082
                    printf("              Can not burn in a failsafe mode.\n");
 
5083
                    printf("              If you want to burn in non failsafe mode, use the \"-nofs\" switch.\n");
 
5084
                }
 
5085
                rc =  1; goto done;
 
5086
            }
 
5087
 
 
5088
            // Patch GUIDS
 
5089
            if  (guids_specified || macs_specified) {
 
5090
                if (!ops.CheckGuidsFlags(fileInfo.devType, ib_dev, guids_specified, eth_dev, macs_specified)) {
 
5091
                    printf("*** ERROR *** %s\n", ops.err());
 
5092
                    rc =  1; goto done;
 
5093
                }
 
5094
 
 
5095
                if (!ops.patchGUIDs(fim,
 
5096
                                    &fileInfo,
 
5097
                                    ib_dev,
 
5098
                                    eth_dev,
 
5099
                                    guids_specified,
 
5100
                                    macs_specified,
 
5101
                                    user_guids,
 
5102
                                    flashInfo.imageOk ? flashInfo.guids : NULL,
 
5103
                                    flashInfo.guidNum,
 
5104
                                    true)) {
 
5105
                    rc =  1; goto done;
 
5106
                }
 
5107
            } else if (!use_image_guids) {
 
5108
                if (!ops.patchGUIDs(fim,
 
5109
                                    &fileInfo,
 
5110
                                    ib_dev,
 
5111
                                    eth_dev,
 
5112
                                    false,
 
5113
                                    false,
 
5114
                                    NULL,
 
5115
                                    flashInfo.guids,
 
5116
                                    flashInfo.guidNum,
 
5117
                                    false)) {
 
5118
                    rc =  1; goto done;
 
5119
                }
 
5120
            }
 
5121
 
 
5122
            if (burn_failsafe && (!fileInfo.isFailsafe || !flashInfo.isFailsafe)) {
 
5123
                printf("*** ERROR *** Failsafe burn failed: FW image in the %s is non failsafe.\n",         fileInfo.isFailsafe ? "flash" : "given file");
 
5124
                printf("              It is impossible to burn %sa non failsafe image in a failsafe mode.\n", fileInfo.isFailsafe ? "over " : "");
 
5125
                printf("              If you want to burn in non failsafe mode, use the \"-nofs\" switch.\n");
 
5126
                rc =  1; goto done;
 
5127
            }
 
5128
 
 
5129
            if (!user_vsd && !(flashInfo.psOk || (flashInfo.infoOffs[Operations::II_PSID] &&
 
5130
                                                flashInfo.infoOffs[Operations::II_VSD]  ))) {
 
5131
                printf("\n");
 
5132
                if (burn_failsafe) {
 
5133
 
 
5134
                    printf("*** ERROR *** Can not extract VSD/PSID info from flash.\n"
 
5135
                           "              Can not burn in a failsafe mode. Please use \"-nofs\" flag to burn in a non failsafe mode.\n");
 
5136
                    rc =  1; goto done;
 
5137
                }  else {
 
5138
                    printf("*** WARNING *** Can not extract VSD/PSID info from flash.\n\n"
 
5139
                           "    To use a specific VSD, abort and re-burn specifying the\n"
 
5140
                           "    needed info (using command line flags -vsd / -use_image_ps).\n"
 
5141
                           "    You can also continue burn using blank VSD.\n");
 
5142
 
 
5143
                    if (!ops.ask_user()) {
 
5144
                        rc =  1; goto done;
 
5145
                    }
 
5146
                }
 
5147
            }
 
5148
 
 
5149
            // Print FW versions:
 
5150
            printf("\n");
 
5151
            printf("    Current FW version on flash:  ");
 
5152
            if (flashInfo.infoOffs[Operations::II_FwVersion]) {
 
5153
                printf("%d.%d.%d\n", flashInfo.fwVer[0], flashInfo.fwVer[1], flashInfo.fwVer[2]);
 
5154
            } else {
 
5155
                printf("N/A\n");
 
5156
            }
 
5157
 
 
5158
            printf("    New FW version:               ");
 
5159
            if (fileInfo.infoOffs[Operations::II_FwVersion]) {
 
5160
                printf("%d.%d.%d\n", fileInfo.fwVer[0], fileInfo.fwVer[1], fileInfo.fwVer[2]);
 
5161
            } else {
 
5162
                printf("N/A\n");
 
5163
            }
 
5164
 
 
5165
            bool updateRequired = true;
 
5166
 
 
5167
            if (fileInfo.infoOffs[Operations::II_FwVersion]  &&
 
5168
                flashInfo.infoOffs[Operations::II_FwVersion]) {
 
5169
 
 
5170
                updateRequired = ops.FwVerLessThan(flashInfo.fwVer,fileInfo.fwVer);
 
5171
            }
 
5172
 
 
5173
            if (!updateRequired) {
 
5174
                printf("\n    Note: The new FW version is not newer than the current FW version on flash.\n");
 
5175
                if (! ops.ask_user()) {
 
5176
                    rc =  RC_FW_ALREADY_UPDATED; goto done;
 
5177
                }
 
5178
            }
 
5179
 
 
5180
            if (fileInfo.infoOffs[Operations::II_IsGa] && !fileInfo.isGa) {
 
5181
                printf("\n    Note: You are attempting to burn a pre-production FW image.\n");
 
5182
                if (! ops.ask_user()){
 
5183
                    rc =  1; goto done;
 
5184
                }
 
5185
            }
 
5186
 
 
5187
            if (!use_image_ps) {
 
5188
                if (fileInfo.psOk || (ops.IsCntx() && fileInfo.infoOffs[Operations::II_VSD])) {
 
5189
                    if (!ops.patchVSD(fim,
 
5190
                                      &fileInfo,
 
5191
                                      user_vsd,
 
5192
                                      user_psid,
 
5193
                                      flashInfo.vsd,
 
5194
                                      NULL,
 
5195
                                      fileInfo.psid )) {
 
5196
                        rc =  1; goto done;
 
5197
                    }
 
5198
                }
 
5199
            }
 
5200
 
 
5201
            // Check PSID and ib -> eth change.
 
5202
 
 
5203
            if (fileInfo.infoOffs[Operations::II_PSID]  &&
 
5204
                flashInfo.infoOffs[Operations::II_PSID] &&
 
5205
                strncmp( fileInfo.psid, flashInfo.psid, PSID_LEN)) {
 
5206
                if (ops.IsCntx() &&
 
5207
                    (!ib_dev && eth_dev) &&
 
5208
                    flashInfo.infoOffs[Operations::II_DeviceType] &&
 
5209
                     ops.CntxIsIb(flashInfo.devType) &&
 
5210
                    !ops.CntxIsEth(flashInfo.devType)) {
 
5211
 
 
5212
                    printf("\n    You are about to replace FW image type from IB to ETH image.\n");
 
5213
                } else {
 
5214
                    printf("\n    You are about to replace current PSID on flash - \"%s\" with a different PSID - \"%s\".\n"
 
5215
                           "    Note: It is highly recommended not to change the PSID.\n",
 
5216
                           flashInfo.psid,
 
5217
                           fileInfo.psid);
 
5218
                }
 
5219
 
 
5220
                if (! ops.ask_user()){
 
5221
                    rc =  1; goto done;
 
5222
                }
 
5223
            }
 
5224
 
 
5225
            // Check exp rom:
 
5226
            if (!fileInfo.expRomFound && flashInfo.expRomFound) {
 
5227
                printf("\n    Expansion-ROM mismatch: \n"
 
5228
                       "    Current FW on flash contains an expansion-ROM.\n"
 
5229
                       "    The new FW image does not contain an expansion-ROM\n");
 
5230
 
 
5231
                if (! ops.ask_user()){
 
5232
                    rc =  1; goto done;
 
5233
                }
 
5234
            }
 
5235
 
 
5236
            _silent = old_silent;
 
5237
 
 
5238
        } else {
 
5239
            // BURN BLOCK:
 
5240
            burn_failsafe = false;
 
5241
        }
 
5242
 
 
5243
        // Burn it
 
5244
        if (burn_failsafe) {
 
5245
            // FS burn
 
5246
            bool ret;
 
5247
            if (ops.IsCntx()) {
 
5248
                ret = ops.CntxFailSafeBurn(*f,
 
5249
                                           fim,
 
5250
                                           !silent,
 
5251
                                           &flashInfo,
 
5252
                                           &fileInfo,
 
5253
                                           false);
 
5254
 
 
5255
            } else {
 
5256
                ret = ops.FailSafeBurn(*f,
 
5257
                                       fim,
 
5258
                                       !silent,
 
5259
                                       single_image_burn);
 
5260
            }
 
5261
 
 
5262
            if (!ret) {
 
5263
                if (f->err()) {
 
5264
                    // The error is in flash access:
 
5265
                    printf("*** ERROR *** Flash access failed during burn: %s\n", f->err());
 
5266
                } else {
 
5267
                    // operation/ algorithm error:
 
5268
                    printf("*** ERROR *** Failsafe burn error: %s\n", ops.err());
 
5269
                }
 
5270
                rc =  1; goto done;
 
5271
            }
 
5272
        } else {
 
5273
            //
 
5274
            // Not failsafe (sequential) burn
 
5275
            //
 
5276
 
 
5277
            // Ask is it OK
 
5278
            printf("\n");
 
5279
            if (burn_block) {
 
5280
                printf("Block burn: The given image will be burnt as is. No fields (such\n");
 
5281
                printf("as GUIDS,VSD) are taken from current image on flash.\n");
 
5282
            }
 
5283
            printf("Burn process will not be failsafe. No checks will be performed.\n");
 
5284
 
 
5285
            printf("ALL flash, including the Invariant Sector will be overwritten.\n");
 
5286
            printf("If this process fails, computer may remain in an inoperable state.\n");
 
5287
 
 
5288
            if (!ops.ask_user()) {
 
5289
                rc =  1; goto done;
 
5290
            }
 
5291
 
 
5292
            // Non FS burn
 
5293
            bool ret;
 
5294
            if (ops.IsCntx() && !burn_block) {
 
5295
                ret = ops.CntxFailSafeBurn(*f,
 
5296
                                           fim,
 
5297
                                           !silent,
 
5298
                                           &flashInfo,
 
5299
                                           &fileInfo,
 
5300
                                           true); // Allow nofs
 
5301
            } else {
 
5302
                ret = ops.write_image(*f, 0, fim.getBuf(), fim.getBufLength(),!silent);
 
5303
            }
 
5304
 
 
5305
 
 
5306
            if (!ret) {
 
5307
                report("\n");
 
5308
                printf("*** ERROR *** Non failsafe burn failed: %s\n", ops.err());
 
5309
                rc =  1; goto done;
 
5310
            }
 
5311
            report("\n");
 
5312
        }
 
5313
    }
 
5314
    break;
 
5315
    case CMD_SET_GUIDS:
 
5316
    {
 
5317
        Operations::ImageInfo info;
 
5318
        u_int32_t guid_sect_addr[2] = {0};
 
5319
        u_int32_t i;
 
5320
 
 
5321
        if (ops.IsCntx()) {
 
5322
            _silent       = true;
 
5323
            if (!ops.VerifyCntx(*fbase, &info, false, true)) {
 
5324
                printf("\n*** ERROR *** Can not set GUIDs: %s. \n", ops.err());
 
5325
                rc =  1; goto done;
 
5326
            }
 
5327
            _silent = false;
 
5328
        }
 
5329
 
 
5330
        if (!ops.QueryAll(*fbase, &info)) {
 
5331
            printf("*** ERROR *** Can not set GUIDs: %s query (%s) failed: %s\n", cmdTarget , cmdAccess, ops.err());
 
5332
            rc =  1; goto done;
 
5333
        }
 
5334
 
 
5335
        if (!info.blankGuids) {
 
5336
            printf("\n*** ERROR *** Can not set GUIDs: Guids are already set.\n");
 
5337
            rc =  1; goto done;
 
5338
        }
 
5339
 
 
5340
        bool ib_dev;
 
5341
        bool eth_dev;
 
5342
 
 
5343
        ops.SetDevFlags(info.devType, ib_dev, eth_dev);
 
5344
 
 
5345
        if (macs_specified || guids_specified) {
 
5346
            if (!ops.CheckGuidsFlags(info.devType, ib_dev, guids_specified, eth_dev, macs_specified)) {
 
5347
                printf("*** ERROR *** %s\n", ops.err());
 
5348
                rc =  1; goto done;
 
5349
            }
 
5350
        } else {
 
5351
            const char* missing_info;
 
5352
            const char* missing_flags;
 
5353
 
 
5354
            if (ib_dev && eth_dev) {
 
5355
                missing_info  = "GUIDs / MACs";
 
5356
                missing_flags = "-guid(s) / -mac(s)";
 
5357
            } else if (ib_dev) {
 
5358
                missing_info  = "GUIDs";
 
5359
                missing_flags = "-guid(s)";
 
5360
            } else {
 
5361
                missing_info  = "MACs";
 
5362
                missing_flags = "-mac(s)";
 
5363
            }
 
5364
 
 
5365
            printf("\n");
 
5366
            printf("*** ERROR *** For set_guids command, "
 
5367
                   "Please specify %s (using command line flags %s ). \n", missing_info, missing_flags);
 
5368
 
 
5369
            rc = 1; goto done;
 
5370
        }
 
5371
 
 
5372
        if (ops.IsCntx() || !info.isFailsafe) {
 
5373
            guid_sect_addr[0] = info.guidPtr;
 
5374
        } else {
 
5375
            int addr_idx = 0;
 
5376
            for (i = 0; i < 2; i++) {
 
5377
                if (info.allImgStart[i]) {
 
5378
                    guid_sect_addr[addr_idx] = info.allImgStart[i] + info.guidPtr;
 
5379
                    addr_idx++;
 
5380
                }
 
5381
            }
 
5382
        }
 
5383
 
 
5384
        for (i = 0; i < 2 && guid_sect_addr[i]; i++ ) {
 
5385
            u_int32_t guid_sect[Operations::MAX_GUIDS*2 + 5]; // Save room for header + crc
 
5386
 
 
5387
            if (!f->read(guid_sect_addr[i] - 16 , guid_sect, 16)) {
 
5388
                printf("*** ERROR *** Failed to read guids section - flash read error (%s)\n", fbase->err());
 
5389
            }
 
5390
 
 
5391
            ops.patchGUIDsSection (guid_sect, 16, user_guids, info.guidNum);
 
5392
 
 
5393
            if (!f->write(guid_sect_addr[i], guid_sect + 4 , info.guidNum * 8 + 4, true)) {
 
5394
                printf("*** ERROR *** Guids set failed - flash write error (%s)\n", fbase->err());
 
5395
            }
 
5396
        }
 
5397
    }
 
5398
    break;
 
5399
 
 
5400
    case CMD_ERASE_SECT:
 
5401
    {
 
5402
        //
 
5403
        // ERASE SECTOR <ADDR>
 
5404
        //     Parameters: <ADDR>
 
5405
        //
 
5406
        u_int32_t    addr;
 
5407
        char         *endp;
 
5408
 
 
5409
        // Address of sector to erase
 
5410
        NEXTC("<ADDR>", "erase");
 
5411
        addr = strtoul(av[i], &endp, 0);
 
5412
        if (*endp) {
 
5413
            printf("Invalid address \"%s\"\n", av[i]);
 
5414
            rc =  1; goto done;
 
5415
        }
 
5416
 
 
5417
        // Erase
 
5418
        if (!f->erase_sector(addr)) {
 
5419
            printf("*** ERROR *** Erase sector failed: %s\n", f->err());
 
5420
            rc =  1; goto done;
 
5421
        }
 
5422
    }
 
5423
    break;
 
5424
 
 
5425
    case CMD_QUERY_FORCE:
 
5426
    case CMD_QUERY:
 
5427
    {
 
5428
        // QUERY
 
5429
        Operations::ImageInfo info;
 
5430
        bool imageOk;
 
5431
        bool checkValidImage = false;
 
5432
 
 
5433
        _silent       = true;
 
5434
        if (ops.GetQuickQuery()) {
 
5435
            printf("\n*** WARNING *** Running quick query - Skipping full image integrity checks.\n");
 
5436
            if (ops.IsCntx()) {
 
5437
                imageOk = ops.VerifyCntx(*fbase, &info, false, true);
 
5438
                checkValidImage = true;
 
5439
            }
 
5440
        } else {
 
5441
            imageOk = ops.Verify(*fbase, &info);
 
5442
            checkValidImage = true;
 
5443
        }
 
5444
        _silent = false;
 
5445
 
 
5446
        if (checkValidImage && !imageOk) {
 
5447
            printf("\n*** ERROR *** %s query (%s) failed. Not a valid image.\n", cmdTarget , cmdAccess);
 
5448
            rc =  1; goto done;
 
5449
        }
 
5450
 
 
5451
        if (!ops.QueryAll(*fbase, &info)) {
 
5452
                printf("*** ERROR *** %s query (%s) failed: %s\n", cmdTarget , cmdAccess, ops.err());
 
5453
                rc =  1; goto done;
 
5454
        }
 
5455
 
 
5456
        ops.DisplayImageInfo(&info);
 
5457
    }
 
5458
    break;
 
5459
 
 
5460
    case CMD_QUERY_ROM:
 
5461
    {
 
5462
        Operations::ImageInfo info;
 
5463
        if (!ops.LoadAsExpRom(*fbase)    ||
 
5464
            !ops.GetExpRomVersion(&info) ||
 
5465
            !ops.DisplayExpRomInfo(&info)) {
 
5466
            printf("*** ERROR *** %s rom query (%s) failed: %s\n", cmdTarget , cmdAccess, ops.err());
 
5467
            rc =  1; goto done;
 
5468
        }
 
5469
    }
 
5470
    break;
 
5471
    case CMD_READ_BLOCK:
 
5472
    {
 
5473
        // READ BLOCK
 
5474
        //     Parameters:  <ADDR> <LENGTH> [OUT_FILENAME]
 
5475
        //     if OUT_FILENAME is given, binari read block is stored
 
5476
        //     in the given file. Otherwise, data is printed to screen.
 
5477
        u_int32_t    addr, length;
 
5478
        u_int8_t     *data;
 
5479
        char         *endp;
 
5480
 
 
5481
        bool         to_file = false;
 
5482
 
 
5483
        // Address and length
 
5484
        NEXTC("<ADDR>", "rb");
 
5485
        addr = strtoul(av[i], &endp, 0);
 
5486
        if (*endp) {
 
5487
            printf("Invalid address \"%s\"\n", av[i]);
 
5488
            rc =  1; goto done;
 
5489
        }
 
5490
        NEXTC("<LENGTH>", "rb");
 
5491
        length = strtoul(av[i], &endp, 0);
 
5492
        if (*endp) {
 
5493
            printf("Invalid length \"%s\"\n", av[i]);
 
5494
            rc =  1; goto done;
 
5495
        }
 
5496
        data = new u_int8_t[length];
 
5497
 
 
5498
        // Output file
 
5499
        FILE*  fh = NULL;
 
5500
 
 
5501
        if (i + 2 == ac)
 
5502
            to_file = true;
 
5503
 
 
5504
        if (to_file) {
 
5505
            NEXTC("<OUT_FILENAME>", "rb");
 
5506
            if ((fh = fopen(av[i], "wb")) == NULL) {
 
5507
                fprintf(stderr, "Can not open ");
 
5508
                perror(av[i]);
 
5509
                rc =  1; goto done;
 
5510
            }
 
5511
        }
 
5512
 
 
5513
        // Read flash
 
5514
        if (!fbase->read(addr, data, length)) {
 
5515
            printf("*** ERROR *** Flash read failed: %s\n", fbase->err());
 
5516
            rc =  1; goto done;
 
5517
        }
 
5518
 
 
5519
        if (to_file) {
 
5520
            // Write output
 
5521
            if (fwrite(data, 1, length, fh) != length) {
 
5522
                perror("Write error");
 
5523
                rc =  1; goto done;
 
5524
            }
 
5525
            fclose(fh);
 
5526
        } else {
 
5527
            for (u_int32_t i = 0; i < length ; i+=4) {
 
5528
                u_int32_t word = *((u_int32_t*)(data + i));
 
5529
 
 
5530
                word  = __be32_to_cpu(word);
 
5531
                printf("0x%08x ", word);
 
5532
            }
 
5533
            printf("\n");
 
5534
        }
 
5535
        delete [] data;
 
5536
    }
 
5537
    break;
 
5538
 
 
5539
    case CMD_READ_WORD:
 
5540
    {
 
5541
        // READ DWORD <ADDR>
 
5542
        //     Parameters: <ADDR>
 
5543
        u_int32_t    data, addr;
 
5544
        char         *endp;
 
5545
 
 
5546
        // Address
 
5547
        NEXTC("<ADDR>", "rw");
 
5548
        addr = strtoul(av[i], &endp, 0);
 
5549
        if (*endp) {
 
5550
            printf("Invalid address \"%s\"\n", av[i]);
 
5551
            rc =  1; goto done;
 
5552
        }
 
5553
 
 
5554
        // Read
 
5555
        if (!f->read(addr, &data)) {
 
5556
            printf("*** ERROR *** Flash read failed: %s\n", f->err());
 
5557
            rc =  1; goto done;
 
5558
        }
 
5559
        printf("0x%08x\n", (unsigned int)__cpu_to_be32(data));
 
5560
 
 
5561
    }
 
5562
    break;
 
5563
 
 
5564
    case CMD_VERIFY:
 
5565
    {
 
5566
        // VERIFY
 
5567
        if (!ops.Verify(*fbase, NULL, true)) {
 
5568
            printf("\n*** ERROR *** FW image verification failed");
 
5569
            if (ops.err()) {
 
5570
                printf(": %s", ops.err());
 
5571
            }
 
5572
            printf(". AN HCA DEVICE CAN NOT BOOT FROM THIS IMAGE.\n");
 
5573
            rc =  1; goto done;
 
5574
        } else {
 
5575
            printf("\nFW image verification succeeded. Image is bootable.\n\n");
 
5576
        }
 
5577
    }
 
5578
    break;
 
5579
 
 
5580
    case CMD_DUMP_CONF:
 
5581
    {
 
5582
        // Dump conf
 
5583
        _silent = true;
 
5584
 
 
5585
        char* conf_file = NULL;
 
5586
        if (i + 2 <= ac) {
 
5587
            NEXTC("<OUT_FILENAME>", "dc");
 
5588
            conf_file = av[i];
 
5589
        }
 
5590
 
 
5591
        ops.Verify(*fbase);
 
5592
 
 
5593
        if(!ops.DumpConf(conf_file)) {
 
5594
            printf("*** ERROR *** Failed dumping FW configuration: %s\n", ops.err());
 
5595
            rc =  1; goto done;
 
5596
        }
 
5597
    }
 
5598
    break;
 
5599
 
 
5600
    case CMD_READ_IMAGE:
 
5601
    {
 
5602
        // Dump conf
 
5603
        _silent = true;
 
5604
 
 
5605
        char* img_file = NULL;
 
5606
        NEXTC("<OUT_FILENAME>", "ri");
 
5607
        img_file = av[i];
 
5608
 
 
5609
        // For ConnectX, read only a single image. For other HCAs, try to read both images, since
 
5610
        // the distributed image binary file also contains both images.
 
5611
        ops.Verify(*f, NULL, !ops.IsCntx());
 
5612
 
 
5613
        //printf("Last addr: 0x%08x\n", ops._last_image_addr);
 
5614
 
 
5615
        u_int32_t length = ops._last_image_addr;
 
5616
        u_int8_t* data = new u_int8_t[length];
 
5617
 
 
5618
        FILE* fh;
 
5619
 
 
5620
        if ((fh = fopen(av[i], "wb")) == NULL) {
 
5621
            fprintf(stderr, "Can not open ");
 
5622
            perror(av[i]);
 
5623
            rc =  1; goto done;
 
5624
        }
 
5625
 
 
5626
        // Read flash
 
5627
        if (!f->read(0, data, length)) {
 
5628
            printf("*** ERROR *** Flash read failed: %s\n", f->err());
 
5629
            rc =  1; goto done;
 
5630
        }
 
5631
 
 
5632
        // Write output
 
5633
        if (fwrite(data, 1, length, fh) != length) {
 
5634
            perror("Write error");
 
5635
            rc =  1; goto done;
 
5636
        }
 
5637
        fclose(fh);
 
5638
 
 
5639
        delete [] data;
 
5640
    }
 
5641
    break;
 
5642
 
 
5643
    case CMD_WRITE_BLOCK:
 
5644
    {
 
5645
        // WRITE BLOCK
 
5646
        //     Parameters:  <IN_FILENAME> <ADDR>
 
5647
        u_int32_t    addr;
 
5648
        char         *endp;
 
5649
 
 
5650
        // Input file
 
5651
        FImage fim;
 
5652
 
 
5653
        NEXTC("<IN_FILENAME>", "wb");
 
5654
 
 
5655
        image_fname = av[i];
 
5656
 
 
5657
        // Address
 
5658
        NEXTC("<ADDR>", "wb");
 
5659
        addr = strtoul(av[i], &endp, 0);
 
5660
        if (*endp) {
 
5661
            printf("Invalid address \"%s\"\n", av[i]);
 
5662
            rc =  1; goto done;
 
5663
        }
 
5664
 
 
5665
        if (!fim.open(image_fname)) {
 
5666
            printf("*** ERROR *** Image file open failed: %s\n", fim.err());
 
5667
            rc =  1; goto done;
 
5668
        }
 
5669
 
 
5670
        // Write flash
 
5671
        if (!ops.write_image(*f, addr, fim.getBuf(), fim.getBufLength(), !silent)) {
 
5672
            printf("*** ERROR *** Flash write failed: %s\n", ops.err());
 
5673
            rc =  1; goto done;
 
5674
        }
 
5675
    }
 
5676
    break;
 
5677
 
 
5678
    case CMD_WRITE_WORD:
 
5679
    {
 
5680
        // WRITE DWORD
 
5681
        //     Parameters: <ADDR> <DATA>
 
5682
        u_int32_t    data, addr;
 
5683
        char         *endp;
 
5684
 
 
5685
        // Address and data
 
5686
        NEXTC("<ADDR>", "ww");
 
5687
        addr = strtoul(av[i], &endp, 0);
 
5688
        if (*endp) {
 
5689
            printf("Invalid address \"%s\"\n", av[i]);
 
5690
            rc =  1; goto done;
 
5691
        }
 
5692
        NEXTC("<DATA>", "ww");
 
5693
        data = __cpu_to_be32(strtoul(av[i], &endp, 0));
 
5694
        if (*endp) {
 
5695
            printf("Invalid data \"%s\"\n", av[i]);
 
5696
            rc =  1; goto done;
 
5697
        }
 
5698
 
 
5699
        //f->curr_sector = 0xffffffff;  // First time erase sector
 
5700
        if (!f->write(addr, data)) {
 
5701
            printf("*** ERROR *** Flash write failed: %s\n", f->err());
 
5702
            rc =  1; goto done;
 
5703
        }
 
5704
    }
 
5705
    break;
 
5706
 
 
5707
    case CMD_WRITE_BLOCK_NE:
 
5708
    {
 
5709
        // WRITE DWORD WITHOUT ERASE
 
5710
        //     Parameters: <ADDR> <SIZE> <DATA>
 
5711
        u_int32_t    size, addr;
 
5712
        char         *endp;
 
5713
 
 
5714
        // Address and data
 
5715
        NEXTC("<ADDR>", "wbne");
 
5716
        addr = strtoul(av[i], &endp, 0);
 
5717
        if (*endp) {
 
5718
            printf("Invalid address \"%s\"\n", av[i]);
 
5719
            rc =  1; goto done;
 
5720
        }
 
5721
        NEXTC("<SIZE>", "wbne");
 
5722
        size = strtoul(av[i], &endp, 0);
 
5723
        if (*endp || size % 4) {
 
5724
            printf("Invalid size \"%s\"\n", av[i]);
 
5725
            rc =  1; goto done;
 
5726
        }
 
5727
        vector<u_int32_t> data_vec(size/4);
 
5728
        for (u_int32_t w = 0; w < size/4 ; w++) {
 
5729
            NEXTC("<DATA>", "wbne");
 
5730
            data_vec[w] = __cpu_to_be32(strtoul(av[i], &endp, 0));
 
5731
            if (*endp) {
 
5732
                printf("Invalid data \"%s\"\n", av[i]);
 
5733
                rc =  1; goto done;
 
5734
            }
 
5735
 
 
5736
            //printf("-D- writing: %08x : %08x\n", addr + w*4 , data_vec[w]);
 
5737
        }
 
5738
 
 
5739
        if (!f->write(addr, &data_vec[0], size, true)) {
 
5740
            printf("*** ERROR *** Flash write failed: %s\n", f->err());
 
5741
            rc =  1; goto done;
 
5742
        }
 
5743
    }
 
5744
    break;
 
5745
 
 
5746
    case CMD_WRITE_WORD_NE:
 
5747
    {
 
5748
        // WRITE DWORD WITHOUT ERASE
 
5749
        //     Parameters: <ADDR> <DATA>
 
5750
        u_int32_t    data, addr;
 
5751
        char         *endp;
 
5752
 
 
5753
        // Address and data
 
5754
        NEXTC("<ADDR>", "wwne");
 
5755
        addr = strtoul(av[i], &endp, 0);
 
5756
        if (*endp) {
 
5757
            printf("Invalid address \"%s\"\n", av[i]);
 
5758
            rc =  1; goto done;
 
5759
        }
 
5760
        NEXTC("<DATA>", "wwne");
 
5761
        data = __cpu_to_be32(strtoul(av[i], &endp, 0));
 
5762
        if (*endp) {
 
5763
            printf("Invalid data \"%s\"\n", av[i]);
 
5764
            rc =  1; goto done;
 
5765
        }
 
5766
 
 
5767
        if (!f->write(addr, &data, 4, true)) {
 
5768
            printf("*** ERROR *** Flash write failed: %s\n", f->err());
 
5769
            rc =  1; goto done;
 
5770
        }
 
5771
    }
 
5772
    break;
 
5773
 
 
5774
    case CMD_CFI:
 
5775
    {
 
5776
        if (!f->print_attr() || !f->print_attr_old_format()) {
 
5777
            printf("*** ERROR *** Cfi query failed: %s\n", f->err());
 
5778
            rc =  1; goto done;
 
5779
        }
 
5780
    }
 
5781
    break;
 
5782
 
 
5783
    case CMD_CLEAR_SEM:
 
5784
        // Do nothing - opening the device already cleared the semaphore.
 
5785
        break;
 
5786
 
 
5787
    case CMD_SWRESET:
 
5788
        printf("Resetting device %s ...\n", device);
 
5789
        if (!f->sw_reset()) {
 
5790
            printf("*** ERROR *** Software reset failed: %s\n", f->err());
 
5791
            rc =  1; goto done;
 
5792
        }
 
5793
 
 
5794
        break;
 
5795
 
 
5796
    default:
 
5797
        printf("*** INTERNAL ERROR *** Invalid command %d.\n", cmd);
 
5798
        rc =  1; goto done;
 
5799
    }
 
5800
 
 
5801
done:
 
5802
 
 
5803
    //mask signals
 
5804
    for (i = 0 ; i < (int)(sizeof(g_signals_for_termination)/sizeof(g_signals_for_termination[0])) ; i++ ) {
 
5805
        signal (g_signals_for_termination[i], SIG_IGN);
 
5806
    }
 
5807
 
 
5808
    return rc;
 
5809
}
 
5810