3
* flint.cpp - FLash INTerface
5
* Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved.
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:
13
* Redistribution and use in source and binary forms, with or
14
* without modification, are permitted provided that the following
17
* - Redistributions of source code must retain the above
18
* copyright notice, this list of conditions and the following
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.
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
35
* Version: $Id: flint.cpp 4624 2008-08-26 08:32:49Z orenk $
47
#include <sys/types.h>
67
// DJGPP - GCC PORT TO MS DOS
70
#include <mtcr.h> // This contains the u_* types definitions
72
#include <netinet/in.h>
75
#define bswap_32(x) ntohl(x)
77
// djgpp stdio does not define vsnprintf. I simply call vsprintf (and pray ...)
78
#define vsnprintf(buf, len, format, args) (vsprintf(buf, format, args))
85
#include <netinet/in.h>
93
// Windows (Under DDK)
100
#define usleep(x) Sleep((x)/1000)
101
#define sleep(x) Sleep((x)*1000)
103
#define vsnprintf _vsnprintf
104
#define strtoull _strtoui64
105
#define isatty _isatty
107
#define COMP_CDECL __cdecl
109
#define __LITTLE_ENDIAN 1234
110
#define __BIG_ENDIAN 4321
111
#define __BYTE_ORDER __LITTLE_ENDIAN
114
#if __BYTE_ORDER == __LITTLE_ENDIAN
115
#define bswap_32(x) ntohl(x)
117
#error windows is assumed to run a on little endian architecture
128
#ifndef DEV_MST_EXAMPLE1
129
#define DEV_MST_EXAMPLE1 "/dev/mst/mt25418_pci_cr0"
132
#ifndef DEV_MST_EXAMPLE2
133
#define DEV_MST_EXAMPLE2 "/dev/mst/mt25418_pciconf0"
138
#define FLINT_NAME "%1$s"
140
#define FLINT_NAME "./flint"
144
namespace std {}; using namespace std;
147
//char* _versionID = VERSION_ID ;
148
#define __VFSTR(x) #x
149
#define _VFSTR(x) __VFSTR(x)
150
const char* _versionID = _VFSTR( VERSION_ID ) ;
152
const char* _versionID = "ofed_1.4";
155
const char* _svnID = "$Revision: 4624 $";
157
#ifndef __be32_to_cpu
158
#define __be32_to_cpu(x) ntohl(x)
160
#define bswap_32(x) (htonl(x))
163
#ifndef __cpu_to_be32
164
#define __cpu_to_be32(x) htonl(x)
167
#if __BYTE_ORDER == __LITTLE_ENDIAN
168
#ifndef __cpu_to_le32
169
#define __cpu_to_le32(x) (x)
171
#ifndef __le32_to_cpu
172
#define __le32_to_cpu(x) (x)
174
#elif __BYTE_ORDER == __BIG_ENDIAN
175
#ifndef __cpu_to_le32
176
#define __cpu_to_le32(x) bswap_32(x)
178
#ifndef __le32_to_cpu
179
#define __le32_to_cpu(x) bswap_32(x)
182
#ifndef __cpu_to_le32
183
#define __cpu_to_le32(x) bswap_32(__cpu_to_be32(x))
185
#ifndef __le32_to_cpu
186
#define __le32_to_cpu(x) __be32_to_cpu(bswap_32(x))
191
////////////////////////////////////////////////////////////////////////
193
// ****************************************************************** //
194
// Miscellaneous global stuff //
195
// ****************************************************************** //
197
////////////////////////////////////////////////////////////////////////
198
typedef struct guid {
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);
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);
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); \
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); \
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); \
231
#define TOCPUBY64(s) do { \
233
for (unsigned ii=0; ii<sizeof(s)/sizeof(guid_t); ii++,p++) \
234
be_guid_to_cpu(p,p); \
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++) \
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++) \
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++) \
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++) \
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++) \
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++) \
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)
278
ErrMsg() : _err(0) { }
279
~ErrMsg() { err_clear(); }
280
const char *err() const { return _err; }
281
void err_clear() { delete [] _err; _err = 0; }
285
char *vprint(const char *format, va_list args)
287
const int INIT_VAL = 1024;
288
int max_str, max_buf = INIT_VAL;
293
out_buf = new char[max_buf];
294
max_str = max_buf - 1;
296
if (vsnprintf(out_buf, max_str, format, args) < max_str)
304
bool errmsg(const char *format, ...)
306
__attribute__ ((format (printf, 2, 3)))
316
bool ErrMsg::errmsg(const char *format, ...) {
319
char* prev_err = _err;
321
va_start(args, format);
322
_err = vprint(format, args);
332
SIGNATURE = 0x5a445a44,
333
MELLANOX_VENDOR_ID = 0x15b3
339
u_int32_t fw_reserved[5];
362
const char* g_sectNames[] = {
363
"UNKNOWN (0 - Reserved)",
385
#define MAX_SECTION_SIZE 0x400000
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;
392
char bsn[BOARD_ID_BSN_LEN];
393
char bid[BOARD_ID_BID_LEN];
396
int const VSD_LEN = 208;
397
int const PSID_LEN = 16;
398
int const PRODUCT_VER_LEN = 16;
401
// TODO: Remove the below globals to class members.
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;
410
bool _unlock_bypass = false;
412
bool _byte_write = false;
415
void report(const char *format, ...)
417
__attribute__ ((format (printf, 1, 2)))
420
void report(const char *format, ...)
425
va_start(args, format);
426
vprintf(format, args);
431
void report_erase(const char *format, ...)
441
va_start(args, format);
442
vsnprintf(buf, sizeof buf, format, args);
446
for(i=0; i < len; ++i)
451
////////////////////////////////////////////////////////////////////////
453
// ****************************************************************** //
454
// CRC16 CALCULATION //
455
// ****************************************************************** //
457
////////////////////////////////////////////////////////////////////////
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);
471
////////////////////////////////////////////////////////////////////////
472
void Crc16::add(u_int32_t o)
475
printf("Crc16::add(%08x)\n", o);
476
for (int i=0; i<32; i++) {
478
_crc = (u_int16_t) ((((_crc<<1) | (o>>31)) ^ 0x100b) & 0xffff);
480
_crc= (u_int16_t) (((_crc<<1) | (o>>31)) & 0xffff);
481
o = (o<<1) & 0xffffffff;
486
////////////////////////////////////////////////////////////////////////
489
for (int i=0; i<16; i++) {
491
_crc=((_crc<<1) ^ 0x100b) & 0xffff;
493
_crc=(_crc<<1) & 0xffff;
496
// Revert 16 low bits
497
_crc = _crc ^ 0xffff;
502
//////////////////////////////////////////////////////////////////////
504
// class u_int32_ba (bit access):
505
// A uint wrapper which allows easy access to bit/range of bits.
509
// Read_Word( Table.reg ,&a);
510
// int upper_byte = a.range(31,24);
512
// cout << " Bit 15 is 1 \n";
514
// cout << " Bit 15 is 0 \n";
517
// b.range(15,12) = 0xa;
518
// b[31] = 1; // b == 0x8000a000
519
// Write_Word( Table.reg ,b);
521
//////////////////////////////////////////////////////////////////////
526
u_int32_ba(u_int32_t i = 0) :
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);}
537
u_int32_ba range (u_int8_t eptr,
538
u_int8_t sptr) {return u_int32_ba(*this,eptr,sptr);}
541
u_int32_ba(u_int32_ba& other, u_int8_t eptr, u_int8_t sptr) :
548
u_int32_t s_msk = (u_int32_t)-1; // start mask
549
u_int32_t e_msk = (u_int32_t)-1; // end mask
551
s_msk = (s_msk << _sptr1);
552
e_msk = (_eptr >= (sizeof(_bits)*8-1)) ? e_msk : ~(e_msk << (_eptr+1));
554
return(s_msk & e_msk);
564
//////////////////////////////////////////////////////////////////////
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.
572
//////////////////////////////////////////////////////////////////////
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)
581
if (_log2_alignment_size == 0) {
582
_log2_alignment_size = 31;
583
_alignment_size = 1 << _log2_alignment_size;
584
_alignment_mask = _alignment_size - 1;
588
void Init (u_int32_t addr, u_int32_t size) {
593
bool GetNextChunk(u_int32_t& chunk_addr, u_int32_t& chunk_size) {
594
if (_curr_size == 0) {
598
chunk_addr = _curr_addr;
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);
605
chunk_size = _curr_size;
608
_curr_addr += chunk_size;
609
_curr_size -= chunk_size;
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;
625
////////////////////////////////////////////////////////////////////////
627
// ****************************************************************** //
629
// ****************************************************************** //
631
////////////////////////////////////////////////////////////////////////
633
// Common base class for Flash and for FImage
636
class FBase : public ErrMsg{
638
FBase(bool is_flash) :
640
_is_flash(is_flash) {}
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;
649
virtual u_int32_t get_sector_size() = 0;
650
virtual u_int32_t get_size() = 0;
652
virtual u_int32_t get_dev_id() = 0;
654
bool is_flash() {return _is_flash;};
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;
662
MAX_FLASH = 4*1048576
667
// Address translation functions for ConnectX.
668
// Translate between contiguous "logical" addresses
670
// If Failsafe zebra mapping is enabled:
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
677
u_int32_t cont2phys(u_int32_t cont_addr) {
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)));
689
u_int32_t phys2cont(u_int32_t phys_addr) {
691
if (_log2_chunk_size) {
692
result = (phys_addr & (0xffffffff >> (32 - _log2_chunk_size))) |
693
((phys_addr >> 1) & (0xffffffff << ( _log2_chunk_size)));
700
bool _is_image_in_odd_chunks;
701
u_int32_t _log2_chunk_size;
703
const bool _is_flash;
708
class FImage : public FBase {
710
FImage() : FBase(false), _buf(0) {}
711
virtual ~FImage() { close();}
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);
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;}
730
// Flash access (R/W)
732
class Flash : public FBase {
737
_curr_sector(0xffffffff),
741
virtual ~Flash() { close();};
745
virtual bool open (const char *device,
746
bool force_lock = false,
747
bool read_only = false);
749
virtual void close ();
751
virtual bool read (u_int32_t addr,
754
virtual bool read (u_int32_t addr,
757
bool verbose = false);
759
bool cr_write (u_int32_t addr,
760
u_int32_t data) {return mf_cr_write(_mfl, addr, data) == MFE_OK;}
766
u_int32_t get_sector_size () {return _attr.sector_size; }
767
u_int32_t get_size () {return _attr.size;}
769
u_int32_t get_dev_id () {return _attr.hw_dev_id;}
771
u_int32_t get_port_num () {return _port_num;}
775
// Write and Erase functions are performed by the Command Set
777
virtual bool erase_sector (u_int32_t addr);
779
virtual bool write (u_int32_t addr,
782
bool noerase = false);
784
virtual bool write (u_int32_t addr,
788
bool print_attr_old_format();
794
static bool _byte_mode;
803
u_int32_t _curr_sector;
808
////////////////////////////////////////////////////////////////////////
810
// FImage Class Implementation
812
////////////////////////////////////////////////////////////////////////
814
bool FImage::open(const char *fname, bool read_only)
820
read_only = true; // FImage can be opened only for read
822
fh = fopen(fname, "rb");
825
return errmsg("Can not open file \"%s\" - %s\n", fname, strerror(errno));
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));
835
return errmsg("Can not get file size for \"%s\" - %s\n", fname, strerror(errno));
839
//printf("-D- %s size is %d\n", fname, fsize);
841
return errmsg("Image size should be 4-bytes aligned. Make sure file %s is in the right format (binary image)",
845
_buf = new u_int32_t[fsize/4];
846
if ((r_cnt = fread(_buf, 1, fsize, fh)) != fsize) {
848
return errmsg("Read error on file \"%s\" - %s\n",fname, strerror(errno));
850
return errmsg("Read error on file \"%s\" - read only %d bytes (from %ld)\n",
851
fname, r_cnt, (unsigned long)fsize);
860
////////////////////////////////////////////////////////////////////////
867
////////////////////////////////////////////////////////////////////////
868
bool FImage::read(u_int32_t addr, u_int32_t *data)
870
return read(addr, data, 4);
873
////////////////////////////////////////////////////////////////////////
874
bool FImage::read(u_int32_t addr, void *data, int len, bool)
878
return errmsg("Address should be 4-bytes aligned.");
881
return errmsg("Length should be 4-bytes aligned.");
884
return errmsg("read() when not opened");
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)",
890
_log2_chunk_size ? "physical " : "",
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);
902
memcpy((u_int8_t*)data + (chunk_addr - addr),
903
(u_int8_t*)_buf + phys_addr,
910
////////////////////////////////////////////////////////////////////////
911
u_int32_t FImage::get_sector_size()
913
u_int32_t log2_sector_sz_ptr;
914
u_int32_t log2_sector_sz;
917
read(0x24, &signature);
919
if (signature == SIGNATURE) {
921
read(0x14, &log2_sector_sz_ptr);
922
TOCPU1(log2_sector_sz_ptr);
923
log2_sector_sz_ptr &= 0xffff;
925
read(0x30 + log2_sector_sz_ptr, &log2_sector_sz);
926
TOCPU1(log2_sector_sz);
927
log2_sector_sz &= 0xffff;
929
return(1 << log2_sector_sz);
938
////////////////////////////////////////////////////////////////////////
940
// Flash Class Implementation
942
////////////////////////////////////////////////////////////////////////
945
bool Flash::_byte_mode = false;
947
////////////////////////////////////////////////////////////////////////
948
bool Flash::open(const char *device, bool force_lock, bool read_only)
954
rc = mf_open(&_mfl, device);
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);
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.");
965
return errmsg("%s %s", errno == 0 ? "" : strerror(errno), mf_err2str(rc));
968
rc = mf_get_attr(_mfl, &_attr);
970
return errmsg("Failed getting flash attributes for device %s: %s", device, mf_err2str(rc));
973
if (_attr.hw_dev_id == 435) {
976
else if (_attr.hw_dev_id == 25204 || _attr.hw_dev_id == 24204) {
983
rc = mf_set_opt(_mfl, MFO_AMD_BYTE_MODE, 1);
985
return errmsg("Failed setting byte mode fore device %s: %s", device, mf_err2str(rc));
992
////////////////////////////////////////////////////////////////////////
1003
bool Flash::read(u_int32_t addr,
1007
u_int32_t phys_addr = cont2phys(addr);
1008
rc = mf_read(_mfl, phys_addr, 4, (u_int8_t*)data);
1010
return errmsg("Flash read failed at address %s%x : %s",
1011
_log2_chunk_size ? "physical " : "",
1019
////////////////////////////////////////////////////////////////////////
1020
bool Flash::read(u_int32_t addr, void *data, int len, bool verbose)
1023
u_int32_t perc = 0xffffffff;
1026
return errmsg("Address should be 4-bytes aligned.");
1029
return errmsg("Length should be 4-bytes aligned.");
1038
// Much better perf for read in a single chunk. need to work on progress report though.
1039
bool read_in_single_chunk = true;
1041
if (read_in_single_chunk) {
1042
u_int32_t chunk_addr;
1043
u_int32_t chunk_size;
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);
1050
rc = mf_read(_mfl, phys_addr, chunk_size, ((u_int8_t*)data) + chunk_addr - addr);
1052
return errmsg("Flash read failed at address %s%x : %s",
1053
_log2_chunk_size ? "physical " : "",
1060
u_int32_t *p = (u_int32_t *)data;
1061
for (int i=0; i<len/4; i++) {
1062
if (!read(addr, p++))
1069
u_int32_t new_perc = (i * 100) / len;
1070
if (new_perc != perc) {
1071
printf("\b\b\b\b%03d%%", new_perc);
1080
printf("\b\b\b\b100%%");
1088
////////////////////////////////////////////////////////////////////////
1089
bool Flash::write (u_int32_t addr,
1096
noerase = _no_erase || noerase;
1099
return errmsg("Not opened");
1102
return errmsg("Address should be 4-bytes aligned.");
1106
if (cont2phys(addr + cnt) > get_size()) {
1108
"Trying to write %d bytes to address 0x%x, which exceeds max image size (0x%x - half of total flash size).",
1114
u_int8_t *p = (u_int8_t *)data;
1115
u_int32_t sect_size = get_sector_size();
1117
u_int32_t chunk_addr;
1118
u_int32_t chunk_size;
1120
u_int32_t first_set;
1121
for (first_set = 0; ((sect_size >> first_set) & 1) == 0; first_set++ )
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
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))
1143
u_int32_t phys_addr = cont2phys(chunk_addr);
1144
rc = mf_write(_mfl, phys_addr, chunk_size, p);
1146
return errmsg("Flash write of %d bytes to address %s0x%x failed: %s",
1148
_log2_chunk_size ? "physical " : "",
1161
////////////////////////////////////////////////////////////////////////
1162
bool Flash::write(u_int32_t addr, u_int32_t data)
1165
return errmsg("Not opened");
1168
return errmsg("Address should be 4-bytes aligned.");
1173
u_int32_t sector_size = _attr.sector_size;
1174
u_int32_t sector_mask = ~(sector_size - 1);
1176
u_int32_t sector = addr & sector_mask;
1177
u_int32_t word_in_sector = (addr & ~sector_mask)/sizeof(u_int32_t);
1179
if (!read(addr, &word))
1182
return true; // already there
1184
vector<u_int32_t> buff(sector_size/sizeof(u_int32_t));
1185
if (!read(sector, &buff[0] , sector_size))
1187
buff[word_in_sector] = data;
1188
return write(sector, &buff[0], sector_size);
1192
bool Flash::erase_sector (u_int32_t addr) {
1195
u_int32_t phys_addr = cont2phys(addr);
1196
rc = mf_erase_sector(_mfl, phys_addr);
1198
return errmsg("Flash erase of address 0x%x failed: %s",
1206
bool Flash::sw_reset() {
1207
if (_attr.hw_dev_id != 435) {
1208
return errmsg("operation supported only for InfiniScale4 switch over IB interface");
1210
int rc = mf_sw_reset(_mfl);
1212
return errmsg("%s %s", errno == 0 ? "" : strerror(errno), mf_err2str(rc));
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);
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:
1235
printf("\n----Sector Organization Parameters-------------------\n\n");
1237
printf("%-50s ", "Device size:");
1238
printf("[%8li] bytes, or [%2i] Mbit\n",
1239
(long int)_attr.size,
1240
(int) (_attr.size/((long)0x20000)));
1242
printf("%-50s ", "Number of erase block regions:");
1243
printf("%d\n", _attr.num_erase_blocks);
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);
1254
////////////////////////////////////////////////////////////////////////
1258
////////////////////////////////////////////////////////////////////////
1260
// Burn Operations functions
1262
////////////////////////////////////////////////////////////////////////
1264
class Operations : public ErrMsg {
1267
_last_image_addr(0),
1269
_allow_skip_is(false),
1271
_cntx_striped_image(false),
1272
_burn_blank_guids(false),
1273
_quick_query(false){}
1281
enum ImageInfoTags {
1282
II_IiFormatRevision = 0,
1288
II_SuppurtedPsids = 6,
1292
II_Last = 10, // Mark the end of used tag ids
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,
1306
ImageInfo* flash_info,
1307
ImageInfo* image_info,
1308
bool allow_nofs = false);
1310
bool CheckMatchingDevId(u_int32_t hwDevId, u_int32_t imageDevId);
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);
1316
bool LoadAsExpRom (FBase& f);
1318
bool DumpConf (const char* conf_file = NULL);
1319
bool GetExpRomVersion(ImageInfo* info);
1321
bool DisplayExpRomInfo(ImageInfo* info);
1322
bool DisplayImageInfo (ImageInfo* info);
1324
bool QueryAll (FBase& f, ImageInfo* info) {return (IsCntx() ||
1325
(QueryIs(f, info) &&
1326
(!info->isFailsafe || QueryPs(f, info)))) &&
1327
QueryImage(f, info);}
1329
bool getBSN (char *s, guid_t *guid);
1330
bool getGUID (const char *s, guid_t *guid);
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);
1341
void SetDevFlags(u_int16_t devType, bool& ib_dev, bool& eth_dev);
1342
bool CheckGuidsFlags(u_int16_t devType,
1344
bool guids_specified,
1346
bool macs_specified);
1348
bool patchGUIDs (FImage& f,
1354
guid_t new_guids[MAX_GUIDS],
1355
guid_t old_guids[MAX_GUIDS],
1356
u_int32_t num_of_old_guids,
1359
bool printGUIDs(const char* msg, guid_t guids[MAX_GUIDS], bool print_guids, bool print_macs, bool old_guid_fmt);
1361
void SetNumPorts (u_int32_t num_ports) {_num_ports = num_ports;}
1362
void SetAllowSkipIs (bool asis) {_allow_skip_is = asis;}
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;}
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);
1375
bool CheckIsCntx (FBase& f);
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
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
1391
bool IsIs4 (u_int32_t devid) {
1392
return (devid == 435) ||
1398
bool CntxIsMp (u_int32_t devid) {return CntxIsIb(devid) && CntxIsEth(devid);}
1402
// _last_image_addr is set by the Verify() op
1403
u_int32_t _last_image_addr;
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 ...).
1416
memset(allImgStart, 0, sizeof(allImgStart));
1417
memset(guids , 0xff, sizeof(guids));
1421
for (int i=0; i < II_Last; i++ )
1424
expRomFound = false;
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).
1435
u_int32_t allImgStart[2];
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;
1448
// For ConnectX, guids 4:5 are the cards MAC addresses (if applicable)
1449
guid_t guids[MAX_GUIDS];
1454
u_int32_t infoSectPtr;
1456
u_int16_t vsdVendorId;
1457
char vsd[VSD_LEN+1];
1458
char psid[PSID_LEN+1];
1459
char productVer[17];
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}
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.
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;
1479
bool magicPatternFound;
1482
enum {MAX_SW_DEVICES_PER_HW=16};
1488
// Zero terminated list of SW device ids
1489
const u_int32_t swDevIds[MAX_SW_DEVICES_PER_HW];
1492
bool FwVerLessThan(u_int16_t r1[3], u_int16_t r2[3]) {
1494
for (i = 0; i < 3 ; i++)
1497
else if (r1[i] > r2[i])
1500
return false; // equal versions
1503
enum {CNTX_START_POS_SIZE = 6};
1505
static const u_int32_t _cntx_image_start_pos[CNTX_START_POS_SIZE];
1507
static const u_int32_t _cntx_magic_pattern[4];
1509
void patchGUIDsSection (u_int32_t *buf, u_int32_t ind,
1510
guid_t guids[GUIDS], int nguids);
1513
bool FailSafe_burn_image (Flash& f,
1516
const char* image_name,
1521
bool CheckInvariantSector (Flash& f, u_int32_t *data32, int sect_size);
1523
bool FailSafe_burn_internal (Flash& f, void *data, int cnt, bool need_report);
1525
bool checkBoot2 (FBase& f, u_int32_t beg, u_int32_t offs,
1526
u_int32_t& next, const char *pref);
1528
bool checkGen (FBase& f, u_int32_t beg,
1529
u_int32_t offs, u_int32_t& next, const char *pref);
1531
bool checkPS (FBase& f, u_int32_t offs, u_int32_t& next, const char *pref);
1533
bool checkList (FBase& f, u_int32_t offs, u_int32_t fw_start, const char *pref);
1535
bool extractGUIDptr (u_int32_t sign, u_int32_t *buf, int buf_len,
1536
char *pref, u_int32_t *ind, int *nguids);
1539
void recalcSectionCrc (u_int8_t *buf, u_int32_t data_size);
1541
u_int32_t BSN_subfield (const char *s, int beg, int len);
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);
1548
void PatchInfoSect (u_int8_t* rawSect,
1552
bool QueryIs (FBase& f, ImageInfo* info);
1553
bool QueryPs (FBase& f, ImageInfo* info);
1554
bool QueryImage (FBase& f, ImageInfo* info);
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);
1560
bool ParseInfoSect (u_int8_t* buff, u_int32_t byteSize, ImageInfo *info);
1562
u_int32_t _num_ports;
1563
bool _allow_skip_is;
1565
bool _cntx_striped_image;
1567
bool _burn_blank_guids;
1570
static const HwDevData hwDevData[];
1572
std::vector<u_int8_t> _fw_conf_sect;
1573
std::vector<u_int8_t> _rom_sect;
1577
const u_int32_t Operations::_cntx_magic_pattern[4] = {
1578
0x4D544657, // Ascii of "MTFW"
1579
0x8CDFD000, // Random data
1584
const u_int32_t Operations::_cntx_image_start_pos[Operations::CNTX_START_POS_SIZE] = {
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,
1600
{ "InfiniScale IV" , 435 , 0, {48436, 48437, 48438, 0}},
1601
{ NULL , 0 , 0, {0}},// zero devid terminator
1605
// Asks user a yes/no question.
1606
// Returns true if user chose Y, false if user chose N.
1609
bool Operations::ask_user() {
1610
printf("\n Do you want to continue ? (y/n) [n] : ");
1618
return errmsg("-no flag is set");
1622
return errmsg("Not on tty - Can not interact. assuming \"no\"");
1625
fgets(ansbuff, 30, stdin);
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");
1637
bool Operations::write_image(Flash& f, u_int32_t addr, void *data, int cnt, bool need_report)
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;
1644
//f.curr_sector = 0xffffffff; // Erase sector first time
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());
1662
u_int32_t new_perc = ((cnt - towrite) * 100) / cnt;
1663
if (new_perc != perc) {
1664
printf("\b\b\b\b%03d%%", new_perc);
1672
printf("\b\b\b\b100%%");
1677
} // Flash::write_image
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();
1684
if (!f.write( sect_size * (image_idx + 1) + 8, &sig, 4, true))
1691
////////////////////////////////////////////////////////////////////////
1692
bool Operations::repair(Flash& f, const int from, const int to, bool need_report)
1695
u_int32_t sect_size = f.get_sector_size();
1697
report("Repairing: Copy %s image to %s -", from ? "secondary" : "primary" ,
1698
to ? "secondary" : "primary");
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");
1708
report_erase(" READ %s 100%", from ? "SPS" : "PPS");
1710
u_int32_t im_ptr = sect[0];
1711
u_int32_t sig = sect[2];
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);
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");
1729
// Valid image size in sectors
1730
u_int32_t im_size_s = (im_size_b + sect_size - 1) / sect_size;
1732
// Address to copy valid image
1733
u_int32_t write_to = (!to) ? sect_size * 3 : sect_size * (3 + im_size_s);
1735
// f.read valid image
1736
report(" READ FW ");
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");
1744
report_erase(" READ FW 100%");
1746
// Copy it to right place
1747
report("\b WRITE FW ");
1749
if (!write_image(f, write_to, buf, im_size_b, need_report)) {
1750
report("FAILED\n\n");
1755
report_erase(" WRITE FW 100%");
1757
// Set new image address
1759
sect[0] = __be32_to_cpu(write_to);
1761
// Calculate new CRC
1765
for (u_int32_t i = 0; i < (sizeof(sect)/4 - 1) ; i++) {
1766
crc << __be32_to_cpu(sect[i]);
1770
sect[sizeof(sect)/4 - 1] = __be32_to_cpu(crc.get());
1772
// Corrupt signature
1773
u_int32_t valid_signature = sect[2];
1774
sect[2] = 0xffffffff;
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");
1782
report_erase(" WRITE %s 100%", to ? "SPS" : "PPS");
1784
// Validate signature
1785
report("\b SIGNATURE ");
1786
if (!WriteSignature(f, to, valid_signature)) {
1787
report("FAILED\n\n");
1791
report_erase(" SIGNATURE ");
1800
////////////////////////////////////////////////////////////////////////
1801
bool Operations::FailSafe_burn_image(Flash& f,
1804
const char* image_name,
1809
u_int8_t* data8 = (u_int8_t*) data;
1810
u_int32_t sect_size = f.get_sector_size();
1812
report("Burning %-6s FW image without signatures - ", image_name);
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");
1822
// Burn image (from new offset)
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");
1830
report("\b\b\b\bOK \n");
1831
report("Restoring %-6s signature - ", image_name);
1835
if (!write_image(f, ps_addr, data8 + ps_addr, sect_size, false)) {
1836
report("FAILED\n\n");
1840
// Validate signature
1841
u_int32_t sig = SIGNATURE;
1843
if (!f.write(ps_addr + 8, &sig, 4, true)) {
1844
report("FAILED\n\n");
1854
////////////////////////////////////////////////////////////////////////
1855
bool Operations::FailSafe_burn_internal(Flash& f, void *data, int cnt, bool need_report)
1857
u_int32_t *data32 = (u_int32_t *)data;
1859
u_int32_t sect_size = f.get_sector_size();
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];
1870
if ((cnt < (int)(prim_ptr + prim_len)) || (cnt < (int)(scnd_ptr + scnd_len))) {
1871
return errmsg("Invalid image: too small.");
1873
if (prim_len != scnd_len) {
1874
return errmsg("Invalid image: two FW images should have the same size.");
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");
1883
TOCPU1(old_im_size);
1885
u_int32_t prim_order;
1886
u_int32_t scnd_order;
1888
u_int32_t ps_addr[2];
1889
u_int32_t image_addr[2];
1890
const char* image_name[2];
1893
if (prim_len > old_im_size) {
1901
image_name[scnd_order] = "Secondary";
1902
image_addr[scnd_order] = scnd_ptr;
1903
ps_addr [scnd_order] = sect_size * 2;
1905
image_name[prim_order] = "Primary";
1906
image_addr[prim_order] = prim_ptr;
1907
ps_addr [prim_order] = sect_size;
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)) {
1919
bool Operations::CheckInvariantSector(Flash& f, u_int32_t *data32, int sect_size) {
1922
report("\nRead and verify Invariant Sector - ");
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");
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);
1937
// Now check Invariant sector contents
1938
vector<u_int32_t> buf1(sect_size/4);
1940
if (!f.read(0, &buf1[0] , sect_size)) {
1941
report("FAILED\n\n");
1945
int first_diff = -1;
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)
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]);
1961
printf(" The invariant sector can not be burnt in a failsafe manner.\n");
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");
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");
1975
return errmsg("Invariant sector mismatch");
1984
////////////////////////////////////////////////////////////////////////
1985
bool Operations::FailSafeBurn(Flash& f, FImage& fim, bool need_report, bool single_image_burn)
1987
u_int32_t *data32 = fim.getBuf();
1988
u_int8_t *data8 = (u_int8_t *) data32;
1990
int size = fim.getBufLength();
1994
u_int32_t sect_size = f.get_sector_size();
1995
u_int32_t img_sect_size = fim.get_sector_size();
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",
2005
if (size < (int)sect_size * 3) {
2006
report("FAILED\n\n");
2007
return errmsg("Image is too small.");
2010
if (!CheckInvariantSector(f, data32, sect_size)) {
2014
// Check signatures in image
2015
u_int32_t actual_signature = data32[sect_size/4 + 2];
2017
u_int32_t signature_for_compare = actual_signature;
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);
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);
2031
// Corrupt signatures in image
2032
data32[sect_size/4 + 2] = 0xffffffff;
2033
data32[(sect_size * 2)/4 + 2] = 0xffffffff;
2035
bool cur_image_ok[2] = {false, false};
2036
u_int32_t cur_image_addr[2];
2037
u_int32_t cur_image_size[2];
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)) {
2045
TOCPU1(signature_for_compare);
2046
if (signature_for_compare == SIGNATURE) {
2047
cur_image_ok[i] = true;
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");
2055
TOCPU1(cur_image_addr[i]);
2056
TOCPU1(cur_image_size[i]);
2060
if (!cur_image_ok[0] && !cur_image_ok[1]) {
2062
// Both images are invalid on flash
2063
// --------------------------------
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");
2072
report("Burn FW image without signatures - ");
2074
if (!write_image(f, sect_size, data8 + sect_size, size - sect_size, need_report)) {
2075
report("FAILED\n\n");
2078
report("\b\b\b\bOK \n");
2080
// Restore signatures
2081
report("Restore right signatures - ");
2083
if (!WriteSignature(f, 0, actual_signature)) {
2084
report("FAILED (PPS Signature)\n\n");
2087
if (!WriteSignature(f, 1, actual_signature)) {
2088
report("FAILED (SPS Signature)\n\n");
2097
if (single_image_burn == false) {
2099
if (cur_image_ok[0] == false || cur_image_ok[1] == false) {
2103
assert (cur_image_ok[1] || cur_image_ok[0]);
2105
if (cur_image_ok[1]) {
2113
report("Reparable Error Detected.\n");
2114
if (!repair(f, image_from, image_to, need_report))
2119
// Both images are valid on flash
2121
return FailSafe_burn_internal(f, data, size, need_report);
2126
// Single image burn:
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);
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.
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))
2148
// Now 2 images are valid
2149
cur_image_ok[0] = true;
2151
if (!FailSafe_burn_image(f, data, sect_size, "first", sect_size * 3, frst_new_image_size, need_report))
2154
if (!WriteSignature(f, 1, 0))
2161
if (cur_image_ok[0] && cur_image_ok[1]) {
2162
// Invalidate second image
2163
if (!WriteSignature(f, 1, 0)) {
2168
cur_image_ok[1] = false;
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 ;
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.
2179
// TODO: STOP THIS MOVEMENT BULLSHI%@#&! !!! : Reproduce PS in flint with the correct addr. Locate second image in middle of flash.
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))
2187
// Now 2 images are valid
2188
cur_image_ok[1] = true;
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))
2195
if (!WriteSignature(f, 1, 0))
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))
2205
// Invalidate first image
2206
if (!WriteSignature(f, 0, 0))
2213
report("Bad flash state: Valid images = (%d,%d).\n", cur_image_ok[0], cur_image_ok[1] );
2222
bool Operations::CntxFailSafeBurn(Flash& f,
2225
Operations::ImageInfo* flash_info,
2226
Operations::ImageInfo* image_info,
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;
2234
bool is_curr_image_in_odd_chunks;
2237
if (!image_info->isFailsafe) {
2238
return errmsg("The given image is not a failsae image");
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);
2248
u_int32_t new_image_start;
2250
if (flash_info->imgStart != 0) {
2251
is_curr_image_in_odd_chunks = 1;
2252
new_image_start = 0;
2254
is_curr_image_in_odd_chunks = 0;
2255
new_image_start = (1 << image_info->cntxLog2ChunkSize);
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,
2262
// flash_info->cntxLog2ChunkSize);
2264
if (image_info->isFailsafe) {
2265
f.set_address_convertor(image_info->cntxLog2ChunkSize, !is_curr_image_in_odd_chunks);
2267
f.set_address_convertor(0,0);
2268
new_image_start = 0;
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);
2277
if (!write_image(f, 16 , data8 + 16, image_size - 16, need_report)) {
2278
report("FAILED\n\n");
2281
report("\b\b\b\bOK \n");
2283
report("Restoring %-6s signature - ", image_name);
2287
// Write new signature
2288
if (!f.write(0, data8, 16, true)) {
2289
report("FAILED\n\n");
2293
// Write new image start address to crspace (for SW reset)
2294
f.cr_write(0xf0000, (new_image_start << 8) | 0x06);
2296
if (image_info->isFailsafe) {
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
2302
u_int32_t cntx_image_start[CNTX_START_POS_SIZE];
2303
u_int32_t cntx_image_num;
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");
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");
2325
report("\b\b\b\bOK \n");
2327
if (allow_nofs && image_info->isFailsafe) {
2337
////////////////////////////////////////////////////////////////////////
2339
// ****************************************************************** //
2341
// ****************************************************************** //
2343
////////////////////////////////////////////////////////////////////////
2347
// Cntx image verification flow:
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.
2356
// Verification flow:
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)
2363
// Set address translation according to the fs_zebra_size.
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
2372
bool Operations::CntxFindMagicPattern (FBase& f, u_int32_t addr) {
2374
if (addr + 16 > f.get_size()) {
2377
for (i = 0; i < 4 ; i++) {
2379
READ4(f, addr + i * 4, &w, "Magic Pattern" );
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);
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) {
2395
f.set_address_convertor(0,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];
2408
bool Operations::checkBoot2(FBase& f, u_int32_t beg, u_int32_t offs,
2409
u_int32_t& next, const char *pref)
2413
char *pr = (char *)alloca(strlen(pref) + 512);
2415
sprintf(pr, "%s /0x%08x/ (BOOT2)", pref, offs+beg);
2418
READ4(f, offs+beg+4, &size, pr);
2420
if (size > 1048576 || size < 4) {
2421
report("%s /0x%08x/ - unexpected size (0x%x)\n", pr, offs+beg+4, size);
2425
sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (BOOT2)", pref, offs+beg,
2426
offs+beg+(size+4)*4-1, (size+4)*4);
2429
u_int32_t *buff = (u_int32_t*)alloca((size + 4)*sizeof(u_int32_t));
2431
READBUF(f, offs+beg, buff, size*4 + 16, pr);
2432
TOCPUn(buff, size+4);
2433
CRC1n(crc, buff, size+4);
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");
2443
report("%s - OK (CRC:0x%04x)\n", pr, crc_act&0xffff);
2445
report("%s - OK\n", pr);
2446
next = offs + size*4 + 16;
2450
static int part_cnt;
2452
////////////////////////////////////////////////////////////////////////
2453
bool Operations::checkGen(FBase& f, u_int32_t beg,
2454
u_int32_t offs, u_int32_t& next, const char *pref)
2456
char *pr = (char *)alloca(strlen(pref) + 100);
2458
char unknown_sect_name[128];
2459
const char* sect_name;
2465
sprintf(pr, "%s /0x%08x/ (GeneralHeader)", pref, offs+beg);
2466
READBUF(f, offs+beg, &gph, sizeof(GPH), pr);
2473
if (gph.type < H_FIRST || gph.type >= H_LAST) {
2475
//report("%s /0x%x/ - Invalid partition type (%d)\n",
2476
// pref, offs+beg, gph.type);
2479
return checkBoot2(f, beg, offs, next, pref);
2482
// All partitions here
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;
2493
if (gph.type == H_EMT) {
2494
size = (gph.size + 3) / 4 * 4;
2496
size = gph.size * 4;
2498
sect_name = g_sectNames[gph.type];
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);
2505
if (size > MAX_SECTION_SIZE) {
2506
report("%s - size too big (0x%x)\n",
2513
std::vector<u_int8_t> buffv(size);
2514
u_int32_t *buff = (u_int32_t*)(&(buffv[0]));
2516
READBUF(f, offs+sizeof(gph), buff, size, pr);
2518
TOCPUn(buff,size/4);
2520
CRCn(crc, buff, size/4);
2523
READ4(f, offs+sizeof(gph)+size, &crc_act, pr);
2525
bool blank_crc = false;
2526
if (gph.type == H_GUID && crc_act == 0xffff) {
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");
2535
report("%s - OK (CRC:0x%04x)\n", pr, crc_act&0xffff);
2538
report("%s - BLANK CRC (0xffff)\n", pr);
2540
report("%s - OK\n", pr);
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));
2552
if (gph.type == H_ROM && _rom_sect.empty()) {
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));
2559
// mark last read addr
2560
_last_image_addr = offs + size +sizeof(gph) + 4; // the 4 is for the trailing crc
2565
////////////////////////////////////////////////////////////////////////
2566
bool Operations::checkPS(FBase& f, u_int32_t offs, u_int32_t& next, const char *pref)
2570
f.read(offs, &ps, sizeof(ps));
2574
if (ps.signature != SIGNATURE) {
2575
report("%s Pointer Sector /0x%08x/ - invalid signature (%08x)\n",
2576
pref, offs, ps.signature);
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");
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);
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));
2599
////////////////////////////////////////////////////////////////////////
2600
bool Operations::checkList(FBase& f, u_int32_t offs, u_int32_t fw_start, const char *pref)
2604
CHECKB2(f, offs, fw_start, next_ptr, pref);
2606
while (next_ptr && next_ptr != 0xff000000)
2607
CHECKGN(f, offs, next_ptr, next_ptr, pref);
2612
////////////////////////////////////////////////////////////////////////
2614
bool Operations::CheckIsCntx(FBase& f) {
2616
return ( ((Flash*)&f)->get_dev_id() == 400) ||
2617
( ((Flash*)&f)->get_dev_id() == 435);
2620
u_int32_t found_images;
2621
u_int32_t image_start[CNTX_START_POS_SIZE];
2623
// Image - check if magic pattern is somewhere in the file:
2624
CntxFindAllImageStart(f, image_start, &found_images);
2625
return found_images > 0;
2629
bool Operations::CheckMac(u_int64_t mac) {
2630
if ((mac >> 40) & 0x1) {
2631
return errmsg("Multicast bit (bit 40) is set");
2635
return errmsg("More than 48 bits are used");
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;
2646
f.read(img_addr + 0x28, &fs_info_word);
2647
TOCPU1(fs_info_word);
2649
// printf("-D- fs_info_word=%08x\n", fs_info_word);
2651
checksum = ((fs_info_word ) & 0xff) +
2652
((fs_info_word >> 8) & 0xff) +
2653
((fs_info_word >> 16) & 0xff) +
2654
((fs_info_word >> 24) & 0xff);
2656
if (checksum != 0) {
2657
return errmsg("Corrupted chunk size checksum");
2660
fs_en = (fs_info_word & 0x8) != 0;
2663
log2chunk_size = (fs_info_word & 0x7) + 16;
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.
2678
bool Operations::CheckMatchingDevId(u_int32_t hwDevId, u_int32_t imageDevId) {
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) {
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;
2693
if (devData == NULL) {
2694
for (j = 0; hwDevData[i].swDevIds[j]; j++) {
2695
if (hwDevData[i].swDevIds[j] == imageDevId) {
2696
devData = &hwDevData[i];
2703
if (devData == NULL) {
2704
printf("-W- Unknown device id (%d) in the given FW image. Skipping HW match check.\n",
2707
} else if (devData->hwDevId != hwDevId) {
2708
return errmsg("Trying to burn a \"%s\" image on a \"%s\" device.",
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;
2722
// Look for image in "physical addresses
2723
CntxFindAllImageStart(f, cntx_image_start, &cntx_image_num);
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]);
2736
// Check only the first image. This is enough to ensure that the device is bootable.
2740
bool info_set = false;
2742
// Verify the images:
2743
for (i = 0; i < cntx_image_num; i++ ) {
2745
u_int32_t log2chunk_size;
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());
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]);
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");
2765
report("\n ConnectX non failsafe image:\n\n");
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]);
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;
2781
// In flash, image layout must match the FS Data
2782
if (info && !info_set) {
2783
info->actuallyFailsafe = true;
2788
f.set_address_convertor(log2chunk_size, cntx_image_start[i] != 0);
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.
2796
// So - I try both cases, and see which verify() succeeds.
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.
2803
// For now, get the "striped" indication from user.
2805
if (_cntx_striped_image) {
2806
f.set_address_convertor(log2chunk_size, cntx_image_start[i] != 0);
2808
f.set_address_convertor(0,0); //disable conversion
2810
if (info && !info_set) {
2811
info->actuallyFailsafe = _cntx_striped_image;
2816
bool imgStat = true;
2818
if (!only_get_start) {
2819
imgStat = checkList(f, 0, 0x38, " ");
2822
ret = ret && imgStat;
2828
bool Operations::Verify(FBase& f, Operations::ImageInfo* info, bool both_images)
2830
u_int32_t prim_ptr, scnd_ptr;
2831
u_int32_t signature;
2836
return VerifyCntx(f, info, both_images);
2839
READ4(f, 0x24, &signature, "Signature");
2841
if (signature == SIGNATURE) {
2846
report("\nFailsafe image:\n\n");
2847
CHECKB2(f, 0, 0x28, prim_ptr, "Invariant ");
2849
psStat[0] = checkPS(f, f.get_sector_size(), prim_ptr, "Primary ");
2851
ret &= checkList(f, prim_ptr, 0x28, " ");
2855
if (psStat[0] && !both_images) {
2859
psStat[1] = checkPS(f, f.get_sector_size() * 2, scnd_ptr, "Secondary");
2862
scndStat = checkList(f, scnd_ptr, 0x28, " ");
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.
2870
if (psStat[0] == false && psStat[1] == false) {
2875
report("\nShort image:\n");
2876
CHECKLS(f, 0, 0x28, " ");
2882
bool Operations::GetExpRomVersion(ImageInfo* info) {
2883
const char* magic_string = "mlxsign:";
2884
u_int32_t magic_len = strlen(magic_string);
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;
2891
info->expRomValidVersion = false;
2892
if (_rom_sect.empty()) {
2893
return errmsg("Expansion Rom section not found.");
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
2903
if (_rom_sect.size() < 4) {
2904
return errmsg("ROM size (0x%x) is too small", (u_int32_t)_rom_sect.size());
2907
// restore endianess.
2908
TOCPUn(&(_rom_sect[0]), _rom_sect.size()/4);
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.");
2919
for (i = 0; i < rom_checksum_range; i++) {
2920
rom_checksum += _rom_sect[i];
2923
if (rom_checksum != 0) {
2924
return errmsg("Bad ROM Checksum (0x%02x)", rom_checksum);
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]) {
2931
} else if (j == magic_len - 1) {
2942
ver_offset = i + magic_len;
2944
return errmsg("Mellanox version string (%s) not found in ROM section.", magic_string);
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)
2953
// 15:0 Major version If ProductID < 0x10 this field is subversion
2954
// number, otherwise It's product major version.
2956
// 31:16 Minor version Product minor version*. Not valid if
2958
// 15:0 SubMinor version Product sub minor version*. Not valid if
2959
// ProductID < 0x10.
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
2968
tmp = __le32_to_cpu(*((u_int32_t*) &_rom_sect[ver_offset]));
2969
info->expRomProductId = tmp >> 16;
2970
info->expRomVer[0] = tmp & 0xffff;
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;
2977
tmp = __le32_to_cpu(*((u_int32_t*) &_rom_sect[ver_offset + 8]));
2978
info->expRomDevId = tmp >> 16;
2979
info->expRomPort = (tmp >> 12) & 0xf;
2981
info->expRomValidVersion = true;
2985
bool Operations::LoadAsExpRom (FBase& f) {
2987
_rom_sect.resize(f.get_size());
2988
if (!f.read(0, &_rom_sect[0], f.get_size()))
2989
return errmsg(f.err());
2991
TOCPUn(&_rom_sect[0], _rom_sect.size()/4);
2996
bool Operations::DumpConf (const char* conf_file) {
3000
if (conf_file == NULL) {
3003
out = fopen(conf_file, "w");
3006
return errmsg("Can not open file %s for write: %s.", conf_file, strerror(errno));
3010
if (_fw_conf_sect.empty()) {
3011
return errmsg("FW configuration section not found in the given image.");
3014
// restore endianess.
3015
TOCPUn(&(_fw_conf_sect[0]), _fw_conf_sect.size()/4);
3018
uLongf destLen = _fw_conf_sect.size();
3020
vector<u_int8_t> dest(destLen);
3022
int rc = uncompress((Bytef *)&(dest[0]), &destLen,
3023
(const Bytef *)&(_fw_conf_sect[0]), _fw_conf_sect.size());
3027
return errmsg("Failed uncompressing FW configuration section. uncompress returnes %d", rc);
3030
dest.resize(destLen);
3031
dest[destLen] = 0; // Terminating NULL
3032
fprintf(out, "%s", (char*)&(dest[0]));
3034
if (conf_file != NULL) {
3040
return errmsg("Executable was compiled with \"dump configuration\" option disabled.");
3047
////////////////////////////////////////////////////////////////////////
3049
// ****************************************************************** //
3050
// GUIDs TREATMENT //
3051
// ****************************************************************** //
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)
3057
#define BSN_RET do { \
3058
printf("Invalid BSN. Should be MTxxxxx[-]R[xx]ddmmyy-nnn[-cc]\n"); \
3061
#define BSN_RET1(s) do { \
3062
printf("Valid BSN format is: MTxxxxx[-]R[xx]ddmmyy-nnn[-cc]\n%s.\n",s); \
3065
u_int32_t Operations::BSN_subfield(const char *s, int beg, int len)
3068
strncpy(buf, &s[beg], len);
3070
return strtoul(&buf[0], 0, 10);
3072
bool Operations::getBSN(char *s, guid_t *guid)
3074
const u_int64_t COMPANY_ID = 0x0002c9;
3075
const u_int64_t TYPE = 1;
3076
bool cc_present = false;
3081
// Convert to lowercase
3082
for (p = s; *p; p++)
3083
*p = (char)tolower(*p);
3087
if (strncmp(p, "mt", 2)) // MT
3091
if (!isdigit(*p++)) // xxxxx
3093
if (*p == '-') { // - /optional/
3097
if (*p < 'a' || *p > 'z') // R
3101
// Count how many digits after R
3104
while (isdigit(*q++))
3109
p += 6; // skip ddmmyy
3112
p += 8; // skip xxddmmyy
3119
if (*p++ != '-') // -
3121
for (i=0; i<3; i++) // nnn
3126
if (*p++ != '-') // -
3128
for (i=0; i<2; i++) // cc
3133
u_int32_t dd = BSN_subfield(s, 8+date_offs, 2);
3135
BSN_RET1("Day (dd) should not exceed 31");
3137
BSN_RET1("Day (dd) can not be zero");
3138
u_int32_t mm = BSN_subfield(s, 10+date_offs, 2);
3140
BSN_RET1("Months (mm) should not exceed 12");
3142
BSN_RET1("Months (mm) can not be zero");
3143
u_int32_t yy = BSN_subfield(s, 12+date_offs, 2);
3145
BSN_RET1("Year (yy) should not exceed 99");
3147
BSN_RET1("Year (yy) can not be zero");
3148
u_int32_t num = BSN_subfield(s, 15+date_offs, 3);
3150
BSN_RET1("Number (num) should not exceed 999");
3152
BSN_RET1("Number (num) can not be zero");
3155
cc = BSN_subfield(s, 19+date_offs, 2);
3157
BSN_RET1("Chip number (cc) should not exceed 14");
3159
BSN_RET1("Chip number (cc) can not be zero");
3161
u_int64_t id = ((((yy*12+mm-1)*31+ dd-1) * 1000) + num-1) * 112;
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;
3170
bool Operations::getGUID(const char *s, guid_t *guid)
3175
g = strtoull(s, &endp, 16);
3176
if (*endp || (g == 0xffffffffffffffffULL && errno == ERANGE)) {
3177
printf("Invalid GUID syntax (%s) %s \n",
3179
errno ? strerror(errno) : "" );
3182
guid->h = (u_int32_t)(g >> 32);
3183
guid->l = (u_int32_t)(g & 0xffffffff);
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)
3199
u_int32_t signature = buf[(sign + 8)/4];
3201
if (signature != SIGNATURE) {
3202
printf("%s pointer section not valid\n", pref);
3210
*ind = buf[(offs+0x24)/4];
3215
if (*ind >= (u_int32_t)buf_len) {
3216
printf("%s image - illegal GUID pointer (%08x)\n", pref, *ind);
3219
*nguids = buf[*ind/4 - 3];
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);
3234
////////////////////////////////////////////////////////////////////////
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) {
3244
for (i = 0; i < data_size; i += 4) {
3245
crc << __be32_to_cpu(*(u_int32_t*)(buf + i));
3248
*(u_int32_t*)(buf + data_size) = __cpu_to_be32(crc.get());
3251
////////////////////////////////////////////////////////////////////////
3252
void Operations::patchGUIDsSection(u_int32_t *buf, u_int32_t ind,
3253
guid_t guids[MAX_GUIDS], int nguids)
3256
u_int32_t new_buf[MAX_GUIDS*2];
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;
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]);
3268
memcpy(&buf[ind/4], &new_buf[0], nguids * 2 * sizeof(u_int32_t));
3271
if (_burn_blank_guids) {
3272
buf[ind/4 + nguids*2] = __cpu_to_be32(0xffff);
3274
recalcSectionCrc((u_int8_t*)buf + ind - sizeof(GPH), sizeof(GPH) + nguids * 8);
3276
} // patchGUIDsSection
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
3288
void Operations::PatchInfoSect(u_int8_t* rawSect,
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)));
3298
//printf("-D- vsdOffs=%x, vsdSize=%x, infoSize=%x\n", vsdOffs,vsdSize, infoSize );
3300
u_int32_t len = strlen(vsd);
3302
if (len > vsdSize) {
3303
report("Warning: The given VSD length is too large (%d chars). Truncating to %d chars.\n", len, vsdSize);
3307
memset(rawSect + sizeof(GPH) + vsdOffs, 0, vsdSize );
3308
memcpy(rawSect + sizeof(GPH) + vsdOffs, vsd, len);
3311
recalcSectionCrc(rawSect, sizeof(GPH) + infoSize);
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.
3322
void Operations::PatchPs(u_int8_t* rawPs,
3325
u_int32_t imageAddr) {
3327
PS *ps = (PS*)rawPs;
3329
u_int32_t fix_start = 0;
3330
u_int32_t fix_end = 0;
3333
u_int32_t len = strlen(vsd);
3335
memset(&ps->vsd[0], 0, VSD_LEN );
3336
memcpy(&ps->vsd[0], vsd, len);
3340
fix_start +=VSD_LEN;
3343
u_int32_t len = strlen(psid);
3345
memset(&ps->psid[0], 0, PSID_LEN );
3346
memcpy(&ps->psid[0], psid, len );
3347
fix_end += PSID_LEN;
3350
//VSD is kept on flash byte-swapped.
3351
//recode it back before patching
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);
3361
ps->fi_addr = __cpu_to_be32(imageAddr);
3364
recalcSectionCrc((u_int8_t *)ps, sizeof(PS) - 4);
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)
3378
const char* vsd_to_use = curr_vsd ? curr_vsd : "";
3379
const char* psid_to_use = image_psid;
3381
// TODO: Should not give the user_psid param. Do not allow for on-the-fly PSID changes.
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);
3394
psid_to_use = user_psid;
3398
vsd_to_use = user_vsd;
3401
if (IsCntx() && info->infoOffs[II_VSD]) {
3402
PatchInfoSect((u_int8_t*)f.getBuf() + info->infoSectPtr - sizeof(GPH),
3403
info->infoOffs[II_VSD],
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);
3414
bool Operations::printGUIDs(const char* msg, guid_t guids[MAX_GUIDS], bool print_guids, bool print_macs, bool old_guid_fmt) {
3417
if ( print_guids && print_macs) {
3419
} else if (!print_guids && print_macs) {
3421
} else if ( print_guids && !print_macs) {
3424
return errmsg("Internal error: Operations::PrintGuids() with both guid and mac turned off");
3427
printf("%s %s:\n", msg, g_m);
3429
printf(" Node GUID: " GUID_FORMAT "\n", guids[0].h, guids[0].l);
3431
printf(" Port1 GUID: " GUID_FORMAT "\n", guids[1].h, guids[1].l);
3433
printf(" Port2 GUID: " GUID_FORMAT "\n", guids[2].h, guids[2].l);
3435
printf(" Sys.Image GUID: " GUID_FORMAT "\n", guids[3].h, guids[3].l);
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);
3445
void Operations::SetDevFlags(u_int16_t devType, bool& ib_dev, bool& eth_dev) {
3447
if (IsIs4(devType)) {
3451
ib_dev = !IsCntx() || CntxIsIb(devType);
3452
eth_dev = IsCntx() && CntxIsEth(devType);
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).
3467
bool Operations::CheckGuidsFlags (u_int16_t devType,
3469
bool guids_specified,
3471
bool macs_specified) {
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",
3477
} else if (ib_dev && !guids_specified) {
3478
return errmsg("Use -guid(s) flag for IB MT%d device.\n",
3480
} else if (eth_dev && !macs_specified) {
3481
return errmsg("*** ERROR *** Use -mac(s) flag for ETH MT%d device.\n",
3488
////////////////////////////////////////////////////////////////////////
3489
bool Operations::patchGUIDs (FImage& f,
3495
guid_t new_guids[MAX_GUIDS],
3496
guid_t old_guids[MAX_GUIDS],
3497
u_int32_t num_of_old_guids,
3500
guid_t* used_guids = old_guids ? old_guids : new_guids;
3501
u_int32_t *buf = f.getBuf();
3504
bool old_guids_fmt = info->guidNum < GUIDS;
3506
// Print old GUIDs and get confirmation
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.
3514
if (old_guids && !user_guids) {
3515
for (i = 0; i < GUIDS; i++) {
3516
new_guids[i] = old_guids[i];
3520
if (old_guids && !user_macs) {
3521
for (i = GUIDS; i < MAX_GUIDS; i++) {
3522
new_guids[i] = old_guids[i];
3526
used_guids = new_guids;
3531
// To ease upgrade from 4 GUIDS format to 4+2 format, or to move from IB to ETH,
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.
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;
3545
mac |= (old_guids[i+1].l & 0xffffff);
3547
old_guids[GUIDS+i].h = u_int32_t(mac >> 32);
3548
old_guids[GUIDS+i].l = u_int32_t(mac & 0xffffffff);
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 );
3554
guid_t* macs = &used_guids[4];
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",
3563
user_macs ? "given" : "found on flash",
3570
if (new_guids && old_guids) {
3571
printGUIDs(" Current settings of",
3580
printGUIDs(" You are about to burn the image with the following",
3590
// Path GUIDs section
3591
if (info->guidPtr) {
3592
patchGUIDsSection(buf, info->imgStart + info->guidPtr, used_guids, info->guidNum);
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);
3605
////////////////////////////////////////////////////////////////////////
3607
// ****************************************************************** //
3608
// Revision info and board ID //
3609
// ****************************************************************** //
3611
////////////////////////////////////////////////////////////////////////
3613
bool Operations::QueryIs (FBase& f,
3614
Operations::ImageInfo* info) {
3615
u_int32_t signature;
3617
READ4(f, 0x24, &signature, "Signature");
3619
if (signature == SIGNATURE) {
3621
info->isFailsafe = true;
3626
READ4(f, 0x10, &fw_id, "FW ID");
3629
info->isVer = ( fw_id >> 8) && 0xff;
3630
info->devRev = fw_id >> 24;
3633
info->isFailsafe = false;
3637
info->invSectOk = true;
3641
bool Operations::QueryPs (FBase& f,
3642
Operations::ImageInfo* info) {
3644
if (!info->isFailsafe) {
3645
return errmsg("Internal Error: Tried to query PS when image is not failsafe");
3648
u_int32_t prim_ptr, scnd_ptr;
3649
u_int32_t sectSize = f.get_sector_size();
3651
bool currSielent = _silent;
3654
if (checkPS(f, sectSize, prim_ptr, "Primary ")) {
3655
info->allImgStart[0] = prim_ptr;
3656
info->imgStart = prim_ptr;
3657
info->psStart = sectSize;
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;
3667
if (info->allImgStart[0] == 0 && info->allImgStart[1] == 0) {
3668
return errmsg("No valid image found.");
3671
char vsd[VSD_LEN+PSID_LEN+1]; // +1 => Leave a space for \0 when psid size == 16 .
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;
3677
for (u_int32_t i=0; i < sizeof(vsd)/sizeof(u_int32_t); i++)
3678
vsd_dwp[i] = bswap_32(vsd_dwp[i]);
3680
memcpy(info->vsd, vsd, VSD_LEN);
3681
memcpy(info->psid, vsd + VSD_LEN, PSID_LEN);
3683
info->vsd [sizeof(info->vsd) - 1] = '\0';
3684
info->psid[sizeof(info->psid) - 1] = '\0';
3686
_silent = currSielent;
3694
bool Operations::QueryImage (FBase& f,
3695
Operations::ImageInfo* info) {
3697
u_int32_t guid_ptr, nguids;
3698
guid_t guids[MAX_GUIDS];
3702
u_int32_t fw_id_offs;
3703
u_int32_t im_start = info->imgStart;
3706
if (info->isFailsafe && info->actuallyFailsafe) {
3707
f.set_address_convertor(info->cntxLog2ChunkSize, im_start != 0);
3709
f.set_address_convertor(0,0);
3712
im_start = 0; // offset is done by address convertor
3713
info->magicPatternFound = true;
3716
info->magicPatternFound = false;
3720
READ4(f, im_start + fw_id_offs, &fw_id, "FW ID");
3723
info->devRev = fw_id >> 24;
3725
READ4(f, im_start + fw_id_offs + 0x14 , &guid_ptr, "GUID PTR");
3727
info->guidPtr = guid_ptr;
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);
3733
READ4(f, guid_ptr - 3*sizeof(u_int32_t), &nguids, "Number of GUIDs");
3736
if (nguids > MAX_GUIDS) {
3737
report("Failed to read GUIDs - Illegal Number of GUIDs (%d)\n", nguids);
3740
READBUF(f, guid_ptr, guids, nguids * sizeof(u_int64_t), "GUIDS");
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);
3747
info->blankGuids = true;
3749
if ((guids_crc & 0xffff) != 0xffff ) {
3750
info->blankGuids = false;
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;
3761
// Expansion Rom version:
3762
if (_rom_sect.empty()) {
3763
info->expRomFound = false;
3765
info->expRomFound = true;
3766
if (!GetExpRomVersion(info)) {
3767
report("\nWarning: Failed to get ROM Version: %s\n\n", err());
3768
info->expRomValidVersion = false;
3773
u_int32_ba info_ptr_ba;
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");
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);
3787
return errmsg("Failed to read Info Section - Bad checksum for Info section pointer (%08x). Probably the image is corrupted.", info_ptr);
3790
info_ptr = info_ptr_ba.range(23,0);
3791
if (info_ptr_cs == 0 && info_ptr != 0) {
3792
info->infoSectPtr = info_ptr;
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);
3798
READ4(f, info_ptr - 3*sizeof(u_int32_t), &info_size, "Info section size");
3804
u_int8_t* info_buff = (u_int8_t*)alloca(info_size);
3805
READBUF(f, info_ptr, info_buff, info_size, "Info Section");
3807
if (!ParseInfoSect(info_buff, info_size, info)) {
3812
info->imageOk = true;
3817
bool Operations::ParseInfoSect(u_int8_t* buff, u_int32_t byteSize, Operations::ImageInfo *info) {
3819
u_int32_t *p = (u_int32_t*)buff;
3821
u_int32_t tagNum = 0;
3822
bool endFound = false;
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;
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);
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;
3845
tmp = __be32_to_cpu(*(p+1));
3846
info->devType = tmp & 0xffff;
3847
//info->devRev = (tmp >> 16) & 0xff;
3850
case II_VsdVendorId:
3851
tmp = __be32_to_cpu(*(p+1));
3852
info->vsdVendorId = tmp & 0xffff;
3856
tmp = __be32_to_cpu(*(p+1));
3857
info->isGa = tmp ? true : false;;
3861
// set psid only if not previosly found in PS
3863
str = (const char*)p;
3866
for (int i = 0 ; i < PSID_LEN ; i++) {
3867
info->psid[i] = str[i];
3869
info->psid[PSID_LEN] = '\0';
3874
// set psid only if not previosly found in PS
3876
str = (const char*)p;
3879
for (int i = 0 ; i < VSD_LEN ; i++) {
3880
info->vsd[i] = str[i];
3882
info->vsd[VSD_LEN] = '\0';
3888
str = (const char*)p;
3891
for (int i = 0 ; i < PRODUCT_VER_LEN ; i++) {
3892
info->productVer[i] = str[i];
3894
info->productVer[PRODUCT_VER_LEN] = '\0';
3902
//printf("-D- Found tag ID %d of size %d - ignoring.\n", tagId, tagSize);
3905
if (tagId < II_Last) {
3906
info->infoOffs[tagId] = offs + 4;
3910
offs += tagSize + 4;
3914
if (offs != byteSize) {
3916
return errmsg("Info section corrupted: Section data size is %x bytes, "
3917
"but end tag found after %x bytes.", byteSize, offs);
3919
return errmsg("Info section corrupted: Section data size is %x bytes, "
3920
"but end tag not found before section end.", byteSize);
3927
bool Operations::DisplayExpRomInfo(Operations::ImageInfo* info) {
3928
report("Rom Info: ");
3929
if (info->expRomValidVersion) {
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);
3938
report("version=%d", info->expRomVer[0]);
3940
if (info->expRomProductId >= 0x10) {
3941
report(".%d.%d devid=%d",
3946
if (info->expRomPort) {
3947
// Do not display if 0 - port independant
3948
report(" port=%d", info->expRomPort);
3958
bool Operations::DisplayImageInfo(Operations::ImageInfo* info) {
3959
report("Image type: %s\n", info->magicPatternFound ? (CntxIsEth(info->devType) ? "ConnectX" : "FS2") :
3960
info->isFailsafe ? "Failsafe" :
3963
if (info->infoOffs[II_FwVersion]) {
3964
report("FW Version: %d.%d.%d\n", info->fwVer[0], info->fwVer[1], info->fwVer[2]);
3967
if (info->infoOffs[II_ProductVer] && strlen(info->productVer)) {
3968
report("Product Version: %s\n", info->productVer);
3971
if (info->expRomFound) {
3972
DisplayExpRomInfo(info);
3975
if (info->isFailsafe && !IsCntx()) {
3976
report("I.S. Version: %d\n", info->isVer );
3979
if (info->infoOffs[II_DeviceType]) {
3980
report("Device ID: %d\n", info->devType);
3981
if (info->devType == 25204 || info->devType == 24204) {
3983
} else if (IsIs4(info->devType)) {
3988
report("Chip Revision: %X\n", info->devRev);
3991
// TODO: Handle case where devtype not found.
3994
SetDevFlags(info->devType, ib_dev, eth_dev);
3996
const char* mac_indent = "";
3998
//report("GUID Des: Node Port1 ");
3999
report("Description: Node ");
4004
report( "Sys image\n");
4007
for (u_int32_t i=0; i < GUIDS; i++) {
4008
if ((i == 1 && _num_ports < 1) ||
4009
(i == 2 && _num_ports < 2)) {
4012
report(GUID_FORMAT " ", info->guids[i].h, info->guids[i].l);
4019
if (info->guidNum == MAX_GUIDS) {
4021
report("Description:%s Port1 Port2\n", mac_indent);
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);
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());
4038
printf("\nWarning: Can not get MAC addrerss: Expecting %d entries in guid section, got %d. Probably an old FW image. Please update.\n",
4045
if (!info->infoOffs[II_VsdVendorId] || info->vsdVendorId == MELLANOX_VENDOR_ID) {
4046
report("\nBoard ID: %s", info->vsd);
4048
report(" (%s)\n", info->psid);
4052
report("VSD: %s\n", info->vsd);
4053
report("PSID: %s\n", info->psid);
4055
report("\n\nWarning: Not a Mellanox FW image (vendor_id = 0x%04x). VSD and PSID are not displayed.\n\n", info->vsdVendorId);
4058
if (info->infoOffs[II_IsGa]) {
4060
report("BOARD GA: no\n");
4064
if (info->blankGuids) {
4065
report("\nWarning: GUIDs%s values and their CRC are not set.\n",
4066
IsCntx() ? "/MACs" : "");
4071
////////////////////////////////////////////////////////////////////////
4073
// ****************************************************************** //
4075
// ****************************************************************** //
4077
////////////////////////////////////////////////////////////////////////
4078
// sed -e 's/"/\\"/g' < flint.txt | perl -pe 's/^(.*)$/"$1\\n"/'
4079
void usage(const char *sname, bool full = false)
4083
" FLINT - FLash INTerface\n"
4085
"FW (firmware) burning and flash memory operations tool for\n"
4086
"Mellanox Infiniband HCAs and Ethernet NIC cards.\n"
4091
" " FLINT_NAME " [switches...] <command> [parameters...]\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"
4101
// " -crc - Print out each section CRC.\n"
4102
// " Commands affected: verify\n"
4104
" -d[evice] <device> - Device flash is connected to.\n"
4105
" Commands affected: all\n"
4107
" -guid <GUID> - GUID base value. 4 GUIDs\n"
4108
" are automatically assigned to the\n"
4109
" following values:\n"
4111
" guid -> node GUID\n"
4112
" guid+1 -> port1\n"
4113
" guid+2 -> port2\n"
4114
" guid+3 -> system image GUID.\n"
4116
" Note: port2 guid will be assigned even for a"
4117
" single port HCA - The HCA ignores this value.\n"
4119
" Commands affected: burn, sg\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"
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"
4130
" Commands affected: burn, sg\n"
4132
" -mac <MAC> - MAC address base value. 2 MACs\n"
4133
" are automatically assigned to the\n"
4134
" following values:\n"
4139
" Commands affected: burn, sg\n"
4141
" -macs <MACs...> - 2 MACs must be specified here.\n"
4142
" The specified MACs are assigned\n"
4143
" to port1, port2, repectively.\n"
4145
" Commands affected: burn, sg\n"
4146
" Note: -mac/-macs flags are applicable only for Mellanox\n"
4147
" Technologies ethernet products.\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"
4153
" Commands affected: burn\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"
4162
" -h[elp] - Prints this message and exits\n"
4163
" -hh - Prints extended command help\n"
4165
" -i[mage] <image> - Binary image file.\n"
4166
" Commands affected: burn, verify\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"
4173
" -nofs - Burn image in a non failsafe manner.\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"
4179
" -byte_mode - Shift address when accessing flash internal registers. May\n"
4180
" be required for burn/write commands when accessing certain\n"
4184
" -unlock - Use unlock bypass feature of the flash for quicker burn.\n"
4185
" Commands affected: burn\n"
4188
" -s[ilent] - Do not print burn progress flyer.\n"
4189
" Commands affected: burn\n"
4191
" -y[es] - Non interactive mode - assume answer\n"
4192
" \"yes\" to all questions.\n"
4193
" Commands affected: all\n"
4195
" -no - Non interactive mode - assume answer\n"
4196
" \"no\" to all questions.\n"
4197
" Commands affected: all\n"
4199
" -vsd <string> - Write this string, of up to 208 characters, to VSD when burn.\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"
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"
4208
" -v - Version info.\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"
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"
4234
" 0 - Successful completion\n"
4235
" 1 - An error has occurred\n"
4236
" 7 - For burn command - FW already updated - burn was aborted.\n"
4239
const char* full_descr =
4241
"Command descriptions:\n"
4242
"----------------------------\n"
4245
" Burns entire flash from raw binary image.\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"
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"
4265
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " -i image1.bin bb\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"
4284
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " -guid 0x0002c9000100d050 sg\n"
4288
" Erases a sector that contains specified address.\n"
4293
" addr - address of word in sector that you want\n"
4296
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " erase 0x10000\n"
4299
"* Query miscellaneous FW and flash parameters\n"
4306
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " query\n"
4309
"* Query flash device parameters (Common Flash Interface)\n"
4316
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " cfi\n"
4319
"* Read one dword from flash.\n"
4324
" addr - address of word to read\n"
4326
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rw 0x20\n"
4329
"* Verify entire flash.\n"
4336
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " v\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"
4347
" addr - address of word\n"
4348
" data - value of word\n"
4350
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " ww 0x10008 0x5a445a44\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"
4362
" addr - address of word\n"
4363
" data - value of word\n"
4365
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " wwne 0x10008 0x5a445a44\n"
4367
"* Read a data block from the flash and write it to a file or to screen.\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"
4377
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rb 0x10000 100 file.bin\n"
4379
"* Read the FW image from flash and write it to a file.\n"
4384
" file - filename to write the image to (raw binary).\n"
4386
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " ri file.bin\n"
4388
"* Write a block of data to the flash without erasing.\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"
4397
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " wbne 0x10000 12 0x30000 0x76800 0x5a445a44\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"
4406
" file - (optional) filename to write the dumped configuration to. If not given, the data\n"
4407
" is printed to screen\n"
4409
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " dc\n"
4412
printf(descr, sname);
4415
printf(full_descr, sname);
4424
Flash* g_flash = NULL;
4427
HANDLE g_hMainTread = GetCurrentThread();
4432
int g_signals_for_termination[] = {
4442
void TerminationHandler (int signum)
4444
static volatile sig_atomic_t fatal_error_in_progress = 0;
4449
report ("\nWarning: Got SIGINT. Raising SIGTERM\n");
4454
report ("\nWarning: This program can not be interrupted.Please wait for its termination.\n");
4455
signal(signum, TerminationHandler);
4460
if (fatal_error_in_progress)
4462
fatal_error_in_progress = 1;
4464
signal (signum, SIG_DFL);
4466
if (g_flash != NULL) {
4467
report("\n Received signal %d. Cleaning up ...", signum);
4469
sleep(1); // let erase sector end
4470
//g_flash->wait_ready("Process termination");
4479
// Commands database and parsing methods
4485
CI_IMG_OR_DEV = 0x06,
4486
CI_IMG_AND_DEV = 0x08
4512
struct CommandInfo {
4514
const char* cmdName;
4515
bool requireExactMatch;
4517
CommandInput requiredInput;
4518
const char* cmdDescription;
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 , ""}
4544
#define numbel(x) (sizeof(x)/sizeof((x)[0]))
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];
4557
CommandType ParseCommand(const char* cmd) {
4558
u_int32_t cmdLenGiven = strlen(cmd);
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;
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;
4576
bool CheckCommandInputs(const char* dev,
4580
const CommandInfo* cmdInfo = GetCommandInfo(cmd);
4583
printf("*** INTERNAL ERROR *** Unknown command given to CheckCommandInputs() (%d)\n", cmd);
4587
const char* inputDesStr [] = {
4589
"neither a device nor an image file", // CI_NONE
4590
"an image file", // CI_IMG_ONLY,
4592
"a device", // CI_DEV_ONLY,
4594
"either an image file or a device", // CI_IMG_OR_DEV,
4596
"both an image file and a device" // CI_IMG_AND_DEV
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;
4611
if ((given & cmdInfo->requiredInput) == 0) {
4612
printf("*** ERROR *** Command \"%s\" requires %s to be specified",
4614
inputDesStr[cmdInfo->requiredInput]);
4616
if (given != CI_NONE) {
4617
printf(", but %s %s given.\n",
4619
given == CI_IMG_AND_DEV ? "are" : "is");
4630
bool CheckMaxCmdArguments(CommandType cmd, int numArgs) {
4631
const CommandInfo* cmdInfo = GetCommandInfo(cmd);
4633
printf("*** INTERNAL ERROR *** Unknown command given to CheckMaxCmdArguments (%d)\n", cmd);
4637
if (cmdInfo->maxArgs >= 0 && numArgs > cmdInfo->maxArgs) {
4638
printf("*** ERROR *** Command \"%s\" requires %d arguments, but %d arguments were given\n",
4647
////////////////////////////////////////////////////////////////////////
4651
#define RC_FW_ALREADY_UPDATED 7
4653
#define NEXTS(s) do { \
4656
printf("Missed parameter after \"%s\" switch\n", s); \
4659
#define NEXTC(p, s) do { \
4662
printf("Missed %s parameter after \"%s\" command\n", p,s); \
4666
#define SETERR(args) do { printf("*** ERROR *** "); printf args; printf("\n"); return 1; } while(0)
4669
int main(int ac, char *av[])
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;
4683
const char* cmdStr = NULL;
4687
guid_t user_guids[Operations::MAX_GUIDS];
4690
CommandType cmd = CMD_UNKNOWN;
4697
FBase* fbase = NULL;
4698
const char* cmdTarget = NULL;
4699
const char* cmdAccess = NULL;
4701
bool cntx_image = false;
4702
bool cntx_device = false;
4704
// Map termination signal handlers
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);
4716
// Init with FFs - for ConnectX if only MAC or GUID is specified
4717
memset(user_guids, 0xff, sizeof(user_guids));
4719
// Go thru command line options
4720
for (i=1; i < ac; i++) {
4725
if (*av[i] == '-') {
4726
int switchLen = strlen(av[i]);
4728
if (!strcmp(av[i], "-dual_image"))
4729
single_image_burn = false;
4731
else if (!strcmp(av[i], "-clear_semaphore")) {
4732
clear_semaphore = true;
4735
else if (!strncmp(av[i], "-device", switchLen)) {
4739
} else if (!strcmp(av[i], "-v") || !strcmp(av[i], "-vv")) {
4744
if (!strcmp(av[i], "-vv")) {
4745
printf(" SVN %s", _svnID + 1);
4751
} else if (!strcmp(av[i], "-unlock")) {
4752
_unlock_bypass = true;
4753
} else if (!strcmp(av[i], "-noerase"))
4755
else if (!strcmp(av[i], "-noburn"))
4757
else if (!strcmp(av[i], "-crc"))
4759
else if (!strcmp(av[i], "-bytewrite")) {
4761
printf("\"-bytewrite\" should be specifies before \"-device\" switch in the command line.\n");
4765
} else if (!strcmp(av[i], "-vsd")) {
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]);
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]);
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]);
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]);
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;
4793
user_guids[i].h = (u_int32_t)(g>>32);
4794
user_guids[i].l = (u_int32_t)g;
4796
guids_specified = true;
4797
} else if (!strncmp(av[i], "-image", switchLen)) {
4799
image_fname = av[i];
4800
} else if (!strcmp(av[i], "-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;
4807
user_guids[i].h = (u_int32_t)(g>>32);
4808
user_guids[i].l = (u_int32_t)g;
4810
guids_specified = true;
4811
} else if (!strcmp(av[i], "-guids")) {
4813
printf("Exactly four GUIDs must be specified.\n");
4817
for (int j=0; j<Operations::GUIDS; j++) {
4818
GETGUID(av[i+j], &user_guids[j]);
4821
guids_specified = true;
4823
} else if (!strcmp(av[i], "-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;
4830
user_guids[Operations::GUIDS + i].h = (u_int32_t)(g>>32);
4831
user_guids[Operations::GUIDS + i].l = (u_int32_t)g;
4833
macs_specified = true;
4834
} else if (!strcmp(av[i], "-macs")) {
4836
printf("Exactly two MACs must be specified.\n");
4840
for (int j=0; j<Operations::MACS; j++) {
4841
GETGUID(av[i+j], &user_guids[Operations::GUIDS+j]);
4844
macs_specified = true;
4845
} else if (!strncmp(av[i], "-silent", switchLen))
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))
4865
else if (!strcmp(av[i], "-no"))
4867
else if (!strcmp(av[i], "-byte_mode"))
4868
Flash::_byte_mode = true;
4871
else if (!strncmp(av[i], "-hh", 3) || !strncmp(av[i], "--hh", 4)) {
4874
} else if (!strncmp(av[i], "-help", switchLen) || !strncmp(av[i], "--h", 3)) {
4878
printf("*** ERROR *** Invalid switch \"%s\" is specified.\n", av[i]);
4888
if (_assume_yes && _assume_no) {
4889
printf("*** ERROR *** -yes and -no options can not be specified together.\n");
4893
if (ops.GetBurnBlankGuids() && (guids_specified || macs_specified)) {
4894
const char* flag = "-guid(s)";
4896
if (macs_specified && !guids_specified) {
4900
printf("*** ERROR *** -blank_guids and %s options can not be specified together.\n", flag);
4909
if (clear_semaphore) {
4911
printf("*** ERROR *** No command is allowed when -clear_semaphore flag is given.\n");
4914
cmdStr = "clear_semaphore";
4919
printf("*** ERROR *** No command given. See help for details.\n");
4924
// Check and parse command
4926
cmd = ParseCommand(cmdStr);
4928
if (cmd == CMD_UNKNOWN) {
4929
printf("*** ERROR *** Invalid command \"%s\".\n", av[i]);
4933
if (cmd == CMD_CLEAR_SEM) {
4934
clear_semaphore = true;
4937
if (!CheckCommandInputs(device, image_fname, cmd)) {
4941
if (!CheckMaxCmdArguments(cmd, ac - i - 1 )) {
4947
auto_ptr<Flash> tmp(new Flash);
4950
if (f.get() == NULL) {
4951
printf("*** ERROR *** Memory allocation failed\n");
4956
if (!f->open(device, clear_semaphore)) {
4957
printf("*** ERROR *** Can not open %s: %s\n", device, f->err());
4961
ops.SetNumPorts(f->get_port_num());
4963
cmdTarget = "Flash";
4968
cntx_device = ops.CheckIsCntx(*fbase);
4972
if (!fim.open(image_fname)) {
4973
printf("*** ERROR *** Image file open failed: %s\n", fim.err());
4977
cmdTarget = "Image file";
4978
cmdAccess = image_fname;
4982
cntx_image = ops.CheckIsCntx(fim);
4985
ops.SetCntxMode(cntx_image || cntx_device);
4989
case CMD_BURN_BLOCK:
4995
Operations::ImageInfo fileInfo;
4996
Operations::ImageInfo flashInfo;
4997
bool burn_block = (cmd == CMD_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");
5007
// Make checks and replace vsd/guids.
5008
bool old_silent = _silent;
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());
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",
5025
// Get GUID and VSD info from flash
5027
bool read_guids = true;
5028
bool read_ps = true;
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).
5033
bool flash_query_res= true;
5034
if (ops.GetQuickQuery()) {
5035
printf("\n*** WARNING *** Running quick query - Skipping full image integrity checks.\n");
5037
flash_query_res = ops.VerifyCntx(*f, &flashInfo, false, true);
5040
if (flash_query_res) {
5041
flash_query_res = ops.QueryAll(*f, &flashInfo);
5044
flash_query_res = ops.Verify(*f, &flashInfo) && ops.QueryAll(*f, &flashInfo);
5050
ops.SetDevFlags(fileInfo.devType, ib_dev,eth_dev);
5052
if ((user_vsd && user_psid) || use_image_ps)
5055
if (ops.GetBurnBlankGuids() ||
5056
(guids_specified && ib_dev) ||
5057
(macs_specified && eth_dev))
5060
if (read_guids && !flash_query_res) {
5061
const char* missing_info;
5062
const char* missing_flags;
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)";
5071
missing_info = "MACs";
5072
missing_flags = "-mac(s)";
5075
if (read_guids && !flashInfo.imageOk) {
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);
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");
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());
5095
if (!ops.patchGUIDs(fim,
5102
flashInfo.imageOk ? flashInfo.guids : NULL,
5107
} else if (!use_image_guids) {
5108
if (!ops.patchGUIDs(fim,
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");
5129
if (!user_vsd && !(flashInfo.psOk || (flashInfo.infoOffs[Operations::II_PSID] &&
5130
flashInfo.infoOffs[Operations::II_VSD] ))) {
5132
if (burn_failsafe) {
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");
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");
5143
if (!ops.ask_user()) {
5149
// Print FW versions:
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]);
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]);
5165
bool updateRequired = true;
5167
if (fileInfo.infoOffs[Operations::II_FwVersion] &&
5168
flashInfo.infoOffs[Operations::II_FwVersion]) {
5170
updateRequired = ops.FwVerLessThan(flashInfo.fwVer,fileInfo.fwVer);
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;
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()){
5187
if (!use_image_ps) {
5188
if (fileInfo.psOk || (ops.IsCntx() && fileInfo.infoOffs[Operations::II_VSD])) {
5189
if (!ops.patchVSD(fim,
5201
// Check PSID and ib -> eth change.
5203
if (fileInfo.infoOffs[Operations::II_PSID] &&
5204
flashInfo.infoOffs[Operations::II_PSID] &&
5205
strncmp( fileInfo.psid, flashInfo.psid, PSID_LEN)) {
5207
(!ib_dev && eth_dev) &&
5208
flashInfo.infoOffs[Operations::II_DeviceType] &&
5209
ops.CntxIsIb(flashInfo.devType) &&
5210
!ops.CntxIsEth(flashInfo.devType)) {
5212
printf("\n You are about to replace FW image type from IB to ETH image.\n");
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",
5220
if (! ops.ask_user()){
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");
5231
if (! ops.ask_user()){
5236
_silent = old_silent;
5240
burn_failsafe = false;
5244
if (burn_failsafe) {
5248
ret = ops.CntxFailSafeBurn(*f,
5256
ret = ops.FailSafeBurn(*f,
5264
// The error is in flash access:
5265
printf("*** ERROR *** Flash access failed during burn: %s\n", f->err());
5267
// operation/ algorithm error:
5268
printf("*** ERROR *** Failsafe burn error: %s\n", ops.err());
5274
// Not failsafe (sequential) burn
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");
5283
printf("Burn process will not be failsafe. No checks will be performed.\n");
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");
5288
if (!ops.ask_user()) {
5294
if (ops.IsCntx() && !burn_block) {
5295
ret = ops.CntxFailSafeBurn(*f,
5300
true); // Allow nofs
5302
ret = ops.write_image(*f, 0, fim.getBuf(), fim.getBufLength(),!silent);
5308
printf("*** ERROR *** Non failsafe burn failed: %s\n", ops.err());
5317
Operations::ImageInfo info;
5318
u_int32_t guid_sect_addr[2] = {0};
5323
if (!ops.VerifyCntx(*fbase, &info, false, true)) {
5324
printf("\n*** ERROR *** Can not set GUIDs: %s. \n", ops.err());
5330
if (!ops.QueryAll(*fbase, &info)) {
5331
printf("*** ERROR *** Can not set GUIDs: %s query (%s) failed: %s\n", cmdTarget , cmdAccess, ops.err());
5335
if (!info.blankGuids) {
5336
printf("\n*** ERROR *** Can not set GUIDs: Guids are already set.\n");
5343
ops.SetDevFlags(info.devType, ib_dev, eth_dev);
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());
5351
const char* missing_info;
5352
const char* missing_flags;
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)";
5361
missing_info = "MACs";
5362
missing_flags = "-mac(s)";
5366
printf("*** ERROR *** For set_guids command, "
5367
"Please specify %s (using command line flags %s ). \n", missing_info, missing_flags);
5372
if (ops.IsCntx() || !info.isFailsafe) {
5373
guid_sect_addr[0] = info.guidPtr;
5376
for (i = 0; i < 2; i++) {
5377
if (info.allImgStart[i]) {
5378
guid_sect_addr[addr_idx] = info.allImgStart[i] + info.guidPtr;
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
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());
5391
ops.patchGUIDsSection (guid_sect, 16, user_guids, info.guidNum);
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());
5400
case CMD_ERASE_SECT:
5403
// ERASE SECTOR <ADDR>
5404
// Parameters: <ADDR>
5409
// Address of sector to erase
5410
NEXTC("<ADDR>", "erase");
5411
addr = strtoul(av[i], &endp, 0);
5413
printf("Invalid address \"%s\"\n", av[i]);
5418
if (!f->erase_sector(addr)) {
5419
printf("*** ERROR *** Erase sector failed: %s\n", f->err());
5425
case CMD_QUERY_FORCE:
5429
Operations::ImageInfo info;
5431
bool checkValidImage = false;
5434
if (ops.GetQuickQuery()) {
5435
printf("\n*** WARNING *** Running quick query - Skipping full image integrity checks.\n");
5437
imageOk = ops.VerifyCntx(*fbase, &info, false, true);
5438
checkValidImage = true;
5441
imageOk = ops.Verify(*fbase, &info);
5442
checkValidImage = true;
5446
if (checkValidImage && !imageOk) {
5447
printf("\n*** ERROR *** %s query (%s) failed. Not a valid image.\n", cmdTarget , cmdAccess);
5451
if (!ops.QueryAll(*fbase, &info)) {
5452
printf("*** ERROR *** %s query (%s) failed: %s\n", cmdTarget , cmdAccess, ops.err());
5456
ops.DisplayImageInfo(&info);
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());
5471
case CMD_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;
5481
bool to_file = false;
5483
// Address and length
5484
NEXTC("<ADDR>", "rb");
5485
addr = strtoul(av[i], &endp, 0);
5487
printf("Invalid address \"%s\"\n", av[i]);
5490
NEXTC("<LENGTH>", "rb");
5491
length = strtoul(av[i], &endp, 0);
5493
printf("Invalid length \"%s\"\n", av[i]);
5496
data = new u_int8_t[length];
5505
NEXTC("<OUT_FILENAME>", "rb");
5506
if ((fh = fopen(av[i], "wb")) == NULL) {
5507
fprintf(stderr, "Can not open ");
5514
if (!fbase->read(addr, data, length)) {
5515
printf("*** ERROR *** Flash read failed: %s\n", fbase->err());
5521
if (fwrite(data, 1, length, fh) != length) {
5522
perror("Write error");
5527
for (u_int32_t i = 0; i < length ; i+=4) {
5528
u_int32_t word = *((u_int32_t*)(data + i));
5530
word = __be32_to_cpu(word);
5531
printf("0x%08x ", word);
5541
// READ DWORD <ADDR>
5542
// Parameters: <ADDR>
5543
u_int32_t data, addr;
5547
NEXTC("<ADDR>", "rw");
5548
addr = strtoul(av[i], &endp, 0);
5550
printf("Invalid address \"%s\"\n", av[i]);
5555
if (!f->read(addr, &data)) {
5556
printf("*** ERROR *** Flash read failed: %s\n", f->err());
5559
printf("0x%08x\n", (unsigned int)__cpu_to_be32(data));
5567
if (!ops.Verify(*fbase, NULL, true)) {
5568
printf("\n*** ERROR *** FW image verification failed");
5570
printf(": %s", ops.err());
5572
printf(". AN HCA DEVICE CAN NOT BOOT FROM THIS IMAGE.\n");
5575
printf("\nFW image verification succeeded. Image is bootable.\n\n");
5585
char* conf_file = NULL;
5587
NEXTC("<OUT_FILENAME>", "dc");
5593
if(!ops.DumpConf(conf_file)) {
5594
printf("*** ERROR *** Failed dumping FW configuration: %s\n", ops.err());
5600
case CMD_READ_IMAGE:
5605
char* img_file = NULL;
5606
NEXTC("<OUT_FILENAME>", "ri");
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());
5613
//printf("Last addr: 0x%08x\n", ops._last_image_addr);
5615
u_int32_t length = ops._last_image_addr;
5616
u_int8_t* data = new u_int8_t[length];
5620
if ((fh = fopen(av[i], "wb")) == NULL) {
5621
fprintf(stderr, "Can not open ");
5627
if (!f->read(0, data, length)) {
5628
printf("*** ERROR *** Flash read failed: %s\n", f->err());
5633
if (fwrite(data, 1, length, fh) != length) {
5634
perror("Write error");
5643
case CMD_WRITE_BLOCK:
5646
// Parameters: <IN_FILENAME> <ADDR>
5653
NEXTC("<IN_FILENAME>", "wb");
5655
image_fname = av[i];
5658
NEXTC("<ADDR>", "wb");
5659
addr = strtoul(av[i], &endp, 0);
5661
printf("Invalid address \"%s\"\n", av[i]);
5665
if (!fim.open(image_fname)) {
5666
printf("*** ERROR *** Image file open failed: %s\n", fim.err());
5671
if (!ops.write_image(*f, addr, fim.getBuf(), fim.getBufLength(), !silent)) {
5672
printf("*** ERROR *** Flash write failed: %s\n", ops.err());
5678
case CMD_WRITE_WORD:
5681
// Parameters: <ADDR> <DATA>
5682
u_int32_t data, addr;
5686
NEXTC("<ADDR>", "ww");
5687
addr = strtoul(av[i], &endp, 0);
5689
printf("Invalid address \"%s\"\n", av[i]);
5692
NEXTC("<DATA>", "ww");
5693
data = __cpu_to_be32(strtoul(av[i], &endp, 0));
5695
printf("Invalid data \"%s\"\n", av[i]);
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());
5707
case CMD_WRITE_BLOCK_NE:
5709
// WRITE DWORD WITHOUT ERASE
5710
// Parameters: <ADDR> <SIZE> <DATA>
5711
u_int32_t size, addr;
5715
NEXTC("<ADDR>", "wbne");
5716
addr = strtoul(av[i], &endp, 0);
5718
printf("Invalid address \"%s\"\n", av[i]);
5721
NEXTC("<SIZE>", "wbne");
5722
size = strtoul(av[i], &endp, 0);
5723
if (*endp || size % 4) {
5724
printf("Invalid size \"%s\"\n", av[i]);
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));
5732
printf("Invalid data \"%s\"\n", av[i]);
5736
//printf("-D- writing: %08x : %08x\n", addr + w*4 , data_vec[w]);
5739
if (!f->write(addr, &data_vec[0], size, true)) {
5740
printf("*** ERROR *** Flash write failed: %s\n", f->err());
5746
case CMD_WRITE_WORD_NE:
5748
// WRITE DWORD WITHOUT ERASE
5749
// Parameters: <ADDR> <DATA>
5750
u_int32_t data, addr;
5754
NEXTC("<ADDR>", "wwne");
5755
addr = strtoul(av[i], &endp, 0);
5757
printf("Invalid address \"%s\"\n", av[i]);
5760
NEXTC("<DATA>", "wwne");
5761
data = __cpu_to_be32(strtoul(av[i], &endp, 0));
5763
printf("Invalid data \"%s\"\n", av[i]);
5767
if (!f->write(addr, &data, 4, true)) {
5768
printf("*** ERROR *** Flash write failed: %s\n", f->err());
5776
if (!f->print_attr() || !f->print_attr_old_format()) {
5777
printf("*** ERROR *** Cfi query failed: %s\n", f->err());
5784
// Do nothing - opening the device already cleared the semaphore.
5788
printf("Resetting device %s ...\n", device);
5789
if (!f->sw_reset()) {
5790
printf("*** ERROR *** Software reset failed: %s\n", f->err());
5797
printf("*** INTERNAL ERROR *** Invalid command %d.\n", cmd);
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);