LCOV - code coverage report
Current view: directory - .autodirect/swgwork/orenk/projects/ofed/mstflint - flint.cpp (source / functions) Found Hit Coverage
Test: mstflint.info Lines: 3013 92 3.1 %
Date: 2010-01-17 Functions: 129 7 5.4 %

       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                 : 

Generated by: LCOV version 1.7