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