[HCAFWUPDATE] Update to print out PSID and handle
[mirror/winof/.git] / tools / fwupdate / user / flint.cpp
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 2004-2005 Mellanox Technologies Ltd.  All rights reserved.\r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  *\r
30  * $Id$\r
31  */\r
32 \r
33 \r
34 #include "flint-tools.h"\r
35 #include <complib/cl_byteswap.h>\r
36 \r
37 bool DebugMode = false;\r
38 bool DisableBestDevice = false;\r
39 \r
40 static uint32_t TAVOR_TYPE = 23108;\r
41 static uint32_t ARBEL_TYPE = 25208;\r
42 static int mellanox_mode = 0;\r
43 static uint32_t devRevision;\r
44 static uint32_t devType;\r
45 static uint32_t devId;\r
46 static char bestDev[MAXPATHLEN];\r
47 \r
48 char *techSupportMessage = "Use the --force option to skip this check.  This operation\n"\r
49                            "allows any firmware to be placed on the HCA device, but could cause the\n"\r
50                            "the device to cease functioning.  If this occurs, please contact\n"\r
51                            "technical support.\n";\r
52 \r
53 \r
54 #define M_DEBUG printf\r
55 #define LOCK_FILE_NAME  "C:\\fwupdate.lck"\r
56 \r
57 static int file_lock;\r
58 static int FwUpdateLock(void);\r
59 static void FwUpdateUnlock(void);\r
60 \r
61 // global defines\r
62 \r
63 u_int32_t       g_fw_dbg_lvl = CL_DBG_ERROR ;\r
64 \r
65 #define BE2CPU32(s) __be32_to_cpu(s)\r
66 #define TOCPU1(s) s = __be32_to_cpu(s)\r
67 \r
68 #define TOCPU(s,bsz) do {                                                    \\r
69     uint32_t *p = (uint32_t *)(s);                               \\r
70     for (uint32_t ii=0; ii<bsz/sizeof(uint32_t); ii++,p++) \\r
71         *p = __be32_to_cpu(*p);                                          \\r
72     } while(0)\r
73 #define TOCPUBY(s, bsz) do {                                                  \\r
74     uint32_t *p = (uint32_t *)(&s);                              \\r
75     for (uint32_t ii=0; ii<bsz/sizeof(uint32_t); ii++,p++) \\r
76         *p = __be32_to_cpu(*p);                                          \\r
77     } while(0)\r
78 #define CRC(c, s, bsz) do {                                                   \\r
79     uint32_t *p = (uint32_t *)(s);                               \\r
80     for (uint32_t ii=0; ii<bsz/sizeof(uint32_t); ii++)     \\r
81         c << *p++;                                                       \\r
82     } while(0)\r
83 #define CRCBY(c, s, bsz) do {                                                 \\r
84     uint32_t *p = (uint32_t *)(&s);                              \\r
85     for (uint32_t ii=0; ii<bsz/sizeof(uint32_t); ii++)     \\r
86         c << *p++;                                                       \\r
87     } while(0)\r
88 #define CRC1(c, s,bsz) do {                                                  \\r
89     uint32_t *p = (uint32_t *)(s);                               \\r
90     for (uint32_t ii=0; ii<bsz/sizeof(uint32_t) - 1; ii++) \\r
91         {c << *p++;  }                                                     \\r
92     } while(0)\r
93 #define CRC1BY(c, s, bsz) do {                                                \\r
94     uint32_t *p = (uint32_t *)(&s);                              \\r
95     for (uint32_t ii=0; ii<bsz/sizeof(uint32_t) - 1; ii++) \\r
96         { c << *p++;  }                                                     \\r
97     } while(0)\r
98 #define CHECKB2(f,b,o,n,p) do { if (!checkBoot2(f,b,o,n,p)) return false; } while (0)\r
99 #define CHECKGN(f,b,o,n,p) do { if (!checkGen(f,b,o,n,p)) return false; } while (0)\r
100 #define CHECKLS(f,o,p) do { if (!checkList(f,o,p)) return false; } while(0)\r
101 #define READBUF(f,o,d,l,p) do { if (!f.read(o,d,l)) { \\r
102     printf("%s - read error (%s)\n", p, f._err);      \\r
103     return false; }} while (0)\r
104 enum { SIGNATURE=0x5a445a44, SECT_SIZE=0x10000 };\r
105 struct PS {\r
106     uint32_t fi_addr;\r
107     uint32_t fi_size;\r
108     uint32_t signature;\r
109     uint32_t fw_reserved[5];\r
110     uint32_t vsd[52];\r
111         union {\r
112                 uint32_t        as_uint32[4];\r
113                 char            as_str[16];\r
114         } psid;\r
115     uint32_t branch_to;\r
116     uint32_t crc016;\r
117 };\r
118 enum {\r
119         H_FIRST=1,\r
120         H_DDR=1,\r
121         H_CNF=2,\r
122         H_JMP=3,\r
123         H_EMT=4,\r
124         H_ROM=5,\r
125         H_GUID=6,\r
126         H_BOARD_ID=7,\r
127         H_USER_DATA=8,\r
128         H_FW_CONF=9,\r
129         H_LAST  =9\r
130 };\r
131 \r
132 struct GPH {\r
133     uint32_t type;\r
134     uint32_t size;\r
135     uint32_t param;\r
136     uint32_t next;\r
137 };\r
138 \r
139 typedef struct hca_dev {\r
140     ib_al_handle_t *ph_al;\r
141         ib_al_handle_t  h_al;\r
142     ib_ca_handle_t *ph_ca;\r
143         ib_ca_handle_t  h_ca;\r
144     ib_net64_t       *ca_guid;\r
145         HANDLE                  dev_handle;\r
146     size_t           ca_guids_count;\r
147     void            *ptr;\r
148 } hca_dev_t;\r
149 \r
150 #define GUIDS 4\r
151 #define MST_MAX_FLASH   (512*1024)      // 512K\r
152 #define READ4(f,o,d,p) do { if (!f.read(o,d)) {  \\r
153     printf("%s - read error (%s)\n", p, f._err); \\r
154     return false; }} while (0)\r
155     \r
156 // forward function declaration\r
157 uint32_t HcaDevnameToDevId(const char *devname);\r
158 uint32_t HcaDevnameToDevType(const char *devname);\r
159 bool probePciBusForHcaDevice(const char *devname);\r
160 bool isMstLoaded(void);\r
161 bool getGUID(const char *s, uint64_t *guid);\r
162 bool extractGUIDptr(uint32_t sign, uint32_t *buf, uint32_t buf_len, char *pref, uint32_t *ind, uint32_t *nguids);\r
163 void printStatus(const uint32_t status);\r
164 void printPercent(const uint32_t percent, const uint32_t reset);\r
165 \r
166 ////////////////////////////////////////////////////////////////////////\r
167 //                                                                    //\r
168 // ****************************************************************** //\r
169 //                        CRC16 CALCULATION                           //\r
170 // ****************************************************************** //\r
171 //                                                                    //\r
172 ////////////////////////////////////////////////////////////////////////\r
173 class Crc16\r
174 {\r
175 public:\r
176     Crc16(bool d = false) : _debug(d) { clear();       }\r
177     uint16_t       get()              { return _crc;   }\r
178     void           clear()            { _crc = 0xffff; }\r
179     void           operator<<(uint32_t val) { add(val); }\r
180     void           add(uint32_t val);\r
181     void           finish();\r
182 private:\r
183     uint16_t       _crc;\r
184     bool           _debug;\r
185 };\r
186 \r
187 ////////////////////////////////////////////////////////////////////////\r
188 void Crc16::add(uint32_t o)\r
189 {\r
190     if (_debug)\r
191         printf("Crc16::add(%08"PRIx32")\n", o);\r
192     for (uint32_t i=0; i<32; i++)\r
193     {\r
194         if (_crc & 0x8000)\r
195             _crc = (((_crc<<1) | (o>>31)) ^  0x100b) & 0xffff;\r
196         else\r
197             _crc=((_crc<<1) | (o>>31)) & 0xffff;\r
198         o = (o<<1) & 0xffffffff;\r
199     }\r
200 } // Crc16::add\r
201 \r
202 \r
203 ////////////////////////////////////////////////////////////////////////\r
204 void Crc16::finish()\r
205 {\r
206     for (uint32_t i=0; i<16; i++)\r
207     {\r
208         if (_crc & 0x8000)\r
209             _crc=((_crc<<1)  ^  0x100b) & 0xffff;\r
210         else\r
211             _crc=(_crc<<1) & 0xffff;\r
212     }\r
213 \r
214     // Revert 16 low bits\r
215     _crc = _crc ^ 0xffff;\r
216 \r
217 } // Crc16::finish\r
218 \r
219 \r
220 ////////////////////////////////////////////////////////////////////////\r
221 //                                                                    //\r
222 // ****************************************************************** //\r
223 //                        FLASH ACCESS                                //\r
224 // ****************************************************************** //\r
225 //                                                                    //\r
226 ////////////////////////////////////////////////////////////////////////\r
227 //#define FUJITSU_BYTE_MODE\r
228 \r
229 // Common base class for Flash and for FImage\r
230 class FBase\r
231 {\r
232 public:\r
233     FBase()          {m_debug=false;}\r
234 \r
235     virtual bool open(const char *)                           = 0;\r
236     virtual void close()                                      = 0;\r
237     virtual bool read(uint32_t addr, uint32_t *data)  = 0;\r
238     virtual bool read(uint32_t addr, void *data, uint32_t len) = 0;\r
239     virtual bool dump()                                       = 0;\r
240     virtual uint32_t getClassType()                              = 0;\r
241     bool verify();\r
242     void setDebug(bool on) { m_debug = on; };\r
243     bool isDebug() { return m_debug; };\r
244     char *_err;\r
245 \r
246 protected:\r
247     char _msg[1024];\r
248     bool m_debug;\r
249 };\r
250 \r
251 // Flash image (RO)\r
252 class FImage : public FBase\r
253 {\r
254 public:\r
255     FImage() : _buf(0) {  }\r
256     FImage(bool debug) : _buf(0) { setDebug(debug); }\r
257     virtual ~FImage() { close(); }\r
258 \r
259     enum { RawImageFileType = 1 };\r
260 \r
261     uint32_t *getBuf()      { return _buf; }\r
262     uint32_t getBufLength() { return _len; }\r
263     virtual bool open(const char *fname);\r
264     virtual void close();\r
265     virtual bool read(uint32_t addr, uint32_t *data);\r
266     virtual bool read(uint32_t addr, void *data, uint32_t len);\r
267     virtual bool dump();\r
268     virtual uint32_t getClassType() { return RawImageFileType; };\r
269 \r
270 private:\r
271     uint32_t *_buf;\r
272     uint32_t _len;\r
273 };\r
274 \r
275 // Flash access (R/W)\r
276 class Flash : public FBase\r
277 {\r
278 public:\r
279     enum GPIO_STATE { High, Low };\r
280 \r
281     Flash() : curr_sector(0xffffffff), m_curr_bank(0xffffffff), m_gpio_state(Flash::Low) {}\r
282     virtual ~Flash()  { close(); };\r
283 \r
284     enum { SECT_SIZE = 0x10000, SECT_MASK = 0xffff0000, FlashDeviceType = 2 };\r
285         enum {  FW_READ         = 0x00,\r
286                         FW_WRITE        = 0x01,\r
287                         FW_READ_CMD = 0x08,\r
288                         FW_WRITE_CMD= 0x09,\r
289                         FW_OPEN_IF      = 0xe7,\r
290                         FW_CLOSE_IF     = 0x7e };\r
291     uint32_t  curr_sector;\r
292     hca_dev_t  m_mf;\r
293     virtual bool open(const char *);\r
294     virtual void close();\r
295     virtual bool read(uint32_t addr, uint32_t *data);\r
296     virtual bool read(uint32_t addr, void *data, uint32_t len);\r
297     virtual bool dump();\r
298     virtual uint32_t getClassType() { return FlashDeviceType; };\r
299     void setGPIOState(GPIO_STATE state);\r
300     bool format();\r
301     bool write(uint32_t addr, uint32_t data);\r
302     bool write(uint32_t addr, void *data, uint32_t cnt,\r
303                bool noerase = false, bool noverify = false);\r
304     bool write_image(uint32_t addr, void *data, uint32_t cnt, bool eraseInvariant = false, bool report=false);\r
305     bool erase_sector(uint32_t addr);\r
306 \r
307     ib_api_status_t  access(hca_dev_t *mf, u_int32_t offset, void *data, u_int32_t length, u_int32_t operation);\r
308 private:\r
309 \r
310     uint32_t  m_curr_bank;\r
311     GPIO_STATE      m_gpio_state;\r
312     uint32_t  m_dir;\r
313     uint32_t  m_pol;\r
314     uint32_t  m_mod;\r
315     uint32_t  m_data;\r
316 \r
317     bool         hca_open (void);\r
318     void             hca_close ();\r
319     bool          set_bank(uint32_t bank);\r
320     bool          write_internal(uint32_t addr, uint8_t data);\r
321 \r
322     enum FlashCmds {IDLE=0,\r
323                                         READ4=(1<<29),\r
324                                         WRITE1=(2<<29)\r
325         };\r
326 \r
327     enum {      TRANS = 4096 };\r
328     enum {      BANK_SHIFT = 19,\r
329                         BANK_MASK = 0xfff80000\r
330         };\r
331     \r
332         enum {  FLASH    = 0xf01a4, \r
333                         ADDR_MSK=0x7ffffUL, \r
334                         CMD_MASK=0xe0000000UL\r
335         };\r
336     \r
337         enum {  CPUMODE  = 0xf0150, \r
338                         CPUMODE_MSK=0xc0000000UL, \r
339                         CPUMODE_SHIFT=30\r
340         };\r
341     \r
342         enum {  SEMAP63    = 0xf03fc,\r
343                         GPIO_DIR_L = 0xf008c,\r
344                         GPIO_POL_L = 0xf0094,\r
345                         GPIO_MOD_L = 0xf009c,\r
346                         GPIO_DAT_L = 0xf0084,\r
347                         GPIO_DATACLEAR_L = 0xf00d4,\r
348                         GPIO_DATASET_L = 0xf00dc \r
349         };\r
350 \r
351     // FLASH constants\r
352     enum { FLASH_CMD_CNT  = 5000,    // Number of reads till flash cmd is zeroed\r
353            ERASE_DELAY    = 20000,  // Delay between reads when wating for sector erase\r
354            ERASE_CNT      = 80,      // Maximal number of reads when wating for sector erase\r
355            READ_CNT_FAST  = 5000,    // Number of fast reads after write byte\r
356            READ_CNT_SLOW  = 50,      // Number of slow reads after write byte\r
357            READ_DELAY     = 10000,  // Delay between slow reads after write byte\r
358            WR_REPORT_FAST = 256,     // Report frequency when write (fast interfaces)\r
359            WR_REPORT_SLOW = 4,       // Report frequency when write (slow interfaces)\r
360            RD_REPORT_FAST = 4096,    // Report frequency when read (fast interfaces)\r
361            RD_REPORT_SLOW = 64,      // Report frequency when read (slow interfaces)\r
362            GPIO_SEM_TRIES = 10240    // Number of tries to obtain a GPIO sem.\r
363         };\r
364 \r
365 };\r
366 \r
367 bool FImage::dump()\r
368 {\r
369     uint32_t word;\r
370     uint32_t position = 0;\r
371     \r
372     while (1)\r
373     {\r
374         if (!this->read(position, &word))\r
375         {\r
376             break;\r
377         }\r
378 \r
379         if ((position % 16) == 0)\r
380         {\r
381             printf("\n%08"PRIx32": ", position);\r
382         }\r
383         printf(" %08"PRIx32"", word);\r
384 \r
385         position = position + 4;\r
386     }\r
387     printf("\n");\r
388     return true;\r
389 }\r
390 \r
391 ////////////////////////////////////////////////////////////////////////\r
392 bool FImage::open(const char *fname)\r
393 {\r
394     struct _stat        stat_buf;\r
395     int32_t            r_cnt;\r
396 \r
397     uint32_t fd = _open(fname, _O_BINARY | _O_RDONLY, S_IREAD);\r
398     if (!fd )\r
399     {\r
400         sprintf(_msg, "Can't open file \"%s\" - %s\n", fname, \r
401                 strerror(errno));\r
402         _err = &_msg[0];\r
403         return false;\r
404     }\r
405     if (_fstat(fd, &stat_buf) < 0)\r
406     {\r
407         sprintf(_msg, "Can't stat file \"%s\" - %s\n", fname,\r
408                 strerror(errno));\r
409         _err = &_msg[0];\r
410         return false;\r
411     }\r
412     if (stat_buf.st_size & 0x3)\r
413     {\r
414         _err = "Image size should be 4-bytes aligned.";\r
415         return false;\r
416     }\r
417 \r
418     _buf = new uint32_t[stat_buf.st_size/4];\r
419     if ((r_cnt = _read(fd, _buf, stat_buf.st_size)) != stat_buf.st_size)\r
420     {\r
421         if (r_cnt < 0)\r
422             sprintf(_msg, "Read error on file \"%s\" - %s\n",\r
423                     fname, strerror(errno));\r
424         else\r
425             sprintf(_msg, "Read error on file \"%s\" - read only %d bytes (from %ld)\n",\r
426                     fname, r_cnt, stat_buf.st_size);\r
427         _err = &_msg[0];\r
428         return false;\r
429     }\r
430 \r
431     _len = stat_buf.st_size;\r
432     _close(fd);\r
433     return true;\r
434 } // FImage::open\r
435 \r
436 ////////////////////////////////////////////////////////////////////////\r
437 void FImage::close()\r
438 {\r
439     delete [] _buf;\r
440     _buf = 0;\r
441 } // FImage::close\r
442 \r
443 ////////////////////////////////////////////////////////////////////////\r
444 bool FImage::read(uint32_t addr, uint32_t *data)\r
445 {\r
446     if (addr & 0x3)\r
447     {\r
448         _err = "Address should be 4-bytes aligned.";\r
449         return false;\r
450     }\r
451     if (!_buf)\r
452     {\r
453         _err = "Not opened";\r
454         return false;\r
455     }\r
456     if (addr > _len-4)\r
457     {\r
458         sprintf(_msg, "Address (0x%x) is out of image limits\n", addr);\r
459         _err = &_msg[0];\r
460         return false;\r
461     }\r
462     *data = _buf[addr/4];\r
463     return true;\r
464 } // FImage::read\r
465 \r
466 ////////////////////////////////////////////////////////////////////////\r
467 bool FImage::read(uint32_t addr, void *data, uint32_t len)\r
468 {\r
469     if (addr & 0x3)\r
470     {\r
471         _err = "Address should be 4-bytes aligned.";\r
472         return false;\r
473     }\r
474     if (len & 0x3)\r
475     {\r
476         _err = "Length should be 4-bytes aligned.";\r
477         return false;\r
478     }\r
479     if (!_buf)\r
480     {\r
481         _err = "Not opened";\r
482         return false;\r
483     }\r
484 \r
485     uint32_t *p = (uint32_t *)data;\r
486     for (uint32_t i=0; i<len/4; i++)\r
487     {\r
488         if (!read(addr, p++))\r
489             return false;\r
490         addr += 4;\r
491     }\r
492     return true;\r
493 } // FImage::read\r
494 \r
495 Flash device;\r
496 FImage image;\r
497 void __cdecl catch_signal( int sig );\r
498 \r
499 \r
500 ////////////////////////////////////////////////////////////////////////\r
501 #define MWRITE4(offs,val, cmd) access(&m_mf, offs, val, 4, cmd )\r
502 #define MREAD4(offs,val, cmd)  access(&m_mf, offs, val, 4, cmd )\r
503 \r
504 void Flash::setGPIOState(GPIO_STATE state)\r
505 {\r
506     m_gpio_state = state;\r
507 }\r
508 \r
509 bool Flash::dump()\r
510 {\r
511     uint32_t word;\r
512     uint32_t position = 0;\r
513     uint32_t max_size = 0;\r
514     PS    ps;\r
515     \r
516     this->read(SECT_SIZE, &ps, sizeof(ps));\r
517     \r
518     TOCPUBY(ps,sizeof(ps));\r
519 \r
520     // Signature\r
521     if (ps.signature != SIGNATURE)\r
522     {        \r
523         max_size = MST_MAX_FLASH;\r
524     } else\r
525     {\r
526         max_size = ps.fi_size;\r
527     }\r
528 \r
529     while (position < max_size )\r
530     {\r
531         if (!this->read(position, &word))\r
532         {\r
533             break;\r
534         }\r
535 \r
536         if ((position % 16) == 0)\r
537         {\r
538             printf("\n%08"PRIx32": ", position);\r
539         }\r
540         printf(" %08"PRIx32"", word);\r
541 \r
542         position = position + 4;\r
543     }\r
544     printf("\n");\r
545     return true;\r
546 }\r
547 \r
548 bool Flash::format()\r
549 {\r
550     uint32_t position = 0;\r
551     uint32_t max_size = 0;\r
552     PS    ps;\r
553     uint32_t percent = 0;\r
554     uint32_t prev=0;\r
555     this->read(SECT_SIZE, &ps, sizeof(ps));\r
556     \r
557     TOCPUBY(ps, sizeof(ps));\r
558 \r
559     // Signature\r
560     if (ps.signature != SIGNATURE)\r
561     {        \r
562         max_size = MST_MAX_FLASH;\r
563     } else\r
564     {\r
565         max_size = ps.fi_size;\r
566     }\r
567 \r
568     printPercent(0,1);\r
569    \r
570     while (position < max_size )\r
571     {\r
572         this->erase_sector(position);\r
573         percent = (uint32_t)(((float)position / (float)max_size) * 100.00);\r
574         if (percent != prev)\r
575             printPercent(percent,0);\r
576         prev = percent;\r
577         position = position + SECT_SIZE; // increment by 65k sectors\r
578     }\r
579     printPercent(100,0);\r
580     printStatus(0);\r
581     return true;\r
582 }\r
583 \r
584 ////////////////////////////////////////////////////////////////////////\r
585 bool Flash::open(const char *device )\r
586 {\r
587     // Open device\r
588     bool status = false;\r
589     if (!device)\r
590     {\r
591         M_DEBUG("Specify HCA to work with\n");\r
592         return status;\r
593     }              \r
594         m_mf.ph_al = (ib_al_handle_t *)(intn_t)&m_mf.h_al;\r
595         m_mf.ph_ca = (ib_ca_handle_t *)(intn_t)&m_mf.h_ca;\r
596     if ( !(hca_open()))\r
597     {\r
598         M_DEBUG("Failed to open HCA \n");\r
599         return status;\r
600     }\r
601     \r
602     //M_DEBUG("Open HCA  GUID %"PRIx64"\n", cl_ntoh64(*m_mf.ca_guid));\r
603     \r
604     m_curr_bank = 0xffffffff;\r
605 \r
606     // Obtain GPIO Semaphore\r
607     uint32_t cnt=0;\r
608     uint32_t word;\r
609         \r
610         MREAD4(FLASH, &word, FW_OPEN_IF );\r
611 \r
612     while ( !status )\r
613         {\r
614                 MREAD4(SEMAP63, &word, FW_READ_CMD);\r
615                 if( !word )\r
616                 {\r
617                         status = true;\r
618                         break;\r
619                 }\r
620         if (++cnt > GPIO_SEM_TRIES)\r
621         {\r
622             _err = "cannot obtain GPIO semaophore (63)";\r
623             break;\r
624         }\r
625     } /* while */\r
626 \r
627         if ( !status )\r
628         {\r
629                 MREAD4(FLASH, &word, FW_CLOSE_IF );\r
630                 return status;\r
631         }\r
632 \r
633     //M_DEBUG("Acquired GPIO sempahore.\n");\r
634 \r
635     // Save old values\r
636     MREAD4(GPIO_DIR_L, &m_dir, FW_READ_CMD);\r
637     MREAD4(GPIO_POL_L, &m_pol, FW_READ_CMD);\r
638     MREAD4(GPIO_MOD_L, &m_mod, FW_READ_CMD);\r
639     MREAD4(GPIO_DAT_L, &m_data, FW_READ_CMD);\r
640 \r
641     //M_DEBUG("Read GPIO information.\n");\r
642 \r
643     // Set Direction=1, Polarity=0, Mode=0 for 3 GPIO lower bits\r
644     uint32_t dir;\r
645     uint32_t pol;\r
646     uint32_t mod;\r
647 \r
648     dir = m_dir | 0x70;\r
649     pol = m_pol & ~0x70;\r
650     mod = m_mod & ~0x70;\r
651 \r
652     MWRITE4(GPIO_DIR_L, &dir, FW_WRITE_CMD);\r
653     MWRITE4(GPIO_POL_L, &pol, FW_WRITE_CMD);\r
654     MWRITE4(GPIO_MOD_L, &mod, FW_WRITE_CMD);\r
655 \r
656   //  M_DEBUG("Set GPIO bits.\n");\r
657 \r
658     // Set CPUMODE\r
659     MREAD4(CPUMODE, &word, FW_READ_CMD);\r
660     word &= ~CPUMODE_MSK;\r
661     word |= 1 << CPUMODE_SHIFT;\r
662     MWRITE4(CPUMODE, &word, FW_WRITE_CMD);\r
663 \r
664 \r
665     //M_DEBUG("Set cpu mode.\n");\r
666 \r
667     // Reset flash\r
668     status = write_internal(0, 0xf0);\r
669         M_DEBUG("Flash Open %s\n", ((status)?"OK":"FAIL"));\r
670         return status;\r
671 } // Flash::open\r
672 \r
673 ////////////////////////////////////////////////////////////////////////\r
674 void Flash::close()\r
675 {\r
676         uint32_t data = 0;\r
677 \r
678     if (!m_mf.h_ca)\r
679         return;\r
680 \r
681     m_gpio_state = Flash::Low;\r
682     set_bank(0);\r
683 \r
684     // Restore origin values\r
685     MWRITE4(GPIO_DIR_L, &m_dir, FW_WRITE_CMD);\r
686     MWRITE4(GPIO_POL_L, &m_pol, FW_WRITE_CMD);\r
687     MWRITE4(GPIO_MOD_L, &m_mod, FW_WRITE_CMD);\r
688     MWRITE4(GPIO_DAT_L, &m_data, FW_WRITE_CMD);\r
689 \r
690     // Free GPIO Semaphore\r
691     MWRITE4(SEMAP63, &data, FW_WRITE_CMD);\r
692         \r
693         // free kernel BusInterface\r
694         MREAD4(FLASH, &data, FW_CLOSE_IF );\r
695 \r
696     hca_close();\r
697     m_mf.h_ca = 0;\r
698     m_curr_bank = 0xffffffff;\r
699 } // Flash::close\r
700 \r
701 ////////////////////////////////////////////////////////////////////////\r
702 bool Flash::set_bank(uint32_t bank)\r
703 {\r
704         uint32_t        data = 0x70;\r
705     if (!m_mf.h_ca)\r
706     {\r
707         _err = "Not opened";\r
708         return false;\r
709     }\r
710         \r
711     //printf("\n*** Flash::set_bank(0x%"PRIx32") : 0x%"PRIx32"\n", bank, (BANK_SHIFT-4) & 0x70);\r
712     MWRITE4(GPIO_DATACLEAR_L, &data, FW_WRITE_CMD);\r
713     if (m_gpio_state == Flash::Low)\r
714     {\r
715                 data &= (bank >> (BANK_SHIFT-4));\r
716                 MWRITE4(GPIO_DATASET_L, &data, FW_WRITE_CMD );\r
717     } else\r
718     {\r
719                 data |= (bank >> (BANK_SHIFT-4));\r
720         MWRITE4(GPIO_DATASET_L, &data, FW_WRITE_CMD);\r
721     }\r
722 \r
723     return true;\r
724 } // Flash::set_bank\r
725 \r
726 ////////////////////////////////////////////////////////////////////////\r
727 bool Flash::read(uint32_t addr, uint32_t *data)\r
728 {\r
729     if (!m_mf.h_al)\r
730     {\r
731         _err = "Not opened";\r
732         return false;\r
733     }\r
734 \r
735     uint32_t cmd;\r
736     if (addr & 0x3)\r
737     {\r
738         _err = "Address should be 4-bytes aligned.";\r
739         return false;\r
740     }\r
741 \r
742     uint32_t bank = addr & BANK_MASK;\r
743     if (bank != m_curr_bank)\r
744     {\r
745         m_curr_bank = bank;\r
746         if (!set_bank(bank))\r
747             return false;\r
748     }\r
749         MREAD4(addr, &cmd, FW_READ ); // new read \r
750     cmd = __be32_to_cpu(cmd);\r
751     memcpy(data, &cmd, sizeof(uint32_t));\r
752 \r
753     return true;\r
754 } // Flash::read\r
755 \r
756 ////////////////////////////////////////////////////////////////////////\r
757 bool Flash::read(uint32_t addr, void *data, uint32_t len)\r
758 {\r
759     if (addr & 0x3)\r
760     {\r
761         _err = "Address should be 4-bytes aligned.";\r
762         return false;\r
763     }\r
764     if (len & 0x3)\r
765     {\r
766         _err = "Length should be 4-bytes aligned.";\r
767         return false;\r
768     }\r
769 \r
770     uint32_t *p = (uint32_t *)data;\r
771     for (uint32_t i=0; i<len/4; i++)\r
772     {\r
773         if (!read(addr, p++))\r
774             return false;\r
775         addr += 4;\r
776     }\r
777     return true;\r
778 } // Flash::flash_read\r
779 \r
780 ////////////////////////////////////////////////////////////////////////\r
781 bool Flash::write_internal(uint32_t addr, uint8_t data)\r
782 {\r
783         MWRITE4(addr, &data, FW_WRITE);\r
784     return true;\r
785 } // Flash::write_internal\r
786 \r
787 ////////////////////////////////////////////////////////////////////////\r
788 bool Flash::erase_sector(uint32_t addr)\r
789 {\r
790     uint32_t    word = 0;\r
791     uint32_t    cnt = 0;\r
792 \r
793     // Just to insure zeroes because erase completion waits for ones\r
794     if (!write(addr, &word, sizeof(word), true))\r
795         return false;\r
796 \r
797     // erase sector sequence\r
798 #ifdef FUJITSU_BYTE_MODE\r
799     if (!write_internal(0xaaa, 0xaa))\r
800         return false;\r
801     if (!write_internal(0x555, 0x55))\r
802         return false;\r
803     if (!write_internal(0xaaa, 0x80))\r
804         return false;\r
805     if (!write_internal(0xaaa, 0xaa))\r
806         return false;\r
807     if (!write_internal(0x555, 0x55))\r
808         return false;\r
809     if (!write_internal(addr, 0x30))\r
810         return false;\r
811 #else /* FUJITSU_WORD_MODE */\r
812     if (!write_internal(0x555, 0xaa))\r
813         return false;\r
814     if (!write_internal(0x2aa, 0x55))\r
815         return false;\r
816     if (!write_internal(0x555, 0x80))\r
817         return false;\r
818     if (!write_internal(0x555, 0xaa))\r
819         return false;\r
820     if (!write_internal(0x2aa, 0x55))\r
821         return false;\r
822     if (!write_internal(addr, 0x30))\r
823         return false;\r
824 #endif\r
825 \r
826     // Wait while erase completes\r
827     do\r
828     {\r
829         // Timeout checks\r
830         if (++cnt > ERASE_CNT)\r
831         {\r
832             _err = "Flash erase sector timeout";\r
833             return false;\r
834         }\r
835         if (!read(addr, &word))\r
836             return false;\r
837 \r
838         //printf("erase_sector: addr:%08"PRIx32", %08"PRIx32"\n", addr, word);\r
839         Sleep(ERASE_DELAY/1000);\r
840     } while (word != 0xffffffff);\r
841 \r
842     return true;\r
843 } // Flash::erase_sector\r
844 \r
845 ////////////////////////////////////////////////////////////////////////\r
846 bool Flash::write(uint32_t addr, uint32_t data)\r
847 {\r
848     if (!m_mf.h_al)\r
849     {\r
850         _err = "Not opened";\r
851         return false;\r
852     }\r
853     if (addr & 0x3)\r
854     {\r
855         _err = "Address should be 4-bytes aligned.";\r
856         return false;\r
857     }\r
858 \r
859     uint32_t word;\r
860     uint32_t sector = addr & SECT_MASK;\r
861     uint32_t word_in_sector = (addr & ~SECT_MASK)/sizeof(uint32_t);\r
862 \r
863     if (!read(addr, &word))\r
864         return false;\r
865     if (word == data)\r
866         return true;   // already there\r
867 \r
868     uint32_t buff[SECT_SIZE/sizeof(uint32_t)];\r
869     if (!read(sector, buff, SECT_SIZE))\r
870         return false;\r
871     buff[word_in_sector] = data;\r
872     return write(sector, buff, SECT_SIZE);\r
873 } // Flash::write\r
874 \r
875 ////////////////////////////////////////////////////////////////////////\r
876 bool Flash::write(uint32_t addr, void *data, uint32_t cnt,\r
877                   bool noerase, bool noverify)\r
878 {\r
879     if (!m_mf.h_al)\r
880     {\r
881         _err = "Not opened";\r
882         return false;\r
883     }\r
884     if (addr & 0x3)\r
885     {\r
886         _err = "Address should be 4-bytes aligned.";\r
887         return false;\r
888     }\r
889 \r
890         if ( !data )\r
891                 return true;\r
892 \r
893     char         *p = (char *)data;\r
894 \r
895     for (uint32_t i=0; i<cnt; i++,addr++)\r
896     {\r
897         uint32_t  word;\r
898         uint8_t   act, exp;\r
899         uint32_t  cnt1 = 0;\r
900 \r
901             uint32_t bank = addr & BANK_MASK;\r
902             if (bank != m_curr_bank)\r
903             {\r
904                 m_curr_bank = bank;\r
905                 if (!set_bank(bank))\r
906                     return false;\r
907             }\r
908 \r
909             if (!noerase)\r
910             {\r
911                 uint32_t sector = addr & SECT_MASK;\r
912                 if (sector != curr_sector)\r
913                 {\r
914                     curr_sector = sector;\r
915                     if (!erase_sector(curr_sector))\r
916                         return false;\r
917                 }\r
918             }\r
919 \r
920 #ifdef FUJITSU_BYTE_MODE\r
921             if (!write_internal(0xaaa, 0xaa))\r
922                 return false;\r
923             if (!write_internal(0x555, 0x55))\r
924                 return false;\r
925             if (!write_internal(0xaaa, 0xa0))\r
926                 return false;\r
927 #else /* FUJITSU_WORD_MODE */\r
928             if (!write_internal(0x555, 0xaa))\r
929                 return false;\r
930             if (!write_internal(0x2aa, 0x55))\r
931                 return false;\r
932             if (!write_internal(0x555, 0xa0))\r
933                 return false;\r
934 #endif\r
935 \r
936             if (!write_internal(addr, *p++))\r
937                 return false;\r
938            \r
939                         if ( !noverify )\r
940                         {\r
941                                 if ( !read (addr &~3, &word) )\r
942                                         return false;\r
943 #if __BYTE_ORDER == __LITTLE_ENDIAN\r
944                 act = (word >> ((addr & 3) * 8)) & 0xff;\r
945 #elif __BYTE_ORDER == __BIG_ENDIAN\r
946                 act = (word >> ((3 - (addr & 3)) * 8)) & 0xff;\r
947 #endif                  \r
948                                 exp = *(p-1) & 0xff;\r
949                                 if ( act != exp )\r
950                                 {\r
951                                         M_DEBUG("Flash write error - read value %#x doesn't written value %#x", act, exp);\r
952                                         return false;\r
953                                 }\r
954                         }\r
955         }\r
956         return true;\r
957 } // flash_write\r
958 \r
959 void Flash::hca_close (void)\r
960 {\r
961 \r
962     if (m_mf.h_ca)\r
963         ib_close_ca( m_mf.h_ca, NULL );\r
964     if (m_mf.h_al)\r
965         ib_close_al( m_mf.h_al);\r
966 }\r
967  bool Flash::hca_open(void)\r
968 {\r
969     ib_api_status_t ib_status = IB_SUCCESS;\r
970 \r
971     /* Open ibal */\r
972     ib_status = ib_open_al( m_mf.ph_al );\r
973     if ( ib_status != IB_SUCCESS )\r
974     {\r
975         M_DEBUG("Failed ot open AL status %#x\n", ib_status);\r
976         return false;\r
977     }\r
978 \r
979     ib_status = ib_get_ca_guids ( *m_mf.ph_al, NULL, &m_mf.ca_guids_count );\r
980     if (m_mf.ca_guids_count == 0)\r
981     {\r
982         M_DEBUG("FOUND NO GUIDS\n");\r
983         return false;\r
984     }\r
985    \r
986     m_mf.ca_guid =(ib_net64_t *)cl_zalloc(m_mf.ca_guids_count*sizeof(ib_net64_t));\r
987     if(m_mf.ca_guid == NULL)\r
988     {\r
989         M_DEBUG("Failed to allocate memory for CA GUID table\n");\r
990         return false;\r
991     }\r
992 \r
993    ib_status = ib_get_ca_guids (*m_mf.ph_al, m_mf.ca_guid, &m_mf.ca_guids_count );\r
994    if (ib_status != IB_SUCCESS)\r
995    {\r
996        M_DEBUG("Failed to get CA GUIDs\n");\r
997        return false;\r
998    }\r
999 \r
1000    ib_status = ib_open_ca( *m_mf.ph_al, m_mf.ca_guid[0], NULL, &m_mf, m_mf.ph_ca );\r
1001    if (ib_status != IB_SUCCESS)\r
1002    {\r
1003        M_DEBUG("Failed to open CA\n");\r
1004        return false;\r
1005    }\r
1006 \r
1007    return true;\r
1008 }\r
1009 \r
1010 #define STR_LEN 128\r
1011 void printPercent(const uint32_t percent, const uint32_t reset)\r
1012 {\r
1013 #define PRECISION 2\r
1014 #define NO_OF_PARTS (100 / (PRECISION))\r
1015                                 /*"12345678901234567890123456789012345678901234567890"*/\r
1016   char markerBar[NO_OF_PARTS+1] = "                                                  ";\r
1017   static uint32_t prevNoOfXs = 0;\r
1018   uint32_t noOfXs = 0;\r
1019   uint32_t x;\r
1020   char str[STR_LEN];\r
1021   cl_memset(str,0,STR_LEN);\r
1022 \r
1023   markerBar[NO_OF_PARTS+1] = '\0';\r
1024 \r
1025   if (reset == 1)\r
1026   {\r
1027     sprintf(str,"|%s| %3d%%", markerBar, percent);\r
1028     prevNoOfXs = 0;\r
1029   }\r
1030   else\r
1031   {\r
1032     noOfXs = percent / PRECISION;\r
1033     for (x = 0; x < NO_OF_PARTS; x++)\r
1034     {\r
1035       if (x < noOfXs)\r
1036         markerBar[x] = '*';\r
1037     }\r
1038     if (noOfXs>prevNoOfXs)\r
1039     {\r
1040       sprintf(str,"|%s| %3d%%", markerBar, percent);\r
1041       //printf("|%s| %3d%%", markerBar, percent);\r
1042       prevNoOfXs = noOfXs;\r
1043     }\r
1044   }\r
1045   printf("\r%s",str);\r
1046   fflush(stdout);\r
1047 }\r
1048 \r
1049 void printStatus(const uint32_t status)\r
1050 {\r
1051         printf("[%s]\n",((status == 0)?"SUCCESS":"FAILED"));\r
1052 }\r
1053 \r
1054 ////////////////////////////////////////////////////////////////////////\r
1055 bool Flash::write_image(uint32_t addr, void *data, uint32_t cnt, bool eraseInvariant, bool report)\r
1056 {\r
1057     uint8_t  *p = (uint8_t *)data;\r
1058     uint32_t  curr_addr = addr;\r
1059     uint32_t  towrite = cnt;\r
1060     uint32_t  perc = 0xffffffff;\r
1061     bool noerase = false;\r
1062 \r
1063     curr_sector = 0xffffffff;  // Erase sector first time\r
1064     if (report)\r
1065     {\r
1066         printf("writing: ");\r
1067         printPercent(0,1);\r
1068         fflush(stdout);\r
1069     }\r
1070 \r
1071     while (towrite)\r
1072     {   \r
1073         // Write\r
1074         uint32_t trans = (towrite > (uint32_t)TRANS) ? (uint32_t)TRANS : towrite;\r
1075         \r
1076         if (eraseInvariant) \r
1077         {\r
1078             noerase = false;\r
1079         } else\r
1080         {\r
1081             if (curr_addr < SECT_SIZE) \r
1082             {\r
1083                 noerase = true;\r
1084             } else\r
1085             {\r
1086                 noerase = false;\r
1087             }\r
1088         }\r
1089 \r
1090         if (!noerase)\r
1091         {        \r
1092             if (!write(curr_addr, p, trans, noerase, true))\r
1093             {\r
1094                 printStatus(1);\r
1095                 return false;\r
1096             }\r
1097         }\r
1098         p += trans;\r
1099         curr_addr += trans;\r
1100         towrite -= trans;\r
1101 \r
1102         // Report\r
1103         if (report)\r
1104         {\r
1105             uint32_t new_perc = ((cnt - towrite) * 100) / cnt;\r
1106             if (new_perc != perc)\r
1107             {\r
1108                 printPercent(new_perc,0);\r
1109                 fflush(stdout);\r
1110                 perc = new_perc;\r
1111             }\r
1112         }\r
1113     }\r
1114 \r
1115     if (report)\r
1116     {\r
1117         printPercent(100,0);\r
1118         printStatus(0);\r
1119         fflush(stdout);\r
1120     }\r
1121 \r
1122     return true;\r
1123 } //  Flash::write_image\r
1124 \r
1125 \r
1126 /*\r
1127         Note:\r
1128         for read - data return in native Endian mode,\r
1129         for write - data should be written in BigEndian mode \r
1130         check where data is actually converted !!!!\r
1131 */\r
1132 ib_api_status_t Flash::access(hca_dev_t *dev, u_int32_t offset, void *p_data, uint32_t length, uint32_t operation )\r
1133 {\r
1134         \r
1135         ib_ci_op_t                      ci_op;\r
1136         ib_api_status_t         ib_status;\r
1137 \r
1138         BOOL                    dev_status;\r
1139         DWORD                   bytes_ret;\r
1140 \r
1141         ci_op.buf_size = length;\r
1142         ci_op.p_buf     =  p_data;\r
1143         ci_op.buf_info = offset;\r
1144         ci_op.num_bytes_ret = sizeof (ib_ci_op_t);\r
1145         ci_op.command = operation;\r
1146 \r
1147         ib_status = ib_ci_call (m_mf.h_ca, NULL, 0, &ci_op);\r
1148 \r
1149         if ( ib_status != IB_SUCCESS )\r
1150         {\r
1151                 FW_TRACE (FW_DBG_ERROR,("Failed ib_ci_call return status %#x\n", ib_status ));\r
1152                 return ib_status;\r
1153         }\r
1154         return IB_SUCCESS;\r
1155 }\r
1156 \r
1157 bool getGUIDsFromFlash(FBase &device, uint64_t guids[GUIDS])\r
1158 {\r
1159     uint32_t NODE_GUIDH, NODE_GUIDL;\r
1160     uint32_t PORT1_GUIDH, PORT1_GUIDL;\r
1161     uint32_t PORT2_GUIDH, PORT2_GUIDL;\r
1162     uint32_t prim_ptr;\r
1163     uint32_t signature;\r
1164     PS    ps;\r
1165     bool isFailSafe = false;\r
1166 \r
1167     READ4(device, 0x24, &signature, "Signature");\r
1168     TOCPU1(signature);\r
1169 \r
1170     if (signature == SIGNATURE)\r
1171     {\r
1172         // Fail Safe image\r
1173         \r
1174         // Assume flash has been verified, and both images have the same guids, therefore,\r
1175         // we only need to read the primary image's guids\r
1176         device.read(SECT_SIZE, &ps, sizeof(ps));\r
1177         TOCPUBY(ps,sizeof(ps));\r
1178         READ4(device, ps.fi_addr+0x24, &prim_ptr, "Primary Section");        \r
1179         M_DEBUG("Firmware Address  : 0x%"PRIx32"\n", ps.fi_addr);\r
1180         M_DEBUG("Node GUID Offset  : 0x%"PRIx32"\n", prim_ptr);        \r
1181         prim_ptr = BE2CPU32(prim_ptr)+ps.fi_addr;\r
1182         isFailSafe = true;\r
1183     }\r
1184     else\r
1185     {\r
1186         // Short image\r
1187         prim_ptr = signature;       \r
1188     }\r
1189 \r
1190         printf("Found valid GUID pointer     : %08"PRIx32"\n", prim_ptr);\r
1191     if (prim_ptr < MST_MAX_FLASH || isFailSafe) \r
1192     {\r
1193         READ4(device, prim_ptr, &NODE_GUIDH, "Node GUID High");\r
1194         READ4(device, prim_ptr+4, &NODE_GUIDL, "Node GUID Low");\r
1195         guids[0] = BE2CPU32(NODE_GUIDH);\r
1196         guids[0] = (guids[0]<<32) | BE2CPU32(NODE_GUIDL);\r
1197         READ4(device, prim_ptr+8, &PORT1_GUIDH, "Port 1 GUID High");\r
1198         READ4(device, prim_ptr+12, &PORT1_GUIDL, "Port 1 GUID Low");\r
1199         guids[1] = BE2CPU32(PORT1_GUIDH);\r
1200         guids[1] = (guids[1]<<32) | BE2CPU32(PORT1_GUIDL);\r
1201         READ4(device, prim_ptr+16, &PORT2_GUIDH, "Port 2 GUID High");\r
1202         READ4(device, prim_ptr+20, &PORT2_GUIDL, "Port 2 GUID Low");\r
1203         guids[2] = BE2CPU32(PORT2_GUIDH);\r
1204         guids[2] = (guids[2]<<32) | BE2CPU32(PORT2_GUIDL);\r
1205 \r
1206         guids[3] = guids[0];\r
1207         printf("Found device's existing GUIDs:\n");\r
1208         printf("Node  GUID                   : 0x%016"PRIx64"\n", guids[0]);\r
1209         printf("Port1 GUID                   : 0x%016"PRIx64"\n", guids[1]);\r
1210         printf("Port2 GUID                   : 0x%016"PRIx64"\n", guids[2]);\r
1211     } else \r
1212     {\r
1213         printf("Found an invalid GUID pointer!\n");\r
1214         return false;\r
1215     }\r
1216 \r
1217     return true;\r
1218 }\r
1219 \r
1220 bool getGUIDs(char *guidString, uint64_t guids[GUIDS])\r
1221 {\r
1222     uint32_t PORT1_GUIDH, PORT1_GUIDL;\r
1223     uint32_t PORT2_GUIDH, PORT2_GUIDL;\r
1224     uint64_t GUID; //strtoull(guidString, (char **)NULL, 0);\r
1225     uint32_t NODE_GUIDH;\r
1226     uint32_t NODE_GUIDL;\r
1227 \r
1228     if (!getGUID(guidString, &GUID))\r
1229     {\r
1230         return false;\r
1231     }\r
1232 \r
1233     NODE_GUIDH = (uint32_t)(GUID >> 32);\r
1234     NODE_GUIDL = (uint32_t)GUID;\r
1235 \r
1236     if ((NODE_GUIDH & 0xffffffff) == 0x00066a00\r
1237         && ((NODE_GUIDL & 0xf8000000) == 0x98000000 \r
1238             || (NODE_GUIDL & 0xf8000000) == 0xb0000000))\r
1239     {\r
1240         // Always make it a InfiniCon NODE GUID\r
1241         NODE_GUIDL = (NODE_GUIDL & 0x0FFFFFFF) | 0x98000000;\r
1242 \r
1243         // Convert to the InfiniCon Node Guid Convention.\r
1244         PORT1_GUIDH = NODE_GUIDH;\r
1245         PORT1_GUIDL = (NODE_GUIDL & 0x07ffffff) | 0xa0000000;\r
1246         PORT2_GUIDH = NODE_GUIDH | 1;\r
1247         PORT2_GUIDL = (NODE_GUIDL & 0x07ffffff) | 0xa0000000;\r
1248     } else {\r
1249         // Treat everything else as a Mellanox Node Guid Convention.\r
1250         PORT1_GUIDH=NODE_GUIDH;\r
1251         PORT1_GUIDL=NODE_GUIDL+1;\r
1252         if ( PORT1_GUIDL==0 ) {\r
1253             PORT1_GUIDH++;\r
1254         }\r
1255         PORT2_GUIDH=PORT1_GUIDH;\r
1256         PORT2_GUIDL=PORT1_GUIDL+1;\r
1257         if ( PORT2_GUIDL==0 ) {\r
1258             PORT2_GUIDH++;\r
1259         }\r
1260     }\r
1261 \r
1262     guids[0] = NODE_GUIDH;\r
1263     guids[0] = (guids[0]<<32) | NODE_GUIDL;\r
1264 \r
1265     guids[1] = PORT1_GUIDH;\r
1266     guids[1] = (guids[1]<<32) | PORT1_GUIDL;\r
1267 \r
1268     guids[2] = PORT2_GUIDH;\r
1269     guids[2] = (guids[2]<<32) | PORT2_GUIDL;\r
1270 \r
1271     guids[3] = guids[0];\r
1272 \r
1273     printf("Using user specified GUIDs   :\n");\r
1274     printf("Node   GUID                  : 0x%016"PRIx64"\n", guids[0]);\r
1275     printf("Port 1 GUID                  : 0x%016"PRIx64"\n", guids[1]);\r
1276     printf("Port 2 GUID                  : 0x%016"PRIx64"\n", guids[2]);\r
1277     return true;\r
1278 }\r
1279 \r
1280 bool _silent = false;\r
1281 #define report  printf\r
1282 \r
1283 ////////////////////////////////////////////////////////////////////////\r
1284 bool isInvariantSectionEqual(FBase& f1, FBase& f2)\r
1285 {\r
1286     uint32_t size1;\r
1287     uint32_t size2;\r
1288     uint32_t beg  = 0x0;\r
1289     uint32_t offs = 0x28;\r
1290     const char* pr = "isInvariantSectionEqual";\r
1291     uint32_t *buf1;\r
1292     uint32_t *buf2;\r
1293     bool status = true;\r
1294 \r
1295     // Size\r
1296     READ4(f1, offs+beg+4, &size1, pr);\r
1297     READ4(f2, offs+beg+4, &size2, pr);\r
1298     TOCPU1(size1);\r
1299     TOCPU1(size2);\r
1300 \r
1301 //    M_DEBUG("Invariant sector size1: %"PRId32"\n", size1);\r
1302 //    M_DEBUG("Invariant sector size2: %"PRId32"\n", size2);\r
1303 \r
1304     if (size1 != size2)\r
1305     {\r
1306         M_DEBUG("Invariant sector sizes do not match.\n");\r
1307         return false;\r
1308     }\r
1309 \r
1310     buf1 = (uint32_t *)cl_zalloc((size1+4)*4);\r
1311         if (!buf1)\r
1312         {\r
1313             cl_dbg_out("Failed to allocate memory size =%d", size1+4 );\r
1314             return false;\r
1315         }\r
1316     buf2 = (uint32_t *)cl_zalloc( (size2+4)*4);\r
1317         if (!buf2)\r
1318         {\r
1319             cl_free(buf1);\r
1320             cl_dbg_out("Failed to allocate memory size =%d", size2+4 );\r
1321             return false;\r
1322         }\r
1323     \r
1324     READBUF(f1, offs+beg, buf1, (size1+4)*4, pr);\r
1325     READBUF(f2, offs+beg, buf2, (size2+4)*4, pr);\r
1326     \r
1327     if ( cl_memcmp(buf1, buf2, (size1+4)*4) )\r
1328     {\r
1329        // M_DEBUG("Invariant sections are not equal.\n");\r
1330         status = false;\r
1331     }\r
1332     cl_free(buf1);\r
1333     cl_free(buf2);    \r
1334     return status;\r
1335 } // isInvariantSectionEqual\r
1336 \r
1337 ////////////////////////////////////////////////////////////////////////\r
1338 bool checkBoot2(FBase& f, uint32_t beg, uint32_t offs, uint32_t& next, const char *pref)\r
1339 {\r
1340     char         pr[256];\r
1341     uint32_t size;\r
1342     uint32_t *buff;\r
1343         uint32_t *safe_buf;\r
1344     //sprintf(pr, "%s /0x%08"PRIx32"/ (BOOT2)", pref, offs+beg);\r
1345 \r
1346     // Size\r
1347     READ4(f, offs+beg+4, &size, pr);\r
1348     TOCPU1(size);\r
1349 \r
1350     if (size > 1048576 || size < 4)\r
1351     {\r
1352         report("%s /0x%08"PRIx32"/ - unexpected size (0x%x)\n", pr, offs+beg+4, size);\r
1353         return false;\r
1354     }\r
1355 \r
1356     //sprintf(pr, "%s /0x%08"PRIx32"-0x%08"PRIx32" (0x%06"PRIx32")/ (BOOT2)", pref, offs+beg, offs+beg+(size+4)*4-1, (size+4)*4);\r
1357 \r
1358     // CRC\r
1359     Crc16        crc;\r
1360     buff = (uint32_t*)cl_zalloc((size+4)*4);\r
1361         if (buff)\r
1362                 safe_buf = buff;\r
1363     READBUF(f, offs+beg, buff, (size+4)*4, pr);\r
1364     TOCPU(buff, (size+4)*4 );\r
1365     CRC1(crc, buff, (size+4)*4 );\r
1366     crc.finish();\r
1367     uint32_t crc_act = *(buff+size+3);\r
1368     if (crc.get() != crc_act)\r
1369     {\r
1370         report("%s /0x%08"PRIx32"/ - wrong CRC (exp:0x%x, act:0x%x)\n",\r
1371                pr, offs+beg, crc.get(), crc_act);\r
1372         cl_free(safe_buf);\r
1373         return false;\r
1374     }\r
1375 \r
1376     //report("%s - OK\n", pr);\r
1377     next = offs + (size+4)*4;\r
1378     cl_free(safe_buf);\r
1379     return true;\r
1380 } // checkBoot2\r
1381 \r
1382 static uint32_t part_cnt;\r
1383 \r
1384 ////////////////////////////////////////////////////////////////////////\r
1385 bool checkGen(FBase& f, uint32_t beg,\r
1386               uint32_t offs, uint32_t& next, const char *pref)\r
1387 {\r
1388     uint32_t size=0;\r
1389     char         pr[1024];\r
1390     GPH          gph;\r
1391     cl_memset(pr,0,1024);\r
1392     // GPH\r
1393     sprintf(pr, "%s /0x%08"PRIx32"/ (GeneralHeader)", pref, offs+beg);\r
1394     READBUF(f, offs+beg, &gph, sizeof(GPH), pr);\r
1395     TOCPUBY(gph, sizeof(GPH));\r
1396 \r
1397     // Body\r
1398 \r
1399     part_cnt++;\r
1400 \r
1401     // May be BOOT3?\r
1402     if (gph.type < H_FIRST  ||  gph.type > H_LAST)\r
1403     {\r
1404         if (part_cnt > 2)\r
1405         {\r
1406             report("%s /0x%"PRIx32"/ - Invalid partition type (%"PRIx32")\n",\r
1407                    pref, offs+beg, gph.type);\r
1408             return false;\r
1409         }\r
1410         else\r
1411             return checkBoot2(f, beg, offs, next, pref);\r
1412     }\r
1413 \r
1414     // All partitions here\r
1415     offs += beg;\r
1416     switch(gph.type)\r
1417     {\r
1418     case H_DDR:\r
1419         size = gph.size * sizeof(uint32_t);\r
1420         sprintf(pr, "%s /0x%08"PRIx32"-0x%08"PRIx32" (0x%06"PRIx32")/ (DDR)",\r
1421                 pref, offs, offs+size+(unsigned)sizeof(gph)+3, size+(unsigned)sizeof(gph)+4);\r
1422         break;\r
1423     case H_CNF:\r
1424         size = gph.size * sizeof(uint32_t);\r
1425         sprintf(pr, "%s /0x%08"PRIx32"-0x%08"PRIx32" (0x%06"PRIx32")/ (Configuration)",\r
1426                 pref, offs, offs+size+(unsigned)sizeof(gph)+3, size+(unsigned)sizeof(gph)+4);\r
1427         break;\r
1428     case H_JMP:\r
1429         size = gph.size * sizeof(uint32_t);\r
1430         sprintf(pr, "%s /0x%08"PRIx32"-0x%08"PRIx32" (0x%06"PRIx32")/ (Jump addresses)",\r
1431                 pref, offs, offs+size+(unsigned)sizeof(gph)+3, size+(unsigned)sizeof(gph)+4);\r
1432         break;\r
1433     case H_EMT:\r
1434         size = gph.size;\r
1435         size = (size + 3) / 4 * 4;\r
1436         sprintf(pr, "%s /0x%08"PRIx32"-0x%08"PRIx32" (0x%06"PRIx32")/ (EMT Service)",\r
1437                 pref, offs, offs+size+(unsigned)sizeof(gph)+3, size+(unsigned)sizeof(gph)+4);\r
1438         break;\r
1439     case H_FW_CONF:\r
1440         size = gph.size * sizeof(uint32_t);\r
1441         sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (FW Configuration)",\r
1442                 pref, offs, offs+size+(uint32_t)sizeof(gph)+3,\r
1443                 size+(uint32_t)sizeof(gph)+4);\r
1444         break;\r
1445     case H_ROM:\r
1446         size = gph.size * sizeof(uint32_t);\r
1447         sprintf(pr, "%s /0x%08"PRIx32"-0x%08"PRIx32" (0x%06"PRIx32")/ (ROM)",\r
1448                 pref, offs, offs+size+(unsigned)sizeof(gph)+3, size+(unsigned)sizeof(gph)+4);\r
1449         break;\r
1450     case H_GUID:\r
1451         size = gph.size * sizeof(uint32_t);\r
1452         sprintf(pr, "%s /0x%08"PRIx32"-0x%08"PRIx32" (0x%06"PRIx32")/ (GUID)",\r
1453                 pref, offs, offs+size+(unsigned)sizeof(gph)+3, size+(unsigned)sizeof(gph)+4);\r
1454         break;\r
1455     case H_USER_DATA:\r
1456         size = gph.size * sizeof(uint32_t);\r
1457         sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (User Data)",\r
1458                 pref, offs, offs+size+(uint32_t)sizeof(gph)+3,\r
1459                 size+(uint32_t)sizeof(gph)+4);\r
1460         break;\r
1461     case H_BOARD_ID:\r
1462         size = gph.size * sizeof(uint32_t);\r
1463         sprintf(pr, "%s /0x%08"PRIx32"-0x%08"PRIx32" (0x%06"PRIx32")/ (Board ID)",\r
1464                 pref, offs, offs+size+(unsigned)sizeof(gph)+3,size+(u_int32_t)sizeof(gph)+4);\r
1465         break;  \r
1466     default:\r
1467         // For forward compatibility, try analyzing even if section type is uncknown\r
1468         // Assuming the size is in DW, like all other sections (except emt service).\r
1469         // If this assumption is wrong, CRC calc would fail - no harm done.\r
1470         size = gph.size * sizeof(uint32_t);\r
1471         sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (UNKNOWN SECTION TYPE (%d))",\r
1472                 pref, offs, offs+size+(uint32_t)sizeof(gph)+3,\r
1473                 size+(uint32_t)sizeof(gph)+4, gph.type);\r
1474     }\r
1475 \r
1476     // CRC\r
1477     Crc16        crc;\r
1478     uint32_t  *buff;\r
1479     buff = (uint32_t*)cl_zalloc(size);\r
1480     READBUF(f, offs+sizeof(gph), buff, size, pr);\r
1481     TOCPU(buff,size);\r
1482     CRCBY(crc, gph, sizeof(GPH));\r
1483     CRC(crc, buff,size);\r
1484     crc.finish();\r
1485     uint32_t crc_act;\r
1486     READ4(f, offs+sizeof(gph)+size, &crc_act, pr);\r
1487     TOCPU1(crc_act);\r
1488     if (crc.get() != crc_act)\r
1489     {\r
1490         report("%s /0x%08"PRIx32"/ - wrong CRC (exp:0x%x, act:0x%x)\n",\r
1491                pr, offs, crc.get(), crc_act);\r
1492         cl_free(buff);\r
1493         return false;\r
1494     }\r
1495 \r
1496     report("%s - OK\n", pr);\r
1497     next = gph.next;\r
1498     cl_free(buff);\r
1499     return true;\r
1500 } // checkGen\r
1501 \r
1502 ////////////////////////////////////////////////////////////////////////\r
1503 bool checkPS(FBase& f, uint32_t offs, uint32_t& next, const char *pref)\r
1504 {\r
1505     Crc16 crc;\r
1506     PS    ps;\r
1507     f.read(offs, &ps, sizeof(ps));\r
1508     TOCPUBY(ps, sizeof(ps));\r
1509 \r
1510     // Signature\r
1511     if (ps.signature != SIGNATURE)\r
1512     {\r
1513         report("%s Pointer Sector /0x%08"PRIx32"/ - wrong signature (%08"PRIx32")\n",\r
1514                pref, offs, ps.signature);\r
1515         return false;\r
1516     }\r
1517 \r
1518     // CRC\r
1519     CRC1BY(crc, ps, sizeof(PS));\r
1520     crc.finish();\r
1521     if (crc.get() != ps.crc016)\r
1522     {\r
1523         report("%s Pointer Sector /0x%08"PRIx32"/ - wrong CRC (exp:0x%"PRIx32", act:0x%x)\n",\r
1524                pref, offs, ps.crc016, crc.get());\r
1525         return false;\r
1526     }\r
1527 \r
1528     next = ps.fi_addr;\r
1529     report("%s Image /0x%08"PRIx32"-0x%08"PRIx32" (0x%06"PRIx32")/ - OK\n", pref, offs,\r
1530            offs+(unsigned)sizeof(ps)-1, (unsigned)sizeof(ps));\r
1531     return true;\r
1532 } // checkPS\r
1533 \r
1534 ////////////////////////////////////////////////////////////////////////\r
1535 bool checkList(FBase& f, uint32_t offs, const char *pref)\r
1536 {\r
1537     uint32_t next_ptr;\r
1538 \r
1539     CHECKB2(f, offs, 0x28, next_ptr, pref);\r
1540     part_cnt = 1;\r
1541     while (next_ptr && next_ptr != 0xff000000)\r
1542         CHECKGN(f, offs, next_ptr, next_ptr, pref);\r
1543     return true;\r
1544 } // checkList\r
1545 \r
1546 ////////////////////////////////////////////////////////////////////////\r
1547 bool FBase::verify()\r
1548 {\r
1549     uint32_t prim_ptr, scnd_ptr;\r
1550     uint32_t signature;\r
1551     \r
1552     READ4((*this), 0x24, &signature, "Signature");\r
1553     TOCPU1(signature);\r
1554     if (signature == SIGNATURE)\r
1555     {\r
1556         // Full image\r
1557         report("\nFailsafe image:\n\n");\r
1558         CHECKB2((*this), 0, 0x28, prim_ptr, "Invariant      ");\r
1559         report("\n");\r
1560         if (checkPS((*this), SECT_SIZE, prim_ptr, "Primary  "))\r
1561             CHECKLS((*this), prim_ptr, "               ");\r
1562         report("\n");\r
1563         if (checkPS((*this), SECT_SIZE * 2, scnd_ptr, "Secondary"))\r
1564             CHECKLS((*this), scnd_ptr, "               ");\r
1565     }\r
1566     else\r
1567     {\r
1568         // Short image\r
1569         report("\nShort image:\n");\r
1570         CHECKLS((*this), 0, "    ");\r
1571     }\r
1572     \r
1573     return true;\r
1574 } // Verify\r
1575 \r
1576 \r
1577 ////////////////////////////////////////////////////////////////////////\r
1578 //                                                                    //\r
1579 // ****************************************************************** //\r
1580 //                       GUIDs TREATMENT                              //\r
1581 // ****************************************************************** //\r
1582 //                                                                    //\r
1583 ////////////////////////////////////////////////////////////////////////\r
1584 #define GETGUID(s, g) do { if (!getGUID(s,g)) return 1; } while (0)\r
1585 #define GETBSN(s, g)  do { if (!getBSN(s,g)) return 1; } while (0)\r
1586 \r
1587 #define BSN_RET do {                                            \\r
1588     printf("Invalid BSN. Should be MTxxxxxRddmmyy-nnn[-cc]\n"); \\r
1589     return false;                                               \\r
1590 } while(0)\r
1591 #define BSN_RET1(s) do {                                             \\r
1592     printf("Valid BSN format is: MTxxxxxRddmmyy-nnn[-cc]\n%s.\n",s); \\r
1593     return false;                                                    \\r
1594 } while(0)\r
1595 uint32_t BSN_subfield(const char *s, uint32_t beg, uint32_t len)\r
1596 {\r
1597     char buf[64];\r
1598     strncpy(buf, &s[beg], len);\r
1599     buf[len] = '\0';\r
1600     return strtoul(&buf[0], 0, 10);\r
1601 }\r
1602 bool getBSN(char *s, uint64_t *guid)\r
1603 {\r
1604     const uint64_t COMPANY_ID = 0x0002c9;\r
1605     const uint64_t  TYPE      = 1;\r
1606     bool cc_present = false;\r
1607     char *p;\r
1608     uint32_t  i;\r
1609 \r
1610     // Convert to lowercase\r
1611     for (p = s; *p; p++)\r
1612         *p = (char)tolower(*p);\r
1613 \r
1614     // Check validity\r
1615     p = s;\r
1616     if (strncmp(p, "mt", 2))     // MT\r
1617         BSN_RET;\r
1618     p += 2;\r
1619     for (i=0; i<5; i++)\r
1620         if (!isdigit(*p++))      // xxxxx\r
1621             BSN_RET;\r
1622     if (*p < 'a' || *p > 'z')    // R\r
1623         BSN_RET;\r
1624     p++;\r
1625     for (i=0; i<6; i++)          // ddmmyy\r
1626         if (!isdigit(*p++))\r
1627             BSN_RET;\r
1628     if (*p++ != '-')             // -\r
1629         BSN_RET;\r
1630     for (i=0; i<3; i++)          // nnn\r
1631         if (!isdigit(*p++))\r
1632             BSN_RET;\r
1633     if (*p)\r
1634     {\r
1635         cc_present = true;\r
1636         if (*p++ != '-')         // -\r
1637             BSN_RET;\r
1638         for (i=0; i<2; i++)      // cc\r
1639             if (!isdigit(*p++))\r
1640                 BSN_RET;\r
1641     }\r
1642 \r
1643     uint32_t dd = BSN_subfield(s, 8, 2);\r
1644     if (dd > 31)\r
1645         BSN_RET1("Day (dd) should not exceed 31");\r
1646     if (!dd)\r
1647         BSN_RET1("Day (dd) can't be zero");\r
1648     uint32_t mm = BSN_subfield(s, 10, 2);\r
1649     if (mm > 12)\r
1650         BSN_RET1("Months (mm) should not exceed 12");\r
1651     if (!mm)\r
1652         BSN_RET1("Months (mm) can't be zero");\r
1653     uint32_t yy = BSN_subfield(s, 12, 2);\r
1654     if (yy > 99)\r
1655         BSN_RET1("Year (yy) should not exceed 99");\r
1656     if (!yy)\r
1657         BSN_RET1("Year (yy) can't be zero");\r
1658     uint32_t num = BSN_subfield(s, 15, 3);\r
1659     if (num > 999)\r
1660         BSN_RET1("Number (num) should not exceed 999");\r
1661     if (!num)\r
1662         BSN_RET1("Number (num) can't be zero");\r
1663     uint32_t cc = 1;\r
1664     if (cc_present)\r
1665     {\r
1666         cc = BSN_subfield(s, 19, 2);\r
1667         if (cc > 14)\r
1668             BSN_RET1("Chip number (cc) should not exceed 14");\r
1669         if (!cc)\r
1670             BSN_RET1("Chip number (cc) can't be zero");\r
1671     }\r
1672     uint64_t id = ((((yy*12+mm-1)*31+ dd-1) * 1000) + num-1) * 112;\r
1673     id += (cc-1)*8;\r
1674     *guid = (COMPANY_ID << 40) | (TYPE << 32) | id;\r
1675     return true;\r
1676 }\r
1677 \r
1678 bool getGUID(const char *s, uint64_t *guid)\r
1679 {\r
1680     char          str[17], *endp;\r
1681     int          i,j;\r
1682     uint32_t      h,l;\r
1683     memset(str, '0', 15);\r
1684     str[16] = '\0';\r
1685 \r
1686     for (i=(int)strlen(s)-1,j=15;i >= 0 && j >= 0 ; i-- )\r
1687     {\r
1688         if (isxdigit(s[i]))\r
1689             str[j--] = s[i];\r
1690     }\r
1691     l = strtoul(&str[8], &endp, 16);\r
1692     if (*endp)\r
1693     {\r
1694         printf("Invalid GUID syntax (%s)\n", &str[8]);\r
1695         return false;\r
1696     }\r
1697     str[8] = '\0';\r
1698     h = strtoul(&str[0], &endp, 16);\r
1699     if (*endp)\r
1700     {\r
1701         printf("Invalid GUID syntax (%s)\n", str);\r
1702         return false;\r
1703     }\r
1704     *guid = ((uint64_t)h << 32) | l;\r
1705     return true;\r
1706 } // getGUID\r
1707 \r
1708 ////////////////////////////////////////////////////////////////////////\r
1709 bool extractGUIDptr(uint32_t sign, uint32_t *buf, uint32_t buf_len,\r
1710                      char *pref, uint32_t *ind, uint32_t *nguids)\r
1711 {\r
1712     uint32_t offs = 0;\r
1713 \r
1714     // Check signature\r
1715     if (sign)\r
1716     {\r
1717         uint32_t signature = buf[(sign + 8)/4];\r
1718         TOCPU1(signature);\r
1719         if (signature != SIGNATURE)\r
1720         {\r
1721             printf("%s pointer section not valid\n", pref);\r
1722             return false;\r
1723         }\r
1724         offs = buf[sign/4];\r
1725         TOCPU1(offs);\r
1726     }\r
1727 \r
1728     // Get GUID ptr\r
1729     *ind = buf[(offs+0x24)/4];\r
1730     TOCPU1(*ind);\r
1731     *ind += offs;\r
1732     if (*ind >= (uint32_t)buf_len)\r
1733     {\r
1734         printf("%s image - insane GUID pointer (%08"PRIx32")\n", pref, *ind);\r
1735         return false;\r
1736     }\r
1737     *nguids = buf[*ind/4 - 3];\r
1738     TOCPU1(*nguids);\r
1739     *nguids /= 2;\r
1740 \r
1741     // More sanity check\r
1742     if (*nguids > GUIDS)\r
1743     {\r
1744         printf("%s image - insane number of GUIDs (%d)\n", pref, *nguids);\r
1745         return false;\r
1746     }\r
1747 \r
1748     return true;\r
1749 } // extractGUIDptr\r
1750 \r
1751 ////////////////////////////////////////////////////////////////////////\r
1752 void patchGUIDsSection(\r
1753     uint32_t *buf, \r
1754     uint32_t ind,                      \r
1755     uint64_t guids[GUIDS], \r
1756     uint32_t nguids)\r
1757 {\r
1758     uint32_t       i, word;\r
1759     uint32_t       new_buf[GUIDS*2];\r
1760     Crc16              crc;\r
1761 \r
1762     // Form new GUID section\r
1763     for (i=0; i<(uint32_t)nguids; i++)\r
1764     {\r
1765         new_buf[i*2] = (uint32_t)(guids[i] >> 32);\r
1766         new_buf[i*2+1] = (uint32_t)(guids[i] & 0xffffffff);\r
1767     }\r
1768 \r
1769     // Calculate new CRC16\r
1770     for (i=ind/4 - 4; i<ind/4; i++)\r
1771     {\r
1772         word = buf[i];\r
1773         TOCPU1(word);\r
1774         crc << word;\r
1775     }\r
1776     for (i=0; i<(uint32_t)nguids*2; i++)\r
1777         crc << new_buf[i];\r
1778 \r
1779     // Patch GUIDs\r
1780     TOCPU(new_buf,GUIDS*2*4);\r
1781     memcpy(&buf[ind/4], &new_buf[0], nguids * 2 * sizeof(uint32_t));\r
1782 \r
1783     // Insert new CRC\r
1784     crc.finish();\r
1785     word = crc.get();\r
1786     TOCPU1(word);\r
1787     buf[ind/4 + nguids*2] = word;\r
1788 } // patchGUIDsSection\r
1789 \r
1790 ////////////////////////////////////////////////////////////////////////\r
1791 bool patchGUIDs(FImage& f, uint64_t guids[GUIDS],\r
1792                bool interactive)\r
1793 {\r
1794     uint64_t           old_guids[GUIDS];\r
1795     uint32_t       *buf = f.getBuf();\r
1796     uint32_t                buf_len = f.getBufLength();\r
1797     uint32_t       signature = buf[0x24/4];\r
1798     uint32_t       ind1=0,ind2=0;\r
1799     uint32_t                nguid1, nguid2;\r
1800 \r
1801     TOCPU1(signature);\r
1802     if (signature == SIGNATURE)\r
1803     {\r
1804         // fail safe       \r
1805         M_DEBUG("Extracting GUIDs from PPS    : ");\r
1806         if (!extractGUIDptr(SECT_SIZE, buf, buf_len, "Primary", &ind1, &nguid1))\r
1807         {\r
1808             M_DEBUG("Failed\n");\r
1809             return false;\r
1810         }\r
1811 \r
1812         M_DEBUG("[SUCCESS]\n");\r
1813 \r
1814         M_DEBUG("Extracting GUIDs from SPS    : ");\r
1815         if (!extractGUIDptr(SECT_SIZE*2, buf, buf_len, "Secondary", &ind2,\r
1816                             &nguid2))\r
1817         {\r
1818             M_DEBUG("Failed\n");\r
1819             return false;\r
1820         }\r
1821         M_DEBUG("[SUCCESS]\n");\r
1822     }\r
1823     else\r
1824     {\r
1825         // Short image\r
1826         M_DEBUG("Extracting GUIDs from PS     : ");\r
1827         if (!extractGUIDptr(0, buf, buf_len, "Primary", &ind1, &nguid1))\r
1828         {\r
1829             M_DEBUG("Failed\n");\r
1830             return false;\r
1831         }\r
1832 \r
1833         M_DEBUG("[SUCCESS]\n");\r
1834     }\r
1835 \r
1836     // Print old GUIDs and get confirmation\r
1837     if (interactive)\r
1838     {\r
1839         bool old_guids_fmt = nguid1 < GUIDS;\r
1840         for (uint32_t i=0; i<GUIDS; i++)\r
1841         {\r
1842             uint32_t h = buf[ind1/4 + i*2];\r
1843             TOCPU1(h);\r
1844             uint32_t l = buf[ind1/4 + i*2 + 1];\r
1845             TOCPU1(l);\r
1846             old_guids[i] = ((uint64_t)h << 32) | l;\r
1847         }\r
1848         if ( !(old_guids[0] == guids[0]) || !(old_guids[1] == guids[1]) || !(old_guids[2] == guids[2]))\r
1849         {\r
1850             if (old_guids_fmt)\r
1851                 printf("    Old image!!!! Only %d GUIDs may be set.\n", nguid1);\r
1852             printf("    Old GUIDs (inside image) are:\n");\r
1853             printf("        Node:      %016"PRIx64"\n", old_guids[0]);\r
1854             printf("        Port1:     %016"PRIx64"\n", old_guids[1]);\r
1855             printf("        Port2:     %016"PRIx64"\n", old_guids[2]);\r
1856             if (!old_guids_fmt)\r
1857                 printf("        Sys.Image: %016"PRIx64"\n", old_guids[3]);\r
1858             printf("\n    You are about to change them to the following GUIDs:\n");\r
1859             printf("        Node:      %016"PRIx64"\n", guids[0]);\r
1860             printf("        Port1:     %016"PRIx64"\n", guids[1]);\r
1861             printf("        Port2:     %016"PRIx64"\n", guids[2]);\r
1862             if (!old_guids_fmt)\r
1863                 printf("        Sys.Image: %016"PRIx64"\n", guids[3]);\r
1864             printf("\n    Is it OK ? (y/n) [n] : ");\r
1865             fflush(stdout);\r
1866             char c = (char)getchar();\r
1867             if (c != '\n')\r
1868                 while (getchar() != '\n');\r
1869             if (c != 'y')\r
1870                 return false;\r
1871         }\r
1872     }\r
1873 \r
1874     // Path GUIDs section\r
1875     patchGUIDsSection(buf, ind1, guids, nguid1);\r
1876 \r
1877     M_DEBUG("Inserting GUIDs into PPS     : [SUCCESS]\n");\r
1878 \r
1879     if (ind2)\r
1880     {\r
1881         M_DEBUG("Inserting GUIDs into SPS     : [SUCCESS]\n");\r
1882         patchGUIDsSection(buf, ind2, guids, nguid2);\r
1883     }\r
1884 \r
1885     return true;\r
1886 } // patchGUIDs\r
1887 \r
1888 void patchVSDSection(\r
1889     uint32_t *buffer, \r
1890     uint32_t pointerSectorOffset,\r
1891     uint32_t companyid,\r
1892     time_t   timestamp,\r
1893     char     *revision)\r
1894 {\r
1895     uint32_t       i, x, word, offset=0;\r
1896     uint32_t       newbuffer[sizeof(PS)];\r
1897     Crc16          crc;    \r
1898     PS ps;\r
1899 \r
1900     memcpy(newbuffer, (buffer+pointerSectorOffset/sizeof(uint32_t)), sizeof(PS));\r
1901 \r
1902     memcpy(&ps, newbuffer, sizeof(PS));        \r
1903     ps.vsd[0] = __cpu_to_be32(companyid);\r
1904     // Currently time_t is 32 bits, but this will only last until the \r
1905     // year 2037.  Therefore, I am leaving 64bits for when the time_t\r
1906     // size is increased which will probably provide an Epoch time far larger \r
1907     // than man will exist.  Note:  Although, I have provided the space for a \r
1908     // larger time_t this code will need to be modified to handle the 64bit\r
1909     // Epoch time before 2037.\r
1910 #ifdef _WIN64\r
1911         *((uint64_t*)&ps.vsd[1]) = cl_ntoh64(timestamp);\r
1912 #else\r
1913     ps.vsd[1] = (uint32_t)0;\r
1914     ps.vsd[2] = __cpu_to_be32(timestamp);\r
1915 #endif\r
1916     \r
1917     if (NULL != revision)\r
1918     {\r
1919         for (x=3;x<9;x++)\r
1920         {          \r
1921             memcpy(&ps.vsd[x], revision+offset, sizeof(uint32_t));\r
1922             ps.vsd[x] = __cpu_to_be32(ps.vsd[x]);\r
1923             offset = offset + 4;\r
1924         }\r
1925     }\r
1926     memcpy(newbuffer, &ps, sizeof(PS));\r
1927 \r
1928     // Calculate new CRC16\r
1929     for (i=0; i<((sizeof(PS)/sizeof(uint32_t))-1); i++)\r
1930     {\r
1931         word = newbuffer[i];\r
1932         TOCPU1(word);\r
1933         crc << word;\r
1934     }\r
1935 \r
1936     // Insert new CRC\r
1937     crc.finish();\r
1938     word = crc.get();\r
1939     TOCPU1(word);\r
1940     ps.crc016 = word;\r
1941     memcpy(newbuffer, &ps, sizeof(PS));\r
1942     // patch VSD in buffer\r
1943     memcpy(buffer+pointerSectorOffset/sizeof(uint32_t), newbuffer, sizeof(PS));\r
1944 \r
1945 } // patchGUIDsSection\r
1946 \r
1947 bool patchVSDs(FImage &image, char *revision)\r
1948 {\r
1949     uint32_t signature;\r
1950     uint32_t companyid = 0x0000066A; // InfiniCon\r
1951 \r
1952     READ4(image, 0x24, &signature, "Signature");\r
1953     TOCPU1(signature);\r
1954 \r
1955     if (signature == SIGNATURE)\r
1956     {   \r
1957         time_t etime;\r
1958         \r
1959         etime = time(NULL);\r
1960         printf("%s%s", \r
1961                (device.getClassType()==Flash::FlashDeviceType?"Burn Date                    : ":"Creation                    : "),\r
1962                asctime(localtime(&etime)));\r
1963         patchVSDSection(image.getBuf(), SECT_SIZE  , companyid, etime, revision);\r
1964         patchVSDSection(image.getBuf(), SECT_SIZE*2, companyid, etime, revision);\r
1965         return true;\r
1966     }\r
1967     else\r
1968     {\r
1969         //printf("Can not inject VSD into a Short Image.\n");        \r
1970         return false;\r
1971     }\r
1972 }\r
1973 \r
1974 bool burnImageToFlash(FlashCommandLine cl)\r
1975 {\r
1976     //Flash    device;\r
1977     uint64_t guids[GUIDS];\r
1978     bool insertGUIDs = false;\r
1979     uint32_t Fhardwareversion=0;\r
1980     uint32_t Ihardwareversion=0;\r
1981     uint32_t Fsignature=0;\r
1982     uint32_t Isignature=0;\r
1983     \r
1984     if (!device.open(cl.getDeviceName()))\r
1985     {\r
1986         printf("Error: %s %s\n", device._err, cl.getDeviceName());\r
1987         return false;\r
1988     }\r
1989     \r
1990     // We are always able to get the revision from the pci bus.\r
1991         device.read(0x10, &Fhardwareversion, sizeof(Fhardwareversion));\r
1992         TOCPU1(Fhardwareversion);\r
1993         Fhardwareversion >>=24;\r
1994 \r
1995     if (Fhardwareversion > 0xA0)\r
1996     {\r
1997         device.read(0x24, &Fsignature, sizeof(Fsignature));\r
1998         TOCPU1(Fsignature);\r
1999     }\r
2000     \r
2001     if (!cl.isOption(FlashCommandLine::force))\r
2002     {\r
2003         if (Fhardwareversion != 0xA1 && Fhardwareversion != 0xA0)\r
2004         {\r
2005             printf("!!!WARNING!!!\n"\r
2006                    "Unable to determine the device\'s %s firmware revision (unknown rev %x)!\n"\r
2007                    "It could be a corrupted firmware or an unsupported board revision.\n"\r
2008                    "%s"\r
2009                    "Aborting operation.\n",\r
2010                    cl.getDeviceName(),\r
2011                    Fhardwareversion,\r
2012                    techSupportMessage);\r
2013             return false;\r
2014         }\r
2015     } else\r
2016     {\r
2017         printf("!!!WARNING!!! Skipping flash device hardware revision integrity check.\n");\r
2018     }\r
2019 \r
2020     M_DEBUG("Open raw file.\n");\r
2021 \r
2022     if (!image.open(cl.getRawFileName()))\r
2023     {\r
2024         printf("Error: %s %s\n", image._err, cl.getRawFileName());\r
2025         return false;\r
2026     }\r
2027 \r
2028     M_DEBUG("Verify raw file.\n");\r
2029 \r
2030     _silent = true;\r
2031     if (!image.verify())\r
2032     {\r
2033         printf("%s is not a valid image\n", cl.getRawFileName());\r
2034         return false;\r
2035     }\r
2036 \r
2037     image.read(0x24, &Isignature);\r
2038     TOCPU1(Isignature);\r
2039 \r
2040     image.read(0x10, &Ihardwareversion, sizeof(Ihardwareversion));\r
2041         TOCPU1(Ihardwareversion);\r
2042         Ihardwareversion >>=24;\r
2043 \r
2044     M_DEBUG("Verify hardware and signature information.\n");\r
2045 \r
2046     if (!cl.isOption(FlashCommandLine::force))\r
2047     {\r
2048         if (Ihardwareversion != 0xA1 && Ihardwareversion != 0xA0)\r
2049         {\r
2050             printf("!!!WARNING!!!\n"\r
2051                    "Unable to determine the image\'s %s firmware revision (unknown rev %x)!\n"\r
2052                    "It could be a corrupted image or an unsupported board revision.\n"\r
2053                    "%s"\r
2054                    "Aborting operation.\n",\r
2055                    cl.getDeviceName(),\r
2056                    Ihardwareversion,\r
2057                    techSupportMessage);\r
2058             return false;\r
2059         }\r
2060         else if (Fhardwareversion != Ihardwareversion)\r
2061         {\r
2062             printf("!!!WARNING!!! "\r
2063                    "An HCA Rev %X firmware can not be used with HCA Rev %X device!!!\n"\r
2064                    "Aborting operation.\n",\r
2065                    Ihardwareversion,\r
2066                    Fhardwareversion);\r
2067             return false;\r
2068         }\r
2069                 /*\r
2070         if (Fhardwareversion == 0xA0)\r
2071         {\r
2072             if (Isignature == SIGNATURE)\r
2073             {\r
2074                 printf("!!!WARNING!!! "\r
2075                        "Rev A0 HCA's will not work with a fail safe image!!!\n"\r
2076                        "%s"\r
2077                        "Aborting operation.\n", techSupportMessage);\r
2078                 return false;\r
2079             }\r
2080         }\r
2081                 */\r
2082     } else\r
2083     {\r
2084         printf("!!!DANGER!!!! Skipping image file hardware revision integrity check.\n");              \r
2085     }\r
2086 \r
2087     printf("HCA Rev                      : %"PRIX32"\n", Fhardwareversion);\r
2088     printf("Image Rev                    : %"PRIX32"\n", Ihardwareversion);\r
2089 \r
2090     if (!cl.useFlashNodeGUID())\r
2091     {   // the user specified the guid at the command line\r
2092         if (!getGUIDs(cl.getNodeGUID(),guids))\r
2093         {\r
2094             printf("Aborting burn operation.\n");\r
2095             device.close();\r
2096             return false;\r
2097         }\r
2098         insertGUIDs = true;\r
2099     } else\r
2100     {\r
2101         // should we query the flash device for the guids\r
2102         // If we don't query the flash for the guids, and\r
2103         // we don't specify the guids at the command line\r
2104         // then we will use the guids supplied in the raw\r
2105         // image file\r
2106             M_DEBUG("Query the flash device\n");\r
2107         if (!cl.isOption(FlashCommandLine::noquery))\r
2108         {\r
2109             // obtain the guids from the flash\r
2110             if (!getGUIDsFromFlash(device, guids))\r
2111             {            \r
2112                 printf("The image on the flash device appears corrupted!\n"  \r
2113                        "Unable to determine the GUIDs from the flash device %s.\n"\r
2114                        "Try the -n <0xGUID> option.  If this fails, then contact\n" \r
2115                        "SilverStorm Technologies technical support.\n",\r
2116                        cl.getDeviceName());\r
2117                 device.close();\r
2118                 return false;\r
2119             }\r
2120             insertGUIDs = true;\r
2121         }        \r
2122     }\r
2123 \r
2124     bool interactive;\r
2125 \r
2126     if (cl.isOption(FlashCommandLine::no_prompts))\r
2127     {\r
2128         interactive=false;\r
2129     } \r
2130     else\r
2131     {\r
2132         interactive = (_isatty(_fileno( stdin )) > 0 ? true: false);\r
2133     }\r
2134     \r
2135     bool eraseInvariant = false;\r
2136 \r
2137     if (cl.isOption(FlashCommandLine::burn_invariant_section))\r
2138     {   \r
2139         M_DEBUG("Always burn invariant section.\n");\r
2140         eraseInvariant = true;\r
2141     } else // only burn the invariant section if it differs\r
2142     {\r
2143         if (isInvariantSectionEqual(device, image)) \r
2144         {\r
2145             M_DEBUG("The invariant sections are equal.\n");\r
2146             eraseInvariant = false;\r
2147         } else\r
2148         {                     \r
2149             M_DEBUG("The invariant sections differ.\n");\r
2150             eraseInvariant = true;\r
2151         }          \r
2152     }\r
2153 \r
2154     M_DEBUG("Patch GUIDs.\n");\r
2155 \r
2156     // Patch GUIDs\r
2157     if (insertGUIDs && !patchGUIDs(image, guids, interactive))\r
2158     {\r
2159         printf("Aborting burn operation at user request.\n");\r
2160         return true;\r
2161     }\r
2162 \r
2163     M_DEBUG("Patch VSDs.\n");\r
2164 \r
2165     // Patch VSDs\r
2166     if (!patchVSDs(image, NULL))\r
2167     {\r
2168         // if this fails it means it's a short image, and we should just continue on\r
2169     }\r
2170 \r
2171     M_DEBUG("Write firmware.\n");\r
2172 \r
2173     // Burn it\r
2174     if (!device.write_image(0, image.getBuf(), image.getBufLength(), eraseInvariant, (_isatty(_fileno( stdin )) > 0? true: false)) )\r
2175     {\r
2176         printf("Error: %s\n", device._err);\r
2177         return false;\r
2178     }\r
2179     \r
2180     device.close();\r
2181     image.close();\r
2182 \r
2183     return true;\r
2184 }\r
2185 \r
2186 bool patchVSDToRawImage(FlashCommandLine cl)\r
2187 {    \r
2188     printf("Attempting to insert VSD section into the %s file: \n", cl.getRawFileName());\r
2189 \r
2190     if (!image.open(cl.getRawFileName()))\r
2191     {\r
2192         printf("Error: %s\n", image._err);\r
2193         printf("Aborting operation.\n");\r
2194         return false;\r
2195     }\r
2196 \r
2197     if (!patchVSDs(image, cl.getRevisionString()))\r
2198     {\r
2199         printf("Failed.\n"\r
2200                "!!!WARNING!!!\n"\r
2201                "Unable to inject the VSD into a Short Image.\n"\r
2202                "Short images do not support the VSD section.\n"\r
2203                "Only Fail Safe images support the VSD section.\n"\r
2204                "Aborting operation.\n");\r
2205         return false;\r
2206     }\r
2207 \r
2208     FILE *fd;\r
2209     void *write_buffer;\r
2210     uint32_t buflen = image.getBufLength();\r
2211 \r
2212     // it is necessary to close the file prior to re-opening for write privileges\r
2213     // this allows us to write to the same file without using a temporary file\r
2214     write_buffer = malloc(buflen);\r
2215     memcpy(write_buffer, image.getBuf(), buflen); \r
2216     image.close();  \r
2217         \r
2218     // only open the file, if any things fails, then the image verify\r
2219     // will indicate issues\r
2220     if ((fd = fopen(cl.getRawFileName(),"w")) != NULL)\r
2221     {\r
2222         fwrite(write_buffer, buflen, 1, fd);\r
2223         fclose(fd);\r
2224     } else\r
2225     {\r
2226         printf("Failed.\n"\r
2227                "Unable to write to raw image file %s.\n", cl.getRawFileName());\r
2228         _silent=true;\r
2229         if (!image.verify()) // verify file integrity\r
2230         {\r
2231             printf("!!!WARNING!!! "\r
2232                    "The file appears to have been corrupted!!!\n");            \r
2233             return false;\r
2234         } else\r
2235         {\r
2236             printf("File appears to be valid, but the VSD injection failed.\n");\r
2237         }\r
2238         _silent=false;\r
2239 \r
2240         return false;\r
2241     }\r
2242     \r
2243     // ok to free the buffer now\r
2244     free(write_buffer);    \r
2245 \r
2246     if (!image.open(cl.getRawFileName()))\r
2247     {\r
2248         printf("Error: %s\n", image._err);\r
2249         printf("Aborting operation.\n");\r
2250         return false;\r
2251     }\r
2252     _silent=true;\r
2253     if (!image.verify()) // verify file integrity\r
2254     {\r
2255         printf("Failed Verification.\n"\r
2256                "The file %s appears to have been corrupted\n", cl.getRawFileName());\r
2257         return false;\r
2258     }\r
2259     _silent=false;\r
2260     image.close();\r
2261     printf("Insertion                    : [SUCCESS]\n");\r
2262     printf("Done.\n");\r
2263     return true;\r
2264 }\r
2265 \r
2266 bool showInfo(FBase &device, FlashCommandLine cl)\r
2267 {\r
2268     uint32_t NODE_GUIDH, NODE_GUIDL;\r
2269     uint32_t PORT1_GUIDH, PORT1_GUIDL;\r
2270     uint32_t PORT2_GUIDH, PORT2_GUIDL;\r
2271     uint32_t hardwareversion;\r
2272     uint32_t psptr;\r
2273     uint32_t signature;\r
2274     int section = 1;\r
2275     PS    ps;\r
2276         time_t myTime;\r
2277     bool isFailSafe = false;\r
2278     uint64_t guids[GUIDS];\r
2279     char revision[FlashCommandLine::revisionStringLength];\r
2280 \r
2281     READ4(device, 0x24, &signature, "Signature");\r
2282     TOCPU1(signature);\r
2283 \r
2284     if (DebugMode)\r
2285     {\r
2286         _silent=false;\r
2287     } else\r
2288     {\r
2289         _silent=false;\r
2290     }\r
2291     \r
2292     if (signature == SIGNATURE)\r
2293     {\r
2294         uint8_t offset =0, x=0;\r
2295         // Fail Safe image\r
2296         \r
2297         // verify the image invariant section\r
2298         if (!checkBoot2(device, 0, 0x28, psptr, "Invariant\t"))\r
2299         {\r
2300             printf("Invariant section is not valid!");\r
2301             _silent=false;\r
2302             return false;\r
2303         }\r
2304 \r
2305         if (!checkPS(device, SECT_SIZE, psptr, "Primary\t"))\r
2306         {\r
2307             M_DEBUG("Primary section is not valid\n");\r
2308             // If the primary is invalid then try secondary section         \r
2309             if (!checkPS(device, SECT_SIZE*2, psptr, "Secondary\t"))\r
2310             {\r
2311                 printf("Firmware is corrupted.  Unable to display information.\n");\r
2312                 _silent=false;\r
2313                 return false;\r
2314             }\r
2315             section=2; // secondary is valid, use it\r
2316         }\r
2317         \r
2318         device.read(0x10, &hardwareversion, sizeof(hardwareversion));\r
2319                 TOCPU1(hardwareversion);\r
2320                 hardwareversion >>=24;\r
2321         device.read(SECT_SIZE*section, &ps, sizeof(ps));\r
2322         TOCPUBY(ps,sizeof(ps));\r
2323                 printf("PSID              : %s\n",ps.psid.as_str);\r
2324                 printf("Image Type        : Fail Safe\n");\r
2325         if (hardwareversion != 0xA0 && hardwareversion != 0xA1)\r
2326         {\r
2327             printf("Hardware Version  : 0xInvalid\n");\r
2328 \r
2329         } else\r
2330         {\r
2331             printf("Hardware Version  : 0x%"PRIX32"\n", hardwareversion);\r
2332         }\r
2333         printf("Company           : %s\n",  ps.vsd[0]==0x00066A?"SilverStorm Technologies":"Mellanox, Inc");\r
2334 \r
2335                 myTime = ps.vsd[2];\r
2336         printf("%s Date     : %s", (device.getClassType()==Flash::FlashDeviceType?"Burn    ":"Creation"), asctime(localtime(&myTime))); \r
2337 \r
2338         for (x=3;x<9;x++)\r
2339         {                      \r
2340             memcpy(revision+offset, &ps.vsd[x], sizeof(uint32_t));\r
2341             offset = offset + 4;\r
2342         }\r
2343         revision[FlashCommandLine::revisionStringLength-1]='\0';\r
2344         printf("Firmware Revision : %s\n", revision);\r
2345         READ4(device, ps.fi_addr+0x24, &psptr, "pointer section");        \r
2346         printf("Firmware Address  : 0x%"PRIx32"\n", ps.fi_addr);\r
2347         printf("Node GUID Offset  : 0x%"PRIx32"\n", psptr);        \r
2348         psptr = BE2CPU32(psptr)+ps.fi_addr;        \r
2349         isFailSafe = true;\r
2350     }\r
2351     else\r
2352     {\r
2353         if (!checkList(device, 0,""))\r
2354         {\r
2355             printf("Firmware is not valid.  Can not display information.\n");\r
2356             _silent=false;\r
2357             return false;\r
2358         }\r
2359         // Short image\r
2360         // Assume flash has been verified, and both images have the same guids, therefore,\r
2361         // we only need to read the primary image's guids\r
2362         device.read(0x10, &hardwareversion, sizeof(hardwareversion));\r
2363                 TOCPU1(hardwareversion);\r
2364                 hardwareversion >>=24;\r
2365         printf("Image Type        : Short\n");\r
2366         if (hardwareversion != 0xA0 && hardwareversion != 0xA1)\r
2367         {\r
2368             printf("Hardware Version  : 0xInvalid\n");\r
2369 \r
2370         } else\r
2371         {\r
2372             printf("Hardware Version  : 0x%X\n", hardwareversion);\r
2373         }\r
2374         printf("Company           :   Unknown\n");\r
2375         printf("%s Date     :   Unknown\n", (device.getClassType()==Flash::FlashDeviceType?"Burn    ":"Creation")); \r
2376         printf("Firmware Revision :   Unknown\n");   \r
2377         printf("Firmware Address  : 0xUnknown\n");\r
2378         psptr = signature;  \r
2379         if (psptr < MST_MAX_FLASH )\r
2380         {\r
2381             printf("Node GUID Offset  : 0x%"PRIx32"\n", psptr); \r
2382         } else\r
2383         {\r
2384             printf("Node GUID Offset  : 0x%"PRIx32" !!! Error: Invalid !!!\n", psptr); \r
2385         }\r
2386      \r
2387     }\r
2388 \r
2389     if (psptr < MST_MAX_FLASH || isFailSafe) \r
2390     {\r
2391         READ4(device, psptr, &NODE_GUIDH, "Node GUID High");\r
2392         READ4(device, psptr+4, &NODE_GUIDL, "Node GUID Low");\r
2393         guids[0] = BE2CPU32(NODE_GUIDH);\r
2394         guids[0] = (guids[0]<<32) | BE2CPU32(NODE_GUIDL);\r
2395         READ4(device, psptr+8, &PORT1_GUIDH, "Port 1 GUID High");\r
2396         READ4(device, psptr+12, &PORT1_GUIDL, "Port 1 GUID Low");\r
2397         guids[1] = BE2CPU32(PORT1_GUIDH);\r
2398         guids[1] = (guids[1]<<32) | BE2CPU32(PORT1_GUIDL);\r
2399         READ4(device, psptr+16, &PORT2_GUIDH, "Port 2 GUID High");\r
2400         READ4(device, psptr+20, &PORT2_GUIDL, "Port 2 GUID Low");\r
2401         guids[2] = BE2CPU32(PORT2_GUIDH);\r
2402         guids[2] = (guids[2]<<32) | BE2CPU32(PORT2_GUIDL);\r
2403 \r
2404         guids[3] = guids[0];\r
2405         printf("Node  GUID        : 0x%016"PRIx64"\n", guids[0]);\r
2406         printf("Port1 GUID        : 0x%016"PRIx64"\n", guids[1]);\r
2407         printf("Port2 GUID        : 0x%016"PRIx64"\n", guids[2]);\r
2408     } else \r
2409     {\r
2410         printf("Node  GUID        : 0xInvalid\n");\r
2411         printf("Port1 GUID        : 0xInvalid\n");\r
2412         printf("Port2 GUID        : 0xInvalid\n");\r
2413         printf("!!! WARNING: The flash %s is corrupted.\n"\r
2414                "You must use the -n <0xGUID> and --force option to update this device.\n", \r
2415                cl.getDeviceName());           \r
2416         _silent=false;\r
2417         return false;\r
2418     }\r
2419     _silent=false;\r
2420     return true;\r
2421 }\r
2422 \r
2423 ////////////////////////////////////////////////////////////////////////\r
2424 //                                                                    //\r
2425 // ****************************************************************** //\r
2426 //                           MAIN                                     //\r
2427 // ****************************************************************** //\r
2428 //                                                                    //\r
2429 ////////////////////////////////////////////////////////////////////////\r
2430 int __cdecl\r
2431 main(uint32_t ac, char *av[])\r
2432 {\r
2433     FlashCommandLine cl;\r
2434 \r
2435         //try to get lock on box\r
2436         if (FwUpdateLock() != 0 )\r
2437                 return -1;\r
2438         \r
2439         // register unlock func in exit\r
2440         _onexit((_onexit_t)FwUpdateUnlock);\r
2441         \r
2442         cl.parse(ac, av);\r
2443 \r
2444     if (cl.isOption(FlashCommandLine::debug))\r
2445     {\r
2446         DebugMode = true;\r
2447                 g_fw_dbg_lvl = 1;\r
2448     }\r
2449 \r
2450     if (cl.isOption(FlashCommandLine::disable_bestdevice))\r
2451     {\r
2452         DisableBestDevice = true;\r
2453     }\r
2454 \r
2455     \r
2456     if (cl.isOption(FlashCommandLine::flash_format))\r
2457     {\r
2458         if (!device.open(cl.getDeviceName()))\r
2459         {\r
2460             printf("Error: %s %s\n", device._err, cl.getDeviceName());\r
2461             return -1;\r
2462         }\r
2463 \r
2464         device.format();\r
2465         device.close();        \r
2466     }\r
2467 \r
2468         if (cl.isOption(FlashCommandLine::show_image_info))\r
2469     {\r
2470         if (!image.open(cl.getRawFileName()))\r
2471         {\r
2472             printf("Error: %s\n", image._err);\r
2473             return -1;\r
2474         }\r
2475 \r
2476         showInfo(image, cl);\r
2477         image.close();\r
2478     }\r
2479 \r
2480     if (cl.isOption(FlashCommandLine::show_flash_info))\r
2481     {\r
2482         if (!device.open(cl.getDeviceName()))\r
2483         {\r
2484             printf("Error: %s %s\n", device._err, cl.getDeviceName());\r
2485                         return -1;\r
2486         }\r
2487 \r
2488         showInfo(device, cl);\r
2489         device.close();\r
2490     }\r
2491 \r
2492     if (cl.isOption(FlashCommandLine::dump_image))\r
2493     {\r
2494         if (!image.open(cl.getRawFileName()))\r
2495         {\r
2496             printf("Error: %s\n", image._err);\r
2497             return -1;\r
2498         }\r
2499         image.dump();\r
2500         image.close();\r
2501 \r
2502     }\r
2503     \r
2504     if (cl.isOption(FlashCommandLine::dump_flash))\r
2505     {\r
2506         if (!device.open(cl.getDeviceName()))\r
2507         {\r
2508             printf("Error: %s %s\n", device._err, cl.getDeviceName());\r
2509             return -1;\r
2510         }\r
2511         device.dump();\r
2512         device.close();    \r
2513     }\r
2514 \r
2515     if (cl.isOption(FlashCommandLine::verify_image))\r
2516     {\r
2517         if (!image.open(cl.getRawFileName()))\r
2518         {\r
2519             printf("Error: %s\n", image._err);\r
2520             return -1;\r
2521         }\r
2522         image.verify();\r
2523         image.close();\r
2524     }\r
2525 \r
2526     if (cl.isOption(FlashCommandLine::verify_flash))\r
2527     {\r
2528         if (!device.open(cl.getDeviceName()))\r
2529         {\r
2530             printf("Error: %s %s\n", device._err, cl.getDeviceName());\r
2531             return -1;\r
2532         }\r
2533         device.verify();\r
2534         device.close();\r
2535     }\r
2536 \r
2537     if (cl.isOption(FlashCommandLine::write_file))\r
2538     {\r
2539         if (!patchVSDToRawImage(cl))\r
2540         {\r
2541             return -1;\r
2542         }        \r
2543     }\r
2544 \r
2545     if (cl.isOption(FlashCommandLine::burn))\r
2546     {\r
2547         if (!burnImageToFlash(cl))\r
2548         {\r
2549             return -1;\r
2550         }\r
2551 \r
2552         // For A0 HCAs we need to write to both banks of the flash.\r
2553         if ((devType == TAVOR_TYPE) && (devRevision == 0xA0))\r
2554         {\r
2555             device.setGPIOState(Flash::High);\r
2556 \r
2557             if (!burnImageToFlash(cl))\r
2558             {\r
2559                 return -1;\r
2560             }\r
2561         }\r
2562     }\r
2563 \r
2564     return 0;\r
2565 }\r
2566 \r
2567 bool probePciBusForHcaDevice(const char *device)\r
2568 {\r
2569     FILE *stream;\r
2570     char output[MAXPATHLEN];\r
2571         char tmpRevision[5];\r
2572         uint32_t i;\r
2573 \r
2574     devId = HcaDevnameToDevId(device);\r
2575     devType = HcaDevnameToDevType(device);\r
2576 \r
2577         sprintf(output,"lspci -m -n | grep 15b3 | grep %x",devType);\r
2578     stream = _popen(output, "r");\r
2579     \r
2580     if (NULL == stream)\r
2581     {\r
2582         printf("Error probing the PCI bus for HCA devcies.\n");\r
2583         return false;\r
2584     }\r
2585     M_DEBUG("Probing PCI bus for HCA devices.\n");\r
2586         i = 0;\r
2587     while (fgets(output, MAXPATHLEN, stream))\r
2588     {\r
2589         if (mellanox_mode)\r
2590                 {\r
2591                         if (i++ != devId) continue;\r
2592                 } else\r
2593                 {\r
2594                         if (++i != devId) continue;\r
2595                 }\r
2596                         \r
2597         if (strlen(output)>1)\r
2598             output[strlen(output)-1]='\0';\r
2599 \r
2600         tmpRevision[0] = '0';\r
2601         tmpRevision[1] = 'x';\r
2602         tmpRevision[2] = output[37];\r
2603         tmpRevision[3] = output[38];\r
2604         tmpRevision[4] = '\0';\r
2605 \r
2606         // probably should check errno in case of an invalid revision\r
2607         devRevision = strtol(tmpRevision, (char**)NULL, 0);     \r
2608 \r
2609         sprintf(bestDev, "/dev/mst/mt%d_pci_cr%d", devType, devId);\r
2610 \r
2611         M_DEBUG("Trying device %s.\n", bestDev);\r
2612 \r
2613         if (NULL != fopen(bestDev, "r"))\r
2614         {\r
2615             M_DEBUG("HCA %d (Rev. %"PRIx32") using device name %s.\n", devId, devRevision, bestDev);\r
2616         } else\r
2617         {\r
2618             sprintf(bestDev, "/dev/mst/mt%d_pciconf%d", devType, devId);\r
2619             M_DEBUG("Trying device %s.\n", bestDev);\r
2620 \r
2621             if (NULL != fopen(bestDev, "r"))\r
2622             {\r
2623                 M_DEBUG("HCA %d (Rev. %"PRIx32") using device name %s.\n", devId, devRevision, bestDev);\r
2624             } else\r
2625             {\r
2626                 printf("We found HCA %d on the PCI bus, but it does not appear to be operating properly.\n", devId);\r
2627                 printf("Please verify the mst device driver is running without errors.  If the problem persist,\n"\r
2628                    "then contact technical support.\n");\r
2629             }\r
2630                         _pclose(stream);\r
2631                         return false;\r
2632         }       \r
2633         _pclose(stream);    \r
2634         return true;\r
2635     }\r
2636 \r
2637     printf("Specified device %d not found.\n", devId);\r
2638     printf("Found %d device%s of type mt%d\n",i,(i==1)?"":"s",devType);\r
2639     _pclose(stream);    \r
2640     return false;\r
2641 }\r
2642 \r
2643 uint32_t HcaDevnameToDevId(const char *devname)\r
2644 {\r
2645     if (strlen(devname) >= 1)\r
2646     {\r
2647         if (isdigit(devname[strlen(devname)-1]))\r
2648         {\r
2649             return ((uint8_t)devname[strlen(devname)-1])-48;\r
2650         } else\r
2651         {\r
2652             M_DEBUG("Device name should end with a numeric value between 1 and 9.\n");\r
2653         }\r
2654     \r
2655     } else\r
2656     {\r
2657         M_DEBUG("Device name is too short.\n");\r
2658     }\r
2659     \r
2660     M_DEBUG("Invalid device name using default device 1.\n");\r
2661     return 1;\r
2662 }\r
2663 \r
2664 uint32_t HcaDevnameToDevType(const char *devname)\r
2665 {\r
2666         uint32_t type = 0;\r
2667         char *str;\r
2668 \r
2669         str = strstr(devname, "mt");\r
2670         if (str)\r
2671         {\r
2672                 str += 2;\r
2673                 type = strtol(str, NULL, 10);\r
2674         }\r
2675         if ((type != TAVOR_TYPE) && (type != ARBEL_TYPE))\r
2676         {\r
2677         M_DEBUG("Device name should contain device type, using mt23108.\n");\r
2678                 type = TAVOR_TYPE;\r
2679         }\r
2680     return type;\r
2681 }\r
2682 \r
2683 bool isMstLoaded(void)\r
2684 {\r
2685     FILE *stream;\r
2686     char output[MAXPATHLEN];\r
2687 \r
2688     /* Check for infinicon-compiled mst driver. */\r
2689     stream = _popen("/sbin/lsmod | grep mst |cut -d\" \" -f1", "r");\r
2690     \r
2691     if (NULL == stream)\r
2692         return false;\r
2693 \r
2694     fgets(output, MAXPATHLEN, stream);\r
2695 \r
2696     if (strlen(output)>1)\r
2697         output[strlen(output)-1]='\0';\r
2698 \r
2699     _pclose(stream);\r
2700 \r
2701     if ((NULL != output) && (strncmp("mst", output, MAXPATHLEN) == 0))\r
2702         return true;\r
2703 \r
2704     /* That failed - check for mellanox-compiled mst driver. */\r
2705     stream = _popen("/sbin/lsmod | grep mst_pci |cut -d\" \" -f1", "r");\r
2706     \r
2707     if (NULL == stream)\r
2708         return false;\r
2709 \r
2710     fgets(output, MAXPATHLEN, stream);\r
2711 \r
2712     if (strlen(output)>1)\r
2713         output[strlen(output)-1]='\0';\r
2714 \r
2715     _pclose(stream);\r
2716 \r
2717     if ((NULL != output) && (strncmp("mst_pci", output, MAXPATHLEN) == 0))\r
2718     {\r
2719         mellanox_mode = 1;\r
2720         return true;\r
2721     }\r
2722     else\r
2723         return false;\r
2724 }\r
2725 \r
2726 void __cdecl catch_signal( int sig )\r
2727 {\r
2728     //fprintf( stdout, "\nProgram Interrupted.  Closing devices.\n" );\r
2729     //device.close();\r
2730     //image.close();\r
2731     //exit( 0 );\r
2732 }\r
2733 \r
2734 static int\r
2735 FwUpdateLock(void)\r
2736 {\r
2737         int status = 0;\r
2738         if ((file_lock = _open( LOCK_FILE_NAME, _O_CREAT | _O_EXCL, _S_IREAD | _S_IWRITE )) == -1 )\r
2739         {\r
2740                 printf("One instance is running already\n");\r
2741                 status = -1;\r
2742         }\r
2743         return status;\r
2744 }\r
2745 static void \r
2746 FwUpdateUnlock(void)\r
2747 {\r
2748         if ((_close(file_lock)) != -1 )\r
2749         {\r
2750                 if ((_unlink(LOCK_FILE_NAME)) != -1 )\r
2751                 {\r
2752                         return;\r
2753                 }\r
2754         }\r
2755         printf("Unlock can not release lock\n");\r
2756 }