1 : /*
2 : *
3 : * flint.cpp - FLash INTerface
4 : *
5 : * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved.
6 : *
7 : * This software is available to you under a choice of one of two
8 : * licenses. You may choose to be licensed under the terms of the GNU
9 : * General Public License (GPL) Version 2, available from the file
10 : * COPYING in the main directory of this source tree, or the
11 : * OpenIB.org BSD license below:
12 : *
13 : * Redistribution and use in source and binary forms, with or
14 : * without modification, are permitted provided that the following
15 : * conditions are met:
16 : *
17 : * - Redistributions of source code must retain the above
18 : * copyright notice, this list of conditions and the following
19 : * disclaimer.
20 : *
21 : * - Redistributions in binary form must reproduce the above
22 : * copyright notice, this list of conditions and the following
23 : * disclaimer in the documentation and/or other materials
24 : * provided with the distribution.
25 : *
26 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 : * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 : * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 : * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 : * SOFTWARE.
34 : *
35 : * Version: $Id: flint.cpp 5641 2010-01-03 14:26:54Z mohammad $
36 : *
37 : */
38 :
39 :
40 : #include <ctype.h>
41 : #include <stdarg.h>
42 : #include <stdio.h>
43 : #include <string.h>
44 : #include <stdlib.h>
45 : #include <errno.h>
46 : #include <malloc.h>
47 : #include <sys/types.h>
48 : #include <sys/stat.h>
49 : #include <fcntl.h>
50 : #include <assert.h>
51 : #include <time.h>
52 :
53 : #ifndef NO_ZLIB
54 : #include <zlib.h>
55 : #endif
56 :
57 : #include <signal.h>
58 :
59 : #ifndef __WIN__
60 :
61 : //
62 : // GCC Compiler
63 : //
64 :
65 :
66 : #if defined __DJGPP__
67 : //
68 : // DJGPP - GCC PORT TO MS DOS
69 : //
70 :
71 : #include <mtcr.h> // This contains the u_* types definitions
72 :
73 : #include <netinet/in.h>
74 : #include <unistd.h>
75 :
76 : #define bswap_32(x) ntohl(x)
77 :
78 : // djgpp stdio does not define vsnprintf. I simply call vsprintf (and pray ...)
79 : #define vsnprintf(buf, len, format, args) (vsprintf(buf, format, args))
80 :
81 : #else // Linux GCC
82 :
83 : #include <byteswap.h>
84 : #include <endian.h>
85 : #include <alloca.h>
86 : #include <netinet/in.h>
87 : #include <unistd.h>
88 :
89 : #endif // __DJGPP__
90 :
91 : #else // __WIN__
92 :
93 : //
94 : // Windows (Under DDK)
95 : //
96 :
97 : #include <io.h>
98 : #include <Winsock2.h>
99 : #include <mtcr.h>
100 : // Sleep adaptor
101 : #define usleep(x) Sleep((x)/1000)
102 : #define sleep(x) Sleep((x)*1000)
103 :
104 : #define vsnprintf _vsnprintf
105 : #define strtoull _strtoui64
106 : #define isatty _isatty
107 :
108 : #define COMP_CDECL __cdecl
109 :
110 : #define __LITTLE_ENDIAN 1234
111 : #define __BIG_ENDIAN 4321
112 : #define __BYTE_ORDER __LITTLE_ENDIAN
113 :
114 :
115 : #if __BYTE_ORDER == __LITTLE_ENDIAN
116 : #define bswap_32(x) ntohl(x)
117 : #else
118 : #error windows is assumed to run a on little endian architecture
119 : #endif
120 :
121 : #endif // __WIN__
122 :
123 : #include <memory>
124 : #include <vector>
125 :
126 : #include <mflash.h>
127 :
128 :
129 : #ifndef DEV_MST_EXAMPLE1
130 : #define DEV_MST_EXAMPLE1 "/dev/mst/mt25418_pci_cr0"
131 : #endif
132 :
133 : #ifndef DEV_MST_EXAMPLE2
134 : #define DEV_MST_EXAMPLE2 "/dev/mst/mt25418_pciconf0"
135 : #endif
136 :
137 : #ifndef FLINT_NAME
138 : #ifdef __GNUC__
139 : #define FLINT_NAME "%1$s"
140 : #else
141 : #define FLINT_NAME "./flint"
142 : #endif
143 : #endif
144 :
145 : namespace std {}; using namespace std;
146 :
147 : // TODO: Use common functions to windows & linux.
148 : #ifndef __WIN__
149 : #if defined (VERSION_ID) && defined (BLD_VER_STR)
150 : #define __VFSTR(x, y) "MFT "#x" , BUILD "#y
151 : #define _VFSTR(x, y) __VFSTR(x, y)
152 : const char* _versionID = _VFSTR( BLD_VER_STR, VERSION_ID ) ;
153 : #else
154 : const char* _versionID = "MFT 2.6.1 , BUILD 20100104-1702";
155 : #endif
156 : #else
157 : #if defined (VERSION_ID)
158 : #define __VFSTR1(x) #x
159 : #define _VFSTR1(x) __VFSTR1(x)
160 : const char* _versionID = _VFSTR1( VERSION_ID ) ;
161 : #else
162 : const char* _versionID = "MFT 2.6.1 , BUILD 20100104-1702";
163 : #endif
164 : #endif
165 :
166 : const char* _svnID = "$Revision: 5641 $";
167 :
168 : #ifndef __be32_to_cpu
169 : #define __be32_to_cpu(x) ntohl(x)
170 : #ifndef bswap_32
171 : #define bswap_32(x) (htonl(x))
172 : #endif
173 : #endif
174 : #ifndef __cpu_to_be32
175 : #define __cpu_to_be32(x) htonl(x)
176 : #endif
177 :
178 : #if __BYTE_ORDER == __LITTLE_ENDIAN
179 : #ifndef __cpu_to_le32
180 : #define __cpu_to_le32(x) (x)
181 : #endif
182 : #ifndef __le32_to_cpu
183 : #define __le32_to_cpu(x) (x)
184 : #endif
185 : #elif __BYTE_ORDER == __BIG_ENDIAN
186 : #ifndef __cpu_to_le32
187 : #define __cpu_to_le32(x) bswap_32(x)
188 : #endif
189 : #ifndef __le32_to_cpu
190 : #define __le32_to_cpu(x) bswap_32(x)
191 : #endif
192 : #else
193 : #ifndef __cpu_to_le32
194 : #define __cpu_to_le32(x) bswap_32(__cpu_to_be32(x))
195 : #endif
196 : #ifndef __le32_to_cpu
197 : #define __le32_to_cpu(x) __be32_to_cpu(bswap_32(x))
198 : #endif
199 : #endif
200 :
201 :
202 : ////////////////////////////////////////////////////////////////////////
203 : // //
204 : // ****************************************************************** //
205 : // Miscellaneous global stuff //
206 : // ****************************************************************** //
207 : // //
208 : ////////////////////////////////////////////////////////////////////////
209 : typedef struct guid {
210 : u_int32_t h;
211 : u_int32_t l;
212 : } guid_t;
213 :
214 0 : static inline void be_guid_to_cpu(guid_t* to, guid_t* from) {
215 0 : to->h=__be32_to_cpu(from->h);
216 0 : to->l=__be32_to_cpu(from->l);
217 : }
218 :
219 : static inline void cpu_to_be_guid(guid_t* to, guid_t* from) {
220 : to->h=__cpu_to_be32(from->h);
221 : to->l=__cpu_to_be32(from->l);
222 : }
223 : #define MAX_NUM_SUPP_HW_IDS 200
224 : #define MAC_SPACES " "
225 : #define GUID_SPACES " "
226 : #define GUID_FORMAT "%8.8x%8.8x"
227 : #define MAC_FORMAT "%4.4x%8.8x"
228 : #define TOCPU1(s) s = __be32_to_cpu((u_int32_t)(s));
229 : #define CPUTO1(s) s = __cpu_to_be32((u_int32_t)(s));
230 : #define TOCPU(s) do { \
231 : u_int32_t *p = (u_int32_t *)(s); \
232 : for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t); ii++,p++) \
233 : *p = __be32_to_cpu(*p); \
234 : } while(0)
235 : #define TOCPUn(s, n) do { \
236 : u_int32_t *p = (u_int32_t *)(s); \
237 : for (u_int32_t ii=0; ii<(n); ii++,p++) \
238 : *p = __be32_to_cpu(*p); \
239 : } while(0)
240 :
241 : #define CPUTOn(s, n) do { \
242 : u_int32_t *p = (u_int32_t *)(s); \
243 : for (u_int32_t ii=0; ii<(n); ii++,p++) \
244 : *p = __cpu_to_be32(*p); \
245 : } while(0)
246 :
247 : #define TOCPUBY(s) do { \
248 : u_int32_t *p = (u_int32_t *)(&s); \
249 : for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t); ii++,p++) \
250 : *p = __be32_to_cpu(*p); \
251 : } while(0)
252 : #define CPUTOBY(s) do { \
253 : u_int32_t *p = (u_int32_t *)(&s); \
254 : for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t); ii++,p++) \
255 : *p = __cpu_to_be32(*p); \
256 : } while(0)
257 : #define TOCPUBY64(s) do { \
258 : guid_t *p = s; \
259 : for (unsigned ii=0; ii<sizeof(s)/sizeof(guid_t); ii++,p++) \
260 : be_guid_to_cpu(p,p); \
261 : } while(0)
262 : #define CRC(c, s) do { \
263 : u_int32_t *p = (u_int32_t *)(s); \
264 : for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t); ii++) \
265 : c << *p++; \
266 : } while(0)
267 : #define CRCn(c, s, n) do { \
268 : u_int32_t *p = (u_int32_t *)(s); \
269 : for (u_int32_t ii=0; ii<(n); ii++) \
270 : c << *p++; \
271 : } while(0)
272 : #define CRCBY(c, s) do { \
273 : u_int32_t *p = (u_int32_t *)(&s); \
274 : for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t); ii++) \
275 : c << *p++; \
276 : } while(0)
277 : #define CRC1(c, s) do { \
278 : u_int32_t *p = (u_int32_t *)(s); \
279 : for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t) - 1; ii++) \
280 : c << *p++; \
281 : } while(0)
282 : #define CRC1n(c, s, n) do { \
283 : u_int32_t *p = (u_int32_t *)(s); \
284 : for (u_int32_t ii=0; ii<(n) - 1; ii++) \
285 : c << *p++; \
286 : } while(0)
287 0 : #define CRC1BY(c, s) do { \
288 : u_int32_t *p = (u_int32_t *)(&s); \
289 : for (u_int32_t ii=0; ii<sizeof(s)/sizeof(u_int32_t) - 1; ii++) \
290 : c << *p++; \
291 : } while(0)
292 :
293 : #define CHECKB2(f,b,o,n,p) do { if (!checkBoot2(f,b,o,n,p)) return false; } while (0)
294 :
295 : #define CHECKGN(f,b,o,n,p,i) do { if (!checkGen(f,b,o,n,p,i)) return false; } while (0)
296 : #define CHECKLS(f,o,s,p,i) do { if (!checkList(f,o,s,p,i)) return false; } while(0)
297 : #define READ4(f,o,d,p) do { if (!f.read(o,d)) { \
298 : return errmsg("%s - read error (%s)\n", p, f.err()); }} while (0)
299 : #define READBUF(f,o,d,l,p) do { if (!f.read(o,d,l)) { \
300 : return errmsg("%s - read error (%s)\n", p, f.err()); }} while (0)
301 :
302 : #define MAX_ERR_STR_LEN 1024
303 : #define FS2_BOOT_START 0x38
304 : #define IMG_CRC_OFF 0x20
305 : #define FLINT_LOG_ENV "FLINT_LOG_FILE"
306 : #define FLINT_IGNORE_TTY "FLINT_IGNORE_TTY"
307 : #define FS_DATA_OFF 0x28
308 :
309 : class ErrMsg {
310 : public:
311 8 : ErrMsg() : _err(0) {}
312 16 : ~ErrMsg() { err_clear();}
313 0 : const char *err() const { return _err;}
314 16 : void err_clear() { delete [] _err; _err = 0;}
315 :
316 : protected:
317 :
318 : char *vprint(const char *format, va_list args)
319 0 : {
320 0 : const int INIT_VAL = 1024;
321 0 : int max_str, max_buf = INIT_VAL;
322 0 : char *out_buf;
323 :
324 0 : while (1) {
325 0 : out_buf = new char[max_buf];
326 0 : max_str = max_buf - 1;
327 :
328 0 : if (vsnprintf(out_buf, max_str, format, args) < max_str)
329 0 : return out_buf;
330 0 : delete [] out_buf;
331 0 : max_buf *= 2;
332 : }
333 : }
334 :
335 :
336 : bool errmsg(const char *format, ...)
337 : #ifdef __GNUC__
338 : __attribute__ ((format (printf, 2, 3)))
339 : #endif
340 : ;
341 :
342 : private:
343 :
344 : char *_err;
345 : };
346 :
347 :
348 0 : bool ErrMsg::errmsg(const char *format, ...) {
349 0 : va_list args;
350 :
351 0 : char* prev_err = _err;
352 :
353 0 : va_start(args, format);
354 0 : _err = vprint(format, args);
355 0 : va_end(args);
356 :
357 0 : delete[] prev_err;
358 :
359 0 : return false;
360 : }
361 :
362 :
363 : enum {
364 : SIGNATURE = 0x5a445a44,
365 : MELLANOX_VENDOR_ID = 0x15b3
366 : };
367 : struct PS {
368 : u_int32_t fi_addr;
369 : u_int32_t fi_size;
370 : u_int32_t signature;
371 : u_int32_t fw_reserved[5];
372 : u_int32_t vsd[52];
373 : u_int32_t psid[4];
374 : u_int32_t branch_to;
375 : u_int32_t crc016;
376 : };
377 :
378 : enum SectionType {
379 : H_FIRST = 1,
380 : H_DDR = 1,
381 : H_CNF = 2,
382 : H_JMP = 3,
383 : H_EMT = 4,
384 : H_ROM = 5,
385 : H_GUID = 6,
386 : H_BOARD_ID = 7,
387 : H_USER_DATA = 8,
388 : H_FW_CONF = 9,
389 : H_IMG_INFO = 10,
390 : H_DDRZ = 11,
391 : H_HASH_FILE = 12,
392 : H_LAST
393 : };
394 :
395 : const char* g_sectNames[] = {
396 : "UNKNOWN (0 - Reserved)",
397 : "DDR" ,
398 : "Configuration" ,
399 : "Jump addresses" ,
400 : "EMT Service" ,
401 : "ROM" ,
402 : "GUID" ,
403 : "BOARD ID" ,
404 : "User Data" ,
405 : "FW Configuration",
406 : "Image Info" ,
407 : "DDRZ" ,
408 : "Hash File"
409 : };
410 :
411 :
412 : struct GPH {
413 : u_int32_t type;
414 : u_int32_t size;
415 : u_int32_t param;
416 : u_int32_t next;
417 : };
418 :
419 : #define MAX_SECTION_SIZE 0x400000
420 :
421 : const u_int32_t BOARD_ID_BSN_LEN=64;
422 : const u_int32_t BOARD_ID_BID_LEN=32;
423 : const u_int32_t BOARD_ID_PID=7;
424 :
425 : struct BOARD_ID {
426 : char bsn[BOARD_ID_BSN_LEN];
427 : char bid[BOARD_ID_BID_LEN];
428 : };
429 :
430 : int const VSD_LEN = 208;
431 : int const PSID_LEN = 16;
432 : int const PRODUCT_VER_LEN = 16;
433 :
434 : //
435 : // TODO: Remove the below globals to class members.
436 : //
437 : bool _print_crc = false;
438 : bool _silent = false;
439 : bool _assume_yes = false;
440 : bool _assume_no = false;
441 : bool _no_erase = false;
442 : bool _no_burn = false;
443 : bool _unlock_bypass = false;
444 : bool _byte_write = false;
445 :
446 :
447 : void report(const char *format, ...)
448 : #ifdef __GNUC__
449 : __attribute__ ((format (printf, 1, 2)))
450 : #endif
451 : ;
452 : void report(const char *format, ...)
453 0 : {
454 0 : va_list args;
455 :
456 0 : if (!_silent) {
457 0 : va_start(args, format);
458 0 : vprintf(format, args);
459 0 : va_end(args);
460 : }
461 : } // report
462 0 :
463 : void report_erase(const char *format, ...)
464 0 : {
465 0 : va_list args;
466 0 : char buf[256];
467 0 : int i;
468 0 : int len;
469 :
470 0 : if (_silent)
471 0 : return;
472 :
473 0 : va_start(args, format);
474 0 : vsnprintf(buf, sizeof buf, format, args);
475 0 : va_end(args);
476 :
477 0 : len = strlen(buf);
478 0 : for (i=0; i < len; ++i)
479 0 : printf("\b");
480 : } // report_erase
481 :
482 : void report_repair_msg(const char* common_msg)
483 0 : {
484 0 : printf("\r%s OK ", common_msg);
485 : }
486 :
487 : #define MAX_ERR_STR_LEN 1024
488 : #define PRE_ERR_MSG "-E-"
489 : void report_err(char err_buff[MAX_ERR_STR_LEN], const char *format, ...)
490 0 : {
491 0 : va_list args;
492 :
493 0 : va_start(args, format);
494 :
495 0 : if (vsnprintf(err_buff, MAX_ERR_STR_LEN, format, args) >= MAX_ERR_STR_LEN) {
496 0 : strcpy(&err_buff[MAX_ERR_STR_LEN - 5], "...\n");
497 : }
498 0 : fprintf(stderr, PRE_ERR_MSG" %s", err_buff);
499 :
500 : va_end(args);
501 :
502 : return;
503 : }
504 :
505 : void report_warn(const char *format, ...)
506 0 : {
507 0 : va_list args;
508 0 : va_start(args, format);
509 0 : printf("\n-W- ");
510 0 : vfprintf(stdout, format, args);
511 0 : printf("\n");
512 : va_end(args);
513 : }
514 :
515 : ////////////////////////////////////////////////////////////////////////
516 : // //
517 : // ****************************************************************** //
518 : // CRC16 CALCULATION //
519 : // ****************************************************************** //
520 : // //
521 : ////////////////////////////////////////////////////////////////////////
522 : class Crc16 {
523 : public:
524 4 : Crc16(bool d = false) : _debug(d) { clear();}
525 0 : u_int16_t get() { return _crc;}
526 4 : void clear() { _crc = 0xffff;}
527 0 : void operator<<(u_int32_t val) { add(val);}
528 : void add(u_int32_t val);
529 : void finish();
530 : private:
531 : u_int16_t _crc;
532 : bool _debug;
533 : };
534 :
535 : ////////////////////////////////////////////////////////////////////////
536 : void Crc16::add(u_int32_t o)
537 0 : {
538 0 : if (_debug)
539 0 : printf("Crc16::add(%08x)\n", o);
540 0 : for (int i=0; i<32; i++) {
541 0 : if (_crc & 0x8000)
542 0 : _crc = (u_int16_t) ((((_crc<<1) | (o>>31)) ^ 0x100b) & 0xffff);
543 : else
544 0 : _crc= (u_int16_t) (((_crc<<1) | (o>>31)) & 0xffff);
545 0 : o = (o<<1) & 0xffffffff;
546 : }
547 : } // Crc16::add
548 :
549 :
550 : ////////////////////////////////////////////////////////////////////////
551 : void Crc16::finish()
552 0 : {
553 0 : for (int i=0; i<16; i++) {
554 0 : if (_crc & 0x8000)
555 0 : _crc=((_crc<<1) ^ 0x100b) & 0xffff;
556 : else
557 0 : _crc=(_crc<<1) & 0xffff;
558 : }
559 :
560 : // Revert 16 low bits
561 0 : _crc = _crc ^ 0xffff;
562 :
563 : } // Crc16::finish
564 :
565 :
566 : //////////////////////////////////////////////////////////////////////
567 : //
568 : // class u_int32_ba (bit access):
569 : // A uint wrapper which allows easy access to bit/range of bits.
570 : //
571 : // Usage example:
572 : // u_int32_ba a;
573 : // Read_Word( Table.reg ,&a);
574 : // int upper_byte = a.range(31,24);
575 : // if (a[15])
576 : // cout << " Bit 15 is 1 \n";
577 : // else
578 : // cout << " Bit 15 is 0 \n";
579 : //
580 : // u_int32_ba b;
581 : // b.range(15,12) = 0xa;
582 : // b[31] = 1; // b == 0x8000a000
583 : // Write_Word( Table.reg ,b);
584 : //
585 : //////////////////////////////////////////////////////////////////////
586 :
587 :
588 : class u_int32_ba {
589 : public:
590 0 : u_int32_ba(u_int32_t i = 0) :
591 : _bits(i),
592 : _rbits(_bits),
593 : _sptr1(0),
594 0 : _eptr(31) {}
595 :
596 : u_int32_ba operator[](u_int32_t idx) {return range((u_int8_t)idx,(u_int8_t)idx);}
597 0 : u_int32_ba& operator= (u_int32_t i) {_rbits = ((i << _sptr1) & mask()) | (_rbits & ~mask()); return *this;}
598 : u_int32_t* operator& () {return &_bits;}
599 0 : operator u_int32_t () {return((mask() & _rbits) >> _sptr1);}
600 :
601 : u_int32_ba range (u_int8_t eptr,
602 0 : u_int8_t sptr) {return u_int32_ba(*this,eptr,sptr);}
603 :
604 : private:
605 0 : u_int32_ba(u_int32_ba& other, u_int8_t eptr, u_int8_t sptr) :
606 : _bits(other._bits),
607 : _rbits(other._bits),
608 : _sptr1(sptr),
609 0 : _eptr(eptr) {}
610 :
611 0 : u_int32_t mask () {
612 0 : u_int32_t s_msk = (u_int32_t)-1; // start mask
613 0 : u_int32_t e_msk = (u_int32_t)-1; // end mask
614 :
615 0 : s_msk = (s_msk << _sptr1);
616 0 : e_msk = (_eptr >= (sizeof(_bits)*8-1)) ? e_msk : ~(e_msk << (_eptr+1));
617 :
618 : return(s_msk & e_msk);
619 : };
620 :
621 : u_int32_t _bits;
622 : u_int32_t& _rbits;
623 :
624 : u_int8_t _sptr1;
625 : u_int8_t _eptr;
626 : };
627 :
628 : //////////////////////////////////////////////////////////////////////
629 : //
630 : // class Aligner:
631 : // A utillity class for accessing an addr/size region
632 : // in a specific alignment.
633 : // If a 0 alignment is given, infinity (no alignment requirements)
634 : // is assumed - This is to support single flow for the caller.
635 : //
636 : //////////////////////////////////////////////////////////////////////
637 :
638 : class Aligner {
639 : public:
640 0 : Aligner(u_int32_t log2_alignment_size) :
641 : _log2_alignment_size(log2_alignment_size),
642 : _alignment_size(1 << log2_alignment_size),
643 : _alignment_mask(_alignment_size - 1)
644 0 : {
645 0 : if (_log2_alignment_size == 0) {
646 0 : _log2_alignment_size = 31;
647 0 : _alignment_size = 1 << _log2_alignment_size;
648 0 : _alignment_mask = _alignment_size - 1;
649 : }
650 : }
651 :
652 0 : void Init (u_int32_t addr, u_int32_t size) {
653 0 : _curr_addr = addr;
654 0 : _curr_size = size;
655 : }
656 :
657 0 : bool GetNextChunk(u_int32_t& chunk_addr, u_int32_t& chunk_size) {
658 0 : if (_curr_size == 0) {
659 : return false;
660 : }
661 :
662 0 : chunk_addr = _curr_addr;
663 :
664 0 : if ( (_curr_addr >> _log2_alignment_size) !=
665 : ((_curr_addr + _curr_size) >> _log2_alignment_size)) {
666 : // Next chunk crosses alignment boundary
667 0 : chunk_size = _alignment_size - (_curr_addr & _alignment_mask);
668 : } else {
669 0 : chunk_size = _curr_size;
670 : }
671 :
672 0 : _curr_addr += chunk_size;
673 0 : _curr_size -= chunk_size;
674 :
675 : return true;
676 : }
677 :
678 : private:
679 : u_int32_t _curr_addr;
680 : u_int32_t _curr_size;
681 : u_int32_t _log2_alignment_size;
682 : u_int32_t _alignment_size;
683 : u_int32_t _alignment_mask;
684 : };
685 :
686 :
687 :
688 :
689 : ////////////////////////////////////////////////////////////////////////
690 : // //
691 : // ****************************************************************** //
692 : // FLASH ACCESS //
693 : // ****************************************************************** //
694 : // //
695 : ////////////////////////////////////////////////////////////////////////
696 :
697 : // Common base class for Flash and for FImage
698 :
699 :
700 : class FBase : public ErrMsg {
701 : public:
702 4 : FBase(bool is_flash) :
703 : _log2_chunk_size(0),
704 12 : _is_flash(is_flash) {}
705 8 : virtual ~FBase() {}
706 :
707 0 : virtual bool open(const char *, bool) {return false;}
708 : virtual void close() = 0;
709 : virtual bool read(u_int32_t addr, u_int32_t *data) = 0;
710 : virtual bool read(u_int32_t addr, void *data, int len,
711 : bool verbose=false,
712 : const char* message = "") = 0;
713 :
714 : virtual u_int32_t get_sector_size() = 0;
715 : virtual u_int32_t get_size() = 0;
716 :
717 : virtual u_int32_t get_dev_id() = 0;
718 : virtual u_int32_t get_rev_id() = 0;
719 0 : Crc16& get_image_crc() {return _image_crc;};
720 0 : bool is_flash() {return _is_flash;};
721 :
722 0 : virtual void set_address_convertor(u_int32_t log2_chunk_size, bool is_image_in_odd_chunks) {
723 0 : _log2_chunk_size = log2_chunk_size;
724 0 : _is_image_in_odd_chunks = is_image_in_odd_chunks;
725 : }
726 :
727 : enum {
728 : MAX_FLASH = 4*1048576
729 : };
730 :
731 : protected:
732 :
733 : // Address translation functions for ConnectX.
734 : // Translate between contiguous "logical" addresses
735 :
736 : // If Failsafe zebra mapping is enabled:
737 :
738 : // Result is concatenation of:
739 : // The lower log2_chunk_size bits of the cons_addr
740 : // The is_image_in_odd_chunk bit
741 : // The remaining upper bits of the cons_addr
742 :
743 0 : u_int32_t cont2phys(u_int32_t cont_addr) {
744 0 : u_int32_t result;
745 0 : if (_log2_chunk_size) {
746 0 : result = (cont_addr & (0xffffffff >> (32 - _log2_chunk_size))) |
747 : (_is_image_in_odd_chunks << _log2_chunk_size) |
748 : ((cont_addr << 1) & (0xffffffff << (_log2_chunk_size + 1)));
749 : } else {
750 0 : result = cont_addr;
751 0 : }
752 : return result;
753 : }
754 :
755 : u_int32_t phys2cont(u_int32_t phys_addr) {
756 : u_int32_t result;
757 : if (_log2_chunk_size) {
758 : result = (phys_addr & (0xffffffff >> (32 - _log2_chunk_size))) |
759 : ((phys_addr >> 1) & (0xffffffff << ( _log2_chunk_size)));
760 : } else {
761 : result = phys_addr;
762 : }
763 : return result;
764 : }
765 :
766 : bool _is_image_in_odd_chunks;
767 : u_int32_t _log2_chunk_size;
768 : Crc16 _image_crc;
769 : const bool _is_flash;
770 :
771 : };
772 :
773 : // Flash image (RO)
774 : class FImage : public FBase {
775 : public:
776 8 : FImage() : FBase(false), _buf(0) {}
777 8 : virtual ~FImage() { close();}
778 :
779 0 : u_int32_t *getBuf() { return _buf;}
780 0 : u_int32_t getBufLength() { return _len;}
781 : virtual bool open(const char *fname, bool read_only = false);
782 : bool open(u_int32_t *buf, u_int32_t len);
783 : virtual void close();
784 : virtual bool read(u_int32_t addr, u_int32_t *data);
785 : virtual bool read(u_int32_t addr, void *data, int len, bool verbose=false, const char* message= "");
786 :
787 : virtual u_int32_t get_sector_size();
788 0 : virtual u_int32_t get_size() { return getBufLength();}
789 0 : virtual u_int32_t get_dev_id() { return 0;}
790 0 : virtual u_int32_t get_rev_id() { return 0;}
791 :
792 : private:
793 : u_int32_t *_buf;
794 : u_int32_t _len;
795 : };
796 :
797 : //
798 : // Flash access (R/W)
799 : //
800 : class Flash : public FBase {
801 : public:
802 0 : Flash() :
803 : FBase(true),
804 : _mfl(0),
805 : _curr_sector(0xffffffff),
806 : _port_num(0)
807 0 : {}
808 :
809 0 : virtual ~Flash() { close();};
810 :
811 : // FBase Interface
812 :
813 : virtual bool open (const char *device,
814 : bool force_lock = false,
815 : bool read_only = false,
816 : int num_of_banks = 4);
817 :
818 : virtual void close ();
819 :
820 : virtual bool read (u_int32_t addr,
821 : u_int32_t *data);
822 :
823 : virtual bool read (u_int32_t addr,
824 : void* data,
825 : int len,
826 : bool verbose = false,
827 : const char* message = "");
828 :
829 : bool cr_write (u_int32_t addr,
830 0 : u_int32_t data) {return mf_cr_write(_mfl, addr, data) == MFE_OK;}
831 :
832 : //
833 : // Flash Interface
834 : //
835 :
836 0 : u_int32_t get_sector_size () {return _attr.sector_size;}
837 0 : u_int32_t get_size () {return _attr.size;}
838 :
839 0 : u_int32_t get_dev_id () {return _attr.hw_dev_id; }
840 0 : u_int32_t get_rev_id () {return _attr.rev_id; }
841 0 : u_int32_t get_port_num () {return _port_num;}
842 :
843 : bool sw_reset();
844 :
845 : // Write and Erase functions are performed by the Command Set
846 :
847 : virtual bool erase_sector (u_int32_t addr);
848 :
849 : virtual bool write (u_int32_t addr,
850 : void* data,
851 : int cnt,
852 : bool noerase = false);
853 :
854 : virtual bool write (u_int32_t addr,
855 : u_int32_t data);
856 :
857 : bool print_attr();
858 : bool print_attr_old_format();
859 :
860 : enum {
861 : TRANS = 4096
862 : };
863 :
864 : static bool _byte_mode;
865 : static bool _no_flash_verify;
866 :
867 : #ifndef _MSC_VER
868 : protected:
869 : #endif
870 :
871 : mflash* _mfl;
872 : flash_attr _attr;
873 :
874 : u_int32_t _curr_sector;
875 : u_int32_t _port_num;
876 : };
877 :
878 :
879 : ////////////////////////////////////////////////////////////////////////
880 : //
881 : // FImage Class Implementation
882 : //
883 : ////////////////////////////////////////////////////////////////////////
884 :
885 : bool FImage::open(const char *fname, bool read_only)
886 0 : {
887 0 : int fsize;
888 0 : int r_cnt;
889 0 : FILE *fh;
890 :
891 0 : read_only = true; // FImage can be opened only for read
892 :
893 0 : fh = fopen(fname, "rb");
894 :
895 0 : if (!fh) {
896 0 : return errmsg("Can not open file \"%s\" - %s", fname, strerror(errno));
897 : }
898 :
899 : // Get the file size:
900 0 : if (fseek(fh, 0, SEEK_END) < 0) {
901 0 : return errmsg("Can not get file size for \"%s\" - %s", fname, strerror(errno));
902 : }
903 :
904 0 : fsize = ftell(fh);
905 0 : if (fsize < 0) {
906 0 : return errmsg("Can not get file size for \"%s\" - %s", fname, strerror(errno));
907 : }
908 0 : rewind(fh);
909 :
910 : //printf("-D- %s size is %d\n", fname, fsize);
911 0 : if (fsize & 0x3) {
912 0 : return errmsg("Image size should be 4-bytes aligned. Make sure file %s is in the right format (binary image)",
913 : fname);
914 : }
915 :
916 0 : _buf = new u_int32_t[fsize/4];
917 0 : if ((r_cnt = fread(_buf, 1, fsize, fh)) != fsize) {
918 0 : if (r_cnt < 0)
919 0 : return errmsg("Read error on file \"%s\" - %s",fname, strerror(errno));
920 : else
921 0 : return errmsg("Read error on file \"%s\" - read only %d bytes (from %ld)",
922 : fname, r_cnt, (unsigned long)fsize);
923 : }
924 :
925 0 : _len = fsize;
926 0 : fclose(fh);
927 :
928 0 : return true;
929 : } // FImage::open
930 :
931 : bool FImage::open(u_int32_t *buf, u_int32_t len)
932 0 : {
933 0 : _buf = new u_int32_t[len / 4];
934 0 : memcpy(_buf, buf, len);
935 0 : _len = len;
936 0 : return true;
937 : }
938 : ////////////////////////////////////////////////////////////////////////
939 : void FImage::close()
940 4 : {
941 4 : delete [] _buf;
942 4 : _buf = 0;
943 : } // FImage::close
944 :
945 : ////////////////////////////////////////////////////////////////////////
946 : bool FImage::read(u_int32_t addr, u_int32_t *data)
947 0 : {
948 0 : return read(addr, data, 4);
949 : } // FImage::read
950 :
951 : ////////////////////////////////////////////////////////////////////////
952 : bool FImage::read(u_int32_t addr, void *data, int len, bool, const char*)
953 0 : {
954 :
955 0 : if (addr & 0x3) {
956 0 : return errmsg("Address should be 4-bytes aligned.");
957 : }
958 0 : if (len & 0x3) {
959 0 : return errmsg("Length should be 4-bytes aligned.");
960 : }
961 0 : if (!_buf) {
962 0 : return errmsg("read() when not opened");
963 : }
964 :
965 0 : if (cont2phys(addr + len) > _len) {
966 0 : return errmsg("Reading 0x%x bytes from %saddress 0x%x is out of image limits (0x%x bytes)",
967 : len,
968 : _log2_chunk_size ? "physical " : "",
969 : addr,
970 : _len);
971 : }
972 :
973 0 : u_int32_t chunk_addr;
974 0 : u_int32_t chunk_size;
975 0 : Aligner align(_log2_chunk_size);
976 0 : align.Init (addr, len);
977 0 : while (align.GetNextChunk(chunk_addr, chunk_size)) {
978 0 : u_int32_t phys_addr = cont2phys(chunk_addr);
979 :
980 0 : memcpy((u_int8_t*)data + (chunk_addr - addr),
981 : (u_int8_t*)_buf + phys_addr,
982 : chunk_size);
983 : }
984 :
985 0 : return true;
986 : } // FImage::read
987 :
988 : ////////////////////////////////////////////////////////////////////////
989 : u_int32_t FImage::get_sector_size()
990 0 : {
991 0 : u_int32_t log2_sector_sz_ptr;
992 0 : u_int32_t log2_sector_sz;
993 0 : u_int32_t signature;
994 :
995 0 : read(0x24, &signature);
996 0 : TOCPU1(signature);
997 0 : if (signature == SIGNATURE) {
998 : // full image:
999 0 : read(0x14, &log2_sector_sz_ptr);
1000 0 : TOCPU1(log2_sector_sz_ptr);
1001 0 : log2_sector_sz_ptr &= 0xffff;
1002 :
1003 0 : read(0x30 + log2_sector_sz_ptr, &log2_sector_sz);
1004 0 : TOCPU1(log2_sector_sz);
1005 0 : log2_sector_sz &= 0xffff;
1006 :
1007 0 : return(1 << log2_sector_sz);
1008 :
1009 : } else {
1010 0 : return 0;
1011 : }
1012 : }
1013 :
1014 :
1015 :
1016 : ////////////////////////////////////////////////////////////////////////
1017 : //
1018 : // Flash Class Implementation
1019 : //
1020 : ////////////////////////////////////////////////////////////////////////
1021 :
1022 :
1023 : bool Flash::_byte_mode = false;
1024 : bool Flash::_no_flash_verify = false;
1025 :
1026 : ////////////////////////////////////////////////////////////////////////
1027 : bool Flash::open(const char *device, bool force_lock, bool read_only, int num_of_banks)
1028 0 : {
1029 : // Open device
1030 0 : int rc;
1031 0 : read_only = false;
1032 :
1033 0 : rc = mf_open(&_mfl, device, num_of_banks);
1034 :
1035 0 : if ((rc == MFE_SEM_LOCKED) && force_lock) {
1036 0 : report("Warning: Taking flash lock even though semaphore is set.\n");
1037 0 : rc = mf_open_ignore_lock(_mfl);
1038 : }
1039 :
1040 0 : if (rc == MFE_SEM_LOCKED) {
1041 0 : return errmsg("Can not obtain Flash semaphore (63). You can run \"flint -clear_semaphore -d <device>\" to force semaphore unlock. See help for details.");
1042 : } else
1043 0 : if (rc != MFE_OK) {
1044 0 : return errmsg("%s %s", errno == 0 ? "" : strerror(errno), mf_err2str(rc));
1045 : }
1046 :
1047 0 : rc = mf_get_attr(_mfl, &_attr);
1048 0 : if (rc != MFE_OK) {
1049 0 : return errmsg("Failed getting flash attributes for device %s: %s", device, mf_err2str(rc));
1050 : }
1051 :
1052 0 : if (_attr.hw_dev_id == 435) {
1053 0 : _port_num = 0;
1054 0 : } else if (_attr.hw_dev_id == 25204 || _attr.hw_dev_id == 24204) {
1055 0 : _port_num = 1;
1056 : } else {
1057 0 : _port_num = 2;
1058 : }
1059 :
1060 0 : if (_byte_mode) {
1061 0 : rc = mf_set_opt(_mfl, MFO_AMD_BYTE_MODE, 1);
1062 0 : if (rc != MFE_OK) {
1063 0 : return errmsg("Failed setting byte mode for device %s: %s", device, mf_err2str(rc));
1064 : }
1065 : }
1066 0 : if (_no_flash_verify) {
1067 0 : rc = mf_set_opt(_mfl, MFO_NO_VERIFY, 1);
1068 : }
1069 :
1070 0 : return true;
1071 : } // Flash::open
1072 :
1073 : ////////////////////////////////////////////////////////////////////////
1074 : void Flash::close()
1075 0 : {
1076 0 : if (!_mfl)
1077 0 : return;
1078 :
1079 0 : mf_close(_mfl);
1080 0 : _mfl = 0;
1081 : } // Flash::close
1082 :
1083 :
1084 : bool Flash::read(u_int32_t addr,
1085 0 : u_int32_t *data) {
1086 0 : int rc;
1087 :
1088 0 : u_int32_t phys_addr = cont2phys(addr);
1089 0 : rc = mf_read(_mfl, phys_addr, 4, (u_int8_t*)data);
1090 0 : if (rc != MFE_OK) {
1091 0 : return errmsg("Flash read failed at address %s0x%x : %s",
1092 : _log2_chunk_size ? "physical " : "",
1093 : addr,
1094 : mf_err2str(rc));
1095 : }
1096 :
1097 0 : return true;
1098 : }
1099 :
1100 : ////////////////////////////////////////////////////////////////////////
1101 : bool Flash::read(u_int32_t addr, void *data, int len, bool verbose, const char* message)
1102 0 : {
1103 0 : int rc;
1104 0 : u_int32_t perc = 0xffffffff;
1105 :
1106 0 : if (addr & 0x3) {
1107 0 : return errmsg("Address should be 4-bytes aligned.");
1108 : }
1109 0 : if (len & 0x3) {
1110 0 : return errmsg("Length should be 4-bytes aligned.");
1111 : }
1112 :
1113 : // Much better perf for read in a single chunk. need to work on progress report though.
1114 0 : bool read_in_single_chunk = true;
1115 :
1116 0 : if (read_in_single_chunk) {
1117 0 : u_int32_t chunk_addr;
1118 0 : u_int32_t chunk_size;
1119 :
1120 0 : Aligner align(_log2_chunk_size);
1121 0 : align.Init (addr, len);
1122 0 : while (align.GetNextChunk(chunk_addr, chunk_size)) {
1123 0 : u_int32_t phys_addr = cont2phys(chunk_addr);
1124 :
1125 0 : rc = mf_read(_mfl, phys_addr, chunk_size, ((u_int8_t*)data) + chunk_addr - addr);
1126 0 : if (rc != MFE_OK) {
1127 0 : return errmsg("Flash read failed at address %s0x%x : %s",
1128 : _log2_chunk_size ? "physical " : "",
1129 : chunk_addr,
1130 : mf_err2str(rc));
1131 : }
1132 : }
1133 :
1134 : } else {
1135 0 : u_int32_t *p = (u_int32_t *)data;
1136 0 : for (int i=0; i<len/4; i++) {
1137 0 : if (!read(addr, p++))
1138 0 : return false;
1139 :
1140 0 : addr += 4;
1141 :
1142 : // Report
1143 0 : if (verbose) {
1144 0 : u_int32_t new_perc = (i * 100) / len;
1145 0 : if (new_perc != perc) {
1146 0 : printf("\r%s%%%03d", message, new_perc);
1147 0 : fflush(stdout);
1148 :
1149 0 : perc = new_perc;
1150 : }
1151 : }
1152 : }
1153 : }
1154 : // Report
1155 0 : if (verbose) {
1156 0 : printf("\r%s%%100", message);
1157 0 : fflush(stdout);
1158 : }
1159 :
1160 0 : return true;
1161 : } // Flash::read
1162 :
1163 :
1164 : ////////////////////////////////////////////////////////////////////////
1165 : bool Flash::write (u_int32_t addr,
1166 : void* data,
1167 : int cnt,
1168 : bool noerase)
1169 0 : {
1170 :
1171 : // FIX:
1172 0 : noerase = _no_erase || noerase;
1173 :
1174 0 : if (!_mfl) {
1175 0 : return errmsg("Not opened");
1176 : }
1177 0 : if (addr & 0x3) {
1178 0 : return errmsg("Address should be 4-bytes aligned.");
1179 : }
1180 :
1181 :
1182 0 : if (cont2phys(addr + cnt) > get_size()) {
1183 0 : return errmsg(
1184 : "Trying to write %d bytes to address 0x%x, which exceeds max image size (0x%x - half of total flash size).",
1185 : cnt,
1186 : addr,
1187 : get_size() / 2);
1188 : }
1189 :
1190 0 : u_int8_t *p = (u_int8_t *)data;
1191 0 : u_int32_t sect_size = get_sector_size();
1192 :
1193 0 : u_int32_t chunk_addr;
1194 0 : u_int32_t chunk_size;
1195 :
1196 0 : u_int32_t first_set;
1197 0 : for (first_set = 0; ((sect_size >> first_set) & 1) == 0; first_set++ )
1198 : ;
1199 :
1200 0 : Aligner align(first_set);
1201 0 : align.Init (addr, cnt);
1202 0 : while (align.GetNextChunk(chunk_addr, chunk_size)) {
1203 : // Write / Erase in sector_size alligned chunks
1204 0 : int rc;
1205 :
1206 0 : if (!noerase) {
1207 0 : u_int32_t sector = (chunk_addr / sect_size) * sect_size;
1208 0 : if (sector != _curr_sector) {
1209 0 : _curr_sector = sector;
1210 0 : if (!erase_sector(_curr_sector))
1211 0 : return false;
1212 : }
1213 : }
1214 :
1215 0 : if (_no_burn)
1216 0 : continue;
1217 :
1218 : // Actual write:
1219 0 : u_int32_t phys_addr = cont2phys(chunk_addr);
1220 0 : rc = mf_write(_mfl, phys_addr, chunk_size, p);
1221 0 : if (rc != MFE_OK) {
1222 0 : return errmsg("Flash write of %d bytes to address %s0x%x failed: %s",
1223 : chunk_size,
1224 : _log2_chunk_size ? "physical " : "",
1225 : chunk_addr,
1226 : mf_err2str(rc));
1227 : }
1228 :
1229 : // Loop advance
1230 0 : p += chunk_size;
1231 : }
1232 :
1233 0 : return true;
1234 : }
1235 :
1236 :
1237 : ////////////////////////////////////////////////////////////////////////
1238 : bool Flash::write(u_int32_t addr, u_int32_t data)
1239 0 : {
1240 0 : if (!_mfl) {
1241 0 : return errmsg("Not opened");
1242 : }
1243 0 : if (addr & 0x3) {
1244 0 : return errmsg("Address should be 4-bytes aligned.");
1245 : }
1246 :
1247 0 : u_int32_t word;
1248 :
1249 0 : u_int32_t sector_size = _attr.sector_size;
1250 0 : u_int32_t sector_mask = ~(sector_size - 1);
1251 :
1252 0 : u_int32_t sector = addr & sector_mask;
1253 0 : u_int32_t word_in_sector = (addr & ~sector_mask)/sizeof(u_int32_t);
1254 :
1255 0 : if (!read(addr, &word))
1256 0 : return false;
1257 0 : if (word == data)
1258 0 : return true; // already there
1259 :
1260 0 : vector<u_int32_t> buff(sector_size/sizeof(u_int32_t));
1261 0 : if (!read(sector, &buff[0] , sector_size))
1262 0 : return false;
1263 0 : buff[word_in_sector] = data;
1264 0 : return write(sector, &buff[0], sector_size);
1265 : } // Flash::write
1266 :
1267 :
1268 0 : bool Flash::erase_sector (u_int32_t addr) {
1269 0 : int rc;
1270 :
1271 0 : u_int32_t phys_addr = cont2phys(addr);
1272 0 : rc = mf_erase_sector(_mfl, phys_addr);
1273 0 : if (rc != MFE_OK) {
1274 0 : return errmsg("Flash erase of address 0x%x failed: %s",
1275 : phys_addr,
1276 : mf_err2str(rc));
1277 : }
1278 :
1279 0 : return true;
1280 : }
1281 :
1282 0 : bool Flash::sw_reset() {
1283 0 : if (_attr.hw_dev_id != 435) {
1284 0 : return errmsg("operation supported only for InfiniScale4 switch over IB interface");
1285 : }
1286 0 : int rc = mf_sw_reset(_mfl);
1287 0 : if (rc != MFE_OK) {
1288 0 : return errmsg("%s %s", errno == 0 ? "" : strerror(errno), mf_err2str(rc));
1289 : }
1290 0 : return true;
1291 : }
1292 :
1293 :
1294 :
1295 0 : bool Flash::print_attr() {
1296 0 : printf("Flash attributes:\n");
1297 0 : printf(" HwDevId %d\n", _attr.hw_dev_id);
1298 0 : printf(" TotalSize 0x%x\n", _attr.size);
1299 0 : printf(" Banks 0x%x\n", _attr.size/_attr.bank_size );
1300 0 : printf(" SectorSize 0x%x\n", _attr.sector_size );
1301 0 : printf(" WriteBlockSize 0x%x\n", _attr.block_write);
1302 0 : printf(" CmdSet 0x%x\n", _attr.command_set);
1303 :
1304 0 : return true;
1305 : }
1306 :
1307 0 : bool Flash::print_attr_old_format() {
1308 : // Needed for some old tools which parce the size section of the CFI query in oder flint versions:
1309 :
1310 0 : int i;
1311 0 : printf("\n----Sector Organization Parameters-------------------\n\n");
1312 :
1313 0 : printf("%-50s ", "Device size:");
1314 0 : printf("[%8li] bytes, or [%2i] Mbit\n",
1315 : (long int)_attr.size,
1316 : (int) (_attr.size/((long)0x20000)));
1317 :
1318 0 : printf("%-50s ", "Number of erase block regions:");
1319 0 : printf("%d\n", _attr.num_erase_blocks);
1320 :
1321 0 : for (i = 0; i < _attr.num_erase_blocks; i++) {
1322 0 : printf(" Size:[%8lx] bytes, Mask [%08x], [Number:[%4i]\n",
1323 : _attr.erase_block[i].sector_size,
1324 : _attr.erase_block[i].sector_mask,
1325 : _attr.erase_block[i].num_sectors);
1326 : }
1327 0 : return true;
1328 : }
1329 :
1330 : ////////////////////////////////////////////////////////////////////////
1331 :
1332 : //
1333 : // Commands database and parsing methods
1334 : //
1335 : enum CommandInput {
1336 : CI_NONE = 0x01,
1337 : CI_IMG_ONLY = 0x02,
1338 : CI_DEV_ONLY = 0x04,
1339 : CI_IMG_OR_DEV = 0x06,
1340 : CI_IMG_AND_DEV = 0x08
1341 : };
1342 :
1343 : enum CommandType {
1344 : CMD_UNKNOWN,
1345 : CMD_BURN,
1346 : CMD_SET_GUIDS,
1347 : CMD_BURN_BLOCK,
1348 : CMD_QUERY,
1349 : CMD_QUERY_ROM,
1350 : CMD_QUERY_FORCE,
1351 : CMD_VERIFY,
1352 : CMD_READ_WORD,
1353 : CMD_READ_BLOCK,
1354 : CMD_WRITE_WORD,
1355 : CMD_WRITE_WORD_NE,
1356 : CMD_WRITE_BLOCK,
1357 : CMD_WRITE_BLOCK_NE,
1358 : CMD_ERASE_SECT,
1359 : CMD_DUMP_CONF,
1360 : CMD_DUMP_HASH,
1361 : CMD_READ_IMAGE,
1362 : CMD_CFI,
1363 : CMD_CLEAR_SEM,
1364 : CMD_SWRESET,
1365 : CMD_BURN_ROM,
1366 : CMD_REMOVE_ROM,
1367 : CMD_READ_ROM,
1368 : };
1369 :
1370 : struct CommandInfo {
1371 : CommandType cmd;
1372 : const char* cmdName;
1373 : bool requireExactMatch;
1374 : int maxArgs;
1375 : CommandInput requiredInput;
1376 : const char* cmdDescription;
1377 :
1378 : };
1379 :
1380 : CommandInfo const g_commands[] = {
1381 : { CMD_BURN , "burn" ,false , 0, CI_IMG_AND_DEV , ""},
1382 : { CMD_BURN_BLOCK , "bb" ,true , 0, CI_IMG_AND_DEV , ""},
1383 : { CMD_SET_GUIDS , "sg" ,true , 1, CI_DEV_ONLY , ""},
1384 : { CMD_QUERY_FORCE , "qf" ,true , 0, CI_IMG_OR_DEV , ""},
1385 : { CMD_QUERY , "query" ,false , 0, CI_IMG_OR_DEV , ""},
1386 : { CMD_QUERY_ROM , "qrom" ,true , 0, CI_IMG_ONLY , ""},
1387 : { CMD_VERIFY , "verify",false , 0, CI_IMG_OR_DEV , ""},
1388 : { CMD_READ_WORD , "rw" ,true , 1, CI_DEV_ONLY , ""},
1389 : { CMD_READ_BLOCK , "rb" ,true , 3, CI_IMG_OR_DEV , ""},
1390 : { CMD_WRITE_WORD , "ww" ,true , 2, CI_DEV_ONLY , ""},
1391 : { CMD_WRITE_WORD_NE , "wwne" ,true , 2, CI_DEV_ONLY , ""},
1392 : { CMD_WRITE_BLOCK , "wb" ,true , 2, CI_DEV_ONLY , ""},
1393 : { CMD_WRITE_BLOCK_NE , "wbne" ,true ,-1, CI_DEV_ONLY , ""},
1394 : { CMD_ERASE_SECT , "erase" ,false , 1, CI_DEV_ONLY , ""},
1395 : { CMD_DUMP_CONF , "dc" ,true , 1, CI_IMG_OR_DEV , ""},
1396 : { CMD_DUMP_HASH , "dh" ,true , 1, CI_IMG_OR_DEV , ""},
1397 : { CMD_READ_IMAGE , "ri" ,true , 1, CI_DEV_ONLY , ""},
1398 : { CMD_CLEAR_SEM , "clear_semaphore" ,true , 0 , CI_DEV_ONLY , ""},
1399 : { CMD_SWRESET , "swreset",true , 0, CI_DEV_ONLY , ""},
1400 : { CMD_CFI , "cfi" ,true , 0, CI_DEV_ONLY , ""},
1401 : { CMD_BURN_ROM , "brom" ,true , 1, CI_DEV_ONLY , ""},
1402 : { CMD_REMOVE_ROM , "drom" ,true , 0, CI_DEV_ONLY , ""},
1403 : { CMD_READ_ROM , "rrom" ,true , 1, CI_DEV_ONLY , ""},
1404 :
1405 : };
1406 :
1407 : #define numbel(x) (sizeof(x)/sizeof((x)[0]))
1408 :
1409 :
1410 0 : const CommandInfo* GetCommandInfo(CommandType cmd) {
1411 0 : for (u_int32_t i = 0 ; i < numbel(g_commands); i++ ) {
1412 0 : if (cmd == g_commands[i].cmd) {
1413 0 : return &g_commands[i];
1414 : }
1415 : }
1416 :
1417 0 : return NULL;
1418 : }
1419 :
1420 0 : CommandType ParseCommand(const char* cmd) {
1421 0 : u_int32_t cmdLenGiven = strlen(cmd);
1422 :
1423 0 : for (u_int32_t i = 0 ; i < numbel(g_commands); i++ ) {
1424 0 : if (g_commands[i].requireExactMatch ) {
1425 0 : if (!strcmp(cmd, g_commands[i].cmdName)) {
1426 0 : return g_commands[i].cmd;
1427 : }
1428 : } else {
1429 : // Match if given cmd maches the beginning of the checked cmd
1430 0 : if (!strncmp(cmd, g_commands[i].cmdName, cmdLenGiven )) {
1431 0 : return g_commands[i].cmd;
1432 : }
1433 : }
1434 : }
1435 0 : return CMD_UNKNOWN;
1436 : }
1437 :
1438 :
1439 :
1440 : ////////////////////////////////////////////////////////////////////////
1441 : //
1442 : // Burn Operations functions
1443 : //
1444 : ////////////////////////////////////////////////////////////////////////
1445 : #define FULL_VERIFY 0xff
1446 : #define FREE_STR_MAX_LEN 256
1447 : class Operations : public ErrMsg {
1448 : public:
1449 4 : Operations() :
1450 : _last_image_addr(0),
1451 : _num_ports(2),
1452 : _allow_skip_is(false),
1453 : _is_fs2(false),
1454 : _cntx_striped_image(false),
1455 : _burn_blank_guids(false),
1456 : _quick_query(false),
1457 : _ignore_tty(false)
1458 12 : {
1459 4 : initSectToRead(FULL_VERIFY);
1460 : }
1461 :
1462 : enum {
1463 : GUIDS = 4,
1464 : MACS = 2,
1465 : MAX_GUIDS = 32
1466 : };
1467 :
1468 : enum {
1469 : BX_NP_GUIDS = 2,
1470 : BX_SYS_GUIDS = 1,
1471 : BX_GUIDS = BX_NP_GUIDS + BX_SYS_GUIDS,
1472 : BX_IMACS = 3,
1473 : BX_EMACS = 4,
1474 : BX_MACS = BX_EMACS + BX_IMACS,
1475 : BX_WWPNS = 4,
1476 : BX_WWNNS = 1,
1477 : BX_SLICE_GUIDS = BX_WWNNS + BX_WWPNS + BX_MACS + BX_NP_GUIDS,
1478 :
1479 : BX_ALL_GUIDS = (2 * BX_SLICE_GUIDS) + BX_SYS_GUIDS,
1480 : BX_SLICES_NUM = 2,
1481 : };
1482 :
1483 : enum {
1484 : BI_IMACS = 0,
1485 : BI_EMACS = BI_IMACS + BX_IMACS,
1486 : BI_WWPNS = BI_EMACS + BX_EMACS,
1487 : BI_GUIDS = BI_WWPNS + BX_WWPNS,
1488 : BI_WWNNS = BI_GUIDS + BX_NP_GUIDS,
1489 : BI_SYS_GUID = BX_ALL_GUIDS - 1,
1490 : };
1491 :
1492 : enum ImageInfoTags {
1493 : II_IiFormatRevision = 0,
1494 : II_FwVersion = 1,
1495 : II_FwBuildTime = 2,
1496 : II_DeviceType = 3,
1497 : II_PSID = 4,
1498 : II_VSD = 5,
1499 : II_SuppurtedPsids = 6,
1500 : II_ProductVer = 7,
1501 : II_VsdVendorId = 8,
1502 : II_IsGa = 9,
1503 : II_HwDevsId = 10,
1504 : II_MicVersion = 11,
1505 : II_Last = 12, // Mark the end of used tag ids
1506 : II_End = 0xff
1507 : };
1508 :
1509 : enum ExpRomProto {
1510 : ER_IB = 0,
1511 : ER_ETH = 1,
1512 : ER_VPI = 2
1513 : };
1514 :
1515 : struct ImageInfo;
1516 :
1517 : // Burn operations:
1518 : bool write_image (Flash& f, u_int32_t addr, void *data, int cnt, bool need_report, const char* message,
1519 : bool new_line = true);
1520 : bool WriteSignature (Flash& f, u_int32_t image_idx, u_int32_t sig);
1521 : bool repair (Flash& f, const int from, const int to, bool need_report);
1522 : bool FailSafeBurn (Flash& f, FImage& fim, bool need_report, bool single_image_burn);
1523 : bool CntxFailSafeBurn(Flash& f,
1524 : FImage& fim,
1525 : bool need_report,
1526 : ImageInfo* flash_info,
1527 : ImageInfo* image_info,
1528 : bool allow_nofs = false,
1529 : const char* message = NULL);
1530 :
1531 : bool CheckMatchingHwDevId(u_int32_t hwDevId, u_int32_t rev_id, Operations::ImageInfo& info);
1532 : bool CheckMatchingDevId(u_int32_t hwDevId, u_int32_t imageDevId);
1533 : bool CheckMatchingExpRomDevId(Operations::ImageInfo* info);
1534 : bool HwDevIdToSw(u_int32_t hw_dev_id, u_int32_t& sw_dev_id);
1535 : // Image operations:
1536 : bool Verify (FBase& f, ImageInfo* info, bool both_images = false);
1537 : bool VerifyFs2 (FBase& f, ImageInfo* info, bool both_images = false, bool only_get_start = false,
1538 : bool ignore_full_image_crc = false);
1539 :
1540 : bool LoadAsExpRom (FBase& f, ImageInfo* info);
1541 :
1542 : bool DumpConf (const char* conf_file = NULL, SectionType sect_type = H_FW_CONF);
1543 : bool GetExpRomVersion(ImageInfo* info);
1544 :
1545 : bool DisplayExpRomInfo(ImageInfo* info, bool print_pre = true);
1546 : bool DisplayImageInfo (ImageInfo* info);
1547 : bool GetExpRomStrVer(Operations::ImageInfo* info, char* version);
1548 :
1549 0 : bool QueryAll (FBase& f, ImageInfo* info) {return(IsFs2() ||
1550 : (QueryIs(f, info) &&
1551 : (!info->isFailsafe || QueryPs(f, info)))) &&
1552 : QueryImage(f, info);}
1553 :
1554 : bool getBSN (char *s, guid_t *guid);
1555 : bool getGUID (const char *s, guid_t *guid);
1556 :
1557 : bool patchVSD (FImage& f,
1558 : Operations::ImageInfo* info,
1559 : const char *user_vsd,
1560 : const char *user_psid,
1561 : const char *curr_vsd,
1562 : const char *curr_psid,
1563 : const char *image_psid);
1564 :
1565 : // Misc operations
1566 : void SetDevFlags(u_int16_t devType, bool& ib_dev, bool& eth_dev);
1567 : bool CheckGuidsFlags(u_int16_t devType,
1568 : bool guids_specified,
1569 : bool macs_specified,
1570 : bool uids_specified);
1571 :
1572 : bool reportGuidChaneges(ImageInfo* info,
1573 : guid_t new_guids[MAX_GUIDS],
1574 : guid_t old_guids[MAX_GUIDS],
1575 : bool print_guids,
1576 : bool print_macs,
1577 : bool print_uids);
1578 :
1579 : bool patchGUIDs (FImage& f,
1580 : ImageInfo* info,
1581 : bool patch_macs,
1582 : bool patch_uids,
1583 : bool user_guids,
1584 : bool user_macs,
1585 : bool user_uids,
1586 : guid_t new_guids[MAX_GUIDS],
1587 : guid_t old_guids[MAX_GUIDS],
1588 : u_int32_t num_of_old_guids);
1589 :
1590 : bool PrintMacLine (guid_t* new_guids, guid_t* old_guids, int mac_index);
1591 : bool PrintBxMacs (guid_t* new_guids, guid_t* old_guids, int index, int num_of_guids, const char* pre_str);
1592 : bool PrintGuidLine (guid_t* new_guids, guid_t* old_guids, int guid_index);
1593 : bool PrintBxGuids (guid_t* new_guids, guid_t* old_guids, int index, int num_of_guids, const char* pre_str);
1594 : bool PrintUids (guid_t* used_guids, guid_t* old_guids);
1595 : bool PrintGUIDs (guid_t guids[MAX_GUIDS], guid_t old_guids[MAX_GUIDS], bool print_guids, bool print_macs, bool old_guid_fmt);
1596 :
1597 : void initSectToRead(int imp_index);
1598 :
1599 0 : void SetNumPorts (u_int32_t num_ports) {_num_ports = num_ports;}
1600 0 : void SetAllowSkipIs (bool asis) {_allow_skip_is = asis;}
1601 :
1602 0 : void SetBurnBlankGuids(bool b) {_burn_blank_guids = b;}
1603 0 : bool GetBurnBlankGuids() {return _burn_blank_guids;}
1604 0 : void SetQuickQuery(bool b) {_quick_query = b;}
1605 0 : bool GetQuickQuery() {return _quick_query;}
1606 :
1607 : // ConnectX methods
1608 0 : void SetFs2Mode (bool fs2_mode) {_is_fs2 = fs2_mode;}
1609 0 : void SetIgnoreTty (bool ignore_tty) {_ignore_tty = ignore_tty;}
1610 0 : void SetFs2StripedImage(bool si) {_cntx_striped_image = si;}
1611 0 : bool IsFs2 () {return _is_fs2;}
1612 : bool CheckMac (u_int64_t mac);
1613 :
1614 : bool ReportBxMacsQuery (guid_t* guids, int base1, int guids_num, int index, const char* pre_str);
1615 : bool ReportBxGuidsQuery (guid_t* guids, int base1, int guids_num, int index, const char* pre_str);
1616 : bool ReportBxMacsWarnings(guid_t* guids, int index, int warning, int user_uids);
1617 :
1618 : bool CheckCommandInputs(const char* dev, const char* img, CommandType cmd);
1619 : bool CheckMaxCmdArguments(CommandType cmd, int numArgs);
1620 : bool PrintMissGuidErr(bool ib_dev, bool eth_dev, bool bx_dev);
1621 :
1622 : bool AddNewSect(u_int8_t* &new_image_p, u_int8_t* data, GPH gph, u_int32_t* last_next);
1623 : bool UpdateRomInImage(u_int8_t* new_image, u_int8_t* old_image, u_int8_t* rom_data, int rom_size,
1624 : int* new_image_size);
1625 : bool CopyBoot2(u_int8_t* &new_image_p, u_int8_t* &old_image_p);
1626 : bool CopyData(u_int8_t* &new_image, u_int8_t* &old_image, int copy_size);
1627 : bool GetFileSize(FILE* fh, char* file_name, int& rom_size);
1628 : bool IsRomEmpty(ImageInfo* info);
1629 : bool CheckDevImage(FBase& f, ImageInfo& info);
1630 : bool CheckDevImageAndRom(FBase& f, ImageInfo& flash_info);
1631 : bool IntegrateDevRomInImage(FImage& fim, ImageInfo& flashInfo, ImageInfo& fileInfo);
1632 :
1633 : bool UpdateFullImageCRC(u_int32_t* buff, u_int32_t size, bool blank_guids);
1634 : u_int32_t CalcImageCRC(u_int32_t* buff, u_int32_t size);
1635 :
1636 : bool IsFwSupportingRomModify(u_int16_t fw_ver[3]);
1637 :
1638 : bool CheckIsFs2 (FBase& f);
1639 0 : bool CntxIsIb (u_int32_t devid) {return(devid == 25408) || // IB SDR
1640 : (devid == 25418) || // IB DDR
1641 : (devid == 25428) || // IB QDR
1642 : (devid == 26418) || // IB DDR
1643 : (devid == 26428) || // IB QDR
1644 : (devid == 26488) || // IB DDR
1645 : (devid == 4097) || // IB DDR
1646 : (devid == 4098) || // IB QDR
1647 : (devid == 4099) || // IB DDR
1648 : (devid == 4100) || // IB DDR
1649 : (devid == 26438); // IB QDR
1650 : }
1651 :
1652 0 : bool CntxIsEth (u_int32_t devid) {return(devid == 25448) || // ETH
1653 : (devid == 26448) || // ETH
1654 : (devid == 25458) || //
1655 : (devid == 26458) || //
1656 : (devid == 26468) ||
1657 : (devid == 26478) ||
1658 : CntxIsIb(devid); // From FW 2.5.0, CntX ib devices also support ETH
1659 : }
1660 :
1661 0 : bool IsIs4 (u_int32_t devid) {
1662 : return(devid == 435) ||
1663 : (devid == 48436) ||
1664 : (devid == 48437) ||
1665 : (devid == 48438) ||
1666 : (devid == 6100); // HACK
1667 : }
1668 :
1669 0 : bool IsBridgeX(u_int32_t devid) {
1670 : return (devid == 6100) ||
1671 : (devid == 64102) ||
1672 : (devid == 64112) ||
1673 : (devid == 64122);
1674 : }
1675 :
1676 : bool CntxIsMp (u_int32_t devid) {return CntxIsIb(devid) && CntxIsEth(devid);}
1677 :
1678 : bool ask_user (const char *question = NULL);
1679 :
1680 : // _last_image_addr is set by the Verify() op
1681 : u_int32_t _last_image_addr;
1682 :
1683 : //
1684 : // ImageInfo struct: Everything you wanted to know about the FW image (and was afraid to ask).
1685 : // This struct includes both user's info (psid, dev rev , fwver ...) and tools internal
1686 : // info (images locations, guid ptr ...).
1687 : //
1688 : struct ImageInfo {
1689 0 : ImageInfo() :
1690 : invSectOk(false),
1691 : psOk(false),
1692 : imageOk(false),
1693 : blankGuids(false)
1694 0 : {
1695 0 : memset(allImgStart, 0, sizeof(allImgStart));
1696 0 : memset(guids , 0xff, sizeof(guids));
1697 :
1698 0 : psid[0] = '\0';
1699 0 : vsd[0] = '\0';
1700 0 : for (int i=0; i < II_Last; i++ )
1701 0 : infoOffs[i] = 0;
1702 :
1703 0 : expRomFound = false;
1704 : }
1705 :
1706 : // *Ok : The exit status of the specific query.
1707 : // Note - invSectOk = true doesnt mean that invariant sector exists, it
1708 : // only means that the query was OK (and isFailsafe may be false).
1709 :
1710 : bool invSectOk;
1711 : bool psOk;
1712 : bool imageOk;
1713 :
1714 : u_int32_t allImgStart[2];
1715 :
1716 : bool isFailsafe;
1717 :
1718 : // ConnectX:
1719 : // For an image file where the image is marked as FW but actually contiguous, this bit would be cleared.
1720 : bool actuallyFailsafe;
1721 : u_int32_t cntxLog2ChunkSize;
1722 :
1723 : bool validImage[2];
1724 : u_int32_t psStart;
1725 : u_int32_t imgStart;
1726 :
1727 : // For ConnectX, guids 4:5 are the cards MAC addresses (if applicable)
1728 : guid_t guids[MAX_GUIDS];
1729 : u_int32_t guidPtr;
1730 : u_int32_t guidNum;
1731 : bool blankGuids;
1732 :
1733 : u_int32_t infoSectPtr;
1734 :
1735 : u_int16_t vsdVendorId;
1736 : char vsd[VSD_LEN+1];
1737 : char psid[PSID_LEN+1];
1738 : char productVer[17];
1739 :
1740 : bool isGa;
1741 :
1742 : u_int8_t isVer;
1743 : u_int16_t fwVer[3]; // = {major_ver, minor_ver , sum_minor_ver}
1744 : u_int16_t fwTime[6]; // = {year, month, day, hour, minute, second}
1745 :
1746 : u_int16_t devType;
1747 : u_int8_t devRev;
1748 :
1749 : u_int32_t supportedHwId[MAX_NUM_SUPP_HW_IDS];
1750 : int supportedHwIdNum;
1751 :
1752 : u_int32_t imageSize;
1753 : u_int32_t infoOffs[II_Last]; // Offset of the tag data inside the info section data.
1754 : // Can not be 0 (because of tag header) - 0 means not found.
1755 : bool expRomFound;
1756 : bool expRomValidVersion;
1757 : u_int16_t expRomProductId; // 0 - invalid.
1758 : u_int16_t expRomVer[3];
1759 : u_int16_t expRomDevId;
1760 : u_int8_t expRomPort;
1761 : u_int8_t expRomProto;
1762 : char expRomFreestr[FREE_STR_MAX_LEN];
1763 :
1764 : bool magicPatternFound;
1765 : std::vector<u_int8_t> _rom_sect;
1766 : };
1767 :
1768 : enum {
1769 : MAX_SW_DEVICES_PER_HW=32
1770 : };
1771 :
1772 : struct HwDevData {
1773 : const char* name;
1774 : u_int32_t hwDevId;
1775 : int portNum;
1776 : // Zero terminated list of SW device ids
1777 : const u_int32_t swDevIds[MAX_SW_DEVICES_PER_HW];
1778 : };
1779 :
1780 0 : bool FwVerLessThan(u_int16_t r1[3], u_int16_t r2[3]) {
1781 0 : int i;
1782 0 : for (i = 0; i < 3 ; i++)
1783 0 : if (r1[i] < r2[i])
1784 0 : return true;
1785 0 : else if (r1[i] > r2[i])
1786 0 : return false;
1787 :
1788 0 : return false; // equal versions
1789 : }
1790 :
1791 : enum {
1792 : CNTX_START_POS_SIZE = 6
1793 : };
1794 :
1795 : static const u_int32_t _cntx_image_start_pos[CNTX_START_POS_SIZE];
1796 :
1797 : static const u_int32_t _cntx_magic_pattern[4];
1798 : char _err_msg[MAX_ERR_STR_LEN];
1799 :
1800 : void patchGUIDsSection (u_int32_t *buf, u_int32_t ind,
1801 : guid_t guids[GUIDS], int nguids);
1802 :
1803 : private:
1804 :
1805 : bool FailSafe_burn_image (Flash& f,
1806 : void *data,
1807 : int ps_addr,
1808 : const char* image_name,
1809 : int image_addr,
1810 : int image_size,
1811 : bool need_report);
1812 :
1813 : bool CheckInvariantSector (Flash& f, u_int32_t *data32, int sect_size);
1814 :
1815 : bool FailSafe_burn_internal (Flash& f, void *data, int cnt, bool need_report);
1816 :
1817 : bool checkBoot2 (FBase& f, u_int32_t beg, u_int32_t offs,
1818 : u_int32_t& next, const char *pref);
1819 :
1820 : bool checkGen (FBase& f, u_int32_t beg,u_int32_t offs,
1821 : u_int32_t& next, const char *pref, ImageInfo* info);
1822 :
1823 : bool checkPS (FBase& f, u_int32_t offs, u_int32_t& next, const char *pref);
1824 :
1825 : bool checkList (FBase& f, u_int32_t offs, u_int32_t fw_start, const char *pref, ImageInfo* info);
1826 :
1827 : bool extractGUIDptr (u_int32_t sign, u_int32_t *buf, int buf_len,
1828 : char *pref, u_int32_t *ind, int *nguids);
1829 :
1830 : bool CheckAndPrintCrcRes (char* pr, bool blank_crc, u_int32_t off, u_int32_t crc_act, u_int32_t crc_exp);
1831 :
1832 : void recalcSectionCrc (u_int8_t *buf, u_int32_t data_size);
1833 :
1834 : u_int32_t BSN_subfield (const char *s, int beg, int len);
1835 :
1836 : void PatchPs (u_int8_t* rawPs,
1837 : const char vsd[VSD_LEN],
1838 : const char psid[PSID_LEN] = NULL,
1839 : u_int32_t imageAddr = 0);
1840 :
1841 : void PatchInfoSect (u_int8_t* rawSect,
1842 : u_int32_t vsdOffs,
1843 : const char* vsd);
1844 :
1845 : bool QueryIs (FBase& f, ImageInfo* info);
1846 : bool QueryPs (FBase& f, ImageInfo* info);
1847 : bool QueryImage (FBase& f, ImageInfo* info);
1848 :
1849 : bool CntxFindMagicPattern (FBase& f, u_int32_t addr);
1850 : bool CntxFindAllImageStart (FBase& f, u_int32_t start_locations[CNTX_START_POS_SIZE], u_int32_t* found_images);
1851 : bool CntxGetFsData (u_int32_t fs_info_word, bool& fs_en, u_int32_t& log2chunk_size);
1852 :
1853 : bool ParseInfoSect (u_int8_t* buff, u_int32_t byteSize, ImageInfo *info);
1854 : bool GetSectData (std::vector<u_int8_t>& file_sect, const u_int32_t *buff, const u_int32_t size);
1855 : u_int32_t _num_ports;
1856 : bool _allow_skip_is;
1857 : bool _is_fs2;
1858 : bool _cntx_striped_image;
1859 :
1860 : bool _burn_blank_guids;
1861 : bool _quick_query;
1862 : bool _sections_to_read[H_LAST];
1863 : bool _is_full_verify;
1864 : bool _ignore_tty;
1865 : static const HwDevData hwDevData[];
1866 :
1867 : std::vector<u_int8_t> _fw_conf_sect;
1868 : std::vector<u_int8_t> _hash_file_sect;
1869 :
1870 : };
1871 :
1872 :
1873 : const u_int32_t Operations::_cntx_magic_pattern[4] = {
1874 : 0x4D544657, // Ascii of "MTFW"
1875 : 0x8CDFD000, // Random data
1876 : 0xDEAD9270,
1877 : 0x4154BEEF
1878 : };
1879 :
1880 : const u_int32_t Operations::_cntx_image_start_pos[Operations::CNTX_START_POS_SIZE] = {
1881 : 0,
1882 : 0x10000,
1883 : 0x20000,
1884 : 0x40000,
1885 : 0x80000,
1886 : 0x100000
1887 : };
1888 :
1889 : const Operations::HwDevData Operations::hwDevData[] = {
1890 : { "InfiniHost", 23108, 2, {23108, 0}},
1891 : { "InfiniHost III Ex", 25208, 2, {25208, 25218, 0}},
1892 : { "InfiniHost III Lx", 25204, 1, {25204, 0}},
1893 : { "ConnectX", 400, 2, {25408, 25418, 26418, 26438,
1894 : 26428, 25448, 26448, 26468,
1895 : 25458, 26458, 26478, 26488,
1896 : 4097, 4098, 4099, 4100, 0}},
1897 : { "InfiniScale IV", 435, 0, {48436, 48437, 48438, 0}},
1898 : { "BridgeX", 6100, 0, {64102, 64112, 64122, 0}},
1899 : { NULL , 0, 0, {0}},// zero devid terminator
1900 : };
1901 :
1902 : //
1903 : // Asks user a yes/no question.
1904 : // Returns true if user chose Y, false if user chose N.
1905 : //
1906 :
1907 0 : bool Operations::ask_user(const char *question) {
1908 0 : if (question == NULL) {
1909 0 : printf("\n Do you want to continue ? (y/n) [n] : ");
1910 : } else {
1911 0 : printf("\n %s ? (y/n) [n] : ", question);
1912 :
1913 : }
1914 :
1915 0 : if (_assume_yes)
1916 0 : printf("y\n");
1917 : else {
1918 0 : char ansbuff[32];
1919 0 : ansbuff[0] = '\0';
1920 0 : if (_assume_no) {
1921 0 : printf("n\n");
1922 0 : sprintf(_err_msg, "-no flag is set\n");
1923 0 : return false;
1924 : }
1925 0 : if (_ignore_tty == false) {
1926 0 : if (!isatty(0)) {
1927 0 : sprintf(_err_msg, "Not on tty - Can not interact. assuming \"no\"\n");
1928 0 : return false;
1929 : }
1930 : }
1931 0 : fflush(stdout);
1932 0 : fgets(ansbuff, 30, stdin);
1933 :
1934 0 : if ( strcmp(ansbuff, "y\n") &&
1935 : strcmp(ansbuff, "Y\n") &&
1936 : strcmp(ansbuff, "yes\n") &&
1937 : strcmp(ansbuff, "Yes\n") &&
1938 : strcmp(ansbuff, "YES\n")) {
1939 :
1940 0 : sprintf(_err_msg, "Aborted by user\n");
1941 0 : return false;
1942 : }
1943 :
1944 : }
1945 0 : return true;
1946 : }
1947 :
1948 : bool Operations::write_image(Flash& f, u_int32_t addr, void *data, int cnt, bool need_report, const char* message,
1949 : bool new_line)
1950 0 : {
1951 0 : u_int8_t *p = (u_int8_t *)data;
1952 0 : u_int32_t curr_addr = addr;
1953 0 : u_int32_t towrite = cnt;
1954 0 : u_int32_t perc = 0xffffffff;
1955 :
1956 :
1957 0 : while (towrite) {
1958 : // Write
1959 0 : int trans = (towrite > (int)Flash::TRANS) ? (int)Flash::TRANS : towrite;
1960 0 : if (!f.write(curr_addr, p, trans))
1961 0 : return errmsg("Flash write failed: %s", f.err());
1962 0 : p += trans;
1963 0 : curr_addr += trans;
1964 0 : towrite -= trans;
1965 :
1966 : // Report
1967 0 : if (need_report) {
1968 0 : u_int32_t new_perc = ((cnt - towrite) * 100) / cnt;
1969 :
1970 0 : if (new_perc != perc) {
1971 0 : printf("\r%s%%%03d", message, new_perc);
1972 0 : fflush(stdout);
1973 0 : perc = new_perc;
1974 : }
1975 : }
1976 : }
1977 :
1978 0 : if (need_report) {
1979 :
1980 0 : printf("\r%sOK ", message);
1981 0 : if (new_line) {
1982 0 : printf("\n");
1983 : }
1984 0 : fflush(stdout);
1985 : }
1986 :
1987 0 : return true;
1988 : } // Flash::write_image
1989 :
1990 :
1991 : ////////////////////////////////////////////////////////////////////////
1992 0 : bool Operations::WriteSignature(Flash& f, u_int32_t image_idx, u_int32_t sig) {
1993 0 : u_int32_t sect_size = f.get_sector_size();
1994 :
1995 0 : if (!f.write( sect_size * (image_idx + 1) + 8, &sig, 4, true))
1996 0 : return false;
1997 :
1998 0 : return true;
1999 : }
2000 :
2001 :
2002 : ////////////////////////////////////////////////////////////////////////
2003 : bool Operations::repair(Flash& f, const int from, const int to, bool need_report)
2004 0 : {
2005 :
2006 0 : u_int32_t sect_size = f.get_sector_size();
2007 0 : char message[128];
2008 0 : char common_msg[128];
2009 0 : report("Repairing: Copy %s image to %s -", from ? "secondary" : "primary" ,
2010 : to ? "secondary" : "primary");
2011 :
2012 0 : sprintf(common_msg, "Repairing: Copy %s image to %s -", from ? "secondary" : "primary" ,
2013 : to ? "secondary" : "primary");
2014 :
2015 : // Read valid pointer sector
2016 0 : u_int32_t sect[sizeof(PS)/4];
2017 0 : sprintf(message, "%s READ %s ", common_msg, from ? "SPS" : "PPS");
2018 0 : if (!f.read(from ? sect_size*2 : sect_size, sect, sizeof(sect) , need_report, message)) {
2019 0 : report("FAILED\n\n");
2020 0 : return false;
2021 : }
2022 0 : report_repair_msg(common_msg);
2023 :
2024 0 : u_int32_t im_ptr = sect[0];
2025 0 : u_int32_t sig = sect[2];
2026 :
2027 0 : TOCPU1(im_ptr);
2028 0 : TOCPU1(sig);
2029 :
2030 : // Make sure ps ik ok:
2031 0 : if (sig != SIGNATURE) {
2032 0 : return errmsg("Can not copy image. Pointer sector %d signature is bad (%08x).", from, sig);
2033 : }
2034 :
2035 : // Valid image size in bytes
2036 0 : u_int32_t im_size_b;
2037 0 : if (!f.read(sect_size * (from+1) + 4, &im_size_b)) {
2038 0 : report("FAILED\n\n");
2039 0 : return false;
2040 : }
2041 0 : TOCPU1(im_size_b);
2042 :
2043 : // Valid image size in sectors
2044 0 : u_int32_t im_size_s = (im_size_b + sect_size - 1) / sect_size;
2045 :
2046 : // Address to copy valid image
2047 0 : u_int32_t write_to = (!to) ? sect_size * 3 : sect_size * (3 + im_size_s);
2048 :
2049 : // f.read valid image
2050 0 : char *buf = new char[im_size_b];
2051 0 : sprintf(message, "%s READ FW ", common_msg);
2052 0 : if (!f.read(im_ptr, buf, im_size_b, need_report, message)) {
2053 0 : report("FAILED\n\n");
2054 0 : delete [] buf;
2055 0 : return false;
2056 : }
2057 0 : report_repair_msg(common_msg);
2058 :
2059 : // Copy it to right place
2060 0 : sprintf(message, "%s WRITE FW ", common_msg);
2061 0 : if (!write_image(f, write_to, buf, im_size_b, need_report, message, false)) {
2062 0 : report("FAILED\n\n");
2063 0 : delete [] buf;
2064 0 : return false;
2065 : }
2066 0 : delete [] buf;
2067 0 : report_repair_msg(common_msg);
2068 : // Set new image address
2069 : // ++++++
2070 0 : sect[0] = __be32_to_cpu(write_to);
2071 :
2072 : // Calculate new CRC
2073 : // ++++++
2074 0 : Crc16 crc;
2075 :
2076 0 : for (u_int32_t i = 0; i < (sizeof(sect)/4 - 1) ; i++) {
2077 0 : crc << __be32_to_cpu(sect[i]);
2078 : }
2079 0 : crc.finish();
2080 :
2081 0 : sect[sizeof(sect)/4 - 1] = __be32_to_cpu(crc.get());
2082 :
2083 : // Corrupt signature
2084 0 : u_int32_t valid_signature = sect[2];
2085 0 : sect[2] = 0xffffffff;
2086 :
2087 : // Write it to invalid sector
2088 0 : sprintf(message, "%s WRITE %s ", common_msg, to ? "SPS" : "PPS");
2089 0 : if (!write_image(f, to ? sect_size*2 : sect_size, sect, sizeof(sect), need_report, message, false)) {
2090 0 : report("FAILED\n\n");
2091 0 : return false;
2092 : }
2093 0 : report_repair_msg(common_msg);
2094 : // Validate signature
2095 0 : report("\r%s SIGNATURE ", common_msg);
2096 0 : if (!WriteSignature(f, to, valid_signature)) {
2097 0 : report("FAILED\n\n");
2098 0 : return false;
2099 : }
2100 :
2101 0 : report_repair_msg(common_msg);
2102 0 : printf("\n");
2103 0 : return true;
2104 : } // Flash::repair
2105 :
2106 :
2107 :
2108 :
2109 :
2110 : ////////////////////////////////////////////////////////////////////////
2111 : bool Operations::FailSafe_burn_image(Flash& f,
2112 : void *data,
2113 : int ps_addr,
2114 : const char* image_name,
2115 : int image_addr,
2116 : int image_size,
2117 0 : bool need_report) {
2118 :
2119 0 : u_int8_t* data8 = (u_int8_t*) data;
2120 0 : u_int32_t sect_size = f.get_sector_size();
2121 0 : char message[128];
2122 :
2123 0 : sprintf(message, "Burning %-6s FW image without signatures - ", image_name);
2124 : // Invalidate signature
2125 0 : u_int32_t zeros = 0;
2126 0 : if (!f.write(ps_addr + 8, &zeros, 4, true)) {
2127 0 : report("FAILED (Invalidating signature)\n\n");
2128 0 : return false;
2129 : }
2130 :
2131 : // Burn image (from new offset)
2132 : // Both burnt images are taken from the first image in the file - both images in file are identical.
2133 : // (future binary releases may contain a single image).
2134 0 : if (!write_image(f, image_addr, data8 + sect_size * 3, image_size, need_report, message)) {
2135 0 : report("FAILED\n\n");
2136 0 : return false;
2137 : }
2138 0 : report("Restoring %-6s signature - ", image_name);
2139 0 : fflush(stdout);
2140 :
2141 : // Burn PS
2142 0 : if (!write_image(f, ps_addr, data8 + ps_addr, sect_size, false, NULL)) {
2143 0 : report("FAILED\n\n");
2144 0 : return false;
2145 : }
2146 :
2147 : // Validate signature
2148 0 : u_int32_t sig = SIGNATURE;
2149 0 : TOCPU1(sig);
2150 0 : if (!f.write(ps_addr + 8, &sig, 4, true)) {
2151 0 : report("FAILED\n\n");
2152 0 : return false;
2153 : }
2154 :
2155 0 : report("OK \n");
2156 :
2157 0 : return true;
2158 : }
2159 :
2160 :
2161 : ////////////////////////////////////////////////////////////////////////
2162 : bool Operations::FailSafe_burn_internal(Flash& f, void *data, int cnt, bool need_report)
2163 0 : {
2164 0 : u_int32_t *data32 = (u_int32_t *)data;
2165 :
2166 0 : u_int32_t sect_size = f.get_sector_size();
2167 :
2168 : // Extract Primary/Secondary image pointers and lengths
2169 0 : u_int32_t prim_ptr = data32[sect_size / 4];
2170 0 : u_int32_t prim_len = data32[sect_size / 4 + 1];
2171 0 : u_int32_t scnd_ptr = data32[(sect_size * 2) / 4];
2172 0 : u_int32_t scnd_len = data32[(sect_size * 2) / 4 + 1];
2173 0 : TOCPU1(prim_ptr);
2174 0 : TOCPU1(prim_len);
2175 0 : TOCPU1(scnd_ptr);
2176 0 : TOCPU1(scnd_len);
2177 0 : if ((cnt < (int)(prim_ptr + prim_len)) || (cnt < (int)(scnd_ptr + scnd_len))) {
2178 0 : return errmsg("Invalid image: too small.");
2179 : }
2180 0 : if (prim_len != scnd_len) {
2181 0 : return errmsg("Invalid image: two FW images should have the same size.");
2182 : }
2183 :
2184 : // Image size from flash
2185 0 : u_int32_t old_im_size;
2186 0 : if (!f.read(sect_size + 4, &old_im_size)) {
2187 0 : report("FAILED\n\n");
2188 0 : return false;
2189 : }
2190 0 : TOCPU1(old_im_size);
2191 :
2192 0 : u_int32_t prim_order;
2193 0 : u_int32_t scnd_order;
2194 :
2195 0 : u_int32_t ps_addr[2];
2196 0 : u_int32_t image_addr[2];
2197 0 : const char* image_name[2];
2198 :
2199 :
2200 0 : if (prim_len > old_im_size) {
2201 0 : scnd_order = 0;
2202 0 : prim_order = 1;
2203 : } else {
2204 0 : prim_order = 0;
2205 0 : scnd_order = 1;
2206 : }
2207 :
2208 0 : image_name[scnd_order] = "Secondary";
2209 0 : image_addr[scnd_order] = scnd_ptr;
2210 0 : ps_addr [scnd_order] = sect_size * 2;
2211 :
2212 0 : image_name[prim_order] = "Primary";
2213 0 : image_addr[prim_order] = prim_ptr;
2214 0 : ps_addr [prim_order] = sect_size;
2215 :
2216 :
2217 0 : for (int i = 0 ; i < 2 ; i++) {
2218 0 : if (!FailSafe_burn_image(f, data, ps_addr[i], image_name[i], image_addr[i], prim_len, need_report)) {
2219 0 : return false;
2220 : }
2221 : }
2222 :
2223 0 : return true;
2224 : }
2225 :
2226 0 : bool Operations::CheckInvariantSector(Flash& f, u_int32_t *data32, int sect_size) {
2227 0 : int i;
2228 :
2229 0 : report("\nRead and verify Invariant Sector - ");
2230 0 : fflush(stdout);
2231 :
2232 : // Once more check signature - the Inv.Sector signature should be OK
2233 0 : u_int32_t signature;
2234 0 : if (!f.read(0x24, &signature)) {
2235 0 : report("FAILED\n\n");
2236 0 : return false;
2237 : }
2238 0 : TOCPU1(signature);
2239 0 : if (signature != SIGNATURE) {
2240 0 : report("FAILED\n\n");
2241 0 : return errmsg("Flash has wrong signature in Invariant Sector (Expected %08x, got %08x).", SIGNATURE, signature);
2242 : }
2243 :
2244 : // Now check Invariant sector contents
2245 0 : vector<u_int32_t> buf1(sect_size/4);
2246 :
2247 0 : if (!f.read(0, &buf1[0] , sect_size)) {
2248 0 : report("FAILED\n\n");
2249 0 : return false;
2250 : }
2251 :
2252 0 : int first_diff = -1;
2253 :
2254 0 : for (i=0; i < sect_size/4; i++) {
2255 0 : if (buf1[i] != data32[i] && (data32[i] != 0 || buf1[i] != 0xffffffff)) {
2256 0 : if (first_diff == -1)
2257 0 : first_diff = i;
2258 : }
2259 : }
2260 :
2261 : // Check if a diff was found:
2262 0 : if (first_diff != -1) {
2263 0 : report("DIFF DETECTED\n\n");
2264 0 : printf(" Invariant sector mismatch. Address 0x%x "
2265 : " in image: 0x%08x, while on flash: 0x%08x\n\n",
2266 : first_diff*4 , data32[first_diff], buf1[first_diff]);
2267 :
2268 0 : printf(" The invariant sector can not be burnt in a failsafe manner.\n");
2269 :
2270 0 : if (_allow_skip_is) {
2271 0 : printf(" You can continue the FW update without burning the invariant sector.\n"
2272 : " See FW release notes for details on invariant sector updates.\n\n");
2273 :
2274 0 : return ask_user();
2275 :
2276 : } else {
2277 : // Continue with burn
2278 0 : printf(" You can perform the FW update without burning the invariant sector by\n"
2279 : " by specifying the -skip_is flag.\n"
2280 : " See FW release notes for details on invariant sector updates.\n\n");
2281 :
2282 0 : return errmsg("Invariant sector mismatch");
2283 : }
2284 : }
2285 :
2286 0 : report("OK\n");
2287 0 : return true;
2288 :
2289 : }
2290 :
2291 : ////////////////////////////////////////////////////////////////////////
2292 : bool Operations::FailSafeBurn(Flash& f, FImage& fim, bool need_report, bool single_image_burn)
2293 0 : {
2294 0 : u_int32_t *data32 = fim.getBuf();
2295 0 : u_int8_t *data8 = (u_int8_t *) data32;
2296 0 : void* data = data8;
2297 0 : int size = fim.getBufLength();
2298 :
2299 0 : u_int32_t i;
2300 :
2301 0 : u_int32_t sect_size = f.get_sector_size();
2302 0 : u_int32_t img_sect_size = fim.get_sector_size();
2303 :
2304 : // Check that the flash sector size is well defined in the image
2305 0 : if (img_sect_size && (img_sect_size != sect_size)) {
2306 0 : return errmsg("Flash sector size(0x%x) differs from sector size defined in the image (0x%x).\n"
2307 : "This means that the given FW file is not configured to work with the burnt HCA board type.",
2308 : sect_size,
2309 : img_sect_size);
2310 : }
2311 :
2312 0 : if (size < (int)sect_size * 3) {
2313 0 : report("FAILED\n\n");
2314 0 : return errmsg("Image is too small.");
2315 : }
2316 :
2317 0 : if (!CheckInvariantSector(f, data32, sect_size)) {
2318 0 : return false;
2319 : }
2320 :
2321 : // Check signatures in image
2322 0 : u_int32_t actual_signature = data32[sect_size/4 + 2];
2323 :
2324 0 : u_int32_t signature_for_compare = actual_signature;
2325 :
2326 0 : TOCPU1(signature_for_compare);
2327 0 : if (signature_for_compare != SIGNATURE) {
2328 0 : return errmsg("Bad image file given: signature in PPS is 0x%08x (should be 0x%08x)",
2329 : signature_for_compare, SIGNATURE);
2330 : }
2331 0 : signature_for_compare = data32[(sect_size * 2)/4 + 2];
2332 0 : TOCPU1(signature_for_compare);
2333 0 : if (signature_for_compare != SIGNATURE) {
2334 0 : return errmsg("Bad image file given: signature in SPS is 0x%08x (should be 0x%08x)",
2335 : signature_for_compare, SIGNATURE);
2336 : }
2337 :
2338 : // Corrupt signatures in image
2339 0 : data32[sect_size/4 + 2] = 0xffffffff;
2340 0 : data32[(sect_size * 2)/4 + 2] = 0xffffffff;
2341 :
2342 0 : bool cur_image_ok[2] = {false, false};
2343 0 : u_int32_t cur_image_addr[2];
2344 0 : u_int32_t cur_image_size[2];
2345 :
2346 : // Check signatures on flash
2347 0 : report("Read and verify PPS/SPS on flash - ");
2348 0 : for (i = 0 ; i < 2 ; i++) {
2349 0 : if (!f.read(sect_size * (i+1) + 8, &signature_for_compare)) {
2350 :
2351 : }
2352 0 : TOCPU1(signature_for_compare);
2353 0 : if (signature_for_compare == SIGNATURE) {
2354 0 : cur_image_ok[i] = true;
2355 :
2356 0 : if (!f.read(sect_size * (i+1) , &cur_image_addr[i]) ||
2357 : !f.read(sect_size * (i+1) + 4, &cur_image_size[i])) {
2358 0 : report("FAILED\n\n");
2359 0 : return false;
2360 : }
2361 :
2362 0 : TOCPU1(cur_image_addr[i]);
2363 0 : TOCPU1(cur_image_size[i]);
2364 : }
2365 : }
2366 :
2367 0 : if (!cur_image_ok[0] && !cur_image_ok[1]) {
2368 : //
2369 : // Both images are invalid on flash
2370 : // --------------------------------
2371 : //
2372 0 : printf("\nBoth images (primary and secondary) are invalid on flash.\n");
2373 0 : printf("The burning can not be failsafe, but it is harmless for host.\n");
2374 0 : if (!ask_user()) {
2375 0 : return false;
2376 : }
2377 :
2378 : // Burn all image
2379 0 : report("Burn FW image without signatures - ");
2380 0 : fflush(stdout);
2381 0 : if (!write_image(f, sect_size, data8 + sect_size, size - sect_size, need_report, "Burn FW image without signatures")) {
2382 0 : report("FAILED\n\n");
2383 0 : return false;
2384 : }
2385 :
2386 : // Restore signatures
2387 0 : report("Restore right signatures - ");
2388 0 : fflush(stdout);
2389 0 : if (!WriteSignature(f, 0, actual_signature)) {
2390 0 : report("FAILED (PPS Signature)\n\n");
2391 0 : return false;
2392 : }
2393 0 : if (!WriteSignature(f, 1, actual_signature)) {
2394 0 : report("FAILED (SPS Signature)\n\n");
2395 0 : return false;
2396 : }
2397 0 : report("OK\n");
2398 0 : return true;
2399 : } else {
2400 0 : report("OK\n");
2401 : }
2402 :
2403 0 : if (single_image_burn == false) {
2404 :
2405 0 : if (cur_image_ok[0] == false || cur_image_ok[1] == false) {
2406 0 : int image_from;
2407 0 : int image_to;
2408 :
2409 0 : assert (cur_image_ok[1] || cur_image_ok[0]);
2410 :
2411 0 : if (cur_image_ok[1]) {
2412 0 : image_from = 1;
2413 0 : image_to = 0;
2414 : } else {
2415 0 : image_from = 0;
2416 0 : image_to = 1;
2417 : }
2418 :
2419 0 : report("Reparable Error Detected.\n");
2420 0 : if (!repair(f, image_from, image_to, need_report))
2421 0 : return false;
2422 : }
2423 :
2424 : //
2425 : // Both images are valid on flash
2426 : //
2427 0 : return FailSafe_burn_internal(f, data, size, need_report);
2428 :
2429 : } else {
2430 :
2431 : //
2432 : // Single image burn:
2433 : //
2434 :
2435 : // Extract Primary/Secondary image pointers and lengths
2436 0 : u_int32_t frst_new_image_addr = data32[sect_size / 4];
2437 0 : u_int32_t frst_new_image_size = data32[sect_size / 4 + 1];
2438 0 : TOCPU1(frst_new_image_addr);
2439 0 : TOCPU1(frst_new_image_size);
2440 :
2441 0 : if (!cur_image_ok[0] && cur_image_ok[1]) {
2442 : // Second image is valid on flash.
2443 : // If the new image can fit in the first image gap, it would be
2444 : // burnt as first image.
2445 : // Otherwise (new image too big), image on flash is copied from second to
2446 : // first image, and new image would be written as second.
2447 :
2448 0 : if (frst_new_image_addr + frst_new_image_size > cur_image_addr[1]) {
2449 : // New image is too large - can not get in between first image start
2450 : // and current (second) image - move current image to be first.
2451 0 : if (!repair(f, 1, 0, need_report))
2452 0 : return false;
2453 :
2454 : // Now 2 images are valid
2455 0 : cur_image_ok[0] = true;
2456 0 : cur_image_size[0] = cur_image_size[1];
2457 0 : cur_image_addr[0] = sect_size * 3;
2458 : } else {
2459 0 : if (!FailSafe_burn_image(f, data, sect_size, "first", sect_size * 3, frst_new_image_size, need_report))
2460 0 : return false;
2461 :
2462 0 : if (!WriteSignature(f, 1, 0))
2463 0 : return false;
2464 :
2465 0 : return true;
2466 : }
2467 : }
2468 :
2469 0 : if (cur_image_ok[0] && cur_image_ok[1]) {
2470 : // Invalidate second image
2471 0 : if (!WriteSignature(f, 1, 0)) {
2472 0 : report("FAILED\n");
2473 0 : return false;
2474 : }
2475 :
2476 0 : cur_image_ok[1] = false;
2477 : }
2478 :
2479 0 : if (cur_image_ok[0] && !cur_image_ok[1]) {
2480 0 : u_int32_t new_image_size_sect = ((frst_new_image_size - 1) / sect_size) + 1 ;
2481 :
2482 : // First image is valid on flash.
2483 : // If the new image is smaller than current image, it would
2484 : // overwrite the end of current image. In this case, move the current image
2485 : // to the second position and burn in first.
2486 : //
2487 : // TODO: STOP THIS MOVEMENT BULLSHI%@#&! !!! : Reproduce PS in flint with the correct addr. Locate second image in middle of flash.
2488 :
2489 0 : if ( (3 + new_image_size_sect) * sect_size < cur_image_addr[0] + cur_image_size[0]) {
2490 : // New image overwrites end of cur image
2491 : // move current image to be second.
2492 0 : if (!repair(f, 0, 1, need_report))
2493 0 : return false;
2494 :
2495 : // Now 2 images are valid
2496 0 : cur_image_ok[1] = true;
2497 :
2498 : // Burn new image as firse
2499 0 : if (!FailSafe_burn_image(f, data, sect_size, "first",
2500 : sect_size * 3, frst_new_image_size, need_report))
2501 0 : return false;
2502 :
2503 0 : if (!WriteSignature(f, 1, 0))
2504 0 : return false;
2505 :
2506 0 : return true;
2507 :
2508 : } else {
2509 0 : if (!FailSafe_burn_image(f, data, sect_size * 2, "second",
2510 : sect_size * (3 + new_image_size_sect) , frst_new_image_size, need_report))
2511 0 : return false;
2512 :
2513 : // Invalidate first image
2514 0 : if (!WriteSignature(f, 0, 0))
2515 0 : return false;
2516 :
2517 0 : return true;
2518 :
2519 : }
2520 : } else {
2521 0 : report("Bad flash state: Valid images = (%d,%d).\n", cur_image_ok[0], cur_image_ok[1] );
2522 0 : return false;
2523 : }
2524 :
2525 : }
2526 :
2527 0 : return true;
2528 : }
2529 : #define RESTORING_MSG "Restoring signature"
2530 :
2531 : bool Operations::CntxFailSafeBurn(Flash& f,
2532 : FImage& fim,
2533 : bool need_report,
2534 : Operations::ImageInfo* flash_info,
2535 : Operations::ImageInfo* image_info,
2536 : bool allow_nofs,
2537 0 : const char* pre_message) {
2538 :
2539 : // TODO: See getBuf effect on zebra image.
2540 0 : u_int8_t *data8 = (u_int8_t *) fim.getBuf();
2541 0 : int image_size = fim.getBufLength();
2542 0 : u_int32_t zeroes = 0;
2543 0 : char message[128], message1[128], buff[128];
2544 0 : bool is_curr_image_in_odd_chunks;
2545 : //printf("-D- image_info->blankGuids: %#x, flash_info: %#x, burn_blank: %#x\n", image_info->blankGuids,
2546 : // flash_info->blankGuids, _burn_blank_guids);
2547 :
2548 : // Update CRC.
2549 0 : UpdateFullImageCRC(fim.getBuf(), image_size / 4, image_info->blankGuids | _burn_blank_guids); // size in dwords
2550 :
2551 : // TODO: Do we need the verify ORENK
2552 0 : Operations::ImageInfo file_info;
2553 0 : bool curr_silent = _silent;
2554 0 : _silent = true;
2555 0 : if (!Verify(fim, &file_info) || !QueryAll(fim, &file_info)) {
2556 0 : return errmsg("Internal error: Got bad image after updating the CRC. %s", err());
2557 : }
2558 0 : _silent = curr_silent;
2559 :
2560 0 : if (!allow_nofs) {
2561 0 : if (!image_info->isFailsafe) {
2562 0 : return errmsg("The given image is not a failsae image");
2563 : }
2564 :
2565 0 : if (flash_info->cntxLog2ChunkSize != image_info->cntxLog2ChunkSize) {
2566 0 : return errmsg("Failsafe chunk sizes in flash (0x%x) and in image (0x%x) are not the same.",
2567 : 1 << flash_info->cntxLog2ChunkSize,
2568 : 1 << image_info->cntxLog2ChunkSize);
2569 : }
2570 : }
2571 :
2572 0 : u_int32_t new_image_start;
2573 :
2574 0 : if (flash_info->imgStart != 0) {
2575 0 : is_curr_image_in_odd_chunks = 1;
2576 0 : new_image_start = 0;
2577 : } else {
2578 0 : is_curr_image_in_odd_chunks = 0;
2579 0 : new_image_start = (1 << image_info->cntxLog2ChunkSize);
2580 : }
2581 :
2582 : //printf("-I- Chunk=%x . Cur image start=%x burning from %x, flash_log2_chunk_size=%d\n",
2583 : // 1 << flash_info->cntxLog2ChunkSize,
2584 : // flash_info->imgStart,
2585 : // new_image_start,
2586 : // flash_info->cntxLog2ChunkSize);
2587 :
2588 0 : if (image_info->isFailsafe) {
2589 0 : f.set_address_convertor(image_info->cntxLog2ChunkSize, !is_curr_image_in_odd_chunks);
2590 : } else {
2591 0 : f.set_address_convertor(0,0);
2592 0 : new_image_start = 0;
2593 : }
2594 :
2595 : // Go ahead and burn!
2596 : //const char* image_name = new_image_start == 0 ? "first" : "second";
2597 0 : report("\n");
2598 0 : if (pre_message == NULL) {
2599 0 : sprintf(message, "Burning FW image without signatures");
2600 : } else {
2601 0 : sprintf(message, pre_message);
2602 : }
2603 0 : int str_len = strlen(message), restore_len = strlen(RESTORING_MSG);
2604 0 : str_len = (restore_len > str_len) ? restore_len : str_len;
2605 :
2606 0 : sprintf(buff, "%%-%ds - ", str_len);
2607 :
2608 0 : sprintf(message1, buff, message);
2609 :
2610 :
2611 0 : if (!write_image(f, 16 , data8 + 16, image_size - 16, need_report, message1)) {
2612 0 : report("FAILED\n\n");
2613 0 : return false;
2614 : }
2615 :
2616 0 : report(buff, RESTORING_MSG);
2617 :
2618 0 : fflush(stdout);
2619 :
2620 : // Write new signature
2621 0 : if (!f.write(0, data8, 16, true)) {
2622 0 : report("FAILED\n\n");
2623 0 : return false;
2624 : }
2625 :
2626 : // Write new image start address to crspace (for SW reset)
2627 0 : f.cr_write(0xf0000, (new_image_start << 8) | 0x06);
2628 :
2629 0 : if (image_info->isFailsafe) {
2630 0 : if (allow_nofs) {
2631 : // When burning in nofs, remnant of older image with different chunk size
2632 : // may reside on the flash -
2633 : // Invalidate all images marking on flash except the one we've just burnt
2634 :
2635 0 : u_int32_t cntx_image_start[CNTX_START_POS_SIZE];
2636 0 : u_int32_t cntx_image_num;
2637 0 : u_int32_t i;
2638 :
2639 0 : CntxFindAllImageStart(f, cntx_image_start, &cntx_image_num);
2640 : // Address convertor is disabled now - use phys addresses
2641 0 : for (i = 0; i < cntx_image_num; i++) {
2642 0 : if (cntx_image_start[i] != new_image_start) {
2643 0 : if (!f.write(cntx_image_start[i], &zeroes, sizeof(zeroes), true)) {
2644 0 : report("FAILED\n\n");
2645 0 : return false;
2646 : }
2647 : }
2648 : }
2649 : } else {
2650 : // invalidate previous signature
2651 0 : f.set_address_convertor(image_info->cntxLog2ChunkSize, is_curr_image_in_odd_chunks);
2652 0 : if (!f.write(0, &zeroes, sizeof(zeroes), true)) {
2653 0 : report("FAILED\n\n");
2654 0 : return false;
2655 : }
2656 : }
2657 : }
2658 0 : report("OK \n");
2659 :
2660 0 : return true;
2661 : }
2662 :
2663 :
2664 :
2665 :
2666 : ////////////////////////////////////////////////////////////////////////
2667 : // //
2668 : // ****************************************************************** //
2669 : // VERIFY FLASH //
2670 : // ****************************************************************** //
2671 : // //
2672 : ////////////////////////////////////////////////////////////////////////
2673 :
2674 :
2675 : //
2676 : // Cntx image verification flow:
2677 : //
2678 : // The "zebra"failsafe scheme presents few problems:
2679 : // - Need to search for a valid image in the flash.
2680 : // - handle no image / more than a single valid image cases
2681 : // - check image actual start location(s) vs. fs_zebra_size field in the image.
2682 : // - Image file is not striped though its fs_zebra_size sais it is - need to allow that
2683 : // when checking a file.
2684 : //
2685 : // Verification flow:
2686 : //
2687 : // 1. Find image start addresses.
2688 : // if num of start_addr not in [1,2] - Error - corrupted flash
2689 : // 2. for each start_addr:
2690 : // Check that its fs_zebra_size is identical to other images (if exists)
2691 : // For Flash:
2692 : // Set address translation according to the fs_zebra_size.
2693 : // For File:
2694 : // *GUESS* if image is contiguous or striped. This can be according
2695 : // to the file size vs. image size field in the image.
2696 : // Set address translation according to the fs_zebra_size or to 0.
2697 : // verify - same as previous projects nofs image, with the aditional start
2698 : //
2699 :
2700 :
2701 0 : bool Operations::CntxFindMagicPattern (FBase& f, u_int32_t addr) {
2702 0 : int i;
2703 0 : if (addr + 16 > f.get_size()) {
2704 0 : return false;
2705 : }
2706 0 : for (i = 0; i < 4 ; i++) {
2707 0 : u_int32_t w;
2708 0 : READ4(f, addr + i * 4, &w, "Magic Pattern" );
2709 0 : TOCPU1(w);
2710 0 : if (w != _cntx_magic_pattern[i]) {
2711 : //printf("-D- Looking for magic pattern %d addr %06x: Exp=%08x Act=%08x\n", i, addr + i * 4, _cntx_magic_pattern[i], w);
2712 0 : return false;
2713 : }
2714 : }
2715 :
2716 0 : return true;
2717 : }
2718 :
2719 : // FindAllImageStart
2720 : // OUT: start_locations: set to the start addresses of the found image markers (in accending order)
2721 : // OUT: found_images: Number of found images (and number of valid entries in the start_locations array).
2722 0 : bool Operations::CntxFindAllImageStart (FBase& f, u_int32_t start_locations[CNTX_START_POS_SIZE], u_int32_t* found_images) {
2723 0 : int i;
2724 0 : f.set_address_convertor(0,0);
2725 :
2726 0 : *found_images = 0;
2727 0 : for (i = 0; i < CNTX_START_POS_SIZE; i++) {
2728 0 : if (CntxFindMagicPattern(f, _cntx_image_start_pos[i])) {
2729 0 : start_locations[*found_images] = _cntx_image_start_pos[i];
2730 0 : (*found_images)++;
2731 : }
2732 : }
2733 :
2734 0 : return true;
2735 : }
2736 : #define BAD_CRC_MSG "Bad CRC."
2737 :
2738 : bool Operations::checkBoot2(FBase& f, u_int32_t beg, u_int32_t offs,
2739 : u_int32_t& next, const char *pref)
2740 0 : {
2741 0 : u_int32_t size;
2742 :
2743 0 : char *pr = (char *)alloca(strlen(pref) + 512);
2744 :
2745 0 : sprintf(pr, "%s /0x%08x/ (BOOT2)", pref, offs+beg);
2746 :
2747 : // Size
2748 0 : READ4(f, offs+beg+4, &size, pr);
2749 0 : TOCPU1(size);
2750 0 : if (size > 1048576 || size < 4) {
2751 0 : report("%s /0x%08x/ - unexpected size (0x%x)\n", pr, offs+beg+4, size);
2752 0 : return false;
2753 : }
2754 :
2755 0 : sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (BOOT2)", pref, offs+beg,
2756 : offs+beg+(size+4)*4-1, (size+4)*4);
2757 :
2758 0 : if (_is_full_verify == true) {
2759 0 : Crc16 crc;
2760 0 : u_int32_t *buff = (u_int32_t*)alloca((size + 4)*sizeof(u_int32_t));
2761 :
2762 0 : READBUF(f, offs+beg, buff, size*4 + 16, pr);
2763 0 : TOCPUn(buff, size+4);
2764 0 : CRC1n(crc, buff, size+4);
2765 0 : CRC1n(f.get_image_crc(), buff, size+4);
2766 :
2767 :
2768 0 : crc.finish();
2769 :
2770 0 : u_int32_t crc_act = buff[size+3];
2771 0 : if (crc.get() != crc_act) {
2772 0 : report("%s /0x%08x/ - wrong CRC (exp:0x%x, act:0x%x)\n",
2773 : pr, offs+beg, crc.get(), crc_act);
2774 0 : return errmsg(BAD_CRC_MSG);
2775 : }
2776 0 : f.get_image_crc() << crc_act;
2777 :
2778 0 : if (_print_crc)
2779 0 : report("%s - OK (CRC:0x%04x)\n", pr, (crc_act & 0xffff));
2780 : else
2781 0 : report("%s - OK\n", pr);
2782 : }
2783 0 : next = offs + size*4 + 16;
2784 0 : return true;
2785 : } // checkBoot2
2786 :
2787 : static int part_cnt;
2788 :
2789 0 : bool Operations::GetSectData(std::vector<u_int8_t>& file_sect, const u_int32_t *buff, const u_int32_t size) {
2790 :
2791 0 : file_sect.clear();
2792 0 : file_sect.insert(file_sect.end(),
2793 : vector<u_int8_t>::iterator((u_int8_t*)buff),
2794 : vector<u_int8_t>::iterator((u_int8_t*)buff + size));
2795 :
2796 :
2797 0 : return true;
2798 : }
2799 :
2800 : bool Operations::CheckAndPrintCrcRes(char* pr, bool blank_crc, u_int32_t off, u_int32_t crc_act, u_int32_t crc_exp)
2801 0 : {
2802 :
2803 0 : if (!blank_crc && crc_exp != crc_act) {
2804 0 : report("%s /0x%08x/ - wrong CRC (exp:0x%x, act:0x%x)\n",
2805 : pr, off, crc_exp, crc_act);
2806 0 : return errmsg(BAD_CRC_MSG);
2807 : }
2808 0 : if (_print_crc) {
2809 0 : report("%s - OK (CRC:0x%04x)\n", pr, crc_act & 0xffff);
2810 : } else {
2811 0 : if (blank_crc) {
2812 0 : report("%s - BLANK CRC (0xffff)\n", pr);
2813 : } else {
2814 0 : report("%s - OK\n", pr);
2815 : }
2816 : }
2817 0 : return true;
2818 : }
2819 :
2820 : #define CRC_CHECK_OUTPUT "%s /0x%08x-0x%08x (0x%06x)/ (%s)"
2821 : #define PRE_CRC_OUTPUT " "
2822 : ////////////////////////////////////////////////////////////////////////
2823 : bool Operations::checkGen(FBase& f, u_int32_t beg,u_int32_t offs,
2824 : u_int32_t& next, const char *pref, ImageInfo* info)
2825 0 : {
2826 0 : char *pr = (char *)alloca(strlen(pref) + 100);
2827 :
2828 0 : char unknown_sect_name[128];
2829 0 : const char* sect_name;
2830 :
2831 0 : u_int32_t size = 0;
2832 0 : GPH gph;
2833 0 : bool is_sect_to_read;
2834 : // GPH
2835 0 : sprintf(pr, "%s /0x%08x/ (GeneralHeader)", pref, offs+beg);
2836 0 : READBUF(f, offs + beg, &gph, sizeof(GPH), pr);
2837 0 : TOCPUBY(gph);
2838 :
2839 : // Body
2840 0 : part_cnt++;
2841 :
2842 : // May be BOOT3?
2843 0 : if (gph.type < H_FIRST || gph.type >= H_LAST) {
2844 0 : if (part_cnt > 2) {
2845 : //report("%s /0x%x/ - Invalid partition type (%d)\n",
2846 : // pref, offs+beg, gph.type);
2847 : //return false;
2848 : } else {
2849 0 : return checkBoot2(f, beg, offs, next, pref);
2850 : }
2851 : }
2852 :
2853 : // All partitions here
2854 0 : offs += beg;
2855 :
2856 0 : if (gph.type < H_FIRST || gph.type >= H_LAST) {
2857 : // For forward compatibility, try analyzing even if section type is unknown
2858 : // Assuming the size is in DW, like all other sections (except emt service).
2859 : // If this assumption is wrong, CRC calc would fail - no harm done.
2860 0 : sprintf(unknown_sect_name, "UNKNOWN (%d)" , gph.type);
2861 0 : sect_name = unknown_sect_name;
2862 0 : size = gph.size * 4;
2863 0 : is_sect_to_read = true;
2864 :
2865 : } else {
2866 0 : if (gph.type == H_EMT) {
2867 0 : size = (gph.size + 3) / 4 * 4;
2868 : } else {
2869 0 : size = gph.size * 4;
2870 : }
2871 0 : sect_name = g_sectNames[gph.type];
2872 0 : is_sect_to_read = _sections_to_read[gph.type];;
2873 : }
2874 :
2875 0 : sprintf(pr, CRC_CHECK_OUTPUT,
2876 : pref, offs, offs+size+(u_int32_t)sizeof(gph)+3,
2877 : size+(u_int32_t)sizeof(gph)+4, sect_name);
2878 :
2879 0 : if (size > MAX_SECTION_SIZE) {
2880 0 : report("%s - size too big (0x%x)\n",
2881 : pr, size);
2882 0 : return false;
2883 : }
2884 : //printf("-D- gph.type = %d\n", gph.type);
2885 0 : if (is_sect_to_read) {
2886 : // CRC
2887 0 : Crc16 crc;
2888 0 : std::vector<u_int8_t> buffv(size);
2889 0 : u_int32_t *buff = (u_int32_t*)(&(buffv[0]));
2890 :
2891 0 : READBUF(f, offs+sizeof(gph), buff, size, pr);
2892 :
2893 0 : TOCPUn(buff,size/4);
2894 0 : CRCBY(crc, gph);
2895 0 : CRCBY(f.get_image_crc(), gph);
2896 :
2897 0 : CRCn(crc, buff, size/4);
2898 0 : CRCn(f.get_image_crc(), buff, size/4);
2899 : //printf("-D- GEN: CRC is %#x\n", f.get_image_crc().get());
2900 0 : crc.finish();
2901 :
2902 0 : u_int32_t crc_act;
2903 0 : READ4(f, offs+sizeof(gph)+size, &crc_act, pr);
2904 0 : TOCPU1(crc_act);
2905 0 : bool blank_crc = false;
2906 :
2907 :
2908 0 : if (gph.type == H_GUID && crc_act == 0xffff) {
2909 0 : blank_crc = true;
2910 0 : info->blankGuids = true;
2911 : }
2912 :
2913 0 : if (!CheckAndPrintCrcRes(pr, blank_crc, offs, crc_act, crc.get())) {
2914 0 : return false;
2915 :
2916 : }
2917 :
2918 0 : f.get_image_crc() << crc.get();
2919 : // The image info may be null, plesae check that before using it.
2920 0 : if (gph.type == H_FW_CONF) {
2921 0 : GetSectData(_fw_conf_sect, buff, size);
2922 : }
2923 0 : if (gph.type == H_HASH_FILE) {
2924 0 : GetSectData(_hash_file_sect, buff, size);
2925 : }
2926 :
2927 0 : if (gph.type == H_IMG_INFO) {
2928 0 : CPUTOn(buff, size/4);
2929 0 : if (!ParseInfoSect((u_int8_t*)buff, size, info)) {
2930 0 : return errmsg("Failed to read the info sector: %s\n", err());
2931 : }
2932 : }
2933 :
2934 0 : if (info != NULL) {
2935 0 : if (gph.type == H_ROM && info->_rom_sect.empty()) {
2936 0 : GetSectData(info->_rom_sect, buff, size);
2937 : }
2938 : }
2939 :
2940 :
2941 : }
2942 :
2943 :
2944 : // mark last read addr
2945 0 : _last_image_addr = offs + size + sizeof(gph) + 4; // the 4 is for the trailing crc
2946 0 : next = gph.next;
2947 :
2948 0 : return true;
2949 : } // checkGen
2950 :
2951 : ////////////////////////////////////////////////////////////////////////
2952 : bool Operations::checkPS(FBase& f, u_int32_t offs, u_int32_t& next, const char *pref)
2953 0 : {
2954 0 : Crc16 crc;
2955 0 : PS ps;
2956 0 : f.read(offs, &ps, sizeof(ps));
2957 0 : TOCPUBY(ps);
2958 :
2959 : // Signature
2960 0 : if (ps.signature != SIGNATURE) {
2961 0 : report("%s Pointer Sector /0x%08x/ - invalid signature (%08x)\n",
2962 : pref, offs, ps.signature);
2963 0 : return false;
2964 : }
2965 :
2966 : // CRC
2967 0 : CRC1BY(crc, ps);
2968 0 : crc.finish();
2969 0 : if (crc.get() != ps.crc016) {
2970 0 : report("%s Pointer Sector /0x%08x/ - wrong CRC (exp:0x%x, act:0x%x)\n",
2971 : pref, offs, ps.crc016, crc.get());
2972 0 : return errmsg(BAD_CRC_MSG);
2973 : }
2974 :
2975 0 : next = ps.fi_addr;
2976 0 : if (_print_crc)
2977 0 : report("%s Image /0x%08x-0x%08x (0x%06x)/ (Pointer Sector)- OK (CRC:0x%04x)\n", pref, offs,
2978 : offs+(u_int32_t)sizeof(ps)-1, (u_int32_t)sizeof(ps), ps.crc016&0xffff);
2979 : else
2980 0 : report("%s Image /0x%08x-0x%08x (0x%06x)/ (Pointer Sector)- OK\n", pref, offs,
2981 : offs+(u_int32_t)sizeof(ps)-1, (u_int32_t)sizeof(ps));
2982 0 : return true;
2983 : } // checkPS
2984 :
2985 : ////////////////////////////////////////////////////////////////////////
2986 : bool Operations::checkList(FBase& f, u_int32_t offs, u_int32_t fw_start, const char *pref, ImageInfo* info)
2987 0 : {
2988 0 : u_int32_t next_ptr;
2989 :
2990 0 : CHECKB2(f, offs, fw_start, next_ptr, pref);
2991 0 : part_cnt = 1;
2992 0 : while (next_ptr && next_ptr != 0xff000000)
2993 0 : CHECKGN(f, offs, next_ptr, next_ptr, pref, info);
2994 :
2995 0 : return true;
2996 : } // checkList
2997 :
2998 : ////////////////////////////////////////////////////////////////////////
2999 :
3000 0 : bool Operations::CheckIsFs2(FBase& f) {
3001 0 : if (f.is_flash()) {
3002 0 : return ( ((Flash*)&f)->get_dev_id() == 400) ||
3003 : ( ((Flash*)&f)->get_dev_id() == 435) ||
3004 : ( ((Flash*)&f)->get_dev_id() == 6100)
3005 : ;
3006 : } else {
3007 0 : u_int32_t found_images;
3008 0 : u_int32_t image_start[CNTX_START_POS_SIZE];
3009 :
3010 : // Image - check if magic pattern is somewhere in the file:
3011 0 : CntxFindAllImageStart(f, image_start, &found_images);
3012 0 : return found_images > 0;
3013 : }
3014 : }
3015 :
3016 0 : bool Operations::CheckMac(u_int64_t mac) {
3017 0 : if ((mac >> 40) & 0x1) {
3018 0 : return errmsg("Multicast bit (bit 40) is set");
3019 : }
3020 :
3021 0 : if (mac >> 48) {
3022 0 : return errmsg("More than 48 bits are used");
3023 : }
3024 :
3025 0 : return true;
3026 : }
3027 :
3028 :
3029 0 : bool Operations::CntxGetFsData(u_int32_t fs_info_word, bool& fs_en, u_int32_t& log2chunk_size) {
3030 0 : u_int8_t checksum;
3031 : //printf("-D- fs_info_word=%08x\n", fs_info_word);
3032 :
3033 0 : checksum = ((fs_info_word ) & 0xff) +
3034 : ((fs_info_word >> 8) & 0xff) +
3035 : ((fs_info_word >> 16) & 0xff) +
3036 : ((fs_info_word >> 24) & 0xff);
3037 :
3038 0 : if (checksum != 0) {
3039 0 : return errmsg("Corrupted chunk size checksum");
3040 : }
3041 :
3042 0 : fs_en = (fs_info_word & 0x8) != 0;
3043 :
3044 0 : if (fs_en) {
3045 0 : log2chunk_size = (fs_info_word & 0x7) + 16;
3046 : } else {
3047 0 : log2chunk_size = 0;
3048 : }
3049 :
3050 0 : return true;
3051 : }
3052 :
3053 :
3054 : bool Operations::HwDevIdToSw(u_int32_t hw_dev_id, u_int32_t& sw_dev_id)
3055 0 : {
3056 0 : int i;
3057 0 : for (i = 0; hwDevData[i].hwDevId != 0 ; i++) {
3058 0 : if (hwDevData[i].hwDevId == hw_dev_id) {
3059 0 : sw_dev_id = hwDevData[i].swDevIds[0];
3060 0 : return true;
3061 : }
3062 : }
3063 0 : return errmsg("Unknown Hw ID: %#x\n", hw_dev_id);
3064 : }
3065 :
3066 : // This function gets the HW ID of the target device and the dev ID from
3067 : // the image. It then matches the 2 IDs and returns an error in case of
3068 : // missmatch. The match is not 1:1 , since the FW image contains the SW
3069 : // dev id, and a single hw dev id may match multiple SW dev IDs.
3070 : //
3071 0 : bool Operations::CheckMatchingHwDevId(u_int32_t hwDevId, u_int32_t rev_id, Operations::ImageInfo& info) {
3072 :
3073 0 : int i;
3074 0 : u_int32_t sw_dev_id;
3075 :
3076 0 : if (!HwDevIdToSw(hwDevId, sw_dev_id)) {
3077 0 : return false;
3078 : }
3079 0 : u_int32_t hw_dev_rev = (hwDevId & 0xffff) | ((rev_id & 0xff) << 16);
3080 0 : for (i = 0; i < info.supportedHwIdNum; i++) {
3081 : //printf("-D- hw_dev_rev: %#x, supported_hw_id[%d]: %#x\n", hw_dev_rev, i, supported_hw_id[i]);
3082 0 : if (info.supportedHwId[i] == hw_dev_rev) {
3083 0 : return true;
3084 : }
3085 : }
3086 0 : return errmsg("FW image file for device MT%d%X can not be programmed to device MT%d%X",
3087 : info.devType, info.devRev, sw_dev_id, rev_id);
3088 : }
3089 :
3090 0 : bool Operations::CheckMatchingDevId(u_int32_t hwDevId, u_int32_t imageDevId) {
3091 0 : int i, j;
3092 0 : const HwDevData* devData = NULL;
3093 0 : const char* hwDevName = NULL;
3094 : // HACK: InfiniHost III LX may have 2 HW device ids. - Map the second devid to the first.
3095 0 : if (hwDevId == 24204) {
3096 0 : hwDevId = 25204;
3097 : }
3098 :
3099 : // First, find the HW device that the SW id matches
3100 0 : for (i = 0; hwDevData[i].hwDevId != 0 ; i++) {
3101 0 : if (hwDevData[i].hwDevId == hwDevId) {
3102 0 : hwDevName = hwDevData[i].name; // TODO: Check bug if device not found
3103 : }
3104 :
3105 0 : if (devData == NULL) {
3106 0 : for (j = 0; hwDevData[i].swDevIds[j]; j++) {
3107 0 : if (hwDevData[i].swDevIds[j] == imageDevId) {
3108 0 : devData = &hwDevData[i];
3109 0 : break;
3110 : }
3111 : }
3112 : }
3113 : }
3114 :
3115 0 : if (devData == NULL) {
3116 0 : report_warn("Unknown device id (%d) in the given FW image. Skipping HW match check.\n",
3117 : imageDevId);
3118 0 : return true;
3119 0 : } else if (devData->hwDevId != hwDevId) {
3120 0 : return errmsg("Trying to burn a \"%s\" image on a \"%s\" device.",
3121 : devData->name,
3122 : hwDevName);
3123 : }
3124 :
3125 0 : return true;
3126 : }
3127 :
3128 0 : bool Operations::CheckMatchingExpRomDevId(Operations::ImageInfo* info) {
3129 0 : if (info->expRomFound &&
3130 : info->expRomValidVersion &&
3131 : info->expRomProductId >= 0x10 &&
3132 : info->infoOffs[II_DeviceType] &&
3133 : info->devType != info->expRomDevId) {
3134 0 : return errmsg("FW is for device %d, but Exp-ROM is for device %d",
3135 : info->devType,
3136 : info->expRomDevId);
3137 : }
3138 0 : return true;
3139 : }
3140 :
3141 :
3142 : bool Operations::VerifyFs2(FBase& f, Operations::ImageInfo* info, bool both_images, bool only_get_start,
3143 0 : bool ignore_full_image_crc) {
3144 0 : u_int32_t cntx_image_start[CNTX_START_POS_SIZE];
3145 0 : u_int32_t cntx_image_num;
3146 0 : u_int32_t i;
3147 0 : bool ret = true;
3148 0 : u_int32_t act_crc;
3149 0 : bool check_full_crc = false;
3150 :
3151 : // Look for image in "physical addresses
3152 0 : CntxFindAllImageStart(f, cntx_image_start, &cntx_image_num);
3153 :
3154 0 : if (cntx_image_num == 0) {
3155 0 : return errmsg("No valid image found");
3156 0 : } else if (cntx_image_num > 2) {
3157 : // This check may be redundant - Maybe ignore if more than 2 images found
3158 0 : return errmsg("More than 2 image start locations found at addresses 0x%x, 0x%x and 0x%x. Image may be corrupted.",
3159 : cntx_image_start[0],
3160 : cntx_image_start[1],
3161 : cntx_image_start[2]);
3162 : }
3163 :
3164 0 : if (!both_images) {
3165 : // Check only the first image. This is enough to ensure that the device is bootable.
3166 0 : cntx_image_num = 1;
3167 : }
3168 :
3169 0 : bool info_set = false;
3170 :
3171 : // Verify the images:
3172 0 : for (i = 0; i < cntx_image_num; i++ ) {
3173 0 : bool fs_en;
3174 0 : u_int32_t log2chunk_size;
3175 0 : u_int32_t buff[FS2_BOOT_START / 4];
3176 :
3177 0 : f.get_image_crc().clear();
3178 :
3179 0 : f.set_address_convertor(0, 0);
3180 :
3181 0 : READBUF(f, cntx_image_start[i], buff, FS2_BOOT_START, "Image header");
3182 :
3183 0 : TOCPUn(buff, FS2_BOOT_START / 4);
3184 :
3185 0 : u_int32_ba crc_dw = buff[IMG_CRC_OFF / 4];
3186 0 : act_crc = u_int32_t(crc_dw.range(15, 0));
3187 0 : crc_dw.range(15, 0) = 0xffff;
3188 0 : buff[IMG_CRC_OFF / 4] |= crc_dw;
3189 :
3190 0 : CRCn(f.get_image_crc(), buff, FS2_BOOT_START / 4);
3191 : //printf("-D- CRC is %#x\n", f.get_image_crc().get());
3192 0 : if (!CntxGetFsData(buff[FS_DATA_OFF / 4], fs_en, log2chunk_size)) {
3193 0 : report("\n Can not read failsafe info word: %s\n", err());
3194 0 : return(i > 0);
3195 : }
3196 :
3197 : // If fw not enabled, image must start at addr 0
3198 0 : if (!fs_en && cntx_image_start[i] != 0) {
3199 0 : return errmsg("FS2 Non Failsafe image must start at address 0. Found non-fs image at address 0x%x",
3200 : cntx_image_start[i]);
3201 : }
3202 :
3203 0 : if (fs_en) {
3204 0 : report("\n FS2 failsafe image. Start address: 0x%x. Chunk size 0x%x:\n\n", cntx_image_start[i], 1 << log2chunk_size);
3205 0 : report(" NOTE: The addresses below are contiguous logical addresses. Physical addresses on\n"
3206 : " flash may be different, based on the image start address and chunk size\n\n");
3207 : } else {
3208 0 : report("\n FS2 non failsafe image:\n\n");
3209 : }
3210 :
3211 0 : if (fs_en && cntx_image_start[i] != 0 && cntx_image_start[i] != (u_int32_t)(1 << log2chunk_size)) {
3212 0 : return errmsg("FS2 Failsafe image must start at address 0 or at chunk size. Found a failsafe image at address 0x%x",
3213 : cntx_image_start[i]);
3214 : }
3215 :
3216 0 : if (info && !info_set) {
3217 0 : info->imgStart = cntx_image_start[i];
3218 0 : info->isFailsafe = fs_en;
3219 0 : info->actuallyFailsafe = true;
3220 0 : info->cntxLog2ChunkSize = log2chunk_size;
3221 : }
3222 :
3223 0 : if (f.is_flash()) {
3224 : // In flash, image layout must match the FS Data
3225 0 : if (info && !info_set) {
3226 0 : info->actuallyFailsafe = true;
3227 0 : info_set = true;
3228 : }
3229 :
3230 0 : if (fs_en) {
3231 0 : f.set_address_convertor(log2chunk_size, cntx_image_start[i] != 0);
3232 : }
3233 : } else {
3234 : // In an image file there are 2 cases:
3235 : // 1. Image generated by mlxburn
3236 : // The image in the file is contiguous (though it is marked as FS) - no need to set address convertion.
3237 : // 2. The image was raw read from flash. In this case it would be in "zebra" format.
3238 : //
3239 : // So - I try both cases, and see which verify() succeeds.
3240 : //
3241 : // Heuristics that may come in handy:
3242 : // If the image does not start at addr 0, it's not an mlxburn image.
3243 : // If there is more than a single valid image, it's not an mlxburn image.
3244 : // If the file size matches the image size, it is an mlxburn image.
3245 : //
3246 : // For now, get the "striped" indication from user.
3247 :
3248 0 : if (_cntx_striped_image) {
3249 0 : f.set_address_convertor(log2chunk_size, cntx_image_start[i] != 0);
3250 : } else {
3251 0 : f.set_address_convertor(0, 0); //disable conversion
3252 : }
3253 0 : if (info && !info_set) {
3254 0 : info->actuallyFailsafe = _cntx_striped_image;
3255 0 : info_set = true;
3256 : }
3257 : }
3258 :
3259 0 : bool imgStat = true;
3260 :
3261 : // TODO: check what only_get_start means.
3262 0 : if (!only_get_start) {
3263 0 : imgStat = checkList(f, 0, FS2_BOOT_START, PRE_CRC_OUTPUT, info);
3264 : }
3265 0 : f.get_image_crc().finish();
3266 :
3267 0 : u_int32_t full_crc = f.get_image_crc().get();
3268 :
3269 0 : if (!ignore_full_image_crc && info->infoOffs[II_MicVersion]) { // For now we check only that the Mic version existing .
3270 0 : check_full_crc = true;
3271 : }
3272 :
3273 0 : if (imgStat && _is_full_verify && check_full_crc && !only_get_start) {
3274 0 : char pr[256];
3275 0 : sprintf(pr, CRC_CHECK_OUTPUT, PRE_CRC_OUTPUT, 0, _last_image_addr - 1, _last_image_addr,
3276 : "Full Image");
3277 0 : CheckAndPrintCrcRes(pr, info->blankGuids, 0, act_crc, full_crc);
3278 : }
3279 :
3280 0 : if (i == 0) {
3281 0 : ret = ret && imgStat;
3282 : }
3283 : }
3284 0 : return ret;
3285 : }
3286 :
3287 : bool Operations::Verify(FBase& f, Operations::ImageInfo* info, bool both_images)
3288 0 : {
3289 0 : u_int32_t prim_ptr, scnd_ptr;
3290 0 : u_int32_t signature;
3291 :
3292 0 : bool ret = true;
3293 :
3294 0 : if (IsFs2()) {
3295 0 : return VerifyFs2(f, info, both_images);
3296 : }
3297 0 : READ4(f, 0x24, &signature, "Signature");
3298 0 : TOCPU1(signature);
3299 0 : if (signature == SIGNATURE) {
3300 : // Full image
3301 :
3302 0 : bool psStat[2];
3303 :
3304 0 : report("\nFailsafe image:\n\n");
3305 0 : CHECKB2(f, 0, 0x28, prim_ptr, "Invariant ");
3306 0 : report("\n");
3307 0 : psStat[0] = checkPS(f, f.get_sector_size(), prim_ptr, "Primary ");
3308 0 : if (psStat[0]) {
3309 0 : ret &= checkList(f, prim_ptr, 0x28, " ", info);
3310 : }
3311 0 : report("\n");
3312 :
3313 0 : if (psStat[0] && !both_images) {
3314 0 : return ret;
3315 : }
3316 :
3317 0 : psStat[1] = checkPS(f, f.get_sector_size() * 2, scnd_ptr, "Secondary");
3318 0 : bool scndStat;
3319 0 : if (psStat[1]) {
3320 0 : scndStat = checkList(f, scnd_ptr, 0x28, " ", info);
3321 0 : if (!psStat[0]) {
3322 : // If the first image is valid, the HCA would boot OK even if the secondary image is messed up -
3323 : // consider this status only if the first image is not valid.
3324 0 : ret &= scndStat;
3325 : }
3326 : }
3327 :
3328 0 : if (psStat[0] == false && psStat[1] == false) {
3329 0 : ret = false;
3330 : }
3331 : } else {
3332 :
3333 0 : report("\nShort image:\n");
3334 0 : CHECKLS(f, 0, 0x28, " ", info);
3335 : }
3336 :
3337 0 : return ret;
3338 : } // Verify
3339 :
3340 0 : bool Operations::GetExpRomVersion(ImageInfo* info) {
3341 0 : const char* magic_string = "mlxsign:";
3342 0 : u_int32_t magic_len = strlen(magic_string);
3343 0 : u_int32_t i;
3344 0 : bool magic_found = false;
3345 0 : u_int32_t ver_offset;
3346 0 : u_int8_t rom_checksum = 0;
3347 0 : u_int32_t rom_checksum_range;
3348 :
3349 0 : info->expRomValidVersion = false;
3350 0 : if (info->_rom_sect.empty()) {
3351 0 : return errmsg("Expansion Rom section not found.");
3352 : }
3353 : // When checking the version of the expansion rom, only the first image has
3354 : // to be checked. This is because the second image the uefi image does not
3355 : // have to comply with checksumming to 0. To do this you have to read byte
3356 : // 2 (third) of the image and multiply by 512 to get the size of the x86
3357 : // image.
3358 :
3359 : // Checksum:
3360 0 : if (info->_rom_sect.size() < 4) {
3361 0 : return errmsg("ROM size (0x%x) is too small", (u_int32_t)info->_rom_sect.size());
3362 : }
3363 :
3364 : // restore endianess.
3365 0 : TOCPUn(&(info->_rom_sect[0]), info->_rom_sect.size()/4);
3366 :
3367 0 : rom_checksum_range = info->_rom_sect[2] * 512 ;
3368 0 : if (rom_checksum_range > info->_rom_sect.size()) {
3369 0 : return errmsg("ROM size field (0x%2x) is larger than actual ROM size (0x%x)",
3370 : rom_checksum_range ,
3371 : (u_int32_t)info->_rom_sect.size());
3372 0 : } else if (rom_checksum_range == 0) {
3373 0 : return errmsg("ROM size field is 0. Unknown ROM format or corrupted ROM.");
3374 : }
3375 :
3376 0 : for (i = 0; i < rom_checksum_range; i++) {
3377 0 : rom_checksum += info->_rom_sect[i];
3378 : }
3379 :
3380 0 : if (rom_checksum != 0) {
3381 0 : return errmsg("Bad ROM Checksum (0x%02x)", rom_checksum);
3382 : }
3383 :
3384 0 : for (i = 0 ; i < rom_checksum_range; i++) {
3385 0 : for (u_int32_t j = 0; j < magic_len; j++) {
3386 0 : if (info->_rom_sect[i+j] != magic_string[j]) {
3387 0 : break;
3388 0 : } else if (j == magic_len - 1) {
3389 0 : magic_found = true;
3390 : }
3391 : }
3392 :
3393 0 : if (magic_found) {
3394 0 : break;
3395 : }
3396 : }
3397 :
3398 0 : if (magic_found) {
3399 0 : ver_offset = i + magic_len;
3400 : } else {
3401 0 : return errmsg("Mellanox version string (%s) not found in ROM section.", magic_string);
3402 : }
3403 :
3404 : // Following mlxsign:
3405 : // 31:24 0 Compatible with UEFI
3406 : // 23:16 ProductID Product ID:
3407 : // 1 - CLP implementation for Sinai (MT25408)
3408 : // 2 - CLP implementation for Hermon DDR (MT25418)
3409 : // 0X10 - PXE
3410 : // 15:0 Major version If ProductID < 0x10 this field is subversion
3411 : // number, otherwise It's product major version.
3412 : //
3413 : // 31:16 Minor version Product minor version*. Not valid if
3414 : // roductID < 0x10.
3415 : // 15:0 SubMinor version Product sub minor version*. Not valid if
3416 : // ProductID < 0x10.
3417 : //
3418 : // 31:16 Device ID The PCI Device ID (ex. 0x634A for Hermon
3419 : // DDR). Not valid if ProductID < 0x10.
3420 : // 15:12 Port Number Port number: 0 - Port independent, 1 - Port 1, 2 - Port 2
3421 : // 8:11 Reserved
3422 : // 0:7 Protocol type: 0=IB 1=ETH 2=VPI
3423 :
3424 0 : u_int32_t tmp;
3425 :
3426 0 : tmp = __le32_to_cpu(*((u_int32_t*) &info->_rom_sect[ver_offset]));
3427 0 : info->expRomProductId = tmp >> 16;
3428 0 : info->expRomVer[0] = tmp & 0xffff;
3429 0 : if (info->expRomProductId >= 0x10) {
3430 0 : tmp = __le32_to_cpu(*((u_int32_t*) &info->_rom_sect[ver_offset + 4]));
3431 0 : info->expRomVer[1] = tmp >> 16;
3432 0 : info->expRomVer[2] = tmp & 0xffff;
3433 :
3434 0 : tmp = __le32_to_cpu(*((u_int32_t*) &info->_rom_sect[ver_offset + 8]));
3435 0 : info->expRomDevId = tmp >> 16;
3436 0 : info->expRomPort = (tmp >> 12) & 0xf;
3437 0 : info->expRomProto = tmp & 0xff;
3438 0 : } else if (info->expRomProductId == 0xf) {
3439 : // get string length
3440 0 : u_int32_ba tmp_ba= *((u_int32_t*) &info->_rom_sect[ver_offset + 0xc]);
3441 0 : u_int32_t str_len = u_int32_t(tmp_ba.range(15, 8));
3442 0 : u_int32_t sign_length = u_int32_t(tmp_ba.range(7, 0));
3443 0 : u_int32_t dws_num = ((str_len + 3 ) / 4) + 4;
3444 :
3445 0 : if (sign_length < dws_num) {
3446 0 : return errmsg("The Signature length (%d) and the ROM version string length (%d) are not coordinated",
3447 : sign_length, str_len);
3448 : }
3449 : // copy str
3450 0 : strncpy(info->expRomFreestr, (char*)&info->_rom_sect[ver_offset + 0x10], str_len);
3451 0 : info->expRomFreestr[str_len] = '\0';
3452 :
3453 :
3454 0 : tmp_ba = __le32_to_cpu(*((u_int32_t*) &info->_rom_sect[0x18]));
3455 0 : u_int32_t dev_id_off = u_int32_t(tmp_ba.range(15, 0)) + 4;
3456 :
3457 :
3458 0 : if (dev_id_off >= info->_rom_sect.size()) {
3459 0 : return errmsg("The device ID offset %#x is out of range. ROM size: %#x", dev_id_off,
3460 : (u_int32_t)info->_rom_sect.size());
3461 : }
3462 :
3463 : // get devid
3464 0 : tmp_ba = __le32_to_cpu(*((u_int32_t*) &info->_rom_sect[dev_id_off]));
3465 0 : info->expRomDevId = u_int32_t(tmp_ba.range(31, 16));
3466 0 : u_int32_t vendor_id = u_int32_t(tmp_ba.range(15, 0));
3467 :
3468 0 : if ( vendor_id != MELLANOX_VENDOR_ID) {
3469 0 : report_warn("The Exp-ROM PCI vendor ID: %#x does not match the expected value: %#x.\n", vendor_id,
3470 : MELLANOX_VENDOR_ID);
3471 : }
3472 :
3473 :
3474 : }
3475 0 : info->expRomValidVersion = true;
3476 0 : return true;
3477 : }
3478 :
3479 0 : bool Operations::LoadAsExpRom (FBase& f, ImageInfo* info) {
3480 0 : info->_rom_sect.clear();
3481 0 : info->_rom_sect.resize(f.get_size());
3482 0 : if (!f.read(0, &info->_rom_sect[0], f.get_size()))
3483 0 : return errmsg(f.err());
3484 :
3485 0 : TOCPUn(&info->_rom_sect[0], info->_rom_sect.size()/4);
3486 :
3487 0 : return true;
3488 : }
3489 :
3490 0 : bool Operations::DumpConf (const char* conf_file, SectionType sect_type) {
3491 : #ifndef NO_ZLIB
3492 0 : std::vector<u_int8_t> file_sect;
3493 0 : FILE* out;
3494 0 : if (conf_file == NULL) {
3495 0 : out = stdout;
3496 : } else {
3497 0 : out = fopen(conf_file, "w");
3498 :
3499 0 : if (out == NULL) {
3500 0 : return errmsg("Can not open file %s for write: %s.", conf_file, strerror(errno));
3501 : }
3502 : }
3503 0 : if (sect_type == H_HASH_FILE) {
3504 0 : file_sect = _hash_file_sect;
3505 : } else {
3506 0 : file_sect = _fw_conf_sect;
3507 : }
3508 :
3509 0 : if (file_sect.empty()) {
3510 0 : return errmsg("%s section not found in the given image.", g_sectNames[sect_type]);
3511 : }
3512 :
3513 : // restore endianess.
3514 0 : TOCPUn(&(file_sect[0]), file_sect.size()/4);
3515 :
3516 : // uncompress:
3517 0 : uLongf destLen = file_sect.size();
3518 0 : destLen *= 40; // Assuming this is the best compression ratio
3519 0 : vector<u_int8_t> dest(destLen);
3520 :
3521 : int rc = uncompress((Bytef *)&(dest[0]), &destLen,
3522 0 : (const Bytef *)&(file_sect[0]), file_sect.size());
3523 :
3524 0 : if (rc != Z_OK) {
3525 0 : return errmsg("Failed uncompressing FW configuration section. uncompress returnes %d", rc);
3526 : }
3527 :
3528 0 : dest.resize(destLen);
3529 0 : dest[destLen] = 0; // Terminating NULL
3530 0 : fprintf(out, "%s", (char*)&(dest[0]));
3531 :
3532 0 : if (conf_file != NULL) {
3533 0 : fclose(out);
3534 : }
3535 :
3536 0 : return true;
3537 : #else
3538 : return errmsg("Executable was compiled with \"dump configuration\" option disabled.");
3539 : #endif
3540 :
3541 : } // DumpConf
3542 :
3543 :
3544 :
3545 : ////////////////////////////////////////////////////////////////////////
3546 : // //
3547 : // ****************************************************************** //
3548 : // GUIDs TREATMENT //
3549 : // ****************************************************************** //
3550 : // //
3551 : ////////////////////////////////////////////////////////////////////////
3552 : #define GETGUID(s, g) do { if (!ops.getGUID(s,g)) return 1; } while (0)
3553 : #define GETBSN(s, g) do { if (!ops.getBSN(s,g)) return 1; } while (0)
3554 :
3555 : #define BSN_RET do { \
3556 : printf("Invalid BSN. Should be MTxxxxx[-]R[xx]ddmmyy-nnn[-cc]\n"); \
3557 : return false; \
3558 : } while(0)
3559 : #define BSN_RET1(s) do { \
3560 : printf("Valid BSN format is: MTxxxxx[-]R[xx]ddmmyy-nnn[-cc]\n%s.\n",s); \
3561 : return false; \
3562 : } while(0)
3563 : u_int32_t Operations::BSN_subfield(const char *s, int beg, int len)
3564 0 : {
3565 0 : char buf[64];
3566 0 : strncpy(buf, &s[beg], len);
3567 0 : buf[len] = '\0';
3568 0 : return strtoul(&buf[0], 0, 10);
3569 : }
3570 : bool Operations::getBSN(char *s, guid_t *guid)
3571 0 : {
3572 0 : const u_int64_t COMPANY_ID = 0x0002c9;
3573 0 : const u_int64_t TYPE = 1;
3574 0 : bool cc_present = false;
3575 0 : char *p;
3576 0 : int date_offs = 0;
3577 0 : int i;
3578 :
3579 : // Convert to lowercase
3580 0 : for (p = s; *p; p++)
3581 0 : *p = (char)tolower(*p);
3582 :
3583 : // Check validity
3584 0 : p = s;
3585 0 : if (strncmp(p, "mt", 2)) // MT
3586 0 : BSN_RET;
3587 0 : p += 2;
3588 0 : for (i=0; i<5; i++)
3589 0 : if (!isdigit(*p++)) // xxxxx
3590 0 : BSN_RET;
3591 0 : if (*p == '-') { // - /optional/
3592 0 : p++;
3593 0 : date_offs++;
3594 : }
3595 0 : if (*p < 'a' || *p > 'z') // R
3596 0 : BSN_RET;
3597 0 : p++;
3598 :
3599 : // Count how many digits after R
3600 0 : char *q = p;
3601 0 : int ndigits=0;
3602 0 : while (isdigit(*q++))
3603 0 : ndigits++;
3604 :
3605 0 : switch (ndigits) {
3606 : case 6:
3607 0 : p += 6; // skip ddmmyy
3608 0 : break;
3609 : case 8:
3610 0 : p += 8; // skip xxddmmyy
3611 0 : date_offs += 2;
3612 0 : break;
3613 : default:
3614 0 : BSN_RET;
3615 : }
3616 :
3617 0 : if (*p++ != '-') // -
3618 0 : BSN_RET;
3619 0 : for (i=0; i<3; i++) // nnn
3620 0 : if (!isdigit(*p++))
3621 0 : BSN_RET;
3622 0 : if (*p) {
3623 0 : cc_present = true;
3624 0 : if (*p++ != '-') // -
3625 0 : BSN_RET;
3626 0 : for (i=0; i<2; i++) // cc
3627 0 : if (!isdigit(*p++))
3628 0 : BSN_RET;
3629 : }
3630 :
3631 0 : u_int32_t dd = BSN_subfield(s, 8+date_offs, 2);
3632 0 : if (dd > 31)
3633 0 : BSN_RET1("Day (dd) should not exceed 31");
3634 0 : if (!dd)
3635 0 : BSN_RET1("Day (dd) can not be zero");
3636 0 : u_int32_t mm = BSN_subfield(s, 10+date_offs, 2);
3637 0 : if (mm > 12)
3638 0 : BSN_RET1("Months (mm) should not exceed 12");
3639 0 : if (!mm)
3640 0 : BSN_RET1("Months (mm) can not be zero");
3641 0 : u_int32_t yy = BSN_subfield(s, 12+date_offs, 2);
3642 0 : if (yy > 99)
3643 0 : BSN_RET1("Year (yy) should not exceed 99");
3644 0 : if (!yy)
3645 0 : BSN_RET1("Year (yy) can not be zero");
3646 0 : u_int32_t num = BSN_subfield(s, 15+date_offs, 3);
3647 0 : if (num > 999)
3648 0 : BSN_RET1("Number (num) should not exceed 999");
3649 0 : if (!num)
3650 0 : BSN_RET1("Number (num) can not be zero");
3651 0 : int cc = 1;
3652 0 : if (cc_present) {
3653 0 : cc = BSN_subfield(s, 19+date_offs, 2);
3654 0 : if (cc > 14)
3655 0 : BSN_RET1("Chip number (cc) should not exceed 14");
3656 0 : if (!cc)
3657 0 : BSN_RET1("Chip number (cc) can not be zero");
3658 : }
3659 0 : u_int64_t id = ((((yy*12+mm-1)*31+ dd-1) * 1000) + num-1) * 112;
3660 0 : id += (cc-1)*8;
3661 :
3662 0 : u_int64_t g = (COMPANY_ID << 40) | (TYPE << 32) | id;
3663 0 : guid->h = (u_int32_t)(g>>32);
3664 0 : guid->l = (u_int32_t)g;
3665 0 : return true;
3666 : }
3667 :
3668 : bool Operations::getGUID(const char *s, guid_t *guid)
3669 0 : {
3670 0 : char* endp;
3671 0 : u_int64_t g;
3672 :
3673 0 : g = strtoull(s, &endp, 16);
3674 0 : if (*endp || (g == 0xffffffffffffffffULL && errno == ERANGE)) {
3675 0 : report_err(_err_msg, "Invalid GUID syntax (%s) %s \n",
3676 : s,
3677 : errno ? strerror(errno) : "" );
3678 0 : return false;
3679 : }
3680 0 : guid->h = (u_int32_t)(g >> 32);
3681 0 : guid->l = (u_int32_t)(g & 0xffffffff);
3682 0 : return true;
3683 : } // getGUID
3684 :
3685 : ////////////////////////////////////////////////////////////////////////
3686 : bool Operations::extractGUIDptr(u_int32_t sign, u_int32_t *buf, int buf_len,
3687 : char *pref, u_int32_t *ind, int *nguids)
3688 0 : {
3689 0 : u_int32_t offs = 0;
3690 :
3691 0 : if (IsFs2()) {
3692 0 : offs = 16;
3693 : }
3694 :
3695 : // Check signature
3696 0 : if (sign) {
3697 0 : u_int32_t signature = buf[(sign + 8)/4];
3698 0 : TOCPU1(signature);
3699 0 : if (signature != SIGNATURE) {
3700 0 : printf("%s pointer section not valid\n", pref);
3701 0 : return false;
3702 : }
3703 0 : offs = buf[sign/4];
3704 0 : TOCPU1(offs);
3705 : }
3706 :
3707 : // Get GUID ptr
3708 0 : *ind = buf[(offs+0x24)/4];
3709 0 : TOCPU1(*ind);
3710 0 : if (!IsFs2()) {
3711 0 : *ind += offs;
3712 : }
3713 0 : if (*ind >= (u_int32_t)buf_len) {
3714 0 : printf("%s image - illegal GUID pointer (%08x)\n", pref, *ind);
3715 0 : return false;
3716 : }
3717 0 : *nguids = buf[*ind/4 - 3];
3718 :
3719 0 : TOCPU1(*nguids);
3720 0 : *nguids /= 2;
3721 :
3722 : // More sanity check
3723 0 : if (IsFs2() ? (*nguids > MAX_GUIDS) : (*nguids > GUIDS)) {
3724 0 : printf("%s image - illegal number of GUIDs (0x%x)\n", pref, *nguids);
3725 0 : return false;
3726 : }
3727 :
3728 0 : return true;
3729 : } // extractGUIDptr
3730 :
3731 :
3732 :
3733 : ////////////////////////////////////////////////////////////////////////
3734 :
3735 : //
3736 : // This function calculates CRC over the geven buf/size, and stores
3737 : // the crc in the dwors after the data.
3738 : // Caller should make sure CRC word memory is really there.
3739 0 : void Operations::recalcSectionCrc(u_int8_t *buf, u_int32_t data_size) {
3740 0 : Crc16 crc;
3741 0 : u_int32_t i;
3742 :
3743 0 : for (i = 0; i < data_size; i += 4) {
3744 0 : crc << __be32_to_cpu(*(u_int32_t*)(buf + i));
3745 : }
3746 0 : crc.finish();
3747 0 : *(u_int32_t*)(buf + data_size) = __cpu_to_be32(crc.get());
3748 : }
3749 :
3750 : ////////////////////////////////////////////////////////////////////////
3751 : void Operations::patchGUIDsSection(u_int32_t *buf, u_int32_t ind,
3752 : guid_t guids[MAX_GUIDS], int nguids)
3753 0 : {
3754 0 : u_int32_t i;
3755 0 : u_int32_t new_buf[MAX_GUIDS*2];
3756 :
3757 : // Form new GUID section
3758 0 : for (i=0; i<(u_int32_t)nguids; i++) {
3759 0 : new_buf[i*2] = guids[i].h;
3760 0 : new_buf[i*2+1] = guids[i].l;
3761 : }
3762 :
3763 : // Patch GUIDs
3764 0 : for (i=0; i<sizeof(new_buf)/sizeof(u_int32_t); ++i) {
3765 0 : new_buf[i] = _burn_blank_guids ? 0xffffffff : __cpu_to_be32(new_buf[i]);
3766 : }
3767 0 : memcpy(&buf[ind/4], &new_buf[0], nguids * 2 * sizeof(u_int32_t));
3768 :
3769 : // Insert new CRC
3770 0 : if (_burn_blank_guids) {
3771 0 : buf[ind/4 + nguids*2] = __cpu_to_be32(0xffff);
3772 : } else {
3773 0 : recalcSectionCrc((u_int8_t*)buf + ind - sizeof(GPH), sizeof(GPH) + nguids * 8);
3774 : }
3775 : } // patchGUIDsSection
3776 :
3777 :
3778 :
3779 :
3780 : //
3781 : // PatchInfoSect() :
3782 : // This func assumes it gets a pointer (rawSect) to a valid info sect.
3783 : // It patches the it with the given data, recalculated CRC ,
3784 : // and copies it back to the geven data
3785 : //
3786 :
3787 : void Operations::PatchInfoSect(u_int8_t* rawSect,
3788 : u_int32_t vsdOffs,
3789 0 : const char* vsd) {
3790 :
3791 0 : u_int32_t vsdSize = __be32_to_cpu(*((u_int32_t*)(rawSect + sizeof(GPH) + vsdOffs - 4))) & 0xffffff;
3792 0 : u_int32_t infoSize = __be32_to_cpu(*((u_int32_t*)(rawSect + 4)));
3793 :
3794 : // byte size;
3795 0 : infoSize *= 4;
3796 :
3797 : //printf("-D- vsdOffs=%x, vsdSize=%x, infoSize=%x\n", vsdOffs,vsdSize, infoSize );
3798 0 : if (vsd) {
3799 0 : u_int32_t len = strlen(vsd);
3800 :
3801 0 : if (len > vsdSize) {
3802 0 : report("Warning: The given VSD length is too large (%d chars). Truncating to %d chars.\n", len, vsdSize);
3803 0 : len = vsdSize;
3804 : }
3805 :
3806 0 : memset(rawSect + sizeof(GPH) + vsdOffs, 0, vsdSize );
3807 0 : memcpy(rawSect + sizeof(GPH) + vsdOffs, vsd, len);
3808 : }
3809 :
3810 0 : recalcSectionCrc(rawSect, sizeof(GPH) + infoSize);
3811 : }
3812 :
3813 :
3814 : //
3815 : // PatchPs() :
3816 : // This func assumes it gets a pointer (rawPs) to a valid PS.
3817 : // It patches the PS with the given data, recalculated CRC ,
3818 : // and copies it back to the rawPs.
3819 : //
3820 :
3821 : void Operations::PatchPs(u_int8_t* rawPs,
3822 : const char* vsd,
3823 : const char* psid,
3824 0 : u_int32_t imageAddr) {
3825 :
3826 0 : PS *ps = (PS*)rawPs;
3827 :
3828 0 : u_int32_t fix_start = 0;
3829 0 : u_int32_t fix_end = 0;
3830 :
3831 0 : if (vsd) {
3832 0 : u_int32_t len = strlen(vsd);
3833 :
3834 0 : memset(&ps->vsd[0], 0, VSD_LEN );
3835 0 : memcpy(&ps->vsd[0], vsd, len);
3836 :
3837 0 : fix_end += VSD_LEN;
3838 : } else {
3839 0 : fix_start +=VSD_LEN;
3840 : }
3841 0 : if (psid) {
3842 0 : u_int32_t len = strlen(psid);
3843 :
3844 0 : memset(&ps->psid[0], 0, PSID_LEN );
3845 0 : memcpy(&ps->psid[0], psid, len );
3846 0 : fix_end += PSID_LEN;
3847 : }
3848 :
3849 : //VSD is kept on flash byte-swapped.
3850 : //recode it back before patching
3851 0 : u_int32_t *qp;
3852 :
3853 0 : qp = (u_int32_t *)&ps->vsd[0];
3854 0 : for (u_int32_t i=fix_start; i<fix_end/4; i++) {
3855 0 : *qp = bswap_32(*qp);
3856 0 : qp++;
3857 : }
3858 :
3859 0 : if (imageAddr) {
3860 0 : ps->fi_addr = __cpu_to_be32(imageAddr);
3861 : }
3862 :
3863 0 : recalcSectionCrc((u_int8_t *)ps, sizeof(PS) - 4);
3864 : }
3865 :
3866 :
3867 : ////////////////////////////////////////////////////////////////////////
3868 : //Note that vsd1 is a string of bytes.
3869 : bool Operations::patchVSD(FImage& f,
3870 : Operations::ImageInfo* info,
3871 : const char *user_vsd,
3872 : const char *user_psid,
3873 : const char *curr_vsd,
3874 : const char *curr_psid,
3875 : const char *image_psid)
3876 0 : {
3877 0 : const char* vsd_to_use = curr_vsd ? curr_vsd : "";
3878 0 : const char* psid_to_use = image_psid;
3879 :
3880 : // TODO: Should not give the user_psid param. Do not allow for on-the-fly PSID changes.
3881 :
3882 0 : curr_psid = NULL;
3883 : // Form new VSD
3884 :
3885 0 : if (user_psid) {
3886 : // New psid is explicitly given - take it from user
3887 0 : printf("\n You are about to replace current PSID in the image file - \"%s\" with a different PSID - \"%s\".\n"
3888 : " Note: It is highly recommended not to change the image PSID.\n", user_psid, image_psid);
3889 :
3890 0 : if (! ask_user())
3891 0 : return false;
3892 :
3893 0 : psid_to_use = user_psid;
3894 : }
3895 :
3896 0 : if (user_vsd) {
3897 0 : vsd_to_use = user_vsd;
3898 : }
3899 :
3900 0 : if (IsFs2() && info->infoOffs[II_VSD]) {
3901 0 : PatchInfoSect((u_int8_t*)f.getBuf() + info->infoSectPtr - sizeof(GPH),
3902 : info->infoOffs[II_VSD],
3903 : vsd_to_use);
3904 : } else {
3905 0 : PatchPs((u_int8_t*)f.getBuf() + f.get_sector_size(), vsd_to_use, psid_to_use);
3906 0 : PatchPs((u_int8_t*)f.getBuf() + f.get_sector_size() * 2, vsd_to_use, psid_to_use);
3907 : }
3908 :
3909 0 : return true;
3910 : } // pathVSD
3911 :
3912 :
3913 0 : bool Operations::PrintGUIDs(guid_t guids[MAX_GUIDS], guid_t old_guids[MAX_GUIDS], bool print_guids, bool print_macs, bool old_guid_fmt) {
3914 :
3915 0 : if (print_guids) {
3916 0 : printf(" Node GUID: ");
3917 0 : PrintGuidLine(guids,old_guids, 0);
3918 0 : if (_num_ports > 0) {
3919 0 : printf(" Port1 GUID: ");
3920 0 : PrintGuidLine(guids,old_guids, 1);
3921 : }
3922 0 : if (_num_ports > 1) {
3923 0 : printf(" Port2 GUID: ");
3924 0 : PrintGuidLine(guids,old_guids, 2);
3925 : }
3926 0 : if (!old_guid_fmt) {
3927 0 : printf(" Sys.Image GUID: ");
3928 0 : PrintGuidLine(guids,old_guids, 3);
3929 : }
3930 : }
3931 :
3932 0 : if (print_macs) {
3933 0 : printf(" Port1 MAC: ");
3934 0 : PrintMacLine(guids, old_guids, 4);
3935 0 : printf(" Port2 MAC: ");
3936 0 : PrintMacLine(guids, old_guids, 5);
3937 : }
3938 0 : return true;
3939 : }
3940 :
3941 4 : void Operations::initSectToRead(int imp_index) {
3942 56 : for (int i = 0; i < H_LAST; i++) {
3943 52 : if (imp_index == FULL_VERIFY || i == imp_index) {
3944 52 : _sections_to_read[i] = 1;
3945 : } else {
3946 0 : _sections_to_read[i] = 0;
3947 : }
3948 : }
3949 4 : if (imp_index == FULL_VERIFY) {
3950 4 : _is_full_verify = true;
3951 : } else {
3952 0 : _is_full_verify = false;
3953 : }
3954 4 : return;
3955 : }
3956 :
3957 0 : void Operations::SetDevFlags(u_int16_t devType, bool& ib_dev, bool& eth_dev) {
3958 :
3959 0 : if (IsIs4(devType)) {
3960 0 : ib_dev = true;
3961 0 : eth_dev = false;
3962 : } else {
3963 0 : ib_dev = !IsFs2() || CntxIsIb(devType);
3964 0 : eth_dev = IsFs2() && CntxIsEth(devType);
3965 : }
3966 :
3967 0 : if (!ib_dev && !eth_dev) {
3968 : // Unknown device id - for forward compat - assume that ConnectX is MP and
3969 : // prev HCAs are IB only (these flags are for printing only - no real harm can be done).
3970 : // TODO: FS2 does not mean ConnectX now.
3971 0 : ib_dev = true;
3972 0 : if (IsFs2()) {
3973 0 : eth_dev = true;
3974 : } else {
3975 0 : eth_dev = false;
3976 : }
3977 : }
3978 : }
3979 :
3980 : bool Operations::CheckGuidsFlags (u_int16_t devType,
3981 : bool guids_specified,
3982 : bool macs_specified,
3983 0 : bool uids_specified) {
3984 : // Patch GUIDS
3985 0 : if (guids_specified || macs_specified || uids_specified) {
3986 0 : if (IsBridgeX(devType)) {
3987 0 : if (macs_specified || guids_specified) {
3988 0 : return errmsg("-mac(s)/-guid(s) flags is not applicable for MT%d.", devType);
3989 : }
3990 : } else {
3991 0 : if (uids_specified) {
3992 0 : return errmsg("-uid(s) flag is applicable only for BridgeX.");
3993 0 : } else if (!IsFs2() && macs_specified ) {
3994 0 : return errmsg("-mac(s) flag is not applicable for IB MT%d device.",
3995 : devType);
3996 : }// else if (!ib_dev && guids_specified) {
3997 : // return errmsg("-guid(s) flag is not applicable for IB MT%d device.\n",
3998 : // devType);
3999 : //}
4000 : }
4001 : }
4002 0 : return true;
4003 : }
4004 : bool Operations::PrintGuidLine(guid_t* new_guids, guid_t* old_guids, int guid_index)
4005 0 : {
4006 0 : printf(GUID_FORMAT GUID_SPACES, new_guids[guid_index].h, new_guids[guid_index].l);
4007 0 : if (old_guids != NULL) {
4008 0 : printf(GUID_FORMAT, old_guids[guid_index].h, old_guids[guid_index].l);
4009 : }else {
4010 0 : printf(" N/A");
4011 : }
4012 0 : printf("\n");
4013 0 : return true;
4014 : }
4015 :
4016 : bool Operations::PrintBxGuids(guid_t* new_guids, guid_t* old_guids, int index, int num_of_guids, const char* pre_str)
4017 0 : {
4018 0 : int guid_index = index;
4019 0 : int _is_wwpn = ((guid_index - Operations::BI_WWPNS) % Operations::BX_SLICE_GUIDS);
4020 :
4021 0 : for (int i = 0; i < num_of_guids; i++) {
4022 0 : printf(" G%d", (index >= Operations::BX_SLICE_GUIDS));
4023 0 : if (i == 0 && _is_wwpn) {
4024 0 : printf(" Node %s: ", pre_str);
4025 : } else {
4026 0 : int j = _is_wwpn ? i : i + 1;
4027 0 : printf(" Port%d %s: ", j, pre_str);
4028 : }
4029 0 : PrintGuidLine(new_guids, old_guids, guid_index);
4030 0 : guid_index++;
4031 : }
4032 0 : return true;
4033 : }
4034 :
4035 : bool Operations::PrintMacLine(guid_t* new_guids, guid_t* old_guids, int mac_index)
4036 0 : {
4037 0 : printf(" "MAC_FORMAT MAC_SPACES, new_guids[mac_index].h, new_guids[mac_index].l);
4038 0 : if (old_guids != NULL) {
4039 0 : printf(MAC_FORMAT, old_guids[mac_index].h, old_guids[mac_index].l);
4040 : } else {
4041 0 : printf(" N/A");
4042 : }
4043 0 : printf("\n");
4044 0 : return true;
4045 : }
4046 :
4047 : bool Operations::PrintBxMacs(guid_t* new_guids, guid_t* old_guids, int index, int num_of_guids, const char* pre_str)
4048 0 : {
4049 0 : int guid_index = index;
4050 :
4051 0 : for (int i = 0; i < num_of_guids; i++) {
4052 0 : printf(" G%d", (index >= Operations::BX_SLICE_GUIDS));
4053 0 : printf(" Port%d %s: ", i + 1, pre_str);
4054 0 : PrintMacLine(new_guids, old_guids, guid_index);
4055 0 : guid_index++;
4056 : }
4057 0 : return true;
4058 : }
4059 :
4060 : bool Operations::PrintUids(guid_t* new_guids, guid_t* old_guids)
4061 0 : {
4062 0 : int base_index = 0, guid_index;
4063 :
4064 0 : for (int i = 0; i < BX_SLICES_NUM; i++) {
4065 0 : base_index = i * BX_SLICE_GUIDS;
4066 : // Init Guids
4067 0 : PrintBxGuids(new_guids, old_guids, base_index + BI_GUIDS, BX_NP_GUIDS, "Guid");
4068 0 : PrintBxMacs (new_guids, old_guids, base_index + BI_IMACS, BX_IMACS, "IMAC");
4069 0 : PrintBxMacs (new_guids, old_guids, base_index + BI_EMACS, BX_EMACS, "EMAC");
4070 0 : PrintBxGuids(new_guids, old_guids, base_index + BI_WWNNS, BX_WWNNS, "WWNN");
4071 0 : PrintBxGuids(new_guids, old_guids, base_index + BI_WWPNS, BX_WWPNS, "WWPN");
4072 : }
4073 :
4074 : // Init SysGuid
4075 : //INCR_GUID(base_guid1, user_guids[Operations::BI_SYS_GUID], 7);
4076 0 : guid_index = Operations::BI_SYS_GUID;
4077 0 : printf(" System GUID: ");
4078 0 : PrintGuidLine(new_guids, old_guids, guid_index);
4079 0 : return true;
4080 : }
4081 :
4082 : bool Operations::reportGuidChaneges(ImageInfo* info, guid_t new_guids[MAX_GUIDS], guid_t old_guids[MAX_GUIDS],
4083 : bool print_guids, bool print_macs, bool print_uids)
4084 0 : {
4085 :
4086 0 : printf(" You are about to change the Guids/Macs/Uids on the device:\n");
4087 0 : printf(" New Values " GUID_SPACES "Current Values\n");
4088 0 : if (print_uids) {
4089 0 : PrintUids(new_guids, old_guids );
4090 : } else {
4091 0 : PrintGUIDs(new_guids,
4092 : old_guids,
4093 : print_guids,
4094 : print_macs,
4095 : info->guidNum < Operations::GUIDS);
4096 : }
4097 0 : if (!ask_user())
4098 0 : return false;
4099 :
4100 0 : return true;
4101 : }
4102 :
4103 :
4104 :
4105 : ////////////////////////////////////////////////////////////////////////
4106 : bool Operations::patchGUIDs (FImage& f,
4107 : ImageInfo* info,
4108 : bool patch_macs,
4109 : bool patch_uids,
4110 : bool user_guids,
4111 : bool user_macs,
4112 : bool user_uids,
4113 : guid_t new_guids[MAX_GUIDS],
4114 : guid_t old_guids[MAX_GUIDS],
4115 : u_int32_t num_of_old_guids)
4116 0 : {
4117 0 : guid_t* used_guids = old_guids ? old_guids : new_guids;
4118 0 : u_int32_t *buf = f.getBuf();
4119 0 : int i;
4120 0 : bool old_guids_fmt = info->guidNum < GUIDS;
4121 :
4122 : // Print old GUIDs and get confirmation
4123 0 : if (new_guids) {
4124 0 : if (old_guids_fmt)
4125 0 : printf(" Old image!!!! Only %d GUIDs may be set.\n", info->guidNum);
4126 : // if only guids or only macs are specified by user, keep the other
4127 : // as currently set of flash. This is in order to simplify transitions between
4128 : // burning IB and ETH FW.
4129 0 : if (!patch_uids) {
4130 0 : if (old_guids && !user_guids) {
4131 0 : for (i = 0; i < GUIDS; i++) {
4132 0 : new_guids[i] = old_guids[i];
4133 : }
4134 : }
4135 :
4136 0 : if (old_guids && !user_macs) {
4137 0 : for (i = GUIDS; i < MAX_GUIDS; i++) {
4138 0 : new_guids[i] = old_guids[i];
4139 : }
4140 : }
4141 : }
4142 0 : used_guids = new_guids;
4143 : }
4144 :
4145 :
4146 0 : if (!patch_uids) {
4147 0 : if (patch_macs) {
4148 :
4149 : // To ease upgrade from 4 GUIDS format to 4+2 format, or to move from IB to ETH,
4150 : // if macs are not
4151 : // explicitly set in flash, they are derived from the GUIDs according to
4152 : // Mellanox methodology - 48 bit MAC == 64 bit GUID without the middle 16 bits.
4153 :
4154 0 : if (old_guids && ((num_of_old_guids == 4) ||
4155 : (num_of_old_guids == 6 &&
4156 : (old_guids[GUIDS ].h & 0xffff) == 0xffff &&
4157 : (old_guids[GUIDS ].l & 0xffffffff) == 0xffffffff &&
4158 : (old_guids[GUIDS+1].h & 0xffff) == 0xffff &&
4159 : (old_guids[GUIDS+1].l & 0xffffffff) == 0xffffffff))) {
4160 0 : for (i = 0 ; i < MACS; i++) {
4161 0 : u_int64_t mac = old_guids[i+1].h >> 8;
4162 0 : mac <<= 24;
4163 0 : mac |= (old_guids[i+1].l & 0xffffff);
4164 :
4165 0 : old_guids[GUIDS+i].h = u_int32_t(mac >> 32);
4166 0 : old_guids[GUIDS+i].l = u_int32_t(mac & 0xffffffff);
4167 :
4168 : // 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 );
4169 : }
4170 : }
4171 :
4172 0 : guid_t* macs = &used_guids[4];
4173 0 : int i;
4174 :
4175 0 : for (i = 0 ; i < Operations::MACS ; i++) {
4176 0 : u_int64_t mac = (((u_int64_t)macs[i].h) << 32) | macs[i].l;
4177 0 : if (!_burn_blank_guids && !CheckMac(mac)) {
4178 0 : report_err(_err_msg, "Bad mac (" MAC_FORMAT ") %s: %s. Please re-burn with a valid -mac flag value.\n",
4179 : macs[i].h,
4180 : macs[i].l,
4181 : user_macs ? "given" : "found on flash",
4182 : err());
4183 0 : return false;
4184 : }
4185 :
4186 : }
4187 : }
4188 : } else {
4189 0 : if (!_burn_blank_guids) {
4190 0 : for (i = 0; i < BX_SLICES_NUM; i++ ) {
4191 0 : if (ReportBxMacsWarnings(used_guids, i, 0, user_uids) == false) {
4192 0 : return false;
4193 : }
4194 : }
4195 :
4196 : }
4197 : }
4198 : // Path GUIDs section
4199 0 : if (info->guidPtr) {
4200 0 : patchGUIDsSection(buf, info->imgStart + info->guidPtr, used_guids, info->guidNum);
4201 :
4202 0 : if (info->allImgStart[1]) {
4203 : // For no ConnectX HCAs, patch also the secondary image (if found). This is applicable
4204 : // only for nofs burn, where both images are burnt as is.
4205 0 : patchGUIDsSection(buf, info->allImgStart[1] + info->guidPtr, used_guids, info->guidNum);
4206 : }
4207 : }
4208 :
4209 0 : return true;
4210 : } // patchGUIDs
4211 :
4212 :
4213 : ////////////////////////////////////////////////////////////////////////
4214 : // //
4215 : // ****************************************************************** //
4216 : // Revision info and board ID //
4217 : // ****************************************************************** //
4218 : // //
4219 : ////////////////////////////////////////////////////////////////////////
4220 :
4221 : bool Operations::QueryIs (FBase& f,
4222 0 : Operations::ImageInfo* info) {
4223 0 : u_int32_t signature;
4224 :
4225 0 : READ4(f, 0x24, &signature, "Signature");
4226 0 : TOCPU1(signature);
4227 0 : if (signature == SIGNATURE) {
4228 : // Full image
4229 0 : info->isFailsafe = true;
4230 :
4231 : // FW ID
4232 0 : u_int32_t fw_id;
4233 :
4234 0 : READ4(f, 0x10, &fw_id, "FW ID");
4235 0 : TOCPU1(fw_id);
4236 :
4237 0 : info->isVer = ( fw_id >> 8) && 0xff;
4238 0 : info->devRev = fw_id >> 24;
4239 :
4240 : } else {
4241 0 : info->isFailsafe = false;
4242 0 : info->imgStart = 0;
4243 : }
4244 :
4245 0 : info->invSectOk = true;
4246 0 : return true;
4247 : }
4248 :
4249 : bool Operations::QueryPs (FBase& f,
4250 0 : Operations::ImageInfo* info) {
4251 :
4252 0 : if (!info->isFailsafe) {
4253 0 : return errmsg("Internal Error: Tried to query PS when image is not failsafe");
4254 : }
4255 :
4256 0 : u_int32_t prim_ptr, scnd_ptr;
4257 0 : u_int32_t sectSize = f.get_sector_size();
4258 :
4259 0 : bool currSielent = _silent;
4260 0 : _silent = true;
4261 :
4262 0 : if (checkPS(f, sectSize, prim_ptr, "Primary ")) {
4263 0 : info->allImgStart[0] = prim_ptr;
4264 0 : info->imgStart = prim_ptr;
4265 0 : info->psStart = sectSize;
4266 : }
4267 0 : if (checkPS(f, sectSize * 2, scnd_ptr, "Secondary")) {
4268 0 : info->allImgStart[1] = scnd_ptr;
4269 0 : if (info->allImgStart[0] == 0) {
4270 0 : info->imgStart = scnd_ptr;
4271 0 : info->psStart = sectSize * 2;
4272 : }
4273 : }
4274 :
4275 0 : if (info->allImgStart[0] == 0 && info->allImgStart[1] == 0) {
4276 0 : return errmsg("No valid image found.");
4277 : }
4278 :
4279 0 : char vsd[VSD_LEN+PSID_LEN+1]; // +1 => Leave a space for \0 when psid size == 16 .
4280 :
4281 0 : memset(vsd, 0, sizeof(vsd));
4282 0 : READBUF(f, info->psStart + 0x20, vsd, VSD_LEN+PSID_LEN , "Vendor Specific Data (Board ID)");
4283 0 : u_int32_t* vsd_dwp = (u_int32_t*)vsd;
4284 :
4285 0 : for (u_int32_t i=0; i < sizeof(vsd)/sizeof(u_int32_t); i++)
4286 0 : vsd_dwp[i] = bswap_32(vsd_dwp[i]);
4287 :
4288 0 : memcpy(info->vsd, vsd, VSD_LEN);
4289 0 : memcpy(info->psid, vsd + VSD_LEN, PSID_LEN);
4290 :
4291 0 : info->vsd [sizeof(info->vsd) - 1] = '\0';
4292 0 : info->psid[sizeof(info->psid) - 1] = '\0';
4293 :
4294 0 : _silent = currSielent;
4295 :
4296 0 : info->psOk = true;
4297 :
4298 0 : return true;
4299 : }
4300 :
4301 :
4302 : bool Operations::QueryImage (FBase& f,
4303 0 : Operations::ImageInfo* info) {
4304 :
4305 0 : u_int32_t guid_ptr, nguids;
4306 0 : guid_t guids[MAX_GUIDS];
4307 :
4308 : // FW ID
4309 0 : u_int32_t fw_id;
4310 0 : u_int32_t fw_id_offs;
4311 0 : u_int32_t fw_size;
4312 0 : u_int32_t im_start = info->imgStart;
4313 :
4314 0 : if (IsFs2()) {
4315 0 : if (info->isFailsafe && info->actuallyFailsafe) {
4316 0 : f.set_address_convertor(info->cntxLog2ChunkSize, im_start != 0);
4317 : } else {
4318 0 : f.set_address_convertor(0,0);
4319 : }
4320 :
4321 0 : im_start = 0; // offset is done by address convertor
4322 0 : info->magicPatternFound = true;
4323 0 : fw_id_offs = 0x20;
4324 : } else {
4325 0 : info->magicPatternFound = false;
4326 0 : fw_id_offs = 0x10;
4327 : }
4328 :
4329 0 : READ4(f, im_start + fw_id_offs, &fw_id, "FW ID");
4330 0 : TOCPU1(fw_id);
4331 :
4332 0 : READ4(f, im_start + fw_id_offs + 0x10, &fw_size, "FW SIZE");
4333 0 : TOCPU1(fw_size);
4334 0 : info->imageSize = fw_size;
4335 :
4336 0 : info->devRev = fw_id >> 24;
4337 : // Read GUIDs
4338 0 : READ4(f, im_start + fw_id_offs + 0x14 , &guid_ptr, "GUID PTR");
4339 0 : TOCPU1(guid_ptr);
4340 0 : info->guidPtr = guid_ptr;
4341 :
4342 0 : guid_ptr += im_start;
4343 0 : if (guid_ptr >= f.get_size()) {
4344 0 : return errmsg("Failed to read GUIDs - Illegal GUID pointer (%08x). Probably image is corrupted", guid_ptr);
4345 : }
4346 0 : READ4(f, guid_ptr - 3*sizeof(u_int32_t), &nguids, "Number of GUIDs");
4347 0 : TOCPU1(nguids);
4348 0 : nguids /= 2;
4349 0 : if (nguids > MAX_GUIDS) {
4350 0 : return errmsg("Failed to read GUIDs - Illegal Number of GUIDs (%d)", nguids);
4351 : //return false;
4352 : }
4353 0 : READBUF(f, guid_ptr, guids, nguids * sizeof(u_int64_t), "GUIDS");
4354 0 : TOCPUBY64(guids);
4355 :
4356 0 : u_int32_t guids_crc;
4357 0 : READ4(f, guid_ptr + nguids * sizeof(u_int64_t), &guids_crc, "GUIDS CRC");
4358 0 : guids_crc = __be32_to_cpu(guids_crc);
4359 :
4360 0 : info->blankGuids = true;
4361 0 : if ((guids_crc & 0xffff) != 0xffff ) {
4362 0 : info->blankGuids = false;
4363 : }
4364 :
4365 0 : info->guidNum = nguids;
4366 0 : for (u_int32_t i = 0 ; i < nguids ; i++) {
4367 0 : info->guids[i] = guids[i];
4368 0 : if (guids[i].h != 0xffffffff || guids[i].l != 0xffffffff) {
4369 0 : info->blankGuids = false;
4370 : }
4371 : }
4372 : // Expansion Rom version:
4373 0 : if (info->_rom_sect.empty()) {
4374 0 : info->expRomFound = false;
4375 : } else {
4376 0 : info->expRomFound = true;
4377 0 : if (!GetExpRomVersion(info)) {
4378 0 : report_warn("Failed to get ROM Version: %s\n\n", err());
4379 0 : info->expRomValidVersion = false;
4380 : }
4381 : }
4382 :
4383 : // Read Info:
4384 0 : u_int32_ba info_ptr_ba;
4385 0 : u_int32_t info_ptr;
4386 0 : u_int32_t info_size;
4387 0 : u_int8_t info_ptr_cs = 0;
4388 0 : READ4(f, im_start + fw_id_offs + 0xC, &info_ptr, "INFO PTR");
4389 0 : TOCPU1(info_ptr);
4390 :
4391 : // Verify info_ptr checksum (should be 0)
4392 0 : info_ptr_ba = info_ptr;
4393 0 : for (u_int32_t i = 0; i < 4 ; i++) {
4394 0 : info_ptr_cs += (u_int8_t)info_ptr_ba.range(i*8+7, i*8);
4395 : }
4396 :
4397 0 : if (info_ptr_cs) {
4398 0 : return errmsg("Failed to read Info Section - Bad checksum for Info section pointer (%08x). Probably the image is corrupted.", info_ptr);
4399 : }
4400 :
4401 0 : info_ptr = info_ptr_ba.range(23,0);
4402 0 : if (info_ptr_cs == 0 && info_ptr != 0) {
4403 0 : info->infoSectPtr = info_ptr;
4404 :
4405 0 : info_ptr += im_start;
4406 0 : if (info_ptr >= f.get_size()) {
4407 0 : return errmsg("Failed to read Info Section - Info section pointer (%08x) too large. Probably the image is corrupted.", info_ptr);
4408 : }
4409 0 : READ4(f, info_ptr - 3*sizeof(u_int32_t), &info_size, "Info section size");
4410 0 : TOCPU1(info_size);
4411 :
4412 : // byte size;
4413 0 : info_size *= 4;
4414 :
4415 0 : u_int8_t* info_buff = (u_int8_t*)alloca(info_size);
4416 0 : READBUF(f, info_ptr, info_buff, info_size, "Info Section");
4417 :
4418 0 : if (!ParseInfoSect(info_buff, info_size, info)) {
4419 0 : return false;
4420 : }
4421 : }
4422 :
4423 0 : info->imageOk = true;
4424 0 : return true;
4425 : }
4426 :
4427 :
4428 0 : bool Operations::ParseInfoSect(u_int8_t* buff, u_int32_t byteSize, Operations::ImageInfo *info) {
4429 :
4430 0 : u_int32_t *p = (u_int32_t*)buff;
4431 0 : u_int32_t offs = 0;
4432 0 : u_int32_t tagNum = 0;
4433 0 : bool endFound = false;
4434 :
4435 : // TODO: Add new flag on the info which indicates that the ParseInfoSect was already called.
4436 :
4437 0 : while (!endFound && offs < byteSize) {
4438 0 : u_int32_t tagSize = __be32_to_cpu(*p) & 0xffffff;
4439 0 : u_int32_t tagId = __be32_to_cpu(*p) >> 24;
4440 :
4441 0 : if (offs + tagSize > byteSize) {
4442 0 : return errmsg("Info section corrupted: Tag %d (TagId %d, size %d) exceeds Info section size (%d bytes) ",
4443 : tagNum, tagId, tagSize, byteSize);
4444 : }
4445 :
4446 0 : u_int32_t tmp;
4447 0 : const char* str;
4448 :
4449 0 : switch (tagId) {
4450 : case II_FwVersion:
4451 0 : info->fwVer[0] = u_int16_t(__be32_to_cpu(*(p+1)) >> 16);
4452 0 : tmp = __be32_to_cpu(*(p+2));
4453 0 : info->fwVer[1] = tmp >> 16;
4454 0 : info->fwVer[2] = tmp & 0xffff;
4455 0 : break;
4456 :
4457 : case II_DeviceType:
4458 0 : tmp = __be32_to_cpu(*(p+1));
4459 0 : info->devType = tmp & 0xffff;
4460 : //info->devRev = (tmp >> 16) & 0xff;
4461 0 : break;
4462 :
4463 : case II_VsdVendorId:
4464 0 : tmp = __be32_to_cpu(*(p+1));
4465 0 : info->vsdVendorId = tmp & 0xffff;
4466 0 : break;
4467 :
4468 : case II_IsGa:
4469 0 : tmp = __be32_to_cpu(*(p+1));
4470 0 : info->isGa = tmp ? true : false;;
4471 0 : break;
4472 :
4473 : case II_PSID:
4474 : // set psid only if not previosly found in PS
4475 0 : if (!info->psOk) {
4476 0 : str = (const char*)p;
4477 0 : str += 4;
4478 :
4479 0 : for (int i = 0 ; i < PSID_LEN ; i++) {
4480 0 : info->psid[i] = str[i];
4481 : }
4482 0 : info->psid[PSID_LEN] = '\0';
4483 : }
4484 0 : break;
4485 :
4486 : case II_VSD:
4487 : // set psid only if not previosly found in PS
4488 0 : if (!info->psOk) {
4489 0 : str = (const char*)p;
4490 0 : str += 4;
4491 :
4492 0 : for (int i = 0 ; i < VSD_LEN ; i++) {
4493 0 : info->vsd[i] = str[i];
4494 : }
4495 0 : info->vsd[VSD_LEN] = '\0';
4496 : }
4497 0 : break;
4498 :
4499 : case II_ProductVer:
4500 :
4501 0 : str = (const char*)p;
4502 0 : str += 4;
4503 :
4504 0 : for (int i = 0 ; i < PRODUCT_VER_LEN ; i++) {
4505 0 : info->productVer[i] = str[i];
4506 : }
4507 0 : info->productVer[PRODUCT_VER_LEN] = '\0';
4508 0 : break;
4509 : case II_HwDevsId:
4510 0 : u_int32_t i;
4511 0 : for (i = 1; i <= (tagSize / 4); i++) {
4512 0 : info->supportedHwId[i - 1] = __be32_to_cpu(*(p + i));
4513 : }
4514 0 : info->supportedHwIdNum = tagSize / 4;
4515 0 : break;
4516 :
4517 :
4518 : case II_End:
4519 0 : endFound = true;
4520 0 : break;
4521 :
4522 : //default:
4523 : //printf("-D- Found tag ID %d of size %d - ignoring.\n", tagId, tagSize);
4524 : }
4525 :
4526 0 : if (tagId < II_Last) {
4527 0 : info->infoOffs[tagId] = offs + 4;
4528 : }
4529 :
4530 0 : p += tagSize/4 + 1;
4531 0 : offs += tagSize + 4;
4532 0 : tagNum++;
4533 : }
4534 :
4535 0 : if (offs != byteSize) {
4536 0 : if (endFound) {
4537 0 : return errmsg("Info section corrupted: Section data size is 0x%x bytes, "
4538 : "but end tag found after 0x%x bytes.", byteSize, offs);
4539 : } else {
4540 0 : return errmsg("Info section corrupted: Section data size is 0x%x bytes, "
4541 : "but end tag not found before section end.", byteSize);
4542 : }
4543 : }
4544 :
4545 0 : return true;
4546 : }
4547 :
4548 : bool Operations::GetExpRomStrVer(Operations::ImageInfo* info, char* version)
4549 0 : {
4550 0 : if (info->expRomProductId >= 0x10) {
4551 0 : sprintf(version, "%d.%d.%d", info->expRomVer[0], info->expRomVer[1], info->expRomVer[2]);
4552 : } else {
4553 0 : sprintf(version, "%d", info->expRomVer[0]);
4554 : }
4555 0 : return true;
4556 : }
4557 :
4558 0 : bool Operations::DisplayExpRomInfo(Operations::ImageInfo* info, bool print_pre) {
4559 0 : if (print_pre) {
4560 0 : report("Rom Info: ");
4561 : }
4562 0 : if (info->expRomValidVersion) {
4563 0 : if (info->expRomProductId == 0xf) {
4564 0 : report("devid=%d version_id=%s", info->expRomDevId, info->expRomFreestr);
4565 : } else {
4566 0 : report("type=");
4567 0 : switch (info->expRomProductId) {
4568 0 : case 1 : report("CLP1 "); break;
4569 0 : case 2 : report("CLP2 "); break;
4570 0 : case 3 : report("CLP3 "); break;
4571 0 : case 4 : report("CLP4 "); break;
4572 0 : case 0x10: report("GPXE "); break;
4573 0 : default: report("0x%x ", info->expRomProductId);
4574 : }
4575 :
4576 0 : report("version=%d", info->expRomVer[0]);
4577 0 : if (info->expRomProductId >= 0x10) {
4578 0 : report(".%d.%d devid=%d",
4579 : info->expRomVer[1],
4580 : info->expRomVer[2],
4581 : info->expRomDevId);
4582 :
4583 0 : if (info->expRomPort) {
4584 : // Do not display if 0 - port independant
4585 0 : report(" port=%d", info->expRomPort);
4586 : }
4587 :
4588 0 : report(" proto=");
4589 0 : switch (info->expRomProto) {
4590 0 : case ER_IB: report("IB"); break;
4591 0 : case ER_ETH: report("ETH"); break;
4592 0 : case ER_VPI: report("VPI"); break;
4593 0 : default: report("0x%x", info->expRomProto);
4594 : }
4595 : }
4596 : }
4597 0 : report("\n");
4598 : } else {
4599 0 : report("N/A\n");
4600 : }
4601 0 : return true;
4602 : }
4603 :
4604 :
4605 :
4606 : bool Operations::ReportBxGuidsQuery(guid_t* guids, int base1, int guids_num, int index, const char* pre_str)
4607 0 : {
4608 0 : int i, first_index, base, wwnns_index;
4609 :
4610 0 : report("G%d %-14s", index, pre_str);
4611 0 : first_index = index * BX_SLICE_GUIDS;
4612 0 : if (base1 == BI_WWPNS) {
4613 0 : wwnns_index = first_index + (BX_SLICE_GUIDS - 1);
4614 0 : report(GUID_FORMAT " ", guids[wwnns_index].h, guids[wwnns_index].l);
4615 : }
4616 0 : base = first_index + base1;
4617 0 : for (i = base; i < base + guids_num; i++) {
4618 0 : int j = i;
4619 : // HACK
4620 0 : if (i == BI_GUIDS + BX_SLICE_GUIDS) {
4621 : // We display the same node guid on the two slices.
4622 0 : j = BI_GUIDS;
4623 : }
4624 0 : report(GUID_FORMAT " ", guids[j].h, guids[j].l);
4625 : }
4626 0 : printf("\n");
4627 0 : return true;
4628 : }
4629 :
4630 :
4631 : #define PRINT_WARNING "PRINT_WARNING"
4632 :
4633 : bool Operations::ReportBxMacsQuery(guid_t* guids, int base1, int guids_num, int index, const char* pre_str)
4634 0 : {
4635 0 : int i, base;
4636 :
4637 0 : base = index * Operations::BX_SLICE_GUIDS + base1;
4638 0 : report("G%d %-30s", index, pre_str);
4639 0 : for (i = base; i < base + guids_num; i++) {
4640 0 : report(" " MAC_FORMAT , guids[i].h, guids[i].l);
4641 : }
4642 0 : printf("\n");
4643 0 : return true;
4644 : }
4645 :
4646 : bool Operations::ReportBxMacsWarnings(guid_t* guids, int index, int warning, int user_uids)
4647 0 : {
4648 0 : int i, base;
4649 0 : int is_first = 1;
4650 0 : base = index * BX_SLICE_GUIDS + BI_IMACS;
4651 0 : for (i = base; i < base + BX_MACS; i++) {
4652 0 : u_int64_t mac = (((u_int64_t)guids[i].h) << 32) | guids[i].l;
4653 0 : if (!CheckMac(mac)) {
4654 0 : if (warning) {
4655 0 : if (is_first) {
4656 0 : printf("\n\n");
4657 0 : is_first = 0;
4658 : }
4659 0 : printf("Warning: Bad mac address (" MAC_FORMAT "): %s\n", guids[i].h, guids[i].l, err());
4660 : } else {
4661 0 : report_err(_err_msg, "Bad mac (" MAC_FORMAT ") %s: %s. Please re-burn with a valid MACs value.\n",
4662 : guids[i].h,
4663 : guids[i].l,
4664 : user_uids ? "given" : "found on flash",
4665 : err());
4666 0 : return false;
4667 : }
4668 : }
4669 : }
4670 0 : return true;
4671 : }
4672 :
4673 :
4674 0 : bool Operations::DisplayImageInfo(Operations::ImageInfo* info) {
4675 0 : report("Image type: %s\n", info->magicPatternFound ? (CntxIsEth(info->devType) ? "ConnectX" : "FS2") :
4676 : info->isFailsafe ? "Failsafe" :
4677 : "Short");
4678 :
4679 0 : if (info->infoOffs[II_FwVersion]) {
4680 0 : report("FW Version: %d.%d.%d\n", info->fwVer[0], info->fwVer[1], info->fwVer[2]);
4681 : }
4682 : // TODO: Print the mic version and hw devi Ids
4683 : //if (info->infoOffs[II_MicVersion]) {
4684 : // report("MIC Version: Existent\n");
4685 : //}
4686 :
4687 :
4688 :
4689 0 : if (info->infoOffs[II_ProductVer] && strlen(info->productVer)) {
4690 0 : report("Product Version: %s\n", info->productVer);
4691 : }
4692 :
4693 0 : if (info->expRomFound) {
4694 0 : DisplayExpRomInfo(info);
4695 : }
4696 :
4697 0 : if (info->isFailsafe && !IsFs2()) {
4698 0 : report("I.S. Version: %d\n", info->isVer );
4699 : }
4700 :
4701 0 : if (info->infoOffs[II_DeviceType]) {
4702 0 : report("Device ID: %d\n", info->devType);
4703 0 : if (info->devType == 25204 || info->devType == 24204) {
4704 0 : _num_ports = 1;
4705 0 : } else if (IsIs4(info->devType)) {
4706 0 : _num_ports = 0;
4707 : }
4708 : }
4709 :
4710 0 : report("Chip Revision: %X\n", info->devRev);
4711 :
4712 : // GUIDS:
4713 : // TODO: Handle case where devtype not found.
4714 0 : bool ib_dev;
4715 0 : bool eth_dev;
4716 0 : SetDevFlags(info->devType, ib_dev, eth_dev);
4717 :
4718 0 : const char* mac_indent = "";
4719 : //if (info->devType == ) {
4720 : //}
4721 0 : if (IsBridgeX(info->devType)) {
4722 0 : int i, base;
4723 0 : if (info->guidNum != BX_ALL_GUIDS) {
4724 0 : report_err(_err_msg, "Number of UIDs on BridgeX should be %d\n", BX_ALL_GUIDS);
4725 0 : return false;
4726 : }
4727 0 : report("Description: Node Port1 Port2 Port3 Port4\n");
4728 0 : for (i = 0; i < BX_SLICES_NUM; i++) {
4729 0 : base = i * BX_SLICE_GUIDS;
4730 0 : ReportBxGuidsQuery(info->guids, BI_GUIDS, BX_NP_GUIDS, i, "GUIDs:");
4731 0 : ReportBxMacsQuery(info->guids, BI_IMACS, BX_IMACS, i, "IMACs:");
4732 0 : ReportBxMacsQuery(info->guids, BI_EMACS, BX_EMACS, i, "EMACs:");
4733 0 : ReportBxGuidsQuery(info->guids, BI_WWPNS, BX_WWPNS, i, "WWNs: ");
4734 : }
4735 0 : report("SYS GUID: " GUID_FORMAT " ", info->guids[info->guidNum - 1].h, info->guids[info->guidNum - 1].l);
4736 0 : if (!info->blankGuids) {
4737 0 : for (i = 0; i < BX_SLICES_NUM; i++) {
4738 0 : ReportBxMacsWarnings(info->guids, i, 1, 0);
4739 : }
4740 : }
4741 : } else {
4742 0 : if (ib_dev) {
4743 : //report("GUID Des: Node Port1 ");
4744 0 : report("Description: Node ");
4745 0 : if (_num_ports > 0)
4746 0 : report("Port1 ");
4747 0 : if (_num_ports > 1)
4748 0 : report("Port2 ");
4749 0 : report( "Sys image\n");
4750 :
4751 0 : report("GUIDs: ");
4752 0 : for (u_int32_t i=0; i < GUIDS; i++) {
4753 0 : if ((i == 1 && _num_ports < 1) ||
4754 : (i == 2 && _num_ports < 2)) {
4755 0 : continue;
4756 : }
4757 0 : report(GUID_FORMAT " ", info->guids[i].h, info->guids[i].l);
4758 : }
4759 0 : mac_indent = " ";
4760 : }
4761 :
4762 : // MACS:
4763 0 : if (eth_dev) {
4764 0 : if (info->guidNum == 6) {
4765 0 : if (!ib_dev)
4766 0 : report("Description:%s Port1 Port2\n", mac_indent);
4767 : else
4768 0 : printf("\n");
4769 :
4770 0 : report("MACs: %s ", mac_indent);
4771 0 : for (u_int32_t i=GUIDS; i < 6; i++) {
4772 0 : report(" " MAC_FORMAT , info->guids[i].h, info->guids[i].l);
4773 : }
4774 :
4775 0 : for (u_int32_t i=GUIDS; i < 6; i++) {
4776 0 : u_int64_t mac = (((u_int64_t)info->guids[i].h) << 32) | info->guids[i].l;
4777 0 : if (!info->blankGuids && !CheckMac(mac)) {
4778 0 : if (i==GUIDS) printf("\n\n");
4779 0 : printf("Warning: Bad mac address (" MAC_FORMAT "): %s\n", info->guids[i].h, info->guids[i].l, err());
4780 : }
4781 : }
4782 : } else {
4783 0 : report_warn("Can not get MAC address: Expecting %d entries in guid section, got %d. Probably an old FW image. Please update.\n",
4784 : 6,
4785 : info->guidNum);
4786 : }
4787 : }
4788 :
4789 : }
4790 :
4791 :
4792 : // VSD, PSID
4793 0 : if (!info->infoOffs[II_VsdVendorId] || info->vsdVendorId == MELLANOX_VENDOR_ID) {
4794 0 : report("\nBoard ID: %s", info->vsd);
4795 0 : if (info->psid[0])
4796 0 : report(" (%s)\n", info->psid);
4797 : else
4798 0 : report("\n");
4799 :
4800 0 : report("VSD: %s\n", info->vsd);
4801 0 : report("PSID: %s\n", info->psid);
4802 : } else {
4803 0 : report_warn("Not a Mellanox FW image (vendor_id = 0x%04x). VSD and PSID are not displayed.\n", info->vsdVendorId);
4804 : }
4805 :
4806 0 : if (info->infoOffs[II_IsGa]) {
4807 0 : if (!info->isGa) {
4808 0 : report("BOARD GA: no\n");
4809 : }
4810 : }
4811 :
4812 0 : if (info->blankGuids) {
4813 0 : report_warn("GUIDs%s values and their CRC are not set.\n",
4814 : IsFs2() ? "/MACs" : ""); // TODO: IsConnectX?
4815 : }
4816 0 : return true;
4817 : }
4818 :
4819 : ////////////////////////////////////////////////////////////////////////
4820 : // //
4821 : // ****************************************************************** //
4822 : // MAIN //
4823 : // ****************************************************************** //
4824 : // //
4825 : ////////////////////////////////////////////////////////////////////////
4826 : // sed -e 's/"/\\"/g' < flint.txt | perl -pe 's/^(.*)$/"$1\\n"/'
4827 : void usage(const char *sname, bool full = false)
4828 4 : {
4829 4 : const char *descr =
4830 : "\n"
4831 : " FLINT - FLash INTerface\n"
4832 : "\n"
4833 : "FW (firmware) burning and flash memory operations tool for\n"
4834 : "Mellanox Infiniband HCAs and Ethernet NIC cards.\n"
4835 : "\n"
4836 : "Usage:\n"
4837 : "------\n"
4838 : "\n"
4839 : " " FLINT_NAME " [switches...] <command> [parameters...]\n"
4840 : "\n"
4841 : "\n"
4842 : "Switches summary:\n"
4843 : "-----------------\n"
4844 : // " -bsn <BSN> - Mellanox Board Serial Number (BSN).\n"
4845 : // " Valid BSN format is:\n"
4846 : // " MTxxxxx[-]R[xx]ddmmyy-nnn[-cc]\n"
4847 : // " Commands affected: burn\n"
4848 : // "\n"
4849 : // " -crc - Print out each section CRC.\n"
4850 : // " Commands affected: verify\n"
4851 : "\n"
4852 : " -d[evice] <device> - Device flash is connected to.\n"
4853 : " Commands affected: all\n"
4854 : "\n"
4855 : " -guid <GUID> - GUID base value. 4 GUIDs\n"
4856 : " are automatically assigned to the\n"
4857 : " following values:\n"
4858 : "\n"
4859 : " guid -> node GUID\n"
4860 : " guid+1 -> port1\n"
4861 : " guid+2 -> port2\n"
4862 : " guid+3 -> system image GUID.\n"
4863 : "\n"
4864 : " Note: port2 guid will be assigned even for a\n"
4865 : " single port HCA - The HCA ignores this value.\n"
4866 : "\n"
4867 : " Commands affected: burn, sg\n"
4868 : "\n"
4869 : " -guids <GUIDs...> - 4 GUIDs must be specified here.\n"
4870 : " The specified GUIDs are assigned\n"
4871 : " to the following fields, repectively:\n"
4872 : " node, port1, port2 and system image GUID.\n"
4873 : "\n"
4874 : " Note: port2 guid must be specified even for a\n"
4875 : " single port HCA - The HCA ignores this value.\n"
4876 : " It can be set to 0x0.\n"
4877 : "\n"
4878 : " Commands affected: burn, sg\n"
4879 : "\n"
4880 :
4881 : " -mac <MAC> - MAC address base value. 2 MACs\n"
4882 : " are automatically assigned to the\n"
4883 : " following values:\n"
4884 : "\n"
4885 : " mac -> port1\n"
4886 : " mac+1 -> port2\n"
4887 : "\n"
4888 : " Commands affected: burn, sg\n"
4889 : "\n"
4890 : " -macs <MACs...> - 2 MACs must be specified here.\n"
4891 : " The specified MACs are assigned\n"
4892 : " to port1, port2, repectively.\n"
4893 : " Commands affected: burn, sg\n"
4894 : " Note: -mac/-macs flags are applicable only for Mellanox\n"
4895 : " Technologies ethernet products.\n"
4896 : "\n"
4897 : " -uid <UID> - BridgeX only. Derive and set the device UIDs (GUIDs, MACs, WWNs).\n"
4898 : " UIDs are derived from the given base UID according to Mellanox Methodology\n"
4899 : " Commands affected: burn, sg\n"
4900 : "\n"
4901 : " -uids <UIDs...> - BridgeX only. 29 space separated UIDs must be specified here.\n"
4902 : " The specified UIDs are assigned to the following fields, repectively:\n"
4903 : " G0-MAC-PI0 G0-MAC-PI1 G0-MAC-PI2\n"
4904 : " G0-MAC-PE0 G0-MAC-PE1 G0-MAC-PE2 G0-MAC-PE3\n"
4905 : " G0-FC-WWPN-P0 G0-FC-WWPN-P1 G0-FC-WWPN-P2 G0-FC-WWPN-P3\n"
4906 : " G0-IB-NODE-GUID G0-IB-PORT-GUID G0-FC-WWNN\n"
4907 : " G1-MAC-PI0 G1-MAC-PI1 G1-MAC-PI2\n"
4908 : " G1-MAC-PE0 G1-MAC-PE1 G1-MAC-PE2 G1-MAC-PE3\n"
4909 : " G1-FC-WWPN-P0 G1-FC-WWPN-P1 G1-FC-WWPN-P2 G1-FC-WWPN-P3\n"
4910 : " G1-IB-NODE-GUID G1-IB-PORT-GUID G1-FC-WWNN\n"
4911 : " IB-SYSTEM-GUID\n"
4912 : " Commands affected: burn, sg\n"
4913 : "\n"
4914 : " -blank_guids - Burn the image with blank GUIDs and MACs (where\n"
4915 : " applicable). These values can be set later using\n"
4916 : " the \"sg\" command (see details below).\n"
4917 : "\n"
4918 : " Commands affected: burn\n"
4919 : "\n"
4920 : " -clear_semaphore - Force clear the flash semaphore on the device.\n"
4921 : " No command is allowed when this flag is used.\n"
4922 : " NOTE: May result in system instability or flash\n"
4923 : " corruption if the device or another\n"
4924 : " application is currently using the flash.\n"
4925 : " Exercise caution.\n"
4926 : "\n"
4927 : " -h[elp] - Prints this message and exits\n"
4928 : " -hh - Prints extended command help\n"
4929 : "\n"
4930 : " -i[mage] <image> - Binary image file.\n"
4931 : " Commands affected: burn, verify\n"
4932 : "\n"
4933 : " -qq - Run a quick query. When specified, flint will not perform full\n"
4934 : " image integrity checks during the query operation. This may shorten\n"
4935 : " execution time when running over slow interfaces (e.g., I2C, MTUSB-1).\n"
4936 : " Commands affected: burn, query\n"
4937 : "\n"
4938 : " -nofs - Burn image in a non failsafe manner.\n"
4939 : "\n"
4940 : " -allow_psid_change - Allow burning a FW image with a different PSID (Parameter Set ID)than the\n"
4941 : " one currently on flash. Note that changing a PSID may cause the device to\n"
4942 : " malfunction. Use only if you know what you are doing\n"
4943 : "\n"
4944 : " -skip_is - Allow burning the FW image without updating the invariant sector,\n"
4945 : " to ensure failsafe burning even when an invariant sector difference is detected.\n"
4946 : " See the specific FW release notes for more details.\n"
4947 : "\n"
4948 : " -byte_mode - Shift address when accessing flash internal registers. May\n"
4949 : " be required for burn/write commands when accessing certain\n"
4950 : " flash types.\n"
4951 : "\n"
4952 : " -no_flash_verify - Do not verify each write on the flash.\n"
4953 : "\n"
4954 : #if 0
4955 : " -unlock - Use unlock bypass feature of the flash for quicker burn.\n"
4956 : " Commands affected: burn\n"
4957 : "\n"
4958 : #endif
4959 : " -s[ilent] - Do not print burn progress flyer.\n"
4960 : " Commands affected: burn\n"
4961 : "\n"
4962 : " -y[es] - Non interactive mode - assume answer\n"
4963 : " \"yes\" to all questions.\n"
4964 : " Commands affected: all\n"
4965 : "\n"
4966 : " -no - Non interactive mode - assume answer\n"
4967 : " \"no\" to all questions.\n"
4968 : " Commands affected: all\n"
4969 : "\n"
4970 : " -vsd <string> - Write this string, of up to 208 characters, to VSD when burn.\n"
4971 : "\n"
4972 : " -use_image_ps - Burn vsd as appears in the given image - do not keep existing VSD on flash.\n"
4973 : " Commands affected: burn\n"
4974 : "\n"
4975 : " -use_image_guids - Burn (guids/uids/macs) as appears in the given image.\n"
4976 : " Commands affected: burn\n"
4977 : "\n"
4978 : "\n"
4979 : " -use_image_rom - Do not save the ROM which exists in the device.\n"
4980 : " Commands affected: burn\n"
4981 : "\n"
4982 : " -dual_image - Make the burn process burn two images on flash (previously default algorithm). Current\n"
4983 : " default failsafe burn process burns a single image (in alternating locations).\n"
4984 : " Commands affected: burn\n"
4985 : "\n"
4986 : " -banks <banks>\n"
4987 : " - Set the number of attached flash devices (banks)\n"
4988 : "\n"
4989 : " -log <log_file>\n"
4990 : " - Print the burning status to the specified log file\n"
4991 : "\n"
4992 : " -v - Version info.\n"
4993 : "\n"
4994 : "Commands summary (use -hh flag for full commands description):\n"
4995 : "-----------------\n"
4996 : " b[urn] - Burn flash\n"
4997 : " q[uery] - Query misc. flash/firmware characteristics\n"
4998 : " v[erify] - Verify entire flash\n"
4999 : " bb - Burn Block - Burns the given image as is. \n"
5000 : " No checks are done.\n"
5001 : " sg [nocrc] - Set Guids\n"
5002 : " ri <out-file> - Read the fw image on the flash.\n"
5003 : " dc [out-file] - Dump Configuration: print fw configuration file\n"
5004 : " for the given image.\n"
5005 : " dh [out-file] - Dump Hash: print hash file\n"
5006 : " for the given image.\n"
5007 : " e[rase] <addr> - Erase sector\n"
5008 : " rw <addr> - Read one dword from flash\n"
5009 : " ww <addr> < data> \n"
5010 : " - Write one dword to flash\n"
5011 : " wwne <addr> - Write one dword to flash without sector erase\n"
5012 : " wbne <addr> <size> <data ...> \n"
5013 : " - Write a data block to flash without sector erase\n"
5014 : " rb <addr> <size> [out-file]\n"
5015 : " - Read a data block from flash\n"
5016 : " swreset - SW reset the target InfniScale IV device. This command\n"
5017 : " is supported only in the In-Band access method.\n"
5018 : " brom <ROM-file> - Burn the specified ROM file on the flash.\n"
5019 : " rrom <out-file> - Read the ROM section from the flash.\n"
5020 : " drom - Remove the ROM section from the flash.\n"
5021 : "\n"
5022 : " Return values:\n"
5023 : " 0 - Successful completion\n"
5024 : " 1 - An error has occurred\n"
5025 : " 7 - For burn command - FW already updated - burn was aborted.\n"
5026 4 : "\n";
5027 :
5028 4 : const char* full_descr =
5029 : "\n"
5030 : "Command descriptions:\n"
5031 : "----------------------------\n"
5032 : "\n"
5033 : "* Burn flash\n"
5034 : " Burns entire flash from raw binary image.\n"
5035 : "\n"
5036 : " Command:\n"
5037 : " b[urn]\n"
5038 : " Parameters:\n"
5039 : " None\n"
5040 : " Examples:\n"
5041 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " -i image1.bin burn\n"
5042 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE2 " -guid 0x2c9000100d050 -i image1.bin b\n"
5043 : "\n"
5044 : "\n"
5045 : "* Burn Block\n"
5046 : " Burns entire flash from raw binary image as is. No checks are done on the flash or\n"
5047 : " on the given image file. No fields (such as VSD or Guids) are read from flash. \n"
5048 : "\n"
5049 : " Command:\n"
5050 : " bb\n"
5051 : " Parameters:\n"
5052 : " None\n"
5053 : " Examples:\n"
5054 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " -i image1.bin bb\n"
5055 : "\n"
5056 : "\n"
5057 : "* sg\n"
5058 : " Set GUIDs/MACs in the given device.\n"
5059 : " Use -guid(s) and -mac(s) flags to set the desired values.\n"
5060 : " This command is applicable only for images with blank (0xff)\n"
5061 : " GUIDs/MACs values and crc, I.E., that were burnt or generated\n"
5062 : " using -blank_guids flag.\n"
5063 : " The sg command is used in production to apply GUIDs/MACs values\n"
5064 : " to cards that were pre-burnt with blank guids. It is not meant for\n"
5065 : " use in field\n"
5066 : "\n"
5067 : " Command:\n"
5068 : " sg\n"
5069 :
5070 : " Parameters:\n"
5071 : " nocrc: (optional) When specified the flint would not update\n"
5072 : " the full image crc after changing the guids\n"
5073 : " Examples:\n"
5074 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " -guid 0x0002c9000100d050 sg\n"
5075 : "\n"
5076 : "\n"
5077 : "* Erase sector.\n"
5078 : " Erases a sector that contains specified address.\n"
5079 : "\n"
5080 : " Command:\n"
5081 : " e[rase]\n"
5082 : " Parameters:\n"
5083 : " addr - address of word in sector that you want\n"
5084 : " to erase.\n"
5085 : " Example:\n"
5086 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " erase 0x10000\n"
5087 : "\n"
5088 : "\n"
5089 : "* Query miscellaneous FW and flash parameters\n"
5090 : "\n"
5091 : " Command:\n"
5092 : " q[uery]\n"
5093 : " Parameters:\n"
5094 : " None\n"
5095 : " Example:\n"
5096 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " query\n"
5097 : "\n"
5098 : "\n"
5099 : "* Query flash device parameters (Common Flash Interface)\n"
5100 : "\n"
5101 : " Command:\n"
5102 : " cfi\n"
5103 : " Parameters:\n"
5104 : " None\n"
5105 : " Example:\n"
5106 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " cfi\n"
5107 : "\n"
5108 : "\n"
5109 : "* Read one dword from flash.\n"
5110 : "\n"
5111 : " Command:\n"
5112 : " rw\n"
5113 : " Parameters:\n"
5114 : " addr - address of word to read\n"
5115 : " Example:\n"
5116 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rw 0x20\n"
5117 : "\n"
5118 : "\n"
5119 : "* Verify entire flash.\n"
5120 : "\n"
5121 : " Command:\n"
5122 : " v[erify]\n"
5123 : " Parameters:\n"
5124 : " None\n"
5125 : " Example:\n"
5126 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " v\n"
5127 : "\n"
5128 : "\n"
5129 : "* Write one dword to flash.\n"
5130 : " Note that the utility will read an entire flash sector,\n"
5131 : " modify one word and write the sector back. This may take\n"
5132 : " a few seconds.\n"
5133 : "\n"
5134 : " Command:\n"
5135 : " ww\n"
5136 : " Parameters:\n"
5137 : " addr - address of word\n"
5138 : " data - value of word\n"
5139 : " Example:\n"
5140 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " ww 0x10008 0x5a445a44\n"
5141 : "\n"
5142 : "\n"
5143 : "* Write one dword to flash without sector erase.\n"
5144 : " Note that the result of operation is undefined and depends\n"
5145 : " on flash type. Usually \"bitwise AND\" (&) between specified\n"
5146 : " word and previous flash contents will be written to\n"
5147 : " specified address.\n"
5148 : "\n"
5149 : " Command:\n"
5150 : " wwne\n"
5151 : " Parameters:\n"
5152 : " addr - address of word\n"
5153 : " data - value of word\n"
5154 : " Example:\n"
5155 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " wwne 0x10008 0x5a445a44\n"
5156 : "\n"
5157 : "* Read a data block from the flash and write it to a file or to screen.\n"
5158 : "\n"
5159 : " Command:\n"
5160 : " rb\n"
5161 : " Parameters:\n"
5162 : " addr - address of block\n"
5163 : " size - size of data to read in bytes\n"
5164 : " file - filename to write the block (raw binary). If not given, the data\n"
5165 : " is printed to screen\n"
5166 : " Example:\n"
5167 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rb 0x10000 100 file.bin\n"
5168 : "\n"
5169 : "* Read the FW image from flash and write it to a file.\n"
5170 : "\n"
5171 : " Command:\n"
5172 : " ri\n"
5173 : " Parameters:\n"
5174 : " file - filename to write the image to (raw binary).\n"
5175 : " Example:\n"
5176 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " ri file.bin\n"
5177 : "\n"
5178 : "* Write a block of data to the flash without erasing.\n"
5179 : "\n"
5180 : " Command:\n"
5181 : " wbne\n"
5182 : " Parameters:\n"
5183 : " addr - address of block\n"
5184 : " size - size of data to write in bytes\n"
5185 : " data - data to write - space seperated dwords\n"
5186 : " Example:\n"
5187 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " wbne 0x10000 12 0x30000 0x76800 0x5a445a44\n"
5188 : "\n"
5189 : "* Print (to screen or to a file) the FW configuration text file used by the image generation process.\n"
5190 : " This command would fail if the image does not contain a FW configuration section. Existence of this\n"
5191 : " section depends on the version of the image generation tool.\n"
5192 : "\n"
5193 : " Command:\n"
5194 : " dc\n"
5195 : " Parameters:\n"
5196 : " file - (optional) filename to write the dumped configuration to. If not given, the data\n"
5197 : " is printed to screen\n"
5198 : " Example:\n"
5199 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " dc\n"
5200 : "\n"
5201 : "* Print (to screen or to a file) the HASH text file used by the FW.\n"
5202 : " This command would fail if the image does not contain a Hash file.\n"
5203 : "\n"
5204 : " Command:\n"
5205 : " dh\n"
5206 : " Parameters:\n"
5207 : " file - (optional) filename to write the dumped hash to. If not given, the data\n"
5208 : " is printed to screen\n"
5209 : " Example:\n"
5210 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " dh\n"
5211 : "\n"
5212 : "* Burn the specified exp-ROM on the flash.\n"
5213 : "\n"
5214 : " Command:\n"
5215 : " brom\n"
5216 : " Parameters:\n"
5217 : " file - The exp-ROM file.\n"
5218 : " Example:\n"
5219 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " brom exp-rom.rom\n"
5220 : "\n"
5221 : "* Remove the exp-ROM from the flash if it is existing.\n"
5222 : "\n"
5223 :
5224 : " Command:\n"
5225 : " drom\n"
5226 : " Example:\n"
5227 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " drom\n"
5228 : "\n"
5229 : "* Read the exp-ROM from the flash if it is existing.\n"
5230 : "\n"
5231 : " Command:\n"
5232 : " rrom\n"
5233 : " file - filename to write the exp-ROM to.\n"
5234 :
5235 : " Example:\n"
5236 : " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rrom exp-rom.rom\n"
5237 4 : "\n";
5238 :
5239 4 : printf(descr, sname);
5240 :
5241 4 : if (full) {
5242 0 : printf(full_descr, sname);
5243 : }
5244 : }
5245 :
5246 : // The Log file writing implementation
5247 :
5248 : FILE* f_log_fh = NULL;
5249 : #define BURN_INTERRUPTED 0x1234
5250 :
5251 :
5252 : void close_log()
5253 4 : {
5254 4 : if (f_log_fh != NULL) {
5255 0 : fclose(f_log_fh);
5256 : }
5257 4 : return;
5258 : }
5259 :
5260 : #define ARR_SIZE(arr) sizeof(arr)/sizeof(arr[0])
5261 :
5262 0 : const char* month_2monstr (int month) {
5263 : static const char* month_2monstr_arr[] = {
5264 : "Jan",
5265 : "Feb",
5266 : "Mar",
5267 : "Apr",
5268 : "May",
5269 : "Jun",
5270 : "Jul",
5271 : "Aug",
5272 : "Sep",
5273 : "Oct",
5274 : "Nov",
5275 : "Dec",
5276 0 : };
5277 0 : int arr_size = (int)ARR_SIZE(month_2monstr_arr);
5278 0 : return month < arr_size ? month_2monstr_arr[month] : "???";
5279 : }
5280 :
5281 :
5282 : void print_time_to_log()
5283 0 : {
5284 0 : time_t rawtime;
5285 0 : struct tm * timeinfo;
5286 :
5287 0 : if (f_log_fh == NULL) {
5288 0 : return;
5289 : }
5290 :
5291 0 : time ( &rawtime );
5292 0 : timeinfo = localtime ( &rawtime );
5293 :
5294 0 : fprintf(f_log_fh, "%-3s %2d %02d:%02d:%02d ", month_2monstr(timeinfo->tm_mon), timeinfo->tm_mday,
5295 : timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
5296 0 : return;
5297 : }
5298 :
5299 : int print_line_to_log(const char* format, ...)
5300 4 : {
5301 4 : va_list args;
5302 :
5303 4 : if (f_log_fh == NULL) {
5304 0 : return 0;
5305 : }
5306 0 : print_time_to_log();
5307 0 : va_start(args, format);
5308 0 : vfprintf(f_log_fh, format, args);
5309 4 : va_end(args);
5310 :
5311 4 : return 0;
5312 : }
5313 :
5314 : int write_cmd_to_log(char* av[], int ac, CommandType cmd)
5315 0 : {
5316 0 : int i;
5317 0 : char pre_str[50];
5318 0 : if (f_log_fh == NULL) {
5319 0 : return 0;
5320 : }
5321 0 : if (cmd == CMD_BURN_ROM) {
5322 0 : sprintf(pre_str, "ROM");
5323 : } else {
5324 0 : sprintf(pre_str, "FW");
5325 : }
5326 0 : print_time_to_log();
5327 0 : fprintf(f_log_fh, "Start %s burning: ", pre_str);
5328 0 : for (i = 0; i < ac; i++) {
5329 0 : fprintf(f_log_fh, "%s ", av[i]);
5330 : }
5331 0 : fprintf(f_log_fh, "\n");
5332 :
5333 0 : return 0;
5334 : }
5335 :
5336 : int write_result_to_log(int is_failed, const char* err_msg)
5337 4 : {
5338 4 : char msg[MAX_ERR_STR_LEN];
5339 :
5340 4 : strcpy(msg, err_msg);
5341 4 : if (is_failed == 0) {
5342 0 : print_line_to_log("Burn completed successfully\n");
5343 4 : } else if (is_failed == BURN_INTERRUPTED) {
5344 0 : print_line_to_log("Burn interrupted by user\n");
5345 : } else {
5346 4 : int msg_len = strlen(msg);
5347 : // cleanup the msg
5348 8 : for (int i = 0; i < msg_len; i++) {
5349 4 : if (msg[i] == '\n') {
5350 0 : if (i == msg_len - 1) {
5351 0 : msg[i] = '\0';
5352 : } else {
5353 0 : msg[i] = ' ';
5354 : }
5355 : }
5356 : }
5357 4 : print_line_to_log("Burn failed: %s\n", msg);
5358 : }
5359 4 : return 0;
5360 : }
5361 :
5362 :
5363 :
5364 : //
5365 : // Signal handlers
5366 : //
5367 :
5368 : Flash* g_flash = NULL;
5369 :
5370 : #ifdef _WIN32
5371 :
5372 : HANDLE main_thread;
5373 :
5374 : #define GET_MAIN_THREAD() {\
5375 : int rc = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(),\
5376 : &main_thread, 0, FALSE, DUPLICATE_SAME_ACCESS);\
5377 : if (rc == 0) {\
5378 : main_thread = NULL;\
5379 : }\
5380 : }
5381 :
5382 : #define CHECK_WIN_SIGNAL() {\
5383 : if (main_thread == NULL) {\
5384 : report_warn("An internal error occurred. This program can not be interrupted.\n");\
5385 : signal(signum, TerminationHandler);\
5386 : return;\
5387 : }\
5388 : }
5389 :
5390 : #define SUSPEND_MAIN_THREAD() {\
5391 : SuspendThread(main_thread);\
5392 : }
5393 :
5394 : #else
5395 :
5396 : #define GET_MAIN_THREAD()
5397 : #define WIN_TERM_THREAD()
5398 : #define CHECK_WIN_SIGNAL()
5399 : #define SUSPEND_MAIN_THREAD()
5400 : #endif
5401 :
5402 :
5403 :
5404 :
5405 : int g_signals_for_termination[] = {
5406 : SIGINT,
5407 : #ifndef _WIN32
5408 : SIGHUP,
5409 : #endif
5410 : SIGTERM
5411 : };
5412 :
5413 :
5414 :
5415 : void TerminationHandler (int signum)
5416 0 : {
5417 0 : static volatile sig_atomic_t fatal_error_in_progress = 0;
5418 :
5419 : CHECK_WIN_SIGNAL();
5420 0 : if (fatal_error_in_progress)
5421 0 : raise (signum);
5422 0 : fatal_error_in_progress = 1;
5423 :
5424 0 : signal (signum, SIG_DFL);
5425 :
5426 0 : write_result_to_log(BURN_INTERRUPTED, "");
5427 0 : close_log();
5428 0 : if (g_flash != NULL) {
5429 0 : report("\n Received signal %d. Cleaning up ...", signum);
5430 0 : fflush(stdout);
5431 : SUSPEND_MAIN_THREAD();
5432 0 : sleep(1); // let erase sector end
5433 : //g_flash->wait_ready("Process termination");
5434 :
5435 0 : g_flash->close();
5436 0 : report(" Done.\n");
5437 : }
5438 0 : raise(signum);
5439 : }
5440 :
5441 : int get_num_of_banks(char* env, int* num_of_banks)
5442 0 : {
5443 0 : char* endp;
5444 :
5445 0 : *num_of_banks = strtoul(env, &endp, 0);
5446 0 : if (*endp != '\0' || (*num_of_banks < 1 || *num_of_banks > 4)) {
5447 0 : return 1;
5448 : }
5449 0 : return 0;
5450 : }
5451 :
5452 :
5453 : bool Operations::CheckCommandInputs(const char* dev,
5454 : const char* img,
5455 0 : CommandType cmd) {
5456 :
5457 0 : const CommandInfo* cmdInfo = GetCommandInfo(cmd);
5458 :
5459 0 : if (!cmdInfo) {
5460 0 : report_err(_err_msg, "Internal error: Unknown command given to CheckCommandInputs() (%d)\n", cmd);
5461 0 : return false;
5462 : }
5463 :
5464 0 : const char* inputDesStr [] = {
5465 : NULL,
5466 : "neither a device nor an image file", // CI_NONE
5467 : "an image file", // CI_IMG_ONLY,
5468 : NULL,
5469 : "a device", // CI_DEV_ONLY,
5470 : NULL,
5471 : "either an image file or a device", // CI_IMG_OR_DEV,
5472 : NULL,
5473 : "both an image file and a device" // CI_IMG_AND_DEV
5474 0 : };
5475 :
5476 0 : CommandInput given;
5477 :
5478 0 : if ( dev && img) {
5479 0 : given = CI_IMG_AND_DEV;
5480 0 : } else if (!dev && img) {
5481 0 : given = CI_IMG_ONLY;
5482 0 : } else if (dev && !img) {
5483 0 : given = CI_DEV_ONLY;
5484 : } else {
5485 0 : given = CI_NONE;
5486 : }
5487 :
5488 0 : if ((given & cmdInfo->requiredInput) == 0) {
5489 0 : report_err(_err_msg, "Command \"%s\" requires %s to be specified",
5490 : cmdInfo->cmdName,
5491 : inputDesStr[cmdInfo->requiredInput]);
5492 :
5493 0 : if (given != CI_NONE) {
5494 0 : printf(", but %s %s given.\n",
5495 : inputDesStr[given],
5496 : given == CI_IMG_AND_DEV ? "are" : "is");
5497 : } else {
5498 0 : printf(".\n");
5499 : }
5500 :
5501 0 : return false;
5502 : }
5503 :
5504 0 : return true;
5505 : }
5506 :
5507 0 : bool Operations::CheckMaxCmdArguments(CommandType cmd, int numArgs) {
5508 0 : const CommandInfo* cmdInfo = GetCommandInfo(cmd);
5509 0 : if (!cmdInfo) {
5510 0 : report_err(_err_msg, "Internal error: Unknown command given to CheckMaxCmdArguments (%d)\n", cmd);
5511 0 : return false;
5512 : }
5513 :
5514 0 : if (cmdInfo->maxArgs >= 0 && numArgs > cmdInfo->maxArgs) {
5515 0 : report_err(_err_msg, "Command \"%s\" requires %d arguments, but %d arguments were given\n",
5516 : cmdInfo->cmdName,
5517 : cmdInfo->maxArgs,
5518 : numArgs);
5519 0 : return false;
5520 : }
5521 0 : return true;
5522 : }
5523 :
5524 : #define INCR_GUID(base_guid, user_guid, incr_val) { \
5525 : u_int64_t g = base_guid.h; \
5526 : g = (g << 32) | base_guid.l; \
5527 : g += incr_val; \
5528 : user_guid.h = (u_int32_t)(g >> 32); \
5529 : user_guid.l = (u_int32_t)g; \
5530 : }
5531 :
5532 : guid_t GetBaseMac(guid_t base_guid)
5533 0 : {
5534 0 : guid_t base_mac;
5535 0 : base_mac.l = (base_guid.l & 0x00ffffff) | ((base_guid.h & 0xff00) << 16);
5536 0 : base_mac.h = base_guid.h >> 16;
5537 0 : return base_mac;
5538 : }
5539 :
5540 0 : bool InitBxGuids(guid_t* user_guids, guid_t base_guid1) {
5541 :
5542 0 : int base_index = 0;
5543 0 : guid_t base_mac, base_guid;
5544 :
5545 0 : for (int i = 0; i < Operations::BX_SLICES_NUM; i++) {
5546 0 : base_index = i * Operations::BX_SLICE_GUIDS;
5547 0 : INCR_GUID(base_guid1, base_guid, i * 8);
5548 : // Init Guids
5549 0 : int base_guids_index = base_index + Operations::BI_GUIDS;
5550 :
5551 0 : for (int j = 0; j < Operations::BX_NP_GUIDS; j++) {
5552 0 : if (j == 0) {
5553 : // The node guid should be the same one on the two slices.
5554 0 : INCR_GUID(base_guid1, user_guids[base_guids_index + j], j);
5555 : } else {
5556 0 : INCR_GUID(base_guid, user_guids[base_guids_index + j], j);
5557 : }
5558 :
5559 : }
5560 : // Init Macs
5561 0 : base_mac = GetBaseMac(base_guid);
5562 0 : int base_macs_index = base_index + Operations::BI_IMACS;
5563 0 : for (int j = 0; j < Operations::BX_MACS; j++) {
5564 0 : INCR_GUID(base_mac, user_guids[base_macs_index + j], j);
5565 : }
5566 : // Init WWPNSs
5567 0 : int base_wwpn_index = base_index + Operations::BI_WWPNS;
5568 0 : int base_emac_index = base_index + Operations::BI_EMACS;
5569 :
5570 0 : for (int j = 0; j < Operations::BX_WWPNS; j++) {
5571 0 : user_guids[base_wwpn_index + j].l = user_guids[base_emac_index + j].l;
5572 0 : user_guids[base_wwpn_index + j].h = (user_guids[base_emac_index + j].h | (0x2000 << 16));
5573 : }
5574 :
5575 : // Init WWNNS
5576 0 : int base_wwnn_index = base_index + Operations::BI_WWNNS;
5577 0 : base_emac_index = base_index + Operations::BI_EMACS;
5578 :
5579 0 : user_guids[base_wwnn_index].l = user_guids[base_emac_index].l;
5580 0 : user_guids[base_wwnn_index].h = (user_guids[base_emac_index].h | (0x2001 << 16));
5581 : }
5582 :
5583 : // Init SysGuid
5584 0 : INCR_GUID(base_guid1, user_guids[Operations::BI_SYS_GUID], 7);
5585 0 : return true;
5586 : }
5587 : bool Operations::PrintMissGuidErr(bool ib_dev, bool eth_dev, bool bx_dev)
5588 0 : {
5589 0 : const char* missing_info;
5590 0 : const char* missing_flags;
5591 :
5592 0 : if (bx_dev) {
5593 0 : missing_info = "UIDs (GUIDs / MACs / WWNs)";
5594 0 : missing_flags = "-uid(s)";
5595 : } else {
5596 0 : if (ib_dev && eth_dev) {
5597 0 : missing_info = "GUIDs / MACs";
5598 0 : missing_flags = "-guid(s) / -mac(s)";
5599 0 : } else if (ib_dev) {
5600 0 : missing_info = "GUIDs";
5601 0 : missing_flags = "-guid(s)";
5602 : } else {
5603 0 : missing_info = "MACs";
5604 0 : missing_flags = "-mac(s)";
5605 : }
5606 :
5607 : }
5608 0 : return errmsg("Please specify %s (using command line flags %s ).", missing_info, missing_flags);
5609 : }
5610 :
5611 : #define CRC_SECT_SIZE 4
5612 : #define TOTAL_SEC_SIZE(data_size) (data_size + sizeof(GPH) + CRC_SECT_SIZE)
5613 :
5614 : bool Operations::CopyData(u_int8_t* &new_image, u_int8_t* &old_image, int copy_size)
5615 0 : {
5616 0 : memcpy(new_image, old_image, copy_size);
5617 :
5618 0 : new_image += copy_size;
5619 0 : old_image += copy_size;
5620 :
5621 0 : return true;
5622 : }
5623 : #define READ_DW(dw, data) {\
5624 : dw = (*((u_int32_t*)(data)));\
5625 : TOCPU1(dw);\
5626 : }
5627 :
5628 : bool Operations::CopyBoot2(u_int8_t* &new_image_p, u_int8_t* &old_image_p)
5629 0 : {
5630 0 : u_int32_t size;
5631 0 : READ_DW(size, old_image_p + 4);
5632 0 : size = (size + 4) * 4;
5633 0 : CopyData(new_image_p, old_image_p, size);
5634 0 : return true;
5635 : }
5636 :
5637 : bool Operations::AddNewSect(u_int8_t* &new_image_p, u_int8_t* data, GPH gph, u_int32_t* last_next)
5638 0 : {
5639 :
5640 0 : int size = gph.size * 4 ;
5641 :
5642 0 : *last_next = gph.next + sizeof(GPH);
5643 :
5644 0 : CPUTOBY(gph);
5645 :
5646 : // Copy the GPH
5647 0 : memcpy(new_image_p, (u_int8_t*)&gph, sizeof(GPH));
5648 :
5649 : // Copy the data
5650 0 : memcpy(new_image_p + sizeof(GPH), data, size);
5651 :
5652 : // Calc the CRC and copy it
5653 0 : recalcSectionCrc(new_image_p, sizeof(GPH) + size);
5654 :
5655 0 : new_image_p = new_image_p + TOTAL_SEC_SIZE(size);
5656 0 : return true;
5657 : }
5658 :
5659 :
5660 : #define GUID_PTR_OFF 0x34
5661 : #define IMAGE_INFO_PTR 0x2c
5662 : #define IMAGE_SIZE_OFF 0x30
5663 : #define IMAGE_ROM_INDEX 2
5664 :
5665 : #define COPY_DW(dest, dword) {\
5666 : CPUTO1(dword);\
5667 : memcpy(dest, &dword, 4);\
5668 : }
5669 : #define MAJOR_MOD_ROM_FW 2
5670 : #define MINOR_MOD_ROM_FW 6
5671 : #define SUBMINOR_MOD_ROM_FW 1410
5672 :
5673 : bool Operations::IsFwSupportingRomModify(u_int16_t fw_ver[3])
5674 0 : {
5675 0 : u_int16_t supported_fw[3] = {MAJOR_MOD_ROM_FW, MINOR_MOD_ROM_FW, SUBMINOR_MOD_ROM_FW};
5676 0 : return !FwVerLessThan(fw_ver, supported_fw);
5677 : }
5678 : u_int32_t Operations::CalcImageCRC(u_int32_t* buff, u_int32_t size)
5679 0 : {
5680 0 : Crc16 crc;
5681 0 : TOCPUn(buff, size);
5682 0 : CRCn(crc, buff, size);
5683 0 : CPUTOn(buff, size);
5684 0 : crc.finish();
5685 0 : u_int32_t new_crc = crc.get();
5686 0 : return new_crc;
5687 : }
5688 :
5689 : bool Operations::UpdateFullImageCRC(u_int32_t* buff, u_int32_t size, bool blank_guids)
5690 0 : {
5691 : // Writing 0xffff on the CRC field.
5692 0 : u_int32_ba crc_dw = TOCPU1(buff[IMG_CRC_OFF / 4]);
5693 0 : crc_dw.range(15, 0) = 0xffff;
5694 :
5695 :
5696 0 : buff[IMG_CRC_OFF / 4] = CPUTO1(crc_dw);
5697 :
5698 0 : if (blank_guids) {
5699 0 : return true;
5700 : }
5701 :
5702 : // Calc CRC image.
5703 0 : u_int32_t new_crc = CalcImageCRC(buff, size);
5704 :
5705 : // Update the CRC.
5706 0 : TOCPU1(crc_dw);
5707 0 : crc_dw.range(15, 0) = new_crc;
5708 0 : buff[IMG_CRC_OFF / 4] = CPUTO1(crc_dw);
5709 :
5710 0 : return true;
5711 : }
5712 :
5713 : // UpdateRomInImage: it will insert the rom if it receive rom data,
5714 : // otherwise it will remove the rom if it is existing.
5715 : bool Operations::UpdateRomInImage(u_int8_t* new_image, u_int8_t* old_image, u_int8_t* rom_data, int rom_size,
5716 : int* new_image_size)
5717 0 : {
5718 0 : GPH gph;
5719 0 : u_int32_t header;
5720 0 : u_int32_t next_ptr, last_next;
5721 :
5722 0 : u_int8_t *new_image_p, *old_image_p;
5723 0 : new_image_p = new_image;
5724 0 : old_image_p = old_image;
5725 :
5726 : // Copy first section
5727 0 : CopyData(new_image_p, old_image_p, FS2_BOOT_START);
5728 :
5729 : //// Read BOOT2
5730 0 : CopyBoot2(new_image_p, old_image_p);
5731 :
5732 0 : READ_DW(header, old_image_p);
5733 :
5734 0 : if (header < H_FIRST || header >= H_LAST) {
5735 0 : CopyBoot2(new_image_p, old_image_p);
5736 : }
5737 0 : next_ptr = old_image_p - old_image;
5738 :
5739 0 : last_next = next_ptr + sizeof(GPH);
5740 0 : int sect_index = 0, rom_inserted = 0;
5741 :
5742 : // In this case we need to remove the ROM.
5743 0 : if (rom_data == NULL) {
5744 0 : rom_inserted = 1;
5745 : }
5746 :
5747 0 : while (next_ptr && next_ptr != 0xff000000) {
5748 0 : u_int8_t* old_section = old_image + next_ptr;
5749 0 : gph = (*(GPH*)(old_section));
5750 0 : TOCPUBY(gph);
5751 0 : u_int32_t new_image_index = (new_image_p - new_image);
5752 0 : sect_index++;
5753 : //printf("-D- new_image_index = %#x, next_ptr = %#x\n", new_image_index, next_ptr);
5754 0 : next_ptr = gph.next;
5755 0 : u_int8_t* data;
5756 :
5757 : //printf("-D- Before GPH: type = %#x, size = %#x, next = %#x, param = %#x\n", gph.type, gph.size, gph.next, gph.param);
5758 :
5759 0 : if (!rom_inserted && (sect_index == IMAGE_ROM_INDEX || gph.type == H_ROM)) {
5760 : // prepare new ROM.
5761 0 : GPH new_gph;
5762 0 : int rom_whole_size = TOTAL_SEC_SIZE(rom_size);
5763 :
5764 0 : data = rom_data;
5765 0 : new_gph.size = rom_size / 4;
5766 0 : new_gph.next = new_image_index + rom_whole_size;
5767 0 : new_gph.param = 0;
5768 0 : new_gph.type = H_ROM;
5769 :
5770 0 : AddNewSect(new_image_p, data, new_gph, &last_next);
5771 :
5772 0 : rom_inserted = 1;
5773 : }
5774 : // If this section is ROM section we will ignore it.
5775 0 : if (gph.type == H_ROM) {
5776 0 : continue;
5777 : }
5778 :
5779 0 : new_image_index = (new_image_p - new_image);
5780 0 : data = old_section + sizeof(GPH);
5781 0 : if (gph.next != 0xff000000) {
5782 0 : gph.next = new_image_index + TOTAL_SEC_SIZE(gph.size * 4);
5783 : }
5784 :
5785 0 : if (gph.type == H_GUID) {
5786 0 : COPY_DW(new_image + GUID_PTR_OFF, last_next);
5787 0 : } else if (gph.type == H_IMG_INFO) {
5788 0 : u_int32_ba a = last_next;
5789 0 : u_int32_t check_sum = 0;
5790 0 : int i;
5791 0 : for (i = 0; i < 3; i++) {
5792 0 : check_sum += a.range(i * 8 + 7, i * 8);
5793 : }
5794 0 : check_sum = 0x100 - (check_sum % 0x100);
5795 0 : a.range(31, 24) = check_sum;
5796 0 : last_next = u_int32_t(a);
5797 0 : COPY_DW(new_image + IMAGE_INFO_PTR, last_next);
5798 : }
5799 0 : AddNewSect(new_image_p, data, gph, &last_next);
5800 : }
5801 : // Update image size.
5802 0 : u_int32_t size = new_image_p - new_image;
5803 :
5804 0 : *new_image_size = size;
5805 :
5806 0 : COPY_DW(new_image + IMAGE_SIZE_OFF, size);
5807 :
5808 : // Writing 0 on the CRC existing field to let the tool verify the image
5809 : // and get some information which will be needed later.
5810 0 : u_int32_ba crc_dw = TOCPU1(*(u_int32_t*)(&new_image[IMG_CRC_OFF]));
5811 0 : crc_dw.range(23, 16) = 0;
5812 0 : (*(u_int32_t*)(&new_image[IMG_CRC_OFF])) = CPUTO1(crc_dw);
5813 :
5814 0 : return true;
5815 : }
5816 :
5817 : bool Operations::GetFileSize(FILE* fh, char* file_name, int& size)
5818 0 : {
5819 :
5820 : // Get the file size:
5821 0 : if (fseek(fh, 0, SEEK_END) < 0) {
5822 0 : return errmsg("Can not get file size for \"%s\" - %s", file_name, strerror(errno));
5823 : }
5824 0 : size = ftell(fh);
5825 0 : if (size < 0) {
5826 0 : return errmsg("Can not get file size for \"%s\" - %s", file_name, strerror(errno));
5827 : }
5828 0 : if (size & 0x3) {
5829 0 : return errmsg("Expansion ROM size should be 4-bytes aligned. Make sure file %s is in the right format",
5830 : file_name);
5831 : }
5832 0 : rewind(fh);
5833 :
5834 0 : return true;
5835 : }
5836 : bool Operations::IsRomEmpty(ImageInfo* info)
5837 0 : {
5838 0 : return info->_rom_sect.empty();
5839 : }
5840 : bool Operations::CheckDevImage(FBase& f, ImageInfo& flash_info)
5841 0 : {
5842 0 : bool curr_silent = _silent;
5843 0 : _silent = true;
5844 0 : if (GetQuickQuery()) {
5845 0 : initSectToRead(H_ROM);
5846 : }
5847 0 : bool flash_query_res = Verify(f, &flash_info) && QueryAll(f, &flash_info);
5848 0 : if (!flash_query_res) {
5849 0 : return errmsg("Bad FW Image on the flash");
5850 : }
5851 0 : if (!CntxIsEth(flash_info.devType) && !CntxIsIb(flash_info.devType)) {
5852 : // TODO: Indicate the device name.
5853 0 : return errmsg("Unsupported device type %d", flash_info.devType);
5854 : }
5855 0 : _silent = curr_silent;
5856 0 : return true;
5857 : }
5858 : bool Operations::CheckDevImageAndRom(FBase& f, ImageInfo& flash_info)
5859 0 : {
5860 : // Common check for the ROM.
5861 0 : if (!CheckDevImage(f, flash_info)) {
5862 0 : return errmsg(err());
5863 : }
5864 0 : if (IsRomEmpty(&flash_info)) {
5865 0 : return errmsg("Read ROM failed: The FW does not contain a ROM section");
5866 : }
5867 0 : return true;
5868 :
5869 : }
5870 :
5871 :
5872 :
5873 : bool Operations::IntegrateDevRomInImage(FImage& fim, ImageInfo& flashInfo, ImageInfo& fileInfo)
5874 0 : {
5875 0 : u_int32_t rom_size = flashInfo._rom_sect.size();
5876 0 : u_int32_t new_image_size = fim.getBufLength() + TOTAL_SEC_SIZE(rom_size);
5877 0 : vector<u_int8_t> new_data(new_image_size);
5878 0 : int actual_image_size;
5879 :
5880 : // Compine the image and the rom into new daa
5881 0 : if(!UpdateRomInImage((u_int8_t*)(&new_data[0]), (u_int8_t*)(fim.getBuf()),
5882 : (u_int8_t*)(&flashInfo._rom_sect[0]), rom_size, &actual_image_size)) {
5883 0 : return errmsg(err());
5884 : }
5885 :
5886 : // close old image and open new image with the rom.
5887 0 : fim.close();
5888 0 : fim.open((u_int32_t*)(&new_data[0]), actual_image_size);
5889 :
5890 0 : if (!VerifyFs2(fim, &fileInfo, false, false, true) || !QueryAll(fim, &fileInfo)) {
5891 0 : return errmsg(err());
5892 : }
5893 :
5894 0 : return true;
5895 : }
5896 :
5897 0 : bool IsCmdSupportLog(CommandType cmd) {
5898 :
5899 0 : switch (cmd) {
5900 : case CMD_BURN:
5901 : case CMD_BURN_BLOCK:
5902 : case CMD_BURN_ROM:
5903 0 : return true;
5904 : default:
5905 0 : return false;
5906 : }
5907 0 : return false;
5908 : }
5909 :
5910 : void PrintFSBurnErr(Flash& f, Operations& ops, const char* err_msg)
5911 0 : {
5912 0 : if (f.err()) {
5913 : // The error is in flash access:
5914 0 : report_err(ops._err_msg, "Flash access failed during burn %s: %s\n", err_msg, f.err());
5915 : } else {
5916 : // operation/algorithm error:
5917 0 : report_err(ops._err_msg, "Failsafe %s burn error: %s\n", err_msg, ops.err());
5918 : }
5919 : return;
5920 : }
5921 :
5922 :
5923 :
5924 :
5925 :
5926 :
5927 : ////////////////////////////////////////////////////////////////////////
5928 : //
5929 :
5930 : // Return values:
5931 : #define RC_FW_ALREADY_UPDATED 7
5932 :
5933 : #define NEXTS(s) do { \
5934 : if (++i >= ac) \
5935 : { \
5936 : report_err(ops._err_msg, "Missed parameter after \"%s\" switch\n", s); \
5937 : return 1; \
5938 : }} while(0)
5939 : #define NEXTC(p, s) do { \
5940 : if (++i >= ac) \
5941 : { \
5942 : report_err(ops._err_msg, "Missed %s parameter after \"%s\" command\n", p,s); \
5943 : return 1; \
5944 : }} while(0)
5945 :
5946 : #define SETERR(args) do { printf("*** ERROR *** "); printf args; printf("\n"); return 1; } while(0)
5947 :
5948 :
5949 :
5950 : int main(int ac, char *av[])
5951 4 : {
5952 :
5953 4 : char *image_fname=0, *device=0, *log_file=0;
5954 4 : bool clear_semaphore = false;
5955 4 : bool silent = false;
5956 4 : bool guids_specified = false;
5957 4 : bool macs_specified = false;
5958 4 : bool uids_specified = false;
5959 4 : bool burn_failsafe = true;
5960 4 : bool use_image_ps = false;
5961 4 : bool use_image_guids = false;
5962 4 : bool use_image_rom = false;
5963 4 : bool single_image_burn = true;
5964 4 : bool checkMatchingDevId = true;
5965 4 : bool allowPsidChange = false;
5966 4 : bool writeToLog = false;
5967 :
5968 4 : const char* cmdStr = NULL;
5969 :
5970 4 : char *user_vsd=0;
5971 4 : char *user_psid=0;
5972 4 : guid_t user_guids[Operations::MAX_GUIDS];
5973 4 : guid_t base_guid;
5974 4 : int rc = 0;
5975 4 : int num_of_banks = 0;
5976 :
5977 4 : CommandType cmd = CMD_UNKNOWN;
5978 4 : SectionType dump_sect_type = H_FW_CONF;
5979 4 : auto_ptr<Flash> f;
5980 4 : FImage fim;
5981 :
5982 8 : Operations ops;
5983 :
5984 4 : FBase* fbase = NULL;
5985 4 : const char* cmdTarget = NULL;
5986 4 : const char* cmdAccess = NULL;
5987 :
5988 4 : bool fs2_image = false;
5989 4 : bool fs2_device = false;
5990 :
5991 :
5992 : //
5993 : // Map termination signal handlers
5994 : //
5995 4 : int i;
5996 16 : for (i = 0 ; i < (int)(sizeof(g_signals_for_termination)/sizeof(g_signals_for_termination[0])) ; i++ ) {
5997 12 : signal (g_signals_for_termination[i], TerminationHandler);
5998 : }
5999 : GET_MAIN_THREAD();
6000 :
6001 4 : if (ac < 2) {
6002 4 : usage(av[0]);
6003 4 : rc = 1; goto done;
6004 : }
6005 :
6006 : // Init with FFs - for ConnectX if only MAC or GUID is specified
6007 0 : memset(user_guids, 0xff, sizeof(user_guids));
6008 :
6009 : // Go thru command line options
6010 0 : for (i=1; i < ac; i++) {
6011 : //
6012 : // Switches
6013 : // --------
6014 : //
6015 0 : if (*av[i] == '-') {
6016 0 : int switchLen = strlen(av[i]);
6017 :
6018 0 : if (!strcmp(av[i], "-dual_image"))
6019 0 : single_image_burn = false;
6020 :
6021 0 : else if (!strcmp(av[i], "-clear_semaphore")) {
6022 0 : clear_semaphore = true;
6023 : }
6024 :
6025 0 : else if (!strncmp(av[i], "-device", switchLen)) {
6026 0 : NEXTS("-device");
6027 0 : device = av[i];
6028 :
6029 0 : } else if (!strcmp(av[i], "-v") || !strcmp(av[i], "-vv")) {
6030 0 : printf("%s: %s .",
6031 : av[0],
6032 : _versionID);
6033 :
6034 0 : if (!strcmp(av[i], "-vv")) {
6035 0 : printf(" SVN %s", _svnID + 1);
6036 : }
6037 :
6038 0 : printf("\n");
6039 0 : rc = 0; goto done;
6040 :
6041 0 : } else if (!strcmp(av[i], "-unlock")) {
6042 0 : _unlock_bypass = true;
6043 0 : } else if (!strcmp(av[i], "-noerase")) {
6044 0 : _no_erase = true;
6045 0 : } else if (!strcmp(av[i], "-noburn")) {
6046 0 : _no_burn = true;
6047 0 : } else if (!strcmp(av[i], "-crc")) {
6048 0 : _print_crc = true;
6049 0 : } else if (!strcmp(av[i], "-bytewrite")) {
6050 0 : if (device) {
6051 0 : report_err(ops._err_msg, "\"-bytewrite\" should be specified before \"-device\" switch in the command line.\n");
6052 0 : rc = 1; goto done;
6053 : }
6054 0 : _byte_write = true;
6055 0 : } else if (!strcmp(av[i], "-vsd")) {
6056 0 : NEXTS("-vsd");
6057 0 : user_vsd = av[i];
6058 0 : } else if (!strcmp(av[i], "-vsd1")) {
6059 : // -vsd1 is an alias to -vsd, for backward compatibility. Can be removed in the future.
6060 0 : report_warn("Flag \"%s\" is deprecated. It will be removed in the next version. Use \"-vsd\" flag for the same result.\n", av[i]);
6061 0 : NEXTS("-vsd1");
6062 0 : user_vsd = av[i];
6063 0 : } else if (!strcmp(av[i], "-psid")) {
6064 0 : report_warn("Flag \"%s\" is deprecated. It will be removed in the next version.\n", av[i]);
6065 0 : NEXTS("-psid");
6066 0 : user_psid = av[i];
6067 : }
6068 : // -vsd2 is an alias to psid, for backward compatibility. Can be removed in the future.
6069 0 : else if (!strcmp(av[i], "-vsd2")) {
6070 0 : report_warn("Flag \"%s\" is deprecated. It will be removed in the next version.\n", av[i]);
6071 0 : NEXTS("-vsd2");
6072 0 : user_psid = av[i];
6073 0 : } else if (!strcmp(av[i], "-bsn")) {
6074 0 : report_warn("Flag \"%s\" is deprecated. It will be removed in the next version.\n", av[i]);
6075 0 : NEXTS("-bsn");
6076 0 : GETBSN(av[i], &user_guids[0]);
6077 0 : for (int i=1; i<Operations::GUIDS; i++) {
6078 0 : INCR_GUID(user_guids[0], user_guids[i], i);
6079 : }
6080 0 : guids_specified = true;
6081 0 : } else if (!strncmp(av[i], "-image", switchLen)) {
6082 0 : NEXTS("-image");
6083 0 : image_fname = av[i];
6084 0 : } else if (!strcmp(av[i], "-guid")) {
6085 0 : NEXTS("-guid");
6086 0 : GETGUID(av[i], &user_guids[0]);
6087 0 : for (int i=1; i<Operations::GUIDS; i++) {
6088 0 : INCR_GUID(user_guids[0], user_guids[i], i);
6089 : }
6090 0 : guids_specified = true;
6091 0 : } else if (!strcmp(av[i], "-guids")) {
6092 0 : if (i + 4 >= ac) {
6093 0 : report_err(ops._err_msg, "Exactly four GUIDs must be specified.\n");
6094 0 : rc = 1; goto done;
6095 : }
6096 0 : i++;
6097 0 : for (int j=0; j<Operations::GUIDS; j++) {
6098 0 : GETGUID(av[i+j], &user_guids[j]);
6099 : }
6100 0 : i += 3;
6101 0 : guids_specified = true;
6102 :
6103 0 : } else if (!strcmp(av[i], "-mac")) {
6104 0 : NEXTS("-mac");
6105 0 : GETGUID(av[i], &user_guids[Operations::GUIDS]);
6106 0 : for (int i=1; i < Operations::MACS ; i++) {
6107 0 : INCR_GUID(user_guids[Operations::GUIDS], user_guids[Operations::GUIDS + i], i);
6108 : }
6109 0 : macs_specified = true;
6110 0 : } else if (!strcmp(av[i], "-macs")) {
6111 0 : if (i + 2 >= ac) {
6112 0 : report_err(ops._err_msg, "Exactly two MACs must be specified.\n");
6113 0 : rc = 1; goto done;
6114 : }
6115 0 : i++;
6116 0 : for (int j=0; j<Operations::MACS; j++) {
6117 0 : GETGUID(av[i+j], &user_guids[Operations::GUIDS+j]);
6118 : }
6119 0 : i += 1;
6120 0 : macs_specified = true;
6121 0 : } else if (!strcmp(av[i], "-uid")) {
6122 0 : NEXTS("-uid");
6123 0 : GETGUID(av[i], &base_guid);
6124 0 : InitBxGuids(user_guids, base_guid);
6125 0 : uids_specified = true;
6126 0 : } else if (!strcmp(av[i], "-uids")) {
6127 0 : if (i + Operations::BX_ALL_GUIDS >= ac) {
6128 0 : report_err(ops._err_msg, "Exactly %d UIDs must be specified.\n", Operations::BX_ALL_GUIDS);
6129 0 : rc = 1; goto done;
6130 : }
6131 0 : i++;
6132 0 : for (int j = 0; j < Operations::BX_ALL_GUIDS; j++) {
6133 0 : GETGUID(av[i+j], &user_guids[j]);
6134 : }
6135 0 : i += (Operations::BX_ALL_GUIDS - 1);
6136 0 : uids_specified = true;
6137 0 : } else if (!strcmp(av[i], "-banks")) {
6138 0 : NEXTS("-banks");
6139 0 : rc = get_num_of_banks(av[i], &num_of_banks);
6140 0 : if (rc) {
6141 0 : report_err(ops._err_msg, "Bad number of banks(%s), it should be between 1 and 4\n", av[i]);
6142 0 : rc = 1; goto done;
6143 : }
6144 0 : } else if (!strcmp(av[i], "-log")) {
6145 0 : NEXTS("-log");
6146 0 : log_file = av[i];
6147 0 : writeToLog = true;
6148 0 : } else if (!strncmp(av[i], "-silent", switchLen))
6149 0 : silent = true;
6150 0 : else if (!strcmp(av[i], "-use_image_ps"))
6151 0 : use_image_ps = true;
6152 0 : else if (!strcmp(av[i], "-use_image_guids"))
6153 0 : use_image_guids = true;
6154 0 : else if (!strcmp(av[i], "-use_image_rom"))
6155 0 : use_image_rom = true;
6156 0 : else if (!strcmp(av[i], "-no_devid_check"))
6157 0 : checkMatchingDevId = false;
6158 0 : else if (!strncmp(av[i], "-nofs", 5))
6159 0 : burn_failsafe = false;
6160 0 : else if (!strcmp(av[i], "-skip_is"))
6161 0 : ops.SetAllowSkipIs(true);
6162 0 : else if (!strcmp(av[i], "-striped_image"))
6163 0 : ops.SetFs2StripedImage(true);
6164 0 : else if (!strcmp(av[i], "-blank_guids"))
6165 0 : ops.SetBurnBlankGuids(true);
6166 0 : else if (!strcmp(av[i], "-qq"))
6167 0 : ops.SetQuickQuery(true);
6168 0 : else if (!strncmp(av[i], "-yes", switchLen))
6169 0 : _assume_yes = true;
6170 0 : else if (!strcmp(av[i], "-no"))
6171 0 : _assume_no = true;
6172 0 : else if (!strcmp(av[i], "-byte_mode"))
6173 0 : Flash::_byte_mode = true;
6174 0 : else if (!strcmp(av[i], "-no_flash_verify"))
6175 0 : Flash::_no_flash_verify = true;
6176 0 : else if (!strcmp(av[i], "-allow_psid_change"))
6177 0 : allowPsidChange = true;
6178 :
6179 :
6180 0 : else if (!strncmp(av[i], "-hh", 3) || !strncmp(av[i], "--hh", 4)) {
6181 0 : usage(av[0], true);
6182 0 : rc = 0; goto done;
6183 0 : } else if (!strncmp(av[i], "-help", switchLen) || !strncmp(av[i], "--h", 3)) {
6184 0 : usage(av[0]);
6185 0 : rc = 0; goto done;
6186 : } else {
6187 0 : report_err(ops._err_msg, "Invalid switch \"%s\" is specified.\n", av[i]);
6188 0 : rc = 1; goto done;
6189 : }
6190 : } else {
6191 : // Command
6192 0 : cmdStr = av[i];
6193 0 : break;
6194 : }
6195 : }
6196 0 : if (_assume_yes && _assume_no) {
6197 0 : report_err(ops._err_msg, "-yes and -no options can not be specified together.\n");
6198 0 : rc = 1; goto done;
6199 : }
6200 :
6201 0 : if (ops.GetBurnBlankGuids() && (guids_specified || macs_specified || uids_specified)) {
6202 0 : report_err(ops._err_msg, "-blank_guids and (-uid(s) -guid(s) -mac(s)) options can not be specified together.\n");
6203 0 : rc = 1; goto done;
6204 : }
6205 :
6206 :
6207 : //
6208 : // Commands
6209 : // --------
6210 : //
6211 :
6212 0 : if (clear_semaphore) {
6213 0 : if (cmdStr) {
6214 0 : report_err(ops._err_msg, "No command is allowed when -clear_semaphore flag is given.\n");
6215 0 : rc = 1; goto done;
6216 : } else {
6217 0 : cmdStr = "clear_semaphore";
6218 : }
6219 : }
6220 :
6221 0 : if (!cmdStr) {
6222 0 : report_err(ops._err_msg, "No command given. See help for details.\n");
6223 0 : rc = 1; goto done;
6224 : }
6225 :
6226 : //
6227 : // Check and parse command
6228 : //
6229 0 : cmd = ParseCommand(cmdStr);
6230 :
6231 0 : if (cmd == CMD_UNKNOWN) {
6232 0 : report_err(ops._err_msg, "Invalid command \"%s\".\n", av[i]);
6233 0 : rc = 1; goto done;
6234 : }
6235 :
6236 0 : if (cmd == CMD_CLEAR_SEM) {
6237 0 : clear_semaphore = true;
6238 : }
6239 :
6240 0 : if (!ops.CheckCommandInputs(device, image_fname, cmd)) {
6241 0 : rc = 1; goto done;
6242 : }
6243 :
6244 0 : if (!ops.CheckMaxCmdArguments(cmd, ac - i - 1)) {
6245 0 : rc = 1; goto done;
6246 : }
6247 :
6248 0 : if (device) {
6249 : // Open the device
6250 0 : auto_ptr<Flash> tmp(new Flash);
6251 0 : f = tmp;
6252 :
6253 0 : if (f.get() == NULL) {
6254 0 : report_err(ops._err_msg, "Memory allocation failed\n");
6255 0 : rc = 1; goto done;
6256 : }
6257 :
6258 0 : g_flash = f.get();
6259 0 : if (!f->open(device, clear_semaphore, false, num_of_banks)) {
6260 0 : report_err(ops._err_msg, "Can not open %s: %s\n", device, f->err());
6261 0 : rc = 1; goto done;
6262 : }
6263 :
6264 0 : ops.SetNumPorts(f->get_port_num());
6265 :
6266 0 : cmdTarget = "Flash";
6267 0 : cmdAccess = device;
6268 0 : fbase = f.get();
6269 :
6270 : // Connectx Mode:
6271 0 : fs2_device = ops.CheckIsFs2(*fbase);
6272 : }
6273 :
6274 0 : if (image_fname) {
6275 0 : if (!fim.open(image_fname)) {
6276 0 : report_err(ops._err_msg, "Image file open failed: %s\n", fim.err());
6277 0 : rc = 1; goto done;
6278 : }
6279 :
6280 0 : cmdTarget = "Image file";
6281 0 : cmdAccess = image_fname;
6282 0 : fbase = &fim;
6283 :
6284 : // Connectx mode:
6285 0 : fs2_image = ops.CheckIsFs2(fim);
6286 : }
6287 :
6288 0 : ops.SetFs2Mode(fs2_image || fs2_device);
6289 :
6290 : // Get environment variables
6291 0 : if (!writeToLog) {
6292 0 : log_file = getenv(FLINT_LOG_ENV);
6293 0 : if (log_file) {
6294 0 : writeToLog = true;
6295 : }
6296 : }
6297 0 : if (getenv(FLINT_IGNORE_TTY)) {
6298 0 : ops.SetIgnoreTty(true);
6299 : }
6300 :
6301 :
6302 : // Open Log file if it was asked to.
6303 0 : if (writeToLog == true) {
6304 0 : if (IsCmdSupportLog(cmd)) {
6305 0 : f_log_fh = fopen(log_file, "a+");
6306 0 : if (f_log_fh == NULL) {
6307 0 : report_warn("Failed to open log file \"%s\": %s. No logs will be saved\n", log_file,
6308 : strerror(errno));
6309 : }
6310 0 : write_cmd_to_log(av, ac, cmd);
6311 : }
6312 : }
6313 :
6314 0 : switch (cmd) {
6315 : case CMD_BURN:
6316 : case CMD_BURN_BLOCK:
6317 : {
6318 : //
6319 : // BURN
6320 : //
6321 0 : Operations::ImageInfo fileInfo, tmpFileInfo;
6322 0 : Operations::ImageInfo flashInfo;
6323 0 : bool burn_block = (cmd == CMD_BURN_BLOCK);
6324 :
6325 :
6326 0 : if (!burn_block) {
6327 :
6328 0 : if (fs2_image != fs2_device) {
6329 0 : report_err(ops._err_msg, "The given device %s a FS2 image type, but the given image file %s a FS2 FW image\n",
6330 : fs2_device ? "requires" : "does not require",
6331 : fs2_image ? "contains" : "does not contain");
6332 0 : rc = 1; goto done;
6333 : }
6334 :
6335 : // Make checks and replace vsd/guids.
6336 0 : bool old_silent = _silent;
6337 0 : _silent = true;
6338 0 : if (!ops.Verify(fim, &tmpFileInfo) || !ops.QueryAll(fim, &tmpFileInfo)) {
6339 0 : report_err(ops._err_msg, "%s: Not a valid image file (%s)\n", image_fname, ops.err());
6340 0 : rc = 1; goto done;
6341 : }
6342 :
6343 0 : if (checkMatchingDevId) {
6344 0 : if (tmpFileInfo.infoOffs[Operations::II_HwDevsId]) {
6345 0 : if (!ops.CheckMatchingHwDevId(f->get_dev_id(),
6346 : f->get_rev_id(),
6347 : tmpFileInfo)) {
6348 0 : report_err(ops._err_msg, "Device/Image mismatch: %s\n",
6349 : ops.err());
6350 0 : rc = 1; goto done;
6351 : }
6352 0 : } else if (tmpFileInfo.infoOffs[Operations::II_DeviceType]) {
6353 :
6354 0 : if (!ops.CheckMatchingDevId(f->get_dev_id(), tmpFileInfo.devType)) {
6355 0 : report_err(ops._err_msg, "Device/Image mismatch: %s\n",
6356 : ops.err());
6357 0 : rc = 1; goto done;
6358 : }
6359 : }
6360 : }
6361 :
6362 :
6363 : // Get GUID and VSD info from flash
6364 :
6365 0 : bool read_guids = true;
6366 0 : bool read_ps = true;
6367 :
6368 : // Flash query (unlike image file query) does not have to
6369 : // pass. E.G. blank flash and the user supplies the needed data (guids, vsd).
6370 :
6371 0 : bool flash_query_res= true;
6372 0 : if (ops.GetQuickQuery()) {
6373 0 : report_warn("Running quick query - Skipping full image integrity checks.\n");
6374 0 : if (ops.IsFs2()) {
6375 0 : flash_query_res = ops.VerifyFs2(*f, &flashInfo, false, true);
6376 : }
6377 :
6378 0 : if (flash_query_res) {
6379 0 : flash_query_res = ops.QueryAll(*f, &flashInfo);
6380 : }
6381 : } else {
6382 0 : flash_query_res = ops.Verify(*f, &flashInfo) && ops.QueryAll(*f, &flashInfo);
6383 : }
6384 :
6385 : // Check exp rom:
6386 0 : if (flash_query_res && (ops.CntxIsEth(flashInfo.devType) || ops.CntxIsIb(flashInfo.devType)) &&
6387 : (ops.IsFwSupportingRomModify(tmpFileInfo.fwVer) || tmpFileInfo.expRomFound) && !use_image_rom) {
6388 : // Enter here when:
6389 : // The fw on the flash is ok &&
6390 : // The device is hermon &&
6391 : // The image fw supports modifying ROM OR it contains ROM &&.
6392 : // The user didn't ask to burn the image rom.
6393 0 : bool getRomFromDev = false;
6394 :
6395 0 : if (tmpFileInfo.expRomFound && flashInfo.expRomFound) {
6396 0 : printf("\n Note: Both the image file and the flash contain a ROM image.\n"
6397 : " Select \"yes\" to use the ROM from the given image file.\n"
6398 : " Select \"no\" to keep the existing ROM in the flash\n");
6399 0 : _silent = false;
6400 0 : printf("\n Current ROM info on flash: ");
6401 0 : ops.DisplayExpRomInfo(&flashInfo, false);
6402 0 : printf(" ROM info from image file : ");
6403 0 : ops.DisplayExpRomInfo(&tmpFileInfo, false);
6404 0 : _silent = true;
6405 :
6406 0 : if (!ops.ask_user("Use the ROM from the image file")) {
6407 0 : getRomFromDev = true;
6408 : } else {
6409 0 : getRomFromDev = false;
6410 : }
6411 0 : } else if (!tmpFileInfo.expRomFound && flashInfo.expRomFound) {
6412 0 : getRomFromDev = true;
6413 : }
6414 :
6415 0 : if (getRomFromDev == true) {
6416 0 : if (!ops.IntegrateDevRomInImage(fim, flashInfo, fileInfo)) {
6417 0 : report_err(ops._err_msg, "Failed to integrate the device rom into the Image: %s\n",
6418 : ops.err());
6419 0 : rc = 1; goto done;
6420 : }
6421 : } else {
6422 0 : fileInfo = tmpFileInfo;
6423 : }
6424 : } else {
6425 0 : fileInfo = tmpFileInfo;
6426 : }
6427 :
6428 0 : if (!ops.CheckMatchingExpRomDevId(&fileInfo)) {
6429 0 : report_warn("Image file ROM: %s\n", ops.err());
6430 0 : if (!ops.ask_user()) {
6431 0 : rc = 1; goto done;
6432 : }
6433 : }
6434 :
6435 0 : bool ib_dev;
6436 0 : bool eth_dev;
6437 0 : bool bx_dev;
6438 :
6439 0 : bx_dev = ops.IsBridgeX(fileInfo.devType);
6440 0 : ops.SetDevFlags(fileInfo.devType, ib_dev, eth_dev);
6441 :
6442 0 : if ((user_vsd && user_psid) || use_image_ps)
6443 0 : read_ps = false;
6444 :
6445 0 : if (use_image_guids || ops.GetBurnBlankGuids() || (guids_specified && ib_dev) ||
6446 : (macs_specified && eth_dev) || (uids_specified && bx_dev)) {
6447 0 : read_guids = false;
6448 : }
6449 :
6450 0 : if (read_guids && !flash_query_res) {
6451 0 : ops.PrintMissGuidErr(ib_dev, eth_dev, bx_dev);
6452 0 : if (burn_failsafe) {
6453 0 : report_err(ops._err_msg,
6454 : "Can not extract GUIDs info from flash, %s\n"
6455 : " Can not burn in a failsafe mode.\n"
6456 : " If you want to burn in non failsafe mode, use the \"-nofs\" switch.\n", ops.err());
6457 : } else {
6458 0 : report_err(ops._err_msg, "Can not extract GUIDs info from flash, %s\n", ops.err());
6459 : }
6460 0 : rc = 1; goto done;
6461 : }
6462 0 : bool is_guids_specified = guids_specified || macs_specified || uids_specified;
6463 : // Patch GUIDS
6464 0 : if (is_guids_specified) {
6465 0 : if (!ops.CheckGuidsFlags(fileInfo.devType, guids_specified, macs_specified, uids_specified)) {
6466 0 : report_err(ops._err_msg, "%s\n", ops.err());
6467 0 : rc = 1; goto done;
6468 : }
6469 0 : if (!ops.patchGUIDs(fim,
6470 : &fileInfo,
6471 : eth_dev,
6472 : bx_dev,
6473 : guids_specified,
6474 : macs_specified,
6475 : uids_specified,
6476 : user_guids,
6477 : flashInfo.imageOk ? flashInfo.guids : NULL,
6478 : flashInfo.guidNum)) {
6479 0 : rc = 1; goto done;
6480 : }
6481 0 : } else if (!use_image_guids) {
6482 0 : if (!ops.patchGUIDs(fim,
6483 : &fileInfo,
6484 : eth_dev,
6485 : bx_dev,
6486 : false,
6487 : false,
6488 : false,
6489 : NULL,
6490 : flashInfo.guids,
6491 : flashInfo.guidNum)) {
6492 0 : rc = 1; goto done;
6493 : }
6494 : }
6495 :
6496 0 : if (is_guids_specified || use_image_guids) {
6497 0 : guid_t* new_guids = user_guids;
6498 0 : guid_t* old_guids = flashInfo.imageOk ? flashInfo.guids : NULL;
6499 0 : if (!is_guids_specified && use_image_guids) {
6500 0 : new_guids = fileInfo.guids;
6501 : }
6502 0 : if (!ops.reportGuidChaneges(&fileInfo, new_guids, old_guids, ib_dev, eth_dev, bx_dev)) {
6503 0 : rc = 1; goto done;
6504 : }
6505 :
6506 : }
6507 :
6508 :
6509 0 : if (burn_failsafe && (!fileInfo.isFailsafe || !flashInfo.isFailsafe)) {
6510 0 : report_err(ops._err_msg, "Failsafe burn failed: FW image in the %s is non failsafe.\n"
6511 : " It is impossible to burn %sa non failsafe image in a failsafe mode.\n"
6512 : " If you want to burn in non failsafe mode, use the \"-nofs\" switch.\n",
6513 : fileInfo.isFailsafe ? "flash" : "given file", fileInfo.isFailsafe ? "over " : "");
6514 :
6515 0 : rc = 1; goto done;
6516 : }
6517 :
6518 0 : if (!user_vsd && !(flashInfo.psOk || (flashInfo.infoOffs[Operations::II_PSID] &&
6519 : flashInfo.infoOffs[Operations::II_VSD] ))) {
6520 0 : printf("\n");
6521 0 : if (burn_failsafe) {
6522 :
6523 0 : report_err(ops._err_msg, "Can not extract VSD/PSID info from flash.\n"
6524 : " Can not burn in a failsafe mode. Please use \"-nofs\" flag to burn in a non failsafe mode.\n");
6525 0 : rc = 1; goto done;
6526 : } else {
6527 0 : report_warn("Can not extract VSD/PSID info from flash.\n\n"
6528 : " To use a specific VSD, abort and re-burn specifying the\n"
6529 : " needed info (using command line flags -vsd / -use_image_ps).\n"
6530 : " You can also continue burn using blank VSD.\n");
6531 :
6532 0 : if (!ops.ask_user()) {
6533 0 : rc = 1; goto done;
6534 : }
6535 : }
6536 : }
6537 :
6538 : // Print FW versions:
6539 0 : printf("\n");
6540 0 : char curr_ver[124], new_ver[124];
6541 0 : printf(" Current FW version on flash: ");
6542 0 : if (flashInfo.infoOffs[Operations::II_FwVersion]) {
6543 0 : sprintf(curr_ver, "%d.%d.%d", flashInfo.fwVer[0], flashInfo.fwVer[1], flashInfo.fwVer[2]);
6544 : } else {
6545 0 : sprintf(curr_ver, "N/A");
6546 : }
6547 0 : printf(curr_ver); printf("\n");
6548 :
6549 0 : printf(" New FW version: ");
6550 0 : if (fileInfo.infoOffs[Operations::II_FwVersion]) {
6551 0 : sprintf(new_ver, "%d.%d.%d", fileInfo.fwVer[0], fileInfo.fwVer[1], fileInfo.fwVer[2]);
6552 : } else {
6553 0 : sprintf(new_ver, "N/A");
6554 : }
6555 0 : printf(new_ver); printf("\n");
6556 :
6557 0 : print_line_to_log("Current FW version on flash: %s, New FW version: %s\n", curr_ver, new_ver);
6558 :
6559 0 : bool updateRequired = true;
6560 :
6561 0 : if (fileInfo.infoOffs[Operations::II_FwVersion] &&
6562 : flashInfo.infoOffs[Operations::II_FwVersion]) {
6563 :
6564 0 : updateRequired = ops.FwVerLessThan(flashInfo.fwVer, fileInfo.fwVer);
6565 : }
6566 :
6567 0 : if (!updateRequired) {
6568 0 : printf("\n Note: The new FW version is not newer than the current FW version on flash.\n");
6569 0 : if (! ops.ask_user()) {
6570 0 : rc = RC_FW_ALREADY_UPDATED; goto done;
6571 : }
6572 : }
6573 :
6574 0 : if (fileInfo.infoOffs[Operations::II_IsGa] && !fileInfo.isGa) {
6575 0 : printf("\n Note: You are attempting to burn a pre-production FW image.\n");
6576 0 : if (! ops.ask_user()) {
6577 0 : rc = 1; goto done;
6578 : }
6579 : }
6580 :
6581 0 : if (!use_image_ps) {
6582 0 : if (fileInfo.psOk || (ops.IsFs2() && fileInfo.infoOffs[Operations::II_VSD])) {
6583 0 : if (!ops.patchVSD(fim,
6584 : &fileInfo,
6585 : user_vsd,
6586 : user_psid,
6587 : flashInfo.vsd,
6588 : NULL,
6589 : fileInfo.psid )) {
6590 0 : rc = 1; goto done;
6591 : }
6592 : }
6593 : }
6594 :
6595 : // Check PSID and ib -> eth change.
6596 :
6597 0 : if (fileInfo.infoOffs[Operations::II_PSID] &&
6598 : flashInfo.infoOffs[Operations::II_PSID] &&
6599 : strncmp( fileInfo.psid, flashInfo.psid, PSID_LEN)) {
6600 0 : if (ops.IsFs2() &&
6601 : (!ib_dev && eth_dev) &&
6602 : flashInfo.infoOffs[Operations::II_DeviceType] &&
6603 : ops.CntxIsIb(flashInfo.devType) &&
6604 : !ops.CntxIsEth(flashInfo.devType)) {
6605 :
6606 0 : printf("\n You are about to replace FW image type from IB to ETH image.\n");
6607 0 : if (! ops.ask_user()) {
6608 0 : rc = 1; goto done;
6609 : }
6610 : } else {
6611 0 : if (allowPsidChange) {
6612 0 : printf("\n You are about to replace current PSID on flash - \"%s\" with a different PSID - \"%s\".\n"
6613 : " Note: It is highly recommended not to change the PSID.\n",
6614 : flashInfo.psid,
6615 : fileInfo.psid);
6616 0 : if (! ops.ask_user()) {
6617 0 : rc = 1; goto done;
6618 : }
6619 :
6620 : } else {
6621 0 : printf("\n");
6622 0 : report_err(ops._err_msg, "PSID mismatch. The PSID on flash (%s) differs from the PSID in the given image (%s).\n",
6623 : flashInfo.psid,
6624 : fileInfo.psid);
6625 : //printf(" It is highly recommended not to change the PSID. To force a PSID change, use the -allow_psid_change flag\n");
6626 0 : rc = 1; goto done;
6627 : }
6628 : }
6629 :
6630 : }
6631 :
6632 :
6633 0 : _silent = old_silent;
6634 :
6635 : } else {
6636 : // BURN BLOCK:
6637 0 : burn_failsafe = false;
6638 : }
6639 :
6640 : // Burn it
6641 0 : if (burn_failsafe) {
6642 : // FS burn
6643 0 : bool ret;
6644 0 : if (ops.IsFs2()) {
6645 0 : ret = ops.CntxFailSafeBurn(*f,
6646 : fim,
6647 : !silent,
6648 : &flashInfo,
6649 : &fileInfo,
6650 : false);
6651 :
6652 : } else {
6653 0 : ret = ops.FailSafeBurn(*f,
6654 : fim,
6655 : !silent,
6656 : single_image_burn);
6657 : }
6658 0 : if (!ret) {
6659 0 : PrintFSBurnErr(*f, ops, "");
6660 0 : rc = 1; goto done;
6661 : }
6662 : } else {
6663 : //
6664 : // Not failsafe (sequential) burn
6665 : //
6666 :
6667 : // Ask is it OK
6668 0 : printf("\n");
6669 0 : if (burn_block) {
6670 0 : printf("Block burn: The given image will be burnt as is. No fields (such\n");
6671 0 : printf("as GUIDS,VSD) are taken from current image on flash.\n");
6672 : }
6673 0 : printf("Burn process will not be failsafe. No checks will be performed.\n");
6674 :
6675 0 : printf("ALL flash, including the Invariant Sector will be overwritten.\n");
6676 0 : printf("If this process fails, computer may remain in an inoperable state.\n");
6677 :
6678 0 : if (!ops.ask_user()) {
6679 0 : rc = 1; goto done;
6680 : }
6681 :
6682 : // Non FS burn
6683 0 : bool ret;
6684 0 : if (ops.IsFs2() && !burn_block) {
6685 0 : ret = ops.CntxFailSafeBurn(*f,
6686 : fim,
6687 : !silent,
6688 : &flashInfo,
6689 : &fileInfo,
6690 : true); // Allow nofs
6691 : } else {
6692 0 : ret = ops.write_image(*f, 0, fim.getBuf(), fim.getBufLength(),!silent, "");
6693 : }
6694 :
6695 :
6696 0 : if (!ret) {
6697 0 : report("\n");
6698 0 : report_err(ops._err_msg, "Non failsafe burn failed: %s\n", ops.err());
6699 0 : rc = 1; goto done;
6700 : }
6701 0 : report("\n");
6702 : }
6703 : }
6704 0 : break;
6705 :
6706 : case CMD_BURN_ROM:
6707 : {
6708 0 : char *rom_file = NULL;
6709 0 : int rom_size;
6710 0 : FILE *fh_rom;
6711 :
6712 0 : NEXTC("<ROM_FILE>", "brom");
6713 0 : rom_file = av[i];
6714 0 : _silent = true;
6715 :
6716 : // Open Rom file, get its size and read it
6717 0 : fh_rom = fopen(rom_file, "rb");
6718 0 : if (!fh_rom) {
6719 0 : report_err(ops._err_msg, "Can not open file \"%s\" - %s\n", rom_file, strerror(errno));
6720 0 : rc = 1; goto done;
6721 : }
6722 0 : if (!ops.GetFileSize(fh_rom, rom_file, rom_size)) {
6723 0 : report_err(ops._err_msg, "Failed to get ROM file size: %s.\n", ops.err());
6724 0 : fclose(fh_rom);
6725 0 : rc = 1; goto done;
6726 : }
6727 0 : vector<u_int8_t> rom_data(rom_size);
6728 :
6729 : // Read rom data.
6730 0 : if (fread((u_int8_t*)(&rom_data[0]), 1, rom_size, fh_rom) != (unsigned)rom_size) {
6731 0 : report_err(ops._err_msg, "Failed to read ROM file \"%s\": %s\n", rom_file, strerror(errno));
6732 0 : fclose(fh_rom);
6733 0 : rc = 1; goto done;
6734 : }
6735 0 : fclose(fh_rom);
6736 :
6737 0 : Operations::ImageInfo file_info;
6738 0 : Operations::ImageInfo flash_info;
6739 :
6740 0 : if (!ops.CheckDevImage(*f, flash_info)) {
6741 0 : report_err(ops._err_msg, "Burn ROM failed: %s\n", ops.err());
6742 0 : rc = 1; goto done;
6743 : }
6744 0 : if (ops.IsRomEmpty(&flash_info) && !ops.IsFwSupportingRomModify(flash_info.fwVer)) {
6745 0 : report_err(ops._err_msg, "It is not allowed to burn ROM on device which has fw: %d.%d.%d that doesn't contain ROM.\n", flash_info.fwVer[0],
6746 : flash_info.fwVer[1], flash_info.fwVer[2]);
6747 0 : rc = 1; goto done;
6748 : }
6749 :
6750 :
6751 0 : u_int32_t length = ops._last_image_addr;
6752 0 : u_int32_t new_data_size = length + TOTAL_SEC_SIZE(rom_size);
6753 0 : vector<u_int8_t> data(length);
6754 0 : vector<u_int8_t> new_data(new_data_size);
6755 :
6756 : // Read the image.
6757 0 : if (!f->read(0, (u_int8_t*)(&data[0]), length)) {
6758 0 : report_err(ops._err_msg, "Flash read failed: %s\n", f->err());
6759 0 : rc = 1; goto done;
6760 : }
6761 :
6762 0 : int new_image_size;
6763 :
6764 : // Insert the rom to the image.
6765 0 : if(!ops.UpdateRomInImage((u_int8_t*)(&new_data[0]), (u_int8_t*)(&data[0]),
6766 : (u_int8_t*)(&rom_data[0]), rom_size, &new_image_size)) {
6767 0 : report_err(ops._err_msg, "Burning ROM Failed: %s\n", f->err());
6768 0 : rc = 1; goto done;
6769 : }
6770 :
6771 : // open the image
6772 0 : fim.open((u_int32_t*)(&new_data[0]), new_image_size);
6773 :
6774 0 : if (!ops.VerifyFs2(fim, &file_info, false, false, true) || !ops.QueryAll(fim, &file_info)) {
6775 0 : report_err(ops._err_msg, "Internal error: The prepared image is corrupted: %s\n", ops.err());
6776 0 : rc = 1; goto done;
6777 : }
6778 0 : if (!ops.CheckMatchingExpRomDevId(&file_info)) {
6779 0 : report_warn("Image file ROM: %s\n", ops.err());
6780 0 : if (!ops.ask_user()) {
6781 0 : rc = 1; goto done;
6782 : }
6783 : }
6784 0 : _silent = false;
6785 0 : char rom_ver1[50], rom_ver2[50];
6786 0 : printf("\n Current ROM info on flash: ");
6787 0 : if (!ops.IsRomEmpty(&flash_info)) {
6788 0 : ops.DisplayExpRomInfo(&flash_info, false);
6789 0 : ops.GetExpRomStrVer(&flash_info, rom_ver1);
6790 :
6791 : } else {
6792 0 : sprintf(rom_ver1, "N/A");
6793 0 : printf("%s\n", rom_ver1);
6794 : }
6795 0 : printf(" New ROM info: ");
6796 0 : ops.DisplayExpRomInfo(&file_info, false);
6797 0 : ops.GetExpRomStrVer(&file_info, rom_ver2);
6798 :
6799 0 : print_line_to_log("Current ROM version on flash: %s, New ROM version: %s\n", rom_ver1, rom_ver2);
6800 :
6801 :
6802 : // Print the ROM versin of the curerrent and the new ROM.
6803 0 : bool ret = ops.CntxFailSafeBurn(*f, fim, !silent, &flash_info, &flash_info, true, "Burning ROM image");
6804 0 : if (!ret) {
6805 0 : PrintFSBurnErr(*f, ops, "ROM");
6806 0 : rc = 1; goto done;
6807 : }
6808 :
6809 : }
6810 0 : break;
6811 : case CMD_REMOVE_ROM:
6812 : {
6813 0 : Operations::ImageInfo file_info;
6814 0 : Operations::ImageInfo flash_info;
6815 :
6816 : // Verify to get some parameters
6817 0 : _silent = true;
6818 0 : if (!ops.CheckDevImageAndRom(*f, flash_info)) {
6819 0 : report_err(ops._err_msg, "Remove ROM failed: %s\n", ops.err());
6820 0 : rc = 1; goto done;
6821 : }
6822 0 : if (!ops.IsFwSupportingRomModify(flash_info.fwVer)) {
6823 0 : report_err(ops._err_msg, "Remove ROM failed: Unsupported Fw version (%d.%d.%d)\n", flash_info.fwVer[0],
6824 : flash_info.fwVer[1], flash_info.fwVer[2]);
6825 0 : rc = 1; goto done;
6826 : }
6827 :
6828 0 : u_int32_t length = ops._last_image_addr;
6829 0 : vector<u_int8_t> data(length);
6830 0 : vector<u_int8_t> new_data(length);
6831 :
6832 :
6833 : // Read the image.
6834 0 : if (!f->read(0, (u_int8_t*)(&data[0]), length)) {
6835 0 : report_err(ops._err_msg, "Flash read failed: %s\n", f->err());
6836 0 : rc = 1; goto done;
6837 : }
6838 0 : int new_image_size;
6839 0 : if(!ops.UpdateRomInImage((u_int8_t*)(&new_data[0]), (u_int8_t*)(&data[0]),
6840 : NULL, 0, &new_image_size)) {
6841 0 : report_err(ops._err_msg, "Removing ROM Failed: %s\n", f->err());
6842 0 : rc = 1; goto done;
6843 : }
6844 : // Burn the Image after removing the ROM.
6845 0 : fim.open((u_int32_t*)(&new_data[0]), new_image_size);
6846 :
6847 : // To verify the new image and exit if it's not VALID.
6848 0 : if (!ops.VerifyFs2(fim, &file_info, false, false, true) || !ops.QueryAll(fim, &file_info)) {
6849 0 : report_err(ops._err_msg, "Internal error: The prepared image After removing the ROM is corrupted: %s\n", ops.err());
6850 0 : rc = 1; goto done;
6851 : }
6852 :
6853 0 : _silent = false;
6854 : bool ret = ops.CntxFailSafeBurn(*f, fim, !silent, &flash_info, &file_info, true,
6855 0 : "Removing ROM image" );
6856 0 : if (!ret) {
6857 0 : PrintFSBurnErr(*f, ops, "ROM");
6858 0 : rc = 1; goto done;
6859 : }
6860 :
6861 :
6862 : }
6863 0 : break;
6864 : case CMD_READ_ROM:
6865 : {
6866 0 : _silent = true;
6867 :
6868 0 : char* rom_file = NULL;
6869 0 : NEXTC("<OUT_FILENAME>", "rrom");
6870 0 : rom_file = av[i];
6871 :
6872 0 : FILE * file;
6873 0 : if ((file = fopen(rom_file, "r")) != NULL) {
6874 0 : fclose(file);
6875 0 : printf("\n The given ROM file is existing, you are going to overwrite it.\n");
6876 0 : if (!ops.ask_user()) {
6877 0 : rc = 1; goto done;
6878 : }
6879 : }
6880 :
6881 0 : Operations::ImageInfo flash_info;
6882 :
6883 0 : if (!ops.CheckDevImageAndRom(*f, flash_info)) {
6884 0 : report_err(ops._err_msg, "Read ROM failed: %s\n", ops.err());
6885 0 : rc = 1; goto done;
6886 : }
6887 :
6888 0 : u_int32_t length = flash_info._rom_sect.size();
6889 0 : FILE* fh;
6890 0 : if ((fh = fopen(rom_file, "wb")) == NULL) {
6891 0 : report_err(ops._err_msg, "Can not open %s: %s\n", av[i], strerror(errno));
6892 0 : rc = 1; goto done;
6893 : }
6894 :
6895 : // Write output
6896 0 : if (fwrite((u_int8_t*)(&flash_info._rom_sect[0]), 1, length, fh) != length) {
6897 0 : report_err(ops._err_msg, "File write error: %s\n", strerror(errno));
6898 0 : fclose(fh);
6899 0 : rc = 1; goto done;
6900 : }
6901 0 : fclose(fh);
6902 : }
6903 0 : break;
6904 : case CMD_SET_GUIDS:
6905 : {
6906 0 : Operations::ImageInfo info;
6907 0 : u_int32_t guid_sect_addr[2] = {0};
6908 0 : u_int32_t length;
6909 0 : bool update_crc = true;
6910 :
6911 0 : if (i + 2 <= ac) {
6912 0 : NEXTC("<NOCRC>", "sg");
6913 0 : char *nocrc = av[i];
6914 0 : if (strcmp(nocrc, "nocrc")) {
6915 0 : report_err(ops._err_msg, "The sg parameter should be \"nocrc\" or nothing\n");
6916 0 : rc = 1; goto done;
6917 : }
6918 0 : update_crc = false;
6919 : }
6920 :
6921 0 : if (ops.IsFs2()) {
6922 0 : _silent = true;
6923 0 : if (!ops.VerifyFs2(*fbase, &info, false, true)) {
6924 0 : report_err(ops._err_msg, "Can not set GUIDs: %s. \n", ops.err());
6925 0 : rc = 1; goto done;
6926 : }
6927 0 : _silent = false;
6928 : }
6929 0 : if (!ops.QueryAll(*fbase, &info)) {
6930 0 : report_err(ops._err_msg, "Can not set GUIDs: %s query (%s) failed: %s\n", cmdTarget , cmdAccess, ops.err());
6931 0 : rc = 1; goto done;
6932 : }
6933 0 : length = info.imageSize;
6934 0 : if (!info.blankGuids) {
6935 0 : report_err(ops._err_msg, "Can not set GUIDs: Guids are already set.\n");
6936 0 : rc = 1; goto done;
6937 : }
6938 :
6939 0 : bool ib_dev;
6940 0 : bool eth_dev;
6941 0 : bool bx_dev;
6942 0 : u_int32_t i;
6943 :
6944 0 : bx_dev = ops.IsBridgeX(info.devType);
6945 0 : ops.SetDevFlags(info.devType, ib_dev,eth_dev);
6946 :
6947 0 : if (macs_specified || guids_specified || uids_specified) {
6948 0 : if (!ops.CheckGuidsFlags(info.devType, guids_specified, macs_specified, uids_specified)) {
6949 0 : report_err(ops._err_msg, "%s\n", ops.err());
6950 0 : rc = 1; goto done;
6951 : }
6952 : } else {
6953 0 : ops.PrintMissGuidErr(ib_dev, eth_dev, bx_dev);
6954 0 : report_err(ops._err_msg, "For set_guids command, %s", ops.err());
6955 0 : rc = 1; goto done;
6956 : }
6957 :
6958 0 : if (ops.IsFs2() || !info.isFailsafe) {
6959 0 : guid_sect_addr[0] = info.guidPtr;
6960 : } else {
6961 0 : int addr_idx = 0;
6962 0 : for (i = 0; i < 2; i++) {
6963 0 : if (info.allImgStart[i]) {
6964 0 : guid_sect_addr[addr_idx] = info.allImgStart[i] + info.guidPtr;
6965 0 : addr_idx++;
6966 : }
6967 : }
6968 : }
6969 :
6970 0 : for (i = 0; i < 2 && guid_sect_addr[i]; i++ ) {
6971 0 : u_int32_t guid_sect[Operations::MAX_GUIDS*2 + 5]; // Save room for header + crc
6972 :
6973 0 : if (!f->read(guid_sect_addr[i] - 16 , guid_sect, 16)) {
6974 0 : report_err(ops._err_msg, "Failed to read guids section - flash read error (%s)\n", fbase->err());
6975 : }
6976 :
6977 0 : ops.patchGUIDsSection (guid_sect, 16, user_guids, info.guidNum);
6978 :
6979 0 : if (!f->write(guid_sect_addr[i], guid_sect + 4 , info.guidNum * 8 + 4, true)) {
6980 0 : report_err(ops._err_msg, "Guids set failed - flash write error (%s)\n", fbase->err());
6981 : }
6982 : }
6983 0 : if (update_crc && ops.IsFs2()) {
6984 : // Read the image.
6985 0 : vector<u_int8_t> data(length);
6986 :
6987 0 : if (!f->read(0, (u_int32_t*)(&data[0]), length)) {
6988 0 : report_err(ops._err_msg, "Flash read failed: %s\n", f->err());
6989 0 : rc = 1; goto done;
6990 : }
6991 : // TODO: Do we need to update the CRC existing ORENK
6992 : // Calc & Update CRC.
6993 0 : u_int32_t *new_data = (u_int32_t*)(&data[0]);
6994 0 : u_int32_t crc = ops.CalcImageCRC(new_data, length / 4);
6995 0 : u_int32_ba old_dw = __be32_to_cpu(new_data[IMG_CRC_OFF / 4]);
6996 0 : old_dw.range(15, 0) = crc;
6997 0 : u_int32_t new_crc_dw = CPUTO1(old_dw);
6998 :
6999 0 : if (!f->write(IMG_CRC_OFF, &new_crc_dw, 4, true)) {
7000 0 : report_err(ops._err_msg, "Guids set failed - flash write error (%s)\n", fbase->err());
7001 : }
7002 : }
7003 : }
7004 0 : break;
7005 :
7006 : case CMD_ERASE_SECT:
7007 : {
7008 : //
7009 : // ERASE SECTOR <ADDR>
7010 : // Parameters: <ADDR>
7011 : //
7012 0 : u_int32_t addr;
7013 0 : char *endp;
7014 :
7015 : // Address of sector to erase
7016 0 : NEXTC("<ADDR>", "erase");
7017 0 : addr = strtoul(av[i], &endp, 0);
7018 0 : if (*endp) {
7019 0 : report_err(ops._err_msg, "Invalid address \"%s\"\n", av[i]);
7020 0 : rc = 1; goto done;
7021 : }
7022 :
7023 : // Erase
7024 0 : if (!f->erase_sector(addr)) {
7025 0 : report_err(ops._err_msg, "Erase sector failed: %s\n", f->err());
7026 0 : rc = 1; goto done;
7027 : }
7028 : }
7029 0 : break;
7030 :
7031 : case CMD_QUERY_FORCE:
7032 : case CMD_QUERY:
7033 : {
7034 : // QUERY
7035 0 : Operations::ImageInfo info;
7036 0 : bool imageOk;
7037 :
7038 0 : _silent = true;
7039 0 : if (ops.GetQuickQuery()) {
7040 0 : report_warn("Running quick query - Skipping full image integrity checks.\n");
7041 0 : ops.initSectToRead(H_ROM);
7042 : }
7043 :
7044 0 : imageOk = ops.Verify(*fbase, &info);
7045 :
7046 0 : _silent = false;
7047 :
7048 0 : if (!imageOk) {
7049 0 : printf("\n");
7050 0 : report_err(ops._err_msg, "%s query (%s) failed. Not a valid image.\n", cmdTarget , cmdAccess);
7051 0 : rc = 1; goto done;
7052 : }
7053 :
7054 0 : if (!ops.QueryAll(*fbase, &info)) {
7055 0 : report_err(ops._err_msg, "%s query (%s) failed: %s\n", cmdTarget , cmdAccess, ops.err());
7056 0 : rc = 1; goto done;
7057 : }
7058 :
7059 0 : ops.DisplayImageInfo(&info);
7060 : }
7061 0 : break;
7062 :
7063 : case CMD_QUERY_ROM:
7064 : {
7065 0 : Operations::ImageInfo info;
7066 0 : if (!ops.LoadAsExpRom(*fbase, &info) ||
7067 : !ops.GetExpRomVersion(&info) ||
7068 : !ops.DisplayExpRomInfo(&info)) {
7069 0 : report_err(ops._err_msg, "%s rom query (%s) failed: %s\n", cmdTarget , cmdAccess, ops.err());
7070 0 : rc = 1; goto done;
7071 : }
7072 : }
7073 0 : break;
7074 : case CMD_READ_BLOCK:
7075 : {
7076 : // READ BLOCK
7077 : // Parameters: <ADDR> <LENGTH> [OUT_FILENAME]
7078 : // if OUT_FILENAME is given, binari read block is stored
7079 : // in the given file. Otherwise, data is printed to screen.
7080 0 : u_int32_t addr, length;
7081 0 : u_int8_t *data;
7082 0 : char *endp;
7083 :
7084 0 : bool to_file = false;
7085 :
7086 : // Address and length
7087 0 : NEXTC("<ADDR>", "rb");
7088 0 : addr = strtoul(av[i], &endp, 0);
7089 0 : if (*endp) {
7090 0 : report_err(ops._err_msg, "Invalid address \"%s\"\n", av[i]);
7091 0 : rc = 1; goto done;
7092 : }
7093 0 : NEXTC("<LENGTH>", "rb");
7094 0 : length = strtoul(av[i], &endp, 0);
7095 0 : if (*endp) {
7096 0 : report_err(ops._err_msg, "Invalid length \"%s\"\n", av[i]);
7097 0 : rc = 1; goto done;
7098 : }
7099 0 : data = new u_int8_t[length];
7100 :
7101 : // Output file
7102 0 : FILE* fh = NULL;
7103 :
7104 0 : if (i + 2 == ac)
7105 0 : to_file = true;
7106 :
7107 0 : if (to_file) {
7108 0 : NEXTC("<OUT_FILENAME>", "rb");
7109 0 : if ((fh = fopen(av[i], "wb")) == NULL) {
7110 0 : report_err(ops._err_msg, "Can not open %s: %s\n", av[i], strerror(errno));
7111 0 : rc = 1; goto done;
7112 : }
7113 : }
7114 :
7115 : // Read flash
7116 0 : if (!fbase->read(addr, data, length)) {
7117 0 : report_err(ops._err_msg, "Flash read failed: %s\n", fbase->err());
7118 0 : rc = 1; goto done;
7119 : }
7120 :
7121 0 : if (to_file) {
7122 : // Write output
7123 0 : if (fwrite(data, 1, length, fh) != length) {
7124 0 : report_err(ops._err_msg, "File write error\n");
7125 0 : rc = 1; goto done;
7126 : }
7127 0 : fclose(fh);
7128 : } else {
7129 0 : for (u_int32_t i = 0; i < length ; i+=4) {
7130 0 : u_int32_t word = *((u_int32_t*)(data + i));
7131 :
7132 0 : word = __be32_to_cpu(word);
7133 0 : printf("0x%08x ", word);
7134 : }
7135 0 : printf("\n");
7136 : }
7137 0 : delete [] data;
7138 : }
7139 0 : break;
7140 :
7141 : case CMD_READ_WORD:
7142 : {
7143 : // READ DWORD <ADDR>
7144 : // Parameters: <ADDR>
7145 0 : u_int32_t data, addr;
7146 0 : char *endp;
7147 :
7148 : // Address
7149 0 : NEXTC("<ADDR>", "rw");
7150 0 : addr = strtoul(av[i], &endp, 0);
7151 0 : if (*endp) {
7152 0 : report_err(ops._err_msg, "Invalid address \"%s\"\n", av[i]);
7153 0 : rc = 1; goto done;
7154 : }
7155 :
7156 : // Read
7157 0 : if (!f->read(addr, &data)) {
7158 0 : report_err(ops._err_msg, "Flash read failed: %s\n", f->err());
7159 0 : rc = 1; goto done;
7160 : }
7161 0 : printf("0x%08x\n", (unsigned int)__cpu_to_be32(data));
7162 :
7163 : }
7164 0 : break;
7165 :
7166 : case CMD_VERIFY:
7167 : {
7168 : // VERIFY
7169 0 : Operations::ImageInfo info;
7170 0 : if (!ops.Verify(*fbase, &info, true)) {
7171 0 : char err_tmp[MAX_ERR_STR_LEN];
7172 0 : printf("\n");
7173 :
7174 0 : if (ops.err()) {
7175 0 : sprintf(err_tmp, ": %s", ops.err());
7176 : } else {
7177 0 : sprintf(err_tmp, "%s", ". ");
7178 : }
7179 0 : report_err(ops._err_msg, "FW image verification failed%s AN HCA DEVICE CAN NOT BOOT FROM THIS IMAGE.\n",
7180 : err_tmp);
7181 0 : rc = 1; goto done;
7182 : } else {
7183 0 : if (info.blankGuids) {
7184 0 : printf("\n");
7185 0 : report_err(ops._err_msg, "FW image verification failed: BLANK GUIDS. AN HCA DEVICE CAN NOT BOOT FROM THIS IMAGE.\n");
7186 0 : rc = 1; goto done;
7187 : } else {
7188 0 : printf("\nFW image verification succeeded. Image is bootable.\n\n");
7189 : }
7190 : }
7191 : }
7192 0 : break;
7193 :
7194 : case CMD_DUMP_HASH:
7195 : // The defalut dump_sect_type is H_FW_CONF
7196 0 : dump_sect_type = H_HASH_FILE;
7197 : case CMD_DUMP_CONF:
7198 : {
7199 : // Dump conf
7200 0 : Operations::ImageInfo info;
7201 0 : _silent = true;
7202 0 : ops.initSectToRead(dump_sect_type);
7203 0 : char* dump_file = NULL;
7204 0 : if (i + 2 <= ac) {
7205 0 : NEXTC("<OUT_FILENAME>", "dh");
7206 0 : dump_file = av[i];
7207 : }
7208 :
7209 0 : ops.Verify(*fbase, &info);
7210 :
7211 0 : if (!ops.DumpConf(dump_file, dump_sect_type)) {
7212 0 : report_err(ops._err_msg, "Failed dumping %s: %s\n", g_sectNames[dump_sect_type], ops.err());
7213 0 : rc = 1; goto done;
7214 : }
7215 : }
7216 0 : break;
7217 : case CMD_READ_IMAGE:
7218 : {
7219 : // Dump conf
7220 0 : _silent = true;
7221 0 : Operations::ImageInfo info;
7222 :
7223 0 : char* img_file = NULL;
7224 0 : NEXTC("<OUT_FILENAME>", "ri");
7225 0 : img_file = av[i];
7226 :
7227 : // For FS2 image, read only a single image. For other HCAs, try to read both images, since
7228 : // the distributed image binary file also contains both images.
7229 0 : ops.Verify(*f, &info, !ops.IsFs2());
7230 :
7231 : //printf("Last addr: 0x%08x\n", ops._last_image_addr);
7232 :
7233 0 : u_int32_t length = ops._last_image_addr;
7234 0 : vector<u_int8_t> data(length);
7235 :
7236 : // Read flash
7237 0 : if (!f->read(0, (u_int32_t*)(&data[0]), length)) {
7238 0 : report_err(ops._err_msg, "Flash read failed: %s\n", f->err());
7239 0 : rc = 1; goto done;
7240 : }
7241 0 : FILE* fh;
7242 0 : if ((fh = fopen(av[i], "wb")) == NULL) {
7243 0 : report_err(ops._err_msg, "Can not open %s: %s\n", av[i], strerror(errno));
7244 0 : rc = 1; goto done;
7245 : }
7246 :
7247 : // Write output
7248 0 : if (fwrite((u_int8_t*)(&data[0]), 1, length, fh) != length) {
7249 0 : fclose(fh);
7250 0 : report_err(ops._err_msg, "File write error\n");
7251 0 : rc = 1; goto done;
7252 : }
7253 0 : fclose(fh);
7254 : }
7255 0 : break;
7256 :
7257 : case CMD_WRITE_BLOCK:
7258 : {
7259 : // WRITE BLOCK
7260 : // Parameters: <IN_FILENAME> <ADDR>
7261 0 : u_int32_t addr;
7262 0 : char *endp;
7263 :
7264 : // Input file
7265 0 : FImage fim;
7266 :
7267 0 : NEXTC("<IN_FILENAME>", "wb");
7268 :
7269 0 : image_fname = av[i];
7270 :
7271 : // Address
7272 0 : NEXTC("<ADDR>", "wb");
7273 0 : addr = strtoul(av[i], &endp, 0);
7274 0 : if (*endp) {
7275 0 : report_err(ops._err_msg, "Invalid address \"%s\"\n", av[i]);
7276 0 : rc = 1; goto done;
7277 : }
7278 :
7279 0 : if (!fim.open(image_fname)) {
7280 0 : report_err(ops._err_msg, "Image file open failed: %s\n", fim.err());
7281 0 : rc = 1; goto done;
7282 : }
7283 :
7284 : // Write flash
7285 0 : if (!ops.write_image(*f, addr, fim.getBuf(), fim.getBufLength(), !silent, "")) {
7286 0 : report_err(ops._err_msg, "Flash write failed: %s\n", ops.err());
7287 0 : rc = 1; goto done;
7288 : }
7289 : }
7290 0 : break;
7291 :
7292 : case CMD_WRITE_WORD:
7293 : {
7294 : // WRITE DWORD
7295 : // Parameters: <ADDR> <DATA>
7296 0 : u_int32_t data, addr;
7297 0 : char *endp;
7298 :
7299 : // Address and data
7300 0 : NEXTC("<ADDR>", "ww");
7301 0 : addr = strtoul(av[i], &endp, 0);
7302 0 : if (*endp) {
7303 0 : report_err(ops._err_msg, "Invalid address \"%s\"\n", av[i]);
7304 0 : rc = 1; goto done;
7305 : }
7306 0 : NEXTC("<DATA>", "ww");
7307 0 : data = __cpu_to_be32(strtoul(av[i], &endp, 0));
7308 0 : if (*endp) {
7309 0 : report_err(ops._err_msg, "Invalid data \"%s\"\n", av[i]);
7310 0 : rc = 1; goto done;
7311 : }
7312 :
7313 : //f->curr_sector = 0xffffffff; // First time erase sector
7314 0 : if (!f->write(addr, data)) {
7315 0 : report_err(ops._err_msg, "Flash write failed: %s\n", f->err());
7316 0 : rc = 1; goto done;
7317 : }
7318 : }
7319 0 : break;
7320 :
7321 : case CMD_WRITE_BLOCK_NE:
7322 : {
7323 : // WRITE DWORD WITHOUT ERASE
7324 : // Parameters: <ADDR> <SIZE> <DATA>
7325 0 : u_int32_t size, addr;
7326 0 : char *endp;
7327 :
7328 : // Address and data
7329 0 : NEXTC("<ADDR>", "wbne");
7330 0 : addr = strtoul(av[i], &endp, 0);
7331 0 : if (*endp) {
7332 0 : report_err(ops._err_msg, "Invalid address \"%s\"\n", av[i]);
7333 0 : rc = 1; goto done;
7334 : }
7335 0 : NEXTC("<SIZE>", "wbne");
7336 0 : size = strtoul(av[i], &endp, 0);
7337 0 : if (*endp || size % 4) {
7338 0 : report_err(ops._err_msg, "Invalid size \"%s\"\n", av[i]);
7339 0 : rc = 1; goto done;
7340 : }
7341 0 : vector<u_int32_t> data_vec(size/4);
7342 0 : for (u_int32_t w = 0; w < size/4 ; w++) {
7343 0 : NEXTC("<DATA>", "wbne");
7344 0 : data_vec[w] = __cpu_to_be32(strtoul(av[i], &endp, 0));
7345 0 : if (*endp) {
7346 0 : report_err(ops._err_msg, "Invalid data \"%s\"\n", av[i]);
7347 0 : rc = 1; goto done;
7348 : }
7349 : }
7350 :
7351 0 : if (!f->write(addr, &data_vec[0], size, true)) {
7352 0 : report_err(ops._err_msg, "Flash write failed: %s\n", f->err());
7353 0 : rc = 1; goto done;
7354 : }
7355 : }
7356 0 : break;
7357 :
7358 : case CMD_WRITE_WORD_NE:
7359 : {
7360 : // WRITE DWORD WITHOUT ERASE
7361 : // Parameters: <ADDR> <DATA>
7362 0 : u_int32_t data, addr;
7363 0 : char *endp;
7364 :
7365 : // Address and data
7366 0 : NEXTC("<ADDR>", "wwne");
7367 0 : addr = strtoul(av[i], &endp, 0);
7368 0 : if (*endp) {
7369 0 : report_err(ops._err_msg, "Invalid address \"%s\"\n", av[i]);
7370 0 : rc = 1; goto done;
7371 : }
7372 0 : NEXTC("<DATA>", "wwne");
7373 0 : data = __cpu_to_be32(strtoul(av[i], &endp, 0));
7374 0 : if (*endp) {
7375 0 : report_err(ops._err_msg, "Invalid data \"%s\"\n", av[i]);
7376 0 : rc = 1; goto done;
7377 : }
7378 :
7379 0 : if (!f->write(addr, &data, 4, true)) {
7380 0 : report_err(ops._err_msg, "Flash write failed: %s\n", f->err());
7381 0 : rc = 1; goto done;
7382 : }
7383 : }
7384 0 : break;
7385 :
7386 : case CMD_CFI:
7387 : {
7388 0 : if (!f->print_attr() || !f->print_attr_old_format()) {
7389 0 : report_err(ops._err_msg, "Cfi query failed: %s\n", f->err());
7390 0 : rc = 1; goto done;
7391 : }
7392 : }
7393 0 : break;
7394 :
7395 : case CMD_CLEAR_SEM:
7396 : // Do nothing - opening the device already cleared the semaphore.
7397 0 : break;
7398 :
7399 : case CMD_SWRESET:
7400 0 : printf("Resetting device %s ...\n", device);
7401 0 : if (!f->sw_reset()) {
7402 0 : report_err(ops._err_msg, "Software reset failed: %s\n", f->err());
7403 0 : rc = 1; goto done;
7404 : }
7405 :
7406 0 : break;
7407 :
7408 : default:
7409 0 : report_err(ops._err_msg, "Internal error: Invalid command %d.\n", cmd);
7410 0 : rc = 1; goto done;
7411 : }
7412 :
7413 : done:
7414 4 : write_result_to_log(rc, ops._err_msg);
7415 :
7416 4 : close_log();
7417 :
7418 : // Mask signals
7419 16 : for (i = 0 ; i < (int)(sizeof(g_signals_for_termination)/sizeof(g_signals_for_termination[0])) ; i++ ) {
7420 12 : signal (g_signals_for_termination[i], SIG_IGN);
7421 : }
7422 4 : return rc;
7423 4 : }
7424 :
|