From e59119d3e43cadb2df3413be9dffb159ac662b66 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 23 Jan 2006 15:26:21 +0000 Subject: [PATCH] r5156: update to MFT1.0.1 (IBG2.0.1) --- flint.cpp | 2633 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 1687 insertions(+), 946 deletions(-) diff --git a/flint.cpp b/flint.cpp index d377838..430d3cc 100644 --- a/flint.cpp +++ b/flint.cpp @@ -32,7 +32,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * Version: $Id: flint.cpp,v 1.103 2005/06/22 11:31:28 orenk Exp $ + * Version: $Id: flint.cpp 2747 2006-01-17 16:46:17Z orenk $ * */ @@ -57,18 +57,52 @@ #include #endif +#include + +#ifndef __WIN__ + +// +// Linux +// + +#include +#include #include #include -#include -#include #include -#include +#else // __WIN__ + +// +// Windows (Under DDK) +// + +#include +#include + +// Sleep adaptor +#define usleep(x) Sleep((x)/1000) +#define sleep(x) Sleep((x)*1000) -#ifndef O_BINARY - #define O_BINARY 0 +#define vsnprintf _vsnprintf +#define strtoull _strtoui64 +#define isatty _isatty + +#define COMP_CDECL __cdecl + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __BYTE_ORDER __LITTLE_ENDIAN + + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define bswap_32(x) ntohl(x) +#else +#error windows is assumed to run a on little endian architecture #endif +#endif // __WIN__ + #include #include @@ -90,12 +124,22 @@ namespace std {}; using namespace std; +#ifdef VERSION_ID +//char* _versionID = VERSION_ID ; +#define __VFSTR(x) #x +#define _VFSTR(x) __VFSTR(x) +char* _versionID = _VFSTR( VERSION_ID ) ; +#else char* _versionID = "VERSION_ID_HERE"; +#endif -char* _cvsID = "$Revision: 1.103 $"; +char* _svnID = "$Revision: 2747 $"; #ifndef __be32_to_cpu #define __be32_to_cpu(x) ntohl(x) + #ifndef bswap_32 + #define bswap_32(x) (htonl(x)) + #endif #endif #ifndef __cpu_to_be32 #define __cpu_to_be32(x) htonl(x) @@ -226,11 +270,9 @@ static inline void cpu_to_be_guid(guid_t* to, guid_t* from) { #define CHECKGN(f,b,o,n,p) do { if (!checkGen(f,b,o,n,p)) return false; } while (0) #define CHECKLS(f,o,p) do { if (!checkList(f,o,p)) return false; } while(0) #define READ4(f,o,d,p) do { if (!f.read(o,d)) { \ - printf("%s - read error (%s)\n", p, f.err()); \ - return false; }} while (0) + return errmsg("%s - read error (%s)\n", p, f.err()); }} while (0) #define READBUF(f,o,d,l,p) do { if (!f.read(o,d,l)) { \ - printf("%s - read error (%s)\n", p, f.err()); \ - return false; }} while (0) + return errmsg("%s - read error (%s)\n", p, f.err()); }} while (0) #if 1 @@ -295,11 +337,14 @@ private: bool ErrMsg::errmsg(const char *format, ...) { va_list args; - delete [] _err; + char* prev_err = _err; va_start(args, format); _err = vprint(format, args); va_end(args); + + delete[] prev_err; + return false; } @@ -318,17 +363,18 @@ struct PS { u_int32_t crc016; }; enum { - H_FIRST = 1, - H_DDR = 1, - H_CNF = 2, - H_JMP = 3, - H_EMT = 4, - H_ROM = 5, - H_GUID = 6, - H_BOARD_ID=7, - H_USER_DATA=8, - H_FW_CONF=9, - H_LAST =9 + H_FIRST = 1, + H_DDR = 1, + H_CNF = 2, + H_JMP = 3, + H_EMT = 4, + H_ROM = 5, + H_GUID = 6, + H_BOARD_ID = 7, + H_USER_DATA = 8, + H_FW_CONF = 9, + H_IMG_INFO = 10, + H_LAST = 10 }; struct GPH { @@ -347,9 +393,8 @@ struct BOARD_ID { char bid[BOARD_ID_BID_LEN]; }; -int const VSD_LEN = 224; -int const VSD_LAST = 16; -int const VSD_OFFS = VSD_LEN-VSD_LAST; +int const VSD_LEN = 208; +int const PSID_LEN = 16; // // TODO: Remove the below globals to class members. @@ -365,6 +410,7 @@ bool _unlock_bypass = false; bool _byte_write = false; + void report(const char *format, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 1, 2))) @@ -492,7 +538,7 @@ public: _sptr(0), _eptr(31) {} - u_int32_ba operator[](u_int32_t idx) {return range(idx,idx);} + u_int32_ba operator[](u_int32_t idx) {return range((u_int8_t)idx,(u_int8_t)idx);} u_int32_ba& operator= (u_int32_t i) {_rbits = ((i << _sptr) & mask()) | (_rbits & ~mask()); return *this;} u_int32_t* operator& () {return &_bits;} operator u_int32_t () {return((mask() & _rbits) >> _sptr);} @@ -532,7 +578,6 @@ private: // ****************************************************************** // // // //////////////////////////////////////////////////////////////////////// -//#define FUJITSU_BYTE_MODE // Common base class for Flash and for FImage class FBase : public ErrMsg{ @@ -611,7 +656,7 @@ private: // A: Read operation is done in the same way for all flash devices of // the same type (serial or parallel). This is a basic requirement // from the flash, since the HCA HW reads from flash at boot, and -// the way it reads can not be change. +// the way it reads can not be changed. // However, Write and Erase operations protocol varies between flash // vendors. // The term 'command set' is taken from the Common Flash Interface (CFI) @@ -836,7 +881,7 @@ protected: /* It reports two sector sizes, actually works as 1. */ bool _mx_flash_workaround() { return (_cfi_data.num_erase_blocks == 2 && - _cfi_data.manuf_id == 0xff && _cfi_data.device_id == 0xff && + //_cfi_data.manuf_id == 0xff && _cfi_data.device_id == 0xff && _cfi_data.erase_block[0].sector_size == 0x2000 && _cfi_data.erase_block[0].sector_mask == 0xffffe000 && _cfi_data.erase_block[0].num_sectors == 8 && @@ -889,6 +934,8 @@ public: virtual bool wait_ready (const char* msg = NULL); + static void set_byte_mode (bool mode) {CmdSetAmd::set_byte_mode(mode);} + #ifndef _MSC_VER protected: @@ -951,9 +998,12 @@ protected: virtual bool erase_sector (u_int32_t addr); virtual bool reset (); + static void set_byte_mode (bool mode) {_byte_mode = mode;} + protected: ParallelFlash& _f; + static bool _byte_mode; bool unlock_bypass (bool unlock); }; @@ -1119,6 +1169,9 @@ protected: virtual bool set_bank_int (u_int32_t bank); + + virtual bool read_id (u_int8_t *data, u_int8_t cmd); + // // ST's M25P80 command set @@ -1143,7 +1196,8 @@ protected: FC_RDSR = 0x05, FC_WREN = 0x06, FC_READ = 0x03, - FC_RDID = 0x09 + FC_RDID = 0xF9, + FC_RES = 0xAB }; @@ -1174,37 +1228,50 @@ protected: // FImage Class Implementation // //////////////////////////////////////////////////////////////////////// + bool FImage::open(const char *fname, bool read_only) { - struct stat stat_buf; + int fsize; int r_cnt; + FILE *fh; read_only = true; // FImage can be opened only for read - int fd = ::open(fname, O_RDONLY | O_BINARY, 0); - if (fd < 0) { + fh = fopen(fname, "rb"); + + if (!fh) { return errmsg("Can't open file \"%s\" - %s\n", fname, strerror(errno)); } - if (fstat(fd, &stat_buf) < 0) { - return errmsg("Can't stat file \"%s\" - %s\n", fname, strerror(errno)); + + // Get the file size: + if (fseek(fh, 0, SEEK_END) < 0) { + return errmsg("Can't get file size for \"%s\" - %s\n", fname, strerror(errno)); + } + + fsize = ftell(fh); + if (fsize < 0) { + return errmsg("Can't get file size for \"%s\" - %s\n", fname, strerror(errno)); } - //printf("%ld / 0x%lx\n", stat_buf.st_size, stat_buf.st_size); - if (stat_buf.st_size & 0x3) { + rewind(fh); + + //printf("-D- %s size is %d\n", fname, fsize); + if (fsize & 0x3) { return errmsg("Image size should be 4-bytes aligned. Make sure file %s is in the right format (binary image)", fname); } - _buf = new u_int32_t[stat_buf.st_size/4]; - if ((r_cnt = ::read(fd, _buf, stat_buf.st_size)) != stat_buf.st_size) { + _buf = new u_int32_t[fsize/4]; + if ((r_cnt = fread(_buf, 1, fsize, fh)) != fsize) { if (r_cnt < 0) return errmsg("Read error on file \"%s\" - %s\n",fname, strerror(errno)); else return errmsg("Read error on file \"%s\" - read only %d bytes (from %ld)\n", - fname, r_cnt, (unsigned long)stat_buf.st_size); + fname, r_cnt, (unsigned long)fsize); } - _len = stat_buf.st_size; - ::close(fd); + _len = fsize; + fclose(fh); + return true; } // FImage::open @@ -1345,7 +1412,7 @@ bool Flash::lock(bool retry) { u_int32_t word; do { if (++cnt > GPIO_SEM_TRIES) { - return errmsg("Can not obtain Flash semaphore (63). You can use -clear_semaphore to force semaphore unlock. See help for details."); + return errmsg("Can not obtain Flash semaphore (63). You can run \"flint -clear_semaphore -d \" to force semaphore unlock. See help for details."); } MREAD4(SEMAP63, &word); } while (word); @@ -1830,6 +1897,9 @@ bool ParallelFlash::CmdSetAmd::unlock_bypass(bool unlock) { //////////////////////////////////////////////////////////////////////// + +bool ParallelFlash::CmdSetAmd::_byte_mode = false; + bool ParallelFlash::CmdSetAmd::write(u_int32_t addr, void *data, int cnt, bool noerase, bool noverify) { @@ -1910,24 +1980,25 @@ bool ParallelFlash::CmdSetAmd::write(u_int32_t addr, void *data, int cnt, addr += 3; } else if ((u_int8_t)(*p) != 0xff) { -#ifdef FUJITSU_BYTE_MODE - if (!_f.write_internal(0xaaa, 0xaa)) - return false; - if (!_f.write_internal(0x555, 0x55)) - return false; - if (!_f.write_internal(0xaaa, 0xa0)) - return false; -#else // FUJITSU_WORD_MODE - if (!_unlock_bypass) { - if (!_f.write_internal(0x555, 0xaa)) + if (_byte_mode) { + + if (!_f.write_internal(0xaaa, 0xaa)) return false; - if (!_f.write_internal(0x2aa, 0x55)) + if (!_f.write_internal(0x555, 0x55)) return false; - } + if (!_f.write_internal(0xaaa, 0xa0)) + return false; + } else { + if (!_unlock_bypass) { + if (!_f.write_internal(0x555, 0xaa)) + return false; + if (!_f.write_internal(0x2aa, 0x55)) + return false; + } - if (!_f.write_internal(0x555, 0xa0)) - return false; -#endif + if (!_f.write_internal(0x555, 0xa0)) + return false; + } if (!_f.write_internal(addr, *p++)) return false; @@ -2270,35 +2341,36 @@ bool ParallelFlash::CmdSetAmd::erase_sector(u_int32_t addr) return false; // erase sector sequence -#ifdef FUJITSU_BYTE_MODE - if (!_f.write_internal(0xaaa, 0xaa)) - return false; - if (!_f.write_internal(0x555, 0x55)) - return false; - if (!_f.write_internal(0xaaa, 0x80)) - return false; - if (!_f.write_internal(0xaaa, 0xaa)) - return false; - if (!_f.write_internal(0x555, 0x55)) - return false; - if (!_f.write_internal(addr, 0x30)) - return false; -#else // FUJITSU_WORD_MODE - - if (!_f.write_internal(0x555, 0xaa)) - return false; - if (!_f.write_internal(0x2aa, 0x55)) - return false; - if (!_f.write_internal(0x555, 0x80)) - return false; - if (!_f.write_internal(0x555, 0xaa)) - return false; - if (!_f.write_internal(0x2aa, 0x55)) - return false; - if (!_f.write_internal(addr, 0x30)) - return false; + if (_byte_mode ) { + + if (!_f.write_internal(0xaaa, 0xaa)) + return false; + if (!_f.write_internal(0x555, 0x55)) + return false; + if (!_f.write_internal(0xaaa, 0x80)) + return false; + if (!_f.write_internal(0xaaa, 0xaa)) + return false; + if (!_f.write_internal(0x555, 0x55)) + return false; + if (!_f.write_internal(addr, 0x30)) + return false; + } else { + + if (!_f.write_internal(0x555, 0xaa)) + return false; + if (!_f.write_internal(0x2aa, 0x55)) + return false; + if (!_f.write_internal(0x555, 0x80)) + return false; + if (!_f.write_internal(0x555, 0xaa)) + return false; + if (!_f.write_internal(0x2aa, 0x55)) + return false; + if (!_f.write_internal(addr, 0x30)) + return false; -#endif + } // Wait while erase completes do { @@ -2363,7 +2435,7 @@ bool ParallelFlash::CmdSetIntel::erase_sector(u_int32_t addr) } while ((status & FS_Ready) == 0); if (status & FS_Error) { - return _f.errmsg("Status register detected erase error"); + return _f.errmsg("Status register detected erase error (0x%x)", status & FS_Error); } // Reset @@ -2415,22 +2487,24 @@ bool ParallelFlash::get_cfi(struct cfi_query *query) return false; char query_str_x8[4]; - char query_str_x16asx8[4]; + char query_str_x16asx8[8]; if (!read(0x10, query_str_x8, 0x4)) return false; - if (!read(0x20, query_str_x16asx8, 0x4)) + if (!read(0x20, query_str_x16asx8, 0x8)) return false; query_str_x8[3] = '\0'; - query_str_x16asx8[3] = '\0'; + query_str_x16asx8[7] = '\0'; if ( strncmp( query_str_x8 , "QRY" ,3 ) == 0) { // x8 CFI flash (AMD) query_base = 1; - } else if ( strncmp( query_str_x16asx8 , "QQR" ,3 ) == 0) { - // x16 CFI flash worqing in x8 mode (Intel) + } else if ( query_str_x16asx8[0] == 'Q' && + query_str_x16asx8[2] == 'R' && + query_str_x16asx8[4] == 'Y') { + // x16 CFI flash worqing in x8 mode query_base = 2; } else { @@ -2652,14 +2726,10 @@ void SpiFlash::close() { bool SpiFlash::get_cmd_set () { - // TODO: Implement ... - // // Read device ID and allocate command set accordingly. // - _cmd_set = new CmdSetStSpi(*this); - // // Initiate some CFI fields to mimic cfi query procedure of parallel flash: // @@ -2669,8 +2739,56 @@ bool SpiFlash::get_cmd_set () { _cfi_data.erase_block[0].sector_size = 64 * 1024; _cfi_data.erase_block[0].sector_mask = ~(_cfi_data.erase_block[0].sector_size - 1); - // TODO: Check device size and num of devices. Set total device size accordingly - // _cfi_data.device_size = ???; + u_int32_t spi_size = 0; + u_int32_t num_spis = 0; + + for (u_int32_t spi_sel = 0 ; spi_sel < 4 ; spi_sel++) { + if (!set_bank_int(spi_sel)) return false; + + unsigned char es; // electronic signature + u_int32_t cur_spi_size = 0; + + if (!read_id(&es, CmdSetStSpi::FC_RES)) return false; + + if (es >= 0x10 && es < 0x16) { + // Range OK: + + // NOTE: This mapping between electronic signature and device size is device specific! + // This mapping works for ST M25Pxx and Saifun SA25Fxxx families. + cur_spi_size = 1 << (es + 1); + + num_spis++; + + if (spi_sel == 0) { + spi_size = cur_spi_size; + } else if (cur_spi_size != spi_size){ + return errmsg("SPI flash #%d of size 0x%x bytes differs in size from SPI flash #%d of size 0x%x bytes. " + "All flash devices must be of the same size.", + spi_sel, + cur_spi_size, + spi_sel - 1, + spi_size); + } + + + } else if (es == 0xff) { + // No spi device on this chip_select + break; + } else { + return errmsg("Unexpected SPI electronic signature value (0x%2x) when detecting flash size. " + "Flash #%d my be defected.", + es, + spi_sel); + } + + // printf("-D- %3d %08x\n", spi_sel, cur_spi_size); + } + + _cfi_data.device_size = spi_size * num_spis; + _log2_bank_size = log2up(spi_size); + + + _cmd_set = new CmdSetStSpi(*this); return true; } @@ -2759,6 +2877,43 @@ bool SpiFlash::read(u_int32_t addr, u_int32_t *data) } // SpiFlash::read +//////////////////////////////////////////////////////////////////////// +bool SpiFlash::read_id(u_int8_t *data, u_int8_t cmd) +{ + + // + // Prepare command word + // + + u_int32_ba gw_cmd; + u_int32_ba gw_addr; + u_int32_t flash_data; + + gw_cmd[BUSY] = 1; + gw_cmd[READ_OP] = 1; + gw_cmd[SPI_SPECIAL] = 1; + gw_cmd[SPI_NO_ADDR] = 1; + + gw_cmd.range(MSIZE_E, MSIZE_S) = 2; + + gw_addr.range(SPI_CMD_E, SPI_CMD_S) = cmd; + + MWRITE4(FLASH_ADDR, gw_addr); + MWRITE4(FLASH_GW, gw_cmd); + + if (!wait_ready("Read id")) + return false; + + MREAD4(FLASH_DATA, &flash_data); + + /* ID is at offset 3 in word */ + *data = (u_int8_t)(flash_data & 0xff); + + //printf("-D- ES is %02x\n", *data); + + return true; +} // SpiFlash::read + // // TODO: Unify all the block handling code with the CmdSet001 write. // @@ -3063,12 +3218,26 @@ bool SpiFlash::CmdSetStSpi::wait_wip(u_int32_t delay, u_int32_t retrys, u_int32_ class Operations : public ErrMsg { public: - Operations() : _last_image_addr(0), _num_ports(2) {} + Operations() : _last_image_addr(0), _num_ports(2), _allow_skip_is(false) {} enum { GUIDS = 4 }; + enum ImageInfoTags { + II_IiFormatRevision = 0, + II_FwVersion = 1, + II_FwBuildTime = 2, + II_DeviceType = 3, + II_PSID = 4, + II_VSD = 5, + II_SuppurtedPsids = 6, + II_Last = 7, // Mark the end of used tag ids + II_End = 0xff + }; + + struct ImageInfo; + bool write_image (Flash& f, u_int32_t addr, void *data, int cnt, bool need_report); bool WriteSignature (Flash& f, u_int32_t image_idx, u_int32_t sig); bool repair (Flash& f, const int from, const int to, bool need_report); @@ -3077,25 +3246,82 @@ public: bool Verify (FBase& f); bool DumpConf (const char* conf_file = NULL); - bool RevisionInfo (FBase& f, - guid_t guids_out[GUIDS], - char *vsd_out, - bool *fs_image, - bool internal_call = false, - bool read_guids = true, - bool read_ps = true); + + bool DisplayImageInfo(ImageInfo* info); + + bool QueryAll (FBase& f, ImageInfo* info) {return QueryIs(f, info) && + (!info->isFailsafe || QueryPs(f, info)) && + QueryImage(f, info);} bool getBSN (char *s, guid_t *guid); bool getGUID (const char *s, guid_t *guid); - bool patchVSD (FImage& f, char *vsd1, char *curr_psid, const char* new_psid); + bool patchVSD (FImage& f, + const char *user_vsd, + const char *user_psid, + const char *curr_vsd, + const char *curr_psid, + const char *image_psid); - bool patchGUIDs (FImage& f, guid_t guids[GUIDS], bool interactive); + bool patchGUIDs (FImage& f, guid_t guids[GUIDS], guid_t old_guids[GUIDS], bool interactive); void SetNumPorts (u_int32_t num_ports) {_num_ports = num_ports;} + void SetAllowSkipIs (bool asis) {_allow_skip_is = asis;} + + bool ask_user (const char* msg); u_int32_t _last_image_addr; + + // + // ImageInfo struct: Everything you wanted to know about the FW image (and was afraid to ask). + // This struct includes both user's info (psid, dev rev , fwver ...) and tools internal + // info (images locations, guid ptr ...). + // + struct ImageInfo { + ImageInfo() : + invSectOk(false), + psOk(false), + imageOk(false) + { + psid[0] = '\0'; + vsd[0] = '\0'; + for (int i=0; i < II_Last; i++ ) + infoFound[i] = false; + } + + // *Ok : The exit status ofthe specific query. + // Note - invSectOk = true doesnt mean that invariant sector exists, it + // only means that the query was OK (and isFailsafe may be false). + + bool invSectOk; + bool psOk; + bool imageOk; + + bool isFailsafe; + + + bool validImage[2]; + u_int32_t psStart; + u_int32_t imgStart; + + guid_t guids[4]; + char vsd[209]; + char psid[17]; + + u_int8_t isVer; + u_int16_t fwVer[3]; // = {major_ver, minor_ver , sum_minor_ver} + u_int16_t fwTime[6]; // = {year, month, day, hour, minute, second} + + u_int16_t devType; + u_int8_t devRev; + + bool infoFound[II_Last]; + + }; + + + private: bool FailSafe_burn_image (Flash& f, @@ -3106,6 +3332,8 @@ private: int image_size, bool need_report); + bool CheckInvariantSector (Flash& f, u_int32_t *data32, int sect_size); + bool FailSafe_burn_internal (Flash& f, void *data, int cnt, bool need_report); bool checkBoot2 (FBase& f, u_int32_t beg, u_int32_t offs, @@ -3128,33 +3356,51 @@ private: void _patchVSD (FImage& f, int ind, char *vsd); - u_int32_t _num_ports; - - std::vector _fw_conf_sect; + void PatchPs (u_int8_t* rawPs, + const char vsd[VSD_LEN], + const char psid[PSID_LEN] = NULL, + u_int32_t imageAddr = 0); + bool QueryIs (FBase& f, ImageInfo* info); + bool QueryPs (FBase& f, ImageInfo* info); + bool QueryImage (FBase& f, ImageInfo* info); -}; + + bool ParseInfoSect (u_int8_t* buff, u_int32_t byteSize, ImageInfo *info); + u_int32_t _num_ports; + bool _allow_skip_is; + std::vector _fw_conf_sect; +}; // // Asks user a yes/no question. // Returns true if user chose Y, false if user chose N. // -bool ask_user(const char* msg) { + +bool Operations::ask_user(const char* msg) { printf(msg); if (_assume_yes) printf("y\n"); else { + char ansbuff[32]; + ansbuff[0] = '\0'; + + if (!isatty(0)) { + return errmsg("Not on tty - Can't interact. assuming \"no\" for question \"%s\"", msg); + } fflush(stdout); - char c = getchar(); - if (c != '\n') - while (getchar() != '\n'); + fgets(ansbuff, 30, stdin); - if (c != 'y') - return false; + if ( strcmp(ansbuff, "y\n") && + strcmp(ansbuff, "Y\n") && + strcmp(ansbuff, "yes\n") && + strcmp(ansbuff, "Yes\n") && + strcmp(ansbuff, "YES\n")) + return errmsg("Aborted by user"); } return true; } @@ -3442,17 +3688,8 @@ bool Operations::FailSafe_burn_internal(Flash& f, void *data, int cnt, bool need return true; } - - -//////////////////////////////////////////////////////////////////////// -bool Operations::FailSafe_burn(Flash& f, void *data, int size, bool single_image_burn, bool need_report) -{ - u_int32_t *data32 = (u_int32_t *)data; - u_int8_t *data8 = (u_int8_t *)data; - - u_int32_t i; - - u_int32_t sect_size = f.get_sector_size(); +bool Operations::CheckInvariantSector(Flash& f, u_int32_t *data32, int sect_size) { + int i; report("\nRead and verify Invariant Sector - "); fflush(stdout); @@ -3471,23 +3708,70 @@ bool Operations::FailSafe_burn(Flash& f, void *data, int size, bool single_image // Now check Invariant sector contents vector buf1(sect_size/4); - if (size < (int)sect_size * 3) { - report("FAILED\n\n"); - return errmsg("Image is too small."); - } + if (!f.read(0, &buf1[0] , sect_size)) { report("FAILED\n\n"); return false; } + + int first_diff = -1; + for (i=0; i < sect_size/4; i++) { if (buf1[i] != data32[i] && (data32[i] != 0 || buf1[i] != 0xffffffff)) { - report("FAILED\n\n"); - return errmsg("Invariant sector doesn't match. Word #%d (0x%x) " - "in image: 0x%08x, while in flash: 0x%08x", - i, i, data32[i], buf1[i]); + if (first_diff == -1) + first_diff = i; + } + } + + // Check if a diff was found: + if (first_diff != -1) { + report("DIFF DETECTED\n\n"); + printf(" Invariant sector mismatch. Address 0x%x " + " in image: 0x%08x, while in flash: 0x%08x\n\n", + first_diff*4 , data32[first_diff], buf1[first_diff]); + + printf(" The invariant sector can not be burnt in a failsafe manner.\n" + " To force burn of the invariant sector, rerun with -nofs flag.\n"); + + if (_allow_skip_is) { + printf(" You can also continue to update the FW without updating the invariant sector.\n" + " See the firmware release notes for more details.\n\n"); + + return ask_user(" Do you want to continue ? "); + + } else { + // Continue with burn + printf(" You can also update the FW without updating the invariant sector by\n" + " specifying the -skip_is flag.\n" + " See the firmware release notes for more details.\n\n"); + + return errmsg("Invariant sector mismatch"); } } + report("OK\n"); + return true; + +} + +//////////////////////////////////////////////////////////////////////// +bool Operations::FailSafe_burn(Flash& f, void *data, int size, bool single_image_burn, bool need_report) +{ + u_int32_t *data32 = (u_int32_t *)data; + u_int8_t *data8 = (u_int8_t *)data; + + u_int32_t i; + + u_int32_t sect_size = f.get_sector_size(); + + if (size < (int)sect_size * 3) { + report("FAILED\n\n"); + return errmsg("Image is too small."); + } + + if (!CheckInvariantSector(f, data32, sect_size)) { + return false; + } // Check signatures in image u_int32_t actual_signature = data32[sect_size/4 + 2]; @@ -3510,37 +3794,40 @@ bool Operations::FailSafe_burn(Flash& f, void *data, int size, bool single_image data32[sect_size/4 + 2] = 0xffffffff; data32[(sect_size * 2)/4 + 2] = 0xffffffff; - bool image_ok[2] = {false, false}; + bool cur_image_ok[2] = {false, false}; + u_int32_t cur_image_addr[2]; + u_int32_t cur_image_size[2]; // Check signatures on flash report("Read and verify PPS/SPS in flash - "); for (i = 0 ; i < 2 ; i++) { if (!f.read(sect_size * (i+1) + 8, &signature_for_compare)) { - report("FAILED\n\n"); - return false; + } TOCPU1(signature_for_compare); - if (signature_for_compare == SIGNATURE) - image_ok[i] = true; + if (signature_for_compare == SIGNATURE) { + cur_image_ok[i] = true; + + if (!f.read(sect_size * (i+1) , &cur_image_addr[i]) || + !f.read(sect_size * (i+1) + 4, &cur_image_size[i])) { + report("FAILED\n\n"); + return false; + } + + TOCPU1(cur_image_addr[i]); + TOCPU1(cur_image_size[i]); + } } - if (!image_ok[0] && !image_ok[1]) { + if (!cur_image_ok[0] && !cur_image_ok[1]) { // // Both images are invalid in flash // -------------------------------- // printf("\nBoth images (primary and secondary) are invalid in flash.\n"); printf("The burning can't be failsafe, but it is harmless for host.\n"); - printf("\n Do you want to continue ? (y/n) [n] : "); - if (_assume_yes) - printf("y\n"); - else { - fflush(stdout); - char c = getchar(); - if (c != '\n') - while (getchar() != '\n'); - if (c != 'y') - return true; + if(!ask_user("\n Do you want to continue ? (y/n) [n] : ")) { + return false; } // Burn all image @@ -3571,13 +3858,13 @@ bool Operations::FailSafe_burn(Flash& f, void *data, int size, bool single_image if (single_image_burn == false) { - if (image_ok[0] == false || image_ok[1] == false) { + if (cur_image_ok[0] == false || cur_image_ok[1] == false) { int image_from; int image_to; - assert (image_ok[1] || image_ok[0]); + assert (cur_image_ok[1] || cur_image_ok[0]); - if (image_ok[1]) { + if (cur_image_ok[1]) { image_from = 1; image_to = 0; } else { @@ -3602,36 +3889,28 @@ bool Operations::FailSafe_burn(Flash& f, void *data, int size, bool single_image // // Extract Primary/Secondary image pointers and lengths - u_int32_t frst_image_addr = data32[sect_size / 4]; - u_int32_t frst_image_size = data32[sect_size / 4 + 1]; - TOCPU1(frst_image_addr); - TOCPU1(frst_image_size); + u_int32_t frst_new_image_addr = data32[sect_size / 4]; + u_int32_t frst_new_image_size = data32[sect_size / 4 + 1]; + TOCPU1(frst_new_image_addr); + TOCPU1(frst_new_image_size); - if (!image_ok[0] && image_ok[1]) { + if (!cur_image_ok[0] && cur_image_ok[1]) { // Second image is valid on flash. // If the new image can fit in the first image gap, it would be // burnt as first image. // Otherwise (new image too big), image on flash is copied from second to // first image, and new image would be written as second. - // Image size from flash - u_int32_t scnd_image_addr; - if (!f.read(sect_size * 2 , &scnd_image_addr)) { - report("FAILED\n\n"); - return false; - } - TOCPU1(scnd_image_addr); - - if (frst_image_addr + frst_image_size > scnd_image_addr) { + if (frst_new_image_addr + frst_new_image_size > cur_image_addr[1]) { // New image is too large - can't get in between first image start // and current (second) image - move current image to be first. if (!repair(f, 1, 0, need_report)) return false; // Now 2 images are valid - image_ok[0] = true; + cur_image_ok[0] = true; } else { - if (!FailSafe_burn_image(f, data, sect_size, "first", sect_size * 3, frst_image_size, need_report)) + if (!FailSafe_burn_image(f, data, sect_size, "first", sect_size * 3, frst_new_image_size, need_report)) return false; if (!WriteSignature(f, 1, 0)) @@ -3641,7 +3920,7 @@ bool Operations::FailSafe_burn(Flash& f, void *data, int size, bool single_image } } - if (image_ok[0] && image_ok[1]) { + if (cur_image_ok[0] && cur_image_ok[1]) { // Invalidate second image if (!WriteSignature(f, 1, 0)) { @@ -3649,22 +3928,55 @@ bool Operations::FailSafe_burn(Flash& f, void *data, int size, bool single_image return false; } - image_ok[1] = false; + cur_image_ok[1] = false; } - if (image_ok[0] && !image_ok[1]) { - u_int32_t image_size_sect = ((frst_image_size - 1) / sect_size) + 1 ; + if (cur_image_ok[0] && !cur_image_ok[1]) { + u_int32_t new_image_size_sect = ((frst_new_image_size - 1) / sect_size) + 1 ; + + // First image is valid on flash. + // If the new image is smaller than current image, it would + // overwrite the end of current image. In this case, move the current image + // to the second position and burn in first. + // + // TODO: STOP THIS MOVEMENT BULLSHI%@#&! !!! : Reproduce PS in flint with the correct addr. Locate second image in middle of flash. + + if ( (3 + new_image_size_sect) * sect_size < cur_image_addr[0] + cur_image_size[0]) { + // New image overwrites end of cur image + // move current image to be second. + if (!repair(f, 0, 1, need_report)) + return false; - if (!FailSafe_burn_image(f, data, sect_size * 2, "second", sect_size * (3 + image_size_sect) , frst_image_size, need_report)) - return false; + // Now 2 images are valid + cur_image_ok[1] = true; + + // Burn new image as firse + if (!FailSafe_burn_image(f, data, sect_size, "first", + sect_size * 3, frst_new_image_size, need_report)) + return false; + + if (!WriteSignature(f, 1, 0)) + return false; + + return true; + + + } else { + if (!FailSafe_burn_image(f, data, sect_size * 2, "second", + sect_size * (3 + new_image_size_sect) , frst_new_image_size, need_report)) + return false; + + // Invalidate first image + if (!WriteSignature(f, 0, 0)) + return false; + + return true; + + } - // Invalidate first image - if (!WriteSignature(f, 0, 0)) - return false; - return true; } else { - report("Bad flash state: Valid images = (%d,%d).\n", image_ok[0], image_ok[1] ); + report("Bad flash state: Valid images = (%d,%d).\n", cur_image_ok[0], cur_image_ok[1] ); return false; } @@ -3744,7 +4056,12 @@ bool Operations::checkGen(FBase& f, u_int32_t beg, part_cnt++; // May be BOOT3? - if (part_cnt <= 2) { + if (gph.type < H_FIRST || gph.type > H_LAST) { + if (part_cnt > 2) { + //report("%s /0x%x/ - Invalid partition type (%d)\n", + // pref, offs+beg, gph.type); + //return false; + } else return checkBoot2(f, beg, offs, next, pref); } @@ -3794,9 +4111,15 @@ bool Operations::checkGen(FBase& f, u_int32_t beg, pref, offs, offs+size+(u_int32_t)sizeof(gph)+3, size+(u_int32_t)sizeof(gph)+4); break; - case H_BOARD_ID: + case H_IMG_INFO: size = gph.size * sizeof(u_int32_t); - sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (Board ID)", + sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (Image Info)", + pref, offs, offs+size+(u_int32_t)sizeof(gph)+3, + size+(u_int32_t)sizeof(gph)+4); + break; + case H_BOARD_ID: + size = gph.size * sizeof(u_int32_t); + sprintf(pr, "%s /0x%08x-0x%08x (0x%06x)/ (Board ID)", pref, offs, offs+size+(u_int32_t)sizeof(gph)+3, size+(u_int32_t)sizeof(gph)+4); break; @@ -3909,6 +4232,8 @@ bool Operations::Verify(FBase& f) u_int32_t prim_ptr, scnd_ptr; u_int32_t signature; + bool ret = true; + READ4(f, 0x24, &signature, "Signature"); TOCPU1(signature); if (signature == SIGNATURE) { @@ -3918,7 +4243,7 @@ bool Operations::Verify(FBase& f) CHECKB2(f, 0, 0x28, prim_ptr, "Invariant "); report("\n"); if (checkPS(f, f.get_sector_size(), prim_ptr, "Primary ")) - CHECKLS(f, prim_ptr, " "); + ret &= checkList(f, prim_ptr, " "); report("\n"); if (checkPS(f, f.get_sector_size() * 2, scnd_ptr, "Secondary")) CHECKLS(f, scnd_ptr, " "); @@ -3929,7 +4254,7 @@ bool Operations::Verify(FBase& f) CHECKLS(f, 0, " "); } - return true; + return ret; } // Verify @@ -4020,7 +4345,7 @@ bool Operations::getBSN(char *s, guid_t *guid) // Convert to lowercase for (p = s; *p; p++) - *p = tolower(*p); + *p = (char)tolower(*p); // Check validity p = s; @@ -4109,32 +4434,18 @@ bool Operations::getBSN(char *s, guid_t *guid) bool Operations::getGUID(const char *s, guid_t *guid) { - char str[17], *endp; - int i,j, str_beg; - u_int32_t h,l; - memset(str, '0', 15); - str[16] = '\0'; - - if (!strncmp(s, "0x", 2) || !strncmp(s, "0X", 2)) - str_beg = 2; - else - str_beg = 0; - for (i=(int)strlen(s)-1,j=15; i >= str_beg && j >= 0; i--) - str[j--] = s[i]; - - l = strtoul(&str[8], &endp, 16); - if (*endp) { - printf("Invalid GUID syntax (low) (%s)\n", &str[8]); - return false; - } - str[8] = '\0'; - h = strtoul(&str[0], &endp, 16); - if (*endp) { - printf("Invalid GUID syntax (high) (%s)\n", str); + char* endp; + u_int64_t g; + + g = strtoull(s, &endp, 16); + if (*endp || (g == 0xffffffffffffffffULL && errno == ERANGE)) { + printf("Invalid GUID syntax (%s) %s \n", + s, + errno ? strerror(errno) : "" ); return false; } - guid->h = h; - guid->l = l; + guid->h = (u_int32_t)(g >> 32); + guid->l = (u_int32_t)(g & 0xffffffff); return true; } // getGUID @@ -4219,7 +4530,7 @@ void Operations::_patchVSD(FImage& f, int ind, char *vsd) Crc16 crc; PS *ps = (PS*)&buf[ind/4]; - memcpy(&ps->vsd[0], vsd, VSD_LEN); + memcpy(&ps->vsd[0], vsd, VSD_LEN + PSID_LEN); u_int32_t *qp = (u_int32_t *)ps; for (unsigned int i=0; ipsid) + 1]; - char image_psid[sizeof(ps->psid) + 1]; + Crc16 crc; + PS *ps = (PS*)rawPs; - // Form new VSD - memset(vsd, 0, VSD_LEN); - memset(flash_psid, 0 , sizeof(flash_psid)); - memset(image_psid, 0 , sizeof(image_psid)); + u_int32_t fix_start = 0; + u_int32_t fix_end = 0; + if (vsd) { + u_int32_t len = strlen(vsd); + + memset(&ps->vsd[0], 0, VSD_LEN ); + memcpy(&ps->vsd[0], vsd, len); - if (vsd1) - strncpy(&vsd[0], vsd1, VSD_OFFS); + fix_end += VSD_LEN; + } else { + fix_start +=VSD_LEN; + } + if (psid) { + u_int32_t len = strlen(psid); + memset(&ps->psid[0], 0, PSID_LEN ); + memcpy(&ps->psid[0], psid, len ); + fix_end += PSID_LEN; + } - if (new_psid == NULL) { - // New psid is not explicitly given - take it from image - memcpy(image_psid, (char*)ps->psid, sizeof(ps->psid)); + //vsd is kept in flash byte-swapped. + //recode it back before patching + u_int32_t *qp; + qp = (u_int32_t *)&ps->vsd[0]; + for (u_int32_t i=fix_start; ipsid)/4; i++) { - *qp = bswap_32(*qp); - qp++; - } + if (imageAddr) { + ps->fi_addr = __cpu_to_be32(imageAddr); + } - } else { - strncpy(image_psid, new_psid, sizeof(ps->psid)); + qp = (u_int32_t *)ps; + for (unsigned int i=0; icrc016 = __cpu_to_be32(crc016); +} + - if (strncmp( image_psid, (char*) curr_psid, sizeof(ps->psid))) { +//////////////////////////////////////////////////////////////////////// +//Note that vsd1 is a string of bytes. +bool Operations::patchVSD(FImage& f, + const char *user_vsd, + const char *user_psid, + const char *curr_vsd, + const char *curr_psid, + const char *image_psid) +{ + const char* vsd_to_use = curr_vsd ? curr_vsd : ""; + const char* psid_to_use = image_psid; - // Copy the strings to a local buffer to assure '\0' termination (for printf) - strncpy(flash_psid, curr_psid,sizeof(ps->psid)); + // Form new VSD - printf("\n You are about to replace current PSID in flash - \"%s\" with a different PSID - \"%s\".\n", flash_psid, image_psid); + if (user_psid) { + // New psid is explicitly given - take it from user + printf("\n You are about to replace current PSID in the image file - \"%s\" with a different PSID - \"%s\".\n" + " Note: It is highly recommended NOT to change the image PSID.\n", user_psid, image_psid); if (! ask_user("\n Is it OK ? (y/n) [n] : ")) return false; + + psid_to_use = user_psid; } - // Copy correct PSID to image. - strncpy(&vsd[VSD_OFFS], image_psid, VSD_LAST); + if (user_vsd) { + vsd_to_use = user_vsd; + } - //vsd is kept in flash byte-swapped. - //recode it back before patching - u_int32_t *qp = (u_int32_t *)&vsd[0]; - for (int i=0; i 1) + printf(" Port2: " GUID_FORMAT "\n", old_guids[2].h,old_guids[2].l); + if (!image_file_old_guids_fmt) + printf(" Sys.Image: " GUID_FORMAT "\n", old_guids[3].h,old_guids[3].l); + } - printf(" Old GUIDs (inside image) are:\n"); - printf(" Node: " GUID_FORMAT "\n", old_guids[0].h,old_guids[0].l); - printf(" Port1: " GUID_FORMAT "\n", old_guids[1].h,old_guids[1].l); - if (_num_ports > 1) - printf(" Port2: " GUID_FORMAT "\n", old_guids[2].h,old_guids[2].l); - if (!old_guids_fmt) - printf(" Sys.Image: " GUID_FORMAT "\n", old_guids[3].h,old_guids[3].l); - printf("\n You are about to change them to following GUIDs:\n"); - printf(" Node: " GUID_FORMAT "\n", guids[0].h,guids[0].l); - printf(" Port1: " GUID_FORMAT "\n", guids[1].h,guids[1].l); + printf("\n You are about to burn the image with the following GUIDs:\n"); + printf(" Node: " GUID_FORMAT "\n", new_guids[0].h,new_guids[0].l); + printf(" Port1: " GUID_FORMAT "\n", new_guids[1].h,new_guids[1].l); if (_num_ports > 1) - printf(" Port2: " GUID_FORMAT "\n", guids[2].h,guids[2].l); - if (!old_guids_fmt) - printf(" Sys.Image: " GUID_FORMAT "\n", guids[3].h,guids[3].l); + printf(" Port2: " GUID_FORMAT "\n", new_guids[2].h,new_guids[2].l); + if (!image_file_old_guids_fmt) + printf(" Sys.Image: " GUID_FORMAT "\n", new_guids[3].h,new_guids[3].l); if (!ask_user("\n Is it OK ? (y/n) [n] : ")) return false; + + used_guids = new_guids; } // Path GUIDs section if (ind1) - patchGUIDsSection(buf, ind1, guids, nguid1); + patchGUIDsSection(buf, ind1, used_guids, nguid1); if (ind2) - patchGUIDsSection(buf, ind2, guids, nguid2); + patchGUIDsSection(buf, ind2, used_guids, nguid2); if (!interactive) { bool old_guids_fmt = nguid1 < GUIDS; printf("\n Burn image with the following GUIDs:\n"); - printf(" Node: " GUID_FORMAT "\n", guids[0].h,guids[0].l); - printf(" Port1: " GUID_FORMAT "\n", guids[1].h,guids[1].l); + printf(" Node: " GUID_FORMAT "\n", used_guids[0].h,used_guids[0].l); + printf(" Port1: " GUID_FORMAT "\n", used_guids[1].h,used_guids[1].l); if (_num_ports > 1) - printf(" Port2: " GUID_FORMAT "\n", guids[2].h,guids[2].l); + printf(" Port2: " GUID_FORMAT "\n", used_guids[2].h,used_guids[2].l); if (!old_guids_fmt) - printf(" Sys.Image: " GUID_FORMAT "\n", guids[3].h,guids[3].l); + printf(" Sys.Image: " GUID_FORMAT "\n", used_guids[3].h,used_guids[3].l); } return true; } // patchGUIDs @@ -4387,124 +4743,273 @@ bool Operations::patchGUIDs(FImage& f, guid_t guids[GUIDS], bool interactive) // ****************************************************************** // // // //////////////////////////////////////////////////////////////////////// -bool Operations::RevisionInfo(FBase& f, - guid_t guids_out[GUIDS], - char *vsd_out, - bool *fs_image, - bool internal_call, - bool read_guids, - bool read_ps) -{ - char *im_type; - u_int32_t prim_ptr, scnd_ptr, ps_start=0; + +bool Operations::QueryIs (FBase& f, + Operations::ImageInfo* info) { u_int32_t signature; - u_int32_t im_start = 0; READ4(f, 0x24, &signature, "Signature"); TOCPU1(signature); - _silent = true; if (signature == SIGNATURE) { // Full image - report("\nFailsafe image:\n\n"); - if (checkPS(f, f.get_sector_size(), prim_ptr, "Primary ")) { - im_start = prim_ptr; - ps_start = f.get_sector_size(); - } else if (checkPS(f, f.get_sector_size() * 2, scnd_ptr, "Secondary")) { - im_start = scnd_ptr; - ps_start = f.get_sector_size() * 2; - } else { - _silent = internal_call; - report("No valid image found.\n"); - return false; - } - im_type = "FailSafe"; - *fs_image = true; + info->isFailsafe = true; + + // FW ID + u_int32_t fw_id; + + READ4(f, 0x10, &fw_id, "FW ID"); + TOCPU1(fw_id); + + info->isVer = ( fw_id >> 8) && 0xff; + info->devRev = fw_id >> 24; + } else { - // Short image - report("\nShort image:\n"); - im_type = "Short"; - *fs_image = false; + info->isFailsafe = false; + info->imgStart = 0; + } + + info->invSectOk = true; + return true; +} + +bool Operations::QueryPs (FBase& f, + Operations::ImageInfo* info) { + + if (!info->isFailsafe) { + return errmsg("Internal Error: Tried to query PS when image is not failsafe"); + } + + u_int32_t prim_ptr, scnd_ptr; + u_int32_t sectSize = f.get_sector_size(); + + bool currSielent = _silent; + _silent = true; + + if (checkPS(f, sectSize, prim_ptr, "Primary ")) { + info->imgStart = prim_ptr; + info->psStart = sectSize; + } else if (checkPS(f, sectSize * 2, scnd_ptr, "Secondary")) { + info->imgStart = scnd_ptr; + info->psStart = sectSize * 2; + } else { + return errmsg("No valid image found."); } - _silent = internal_call; + char vsd[VSD_LEN+PSID_LEN+1]; // +1 => Leave a space for \0 when psid size == 16 . + + memset(vsd, 0, sizeof(vsd)); + READBUF(f, info->psStart + 0x20, vsd, VSD_LEN+PSID_LEN , "Vendor Specific Data (Board ID)"); + TOCPUBY(vsd); + + memcpy(info->vsd, vsd, VSD_LEN); + memcpy(info->psid, vsd + VSD_LEN, PSID_LEN); + + info->vsd [sizeof(info->vsd) - 1] = '\0'; + info->psid[sizeof(info->psid) - 1] = '\0'; + + _silent = currSielent; + + info->psOk = true; + + return true; +} + + +bool Operations::QueryImage (FBase& f, + Operations::ImageInfo* info) { + + u_int32_t guid_ptr, nguids; + guid_t guids[GUIDS]; // FW ID u_int32_t fw_id; + u_int32_t im_start = info->imgStart; + + READ4(f, im_start + 0x10, &fw_id, "FW ID"); TOCPU1(fw_id); - fw_id >>= 24; + info->devRev = fw_id >> 24; // Read GUIDs - u_int32_t guid_ptr, nguids; - guid_t guids[GUIDS]; + READ4(f, im_start + 0x24, &guid_ptr, "GUID PTR"); + TOCPU1(guid_ptr); + guid_ptr += im_start; + if (guid_ptr >= f.get_size()) { + return errmsg("Failed to read GUIDs - Insane GUID pointer (%08x). Probably image is corrupted", guid_ptr); + } + READ4(f, guid_ptr - 3*sizeof(u_int32_t), &nguids, "Number of GUIDs"); + TOCPU1(nguids); + if (nguids > GUIDS*2) { + report("Failed to read GUIDs - Insane Number of GUIDs (%d)\n", nguids); + return false; + } + READBUF(f, guid_ptr, guids, nguids / 2 * sizeof(u_int64_t), "GUIDS"); + TOCPUBY64(guids); + for (u_int32_t i = 0 ; i < nguids/2 ; i++) { + info->guids[i] = guids[i]; + } - if (read_guids) { - READ4(f, im_start + 0x24, &guid_ptr, "GUID PTR"); - TOCPU1(guid_ptr); - guid_ptr += im_start; - if (guid_ptr >= f.get_size()) { - report("Insane GUID pointer (%08x)\n", guid_ptr); - return false; + // Read Info: + u_int32_ba info_ptr_ba; + u_int32_t info_ptr; + u_int32_t info_size; + u_int8_t info_ptr_cs = 0; + READ4(f, im_start + 0x1C, &info_ptr, "INFO PTR"); + TOCPU1(info_ptr); + + // Verify info_ptr checksum (should be 0) + info_ptr_ba = info_ptr; + for (u_int32_t i = 0; i < 4 ; i++) { + info_ptr_cs += (u_int8_t)info_ptr_ba.range(i*8+7, i*8); + } + + if (info_ptr_cs) { + return errmsg("Failed to read Info Section - Bad checksum for Info section pointer (%08x). Probably image is corrupted", info_ptr); + } + + info_ptr = info_ptr_ba.range(23,0); + if (info_ptr_cs == 0 && info_ptr != 0) { + + info_ptr += im_start; + if (info_ptr >= f.get_size()) { + return errmsg("Failed to read Info Section - Info section pointer (%08x) too large. Probably image is corrupted", info_ptr); } - READ4(f, guid_ptr - 3*sizeof(u_int32_t), &nguids, "Number of GUIDs"); - TOCPU1(nguids); - if (nguids > GUIDS*2) { - report("Insane Number of GUIDs (%d)\n", nguids); + READ4(f, info_ptr - 3*sizeof(u_int32_t), &info_size, "Info section size"); + TOCPU1(info_size); + + // byte size; + info_size *= 4; + + u_int8_t* info_buff = (u_int8_t*)alloca(info_size); + READBUF(f, info_ptr, info_buff, info_size, "Info Section"); + + if (ParseInfoSect(info_buff, info_size, info)) { return false; } - READBUF(f, guid_ptr, guids, nguids / 2 * sizeof(u_int64_t), "GUIDS"); - TOCPUBY64(guids); - memcpy(&guids_out[0], &guids[0], sizeof(guids)); + } + + info->imageOk = true; + return true; +} + + +bool Operations::ParseInfoSect(u_int8_t* buff, u_int32_t byteSize, Operations::ImageInfo *info) { + + u_int32_t *p = (u_int32_t*)buff; + u_int32_t offs = 0; + + bool endFound = false; + + while ((__be32_to_cpu(*p) >> 24) != II_End && offs < byteSize) { + u_int32_t tagSize = __be32_to_cpu(*p) & 0xffffff; + u_int32_t tagId = __be32_to_cpu(*p) >> 24; + + u_int32_t tmp; + + switch (tagId) { + case II_FwVersion: + info->fwVer[0] = __be32_to_cpu(*(p+1)) >> 16; + tmp = __be32_to_cpu(*(p+2)); + info->fwVer[1] = tmp >> 16; + info->fwVer[2] = tmp & 0xffff; + + info->infoFound[tagId] = true; + break; + + case II_DeviceType: + tmp = __be32_to_cpu(*(p+1)); + info->devType = tmp & 0xffff; + //info->devRev = (tmp >> 16) & 0xff; + info->infoFound[tagId] = true; + + case II_PSID: + // set psid only if not previosly found in PS + if (!info->psOk) { + const char* str = (const char*)p; + str += 4; + + for (int i = 0 ; i < PSID_LEN ; i++) { + info->psid[i] = str[i]; + } + info->psid[PSID_LEN] = '\0'; + + info->infoFound[tagId] = true; + + } + break; + + case II_End: + endFound = true; + break; + + //default: + //printf("-D- Found tag ID %d of size %d - ignoring.\n", tagId, tagSize); + } + + p += tagSize/4 + 1; + offs += tagSize; + } + + offs += 4; + if (offs != byteSize) { + if (endFound) { + return errmsg("Info section corrupted: Section data size is %x bytes, " + "but end tag found after %x bytes.", byteSize, offs); + } else { + return errmsg("Info section corrupted: Section data size is %x bytes, " + "but end tag not found before section end.", byteSize); + } } - report("Image type: %s\n" - "Chip rev.: %X\n", - im_type, fw_id); + return true; +} + +bool Operations::DisplayImageInfo(Operations::ImageInfo* info) { + + report("Image type: %s\n", info->isFailsafe ? "Failsafe" : "Short"); - if (read_guids) { - report("GUID Des: Node Port1 "); - if (_num_ports > 1) - report("Port2 "); - report( "Sys image\n"); + if (info->infoFound[II_FwVersion]) { + report("FW Version: %d.%d.%d\n", info->fwVer[0], info->fwVer[1], info->fwVer[2]); + } - report("GUIDs: "); - for (u_int32_t i=0; i 1 ) - report(GUID_FORMAT " ", guids[i].h,guids[i].l); + if (info->isFailsafe) { + report("I.S. Version: %d\n", info->isVer ); } - if (*fs_image && read_ps) { - char vsd[VSD_LEN+1]; // +1 => Leave a space for \0 when psid size == 16 . + if (info->infoFound[II_DeviceType]) { + report("Device ID: %d\n", info->devType); + } - memset(vsd, 0, VSD_LEN+1); - READBUF(f, ps_start + 0x20, vsd, VSD_LEN, "Vendor Specific Data (Board ID)"); - TOCPUBY(vsd); + report("Chip Revision: %X\n", info->devRev); -#if (0) - // Show '\0' in VSD and PSID strings: - bool str_found = false; - for (int i = VSD_OFFS - 2; i >= 0 ; i--) { - if (!str_found && vsd[i] != '\0') - str_found = true; + // GUIDS: + report("GUID Des: Node Port1 "); - if (str_found && vsd[i] == '\0') - vsd[i] = '.'; - } -#endif + if (_num_ports > 1) + report("Port2 "); + report( "Sys image\n"); - report("\nBoard ID: %s", vsd); - if (vsd[VSD_OFFS]) - report(" (%s)\n", &vsd[VSD_OFFS]); - else - report("\n"); - if (vsd_out) - memcpy(vsd_out, &vsd[0], VSD_LEN); - } else + report("GUIDs: "); + for (u_int32_t i=0; i < GUIDS; i++) { + if (i != 2 || _num_ports > 1 ) + report(GUID_FORMAT " ", info->guids[i].h, info->guids[i].l); + } + + + // VSD, PSID + + report("\nBoard ID: %s", info->vsd); + if (info->psid[0]) + report(" (%s)\n", info->psid); + else report("\n"); + report("VSD: %s\n", info->vsd); + report("PSID: %s\n", info->psid); + return true; -} // RevisionInfo +} //////////////////////////////////////////////////////////////////////// // // @@ -4588,6 +5093,8 @@ Flash* get_flash(const char* device, u_int32_t& num_ports) { f = get_serial_flash(mf); break; + case 0xffff: + printf("*** ERROR *** Read a corrupted device id (0x%x). Probably HW/PCI access problem\n", dev_id); default: printf("*** ERROR *** Device type %d not supported.\n", dev_id); } @@ -4606,7 +5113,6 @@ Flash* get_flash(const char* device, u_int32_t& num_ports) { // // //////////////////////////////////////////////////////////////////////// // sed -e 's/"/\\"/g' < flint.txt | perl -pe 's/^(.*)$/"$1\\n"/' - void usage(const char *sname, bool full = false) { const char *descr = @@ -4642,6 +5148,9 @@ void usage(const char *sname, bool full = false) " guid+2 -> port2\n" " guid+3 -> system image GUID.\n" "\n" + " Note: For a single port HCA, port2 guid is assigned\n" + " with the 'guid + 2' value, although it is ignored.\n" + "\n" " Commands affected: burn\n" "\n" " -guids - 4 GUIDs must be specified here.\n" @@ -4649,6 +5158,9 @@ void usage(const char *sname, bool full = false) " the following values, repectively:\n" " node, port1, port2 and system image GUID.\n" "\n" + " Note: For a single port HCA, port2 guid must be\n" + " specified (can be set to 0x0), although it is ignored.\n" + "\n" " Commands affected: burn\n" "\n" " -clear_semaphore - Force clear of the flash semaphore on the device.\n" @@ -4666,6 +5178,14 @@ void usage(const char *sname, bool full = false) "\n" " -nofs - Burn image not in failsafe manner.\n" "\n" + " -skip_is - Allow burning the FW image without updating the invariant sector,\n" + " to insures failsafe burning even when invariant sector difference is detected.\n" + " See the specific FW release notes for more details.\n" + "\n" + " -byte_mode - Shift address when accessing flash internal registers. May\n" + " be required for burn/write commands when accessing certain\n" + " flash types.\n" + "\n" #if 0 " -unlock - Use unlock bypass feature of the flash for quicker burn.\n" " Commands affected: burn\n" @@ -4837,6 +5357,8 @@ void usage(const char *sname, bool full = false) " Example:\n" " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " ri file.bin\n" "\n" + "* Write a block of data to the flash without erasing.\n" + "\n" " Command:\n" " wbne\n" " Parameters:\n" @@ -4849,6 +5371,7 @@ void usage(const char *sname, bool full = false) "* Print (to screen or to a file) the firmware configuration text file used by the image generation process.\n" " This command would fail if the image does not contain a FW configuration section. Existence of this\n" " section depends on the version of the image generation tool.\n" + "\n" " Command:\n" " dc\n" " Parameters:\n" @@ -4872,6 +5395,12 @@ void usage(const char *sname, bool full = false) Flash* g_flash = NULL; +#ifdef _WIN32 +HANDLE g_hMainTread = GetCurrentThread(); +#endif + + + int g_signals_for_termination[] = { SIGINT, #ifndef _WIN32 @@ -4885,6 +5414,21 @@ int g_signals_for_termination[] = { void TerminationHandler (int signum) { static volatile sig_atomic_t fatal_error_in_progress = 0; + +#ifdef _WIN32 + if (signum == 0) { + + report ("\nWarning: Got SIGINT. Raising SIGTERM\n"); + raise(SIGTERM); + return; + } + + report ("\nWarning: This program can not be interrupted.Please wait for its termination.\n"); + signal(signum, TerminationHandler); + return; +#endif + + if (fatal_error_in_progress) raise (signum); fatal_error_in_progress = 1; @@ -4903,6 +5447,166 @@ void TerminationHandler (int signum) raise(signum); } +// +// Commands database and parsing methods +// +enum CommandInput { + CI_NONE = 0x01, + CI_IMG_ONLY = 0x02, + CI_DEV_ONLY = 0x04, + CI_IMG_OR_DEV = 0x06, + CI_IMG_AND_DEV = 0x08 +}; + +enum CommandType { + CMD_UNKNOWN, + CMD_BURN, + CMD_BURN_BLOCK, + CMD_QUERY, + CMD_VERIFY, + CMD_READ_WORD, + CMD_READ_BLOCK, + CMD_WRITE_WORD, + CMD_WRITE_WORD_NE, + CMD_WRITE_BLOCK, + CMD_WRITE_BLOCK_NE, + CMD_ERASE_SECT, + CMD_DUMP_CONF, + CMD_READ_IMAGE, + CMD_CFI, + CMD_CLEAR_SEM +}; + +struct CommandInfo { + CommandType cmd; + const char* cmdName; + bool requireExactMatch; + int maxArgs; + CommandInput requiredInput; + const char* cmdDescription; + +}; + +CommandInfo const g_commands[] = { + { CMD_BURN , "burn" ,false , 0 , CI_IMG_AND_DEV , ""}, + { CMD_BURN_BLOCK , "bb" ,true , 0 , CI_IMG_AND_DEV , ""}, + { CMD_QUERY , "query" ,false , 0 , CI_IMG_OR_DEV , ""}, + { CMD_VERIFY , "verify",false , 0 , CI_IMG_OR_DEV , ""}, + { CMD_READ_WORD , "rw" ,true , 1 , CI_DEV_ONLY , ""}, + { CMD_READ_BLOCK , "rb" ,true , 3 , CI_IMG_OR_DEV , ""}, + { CMD_WRITE_WORD , "ww" ,true , 2 , CI_DEV_ONLY , ""}, + { CMD_WRITE_WORD_NE , "wwne" ,true , 2 , CI_DEV_ONLY , ""}, + { CMD_WRITE_BLOCK , "wb" ,true , 2 , CI_DEV_ONLY , ""}, + { CMD_WRITE_BLOCK_NE , "wbne" ,true ,-1 , CI_DEV_ONLY , ""}, + { CMD_ERASE_SECT , "erase" ,false , 1 , CI_DEV_ONLY , ""}, + { CMD_DUMP_CONF , "dc" ,true , 1 , CI_IMG_OR_DEV , ""}, + { CMD_READ_IMAGE , "ri" ,true , 1 , CI_DEV_ONLY , ""}, + { CMD_CLEAR_SEM , "clear_semaphore" ,true , 0 , CI_DEV_ONLY , ""}, + { CMD_CFI , "cfi" ,true , 0 , CI_DEV_ONLY , ""} +}; + +#define numbel(x) (sizeof(x)/sizeof((x)[0])) + + +const CommandInfo* GetCommandInfo(CommandType cmd) { + for (u_int32_t i = 0 ; i < numbel(g_commands); i++ ) { + if (cmd == g_commands[i].cmd) { + return &g_commands[i]; + } + } + + return NULL; +} + +CommandType ParseCommand(const char* cmd) { + u_int32_t cmdLenGiven = strlen(cmd); + + for (u_int32_t i = 0 ; i < numbel(g_commands); i++ ) { + if (g_commands[i].requireExactMatch ) { + if (!strcmp(cmd, g_commands[i].cmdName)) { + return g_commands[i].cmd; + } + } else { + // Match if given cmd maches the beginning of the checked cmd + if (!strncmp(cmd, g_commands[i].cmdName, cmdLenGiven )) { + return g_commands[i].cmd; + } + } + } + return CMD_UNKNOWN; +} + + +bool CheckCommandInputs(const char* dev, + const char* img, + CommandType cmd) { + + const CommandInfo* cmdInfo = GetCommandInfo(cmd); + + if (!cmdInfo) { + printf("*** INTERNAL ERROR *** Unknown command given to CheckCommandInputs() (%d)\n", cmd); + return false; + } + + char* inputDesStr [] = { + NULL, + "neither a device nor an image file", // CI_NONE + "an image file", // CI_IMG_ONLY, + NULL, + "a device", // CI_DEV_ONLY, + NULL, + "either an image file or a device", // CI_IMG_OR_DEV, + NULL, + "both an image file and a device" // CI_IMG_AND_DEV + }; + + CommandInput given; + + if ( dev && img) { + given = CI_IMG_AND_DEV; + } else if (!dev && img) { + given = CI_IMG_ONLY; + } else if (dev && !img) { + given = CI_DEV_ONLY; + } else { + given = CI_NONE; + } + + if ((given & cmdInfo->requiredInput) == 0) { + printf("*** ERROR *** Command \"%s\" requires %s to be specified", + cmdInfo->cmdName, + inputDesStr[cmdInfo->requiredInput]); + + if (given != CI_NONE) { + printf(", but %s %s given.\n", + inputDesStr[given], + given == CI_IMG_AND_DEV ? "are" : "is"); + } else { + printf(".\n"); + } + + return false; + } + + return true; +} + +bool CheckMaxCmdArguments(CommandType cmd, int numArgs) { + const CommandInfo* cmdInfo = GetCommandInfo(cmd); + if (!cmdInfo) { + printf("*** INTERNAL ERROR *** Unknown command given to CheckMaxCmdArguments (%d)\n", cmd); + return false; + } + + if (cmdInfo->maxArgs >= 0 && numArgs > cmdInfo->maxArgs) { + printf("*** ERROR *** Command \"%s\" requires %d arguments, but %d arguments were given\n", + cmdInfo->cmdName, + cmdInfo->maxArgs, + numArgs); + return false; + } + return true; +} //////////////////////////////////////////////////////////////////////// #define NEXTS(s) do { \ @@ -4918,9 +5622,12 @@ void TerminationHandler (int signum) return 1; \ }} while(0) +#define SETERR(args) do { printf("*** ERROR *** "); printf args; printf("\n"); return 1; } while(0) + + int main(int ac, char *av[]) { - bool fs_image; + char *image_fname=0, *device=0; bool clear_semaphore = false; bool silent = false; @@ -4929,13 +5636,17 @@ int main(int ac, char *av[]) bool use_image_ps = false; bool single_image_burn = true; - char *vsd1=0; - char *psid=0; - guid_t guids[Operations::GUIDS]; - char vsds[VSD_LEN]; + char* cmdStr = NULL; + + char *user_vsd=0; + char *user_psid=0; + guid_t user_guids[Operations::GUIDS]; int rc = 0; + CommandType cmd = CMD_UNKNOWN; + auto_ptr f; + FImage fim; Operations ops; @@ -4947,7 +5658,6 @@ int main(int ac, char *av[]) signal (g_signals_for_termination[i], TerminationHandler); } - if (ac < 2) { usage(av[0]); rc = 1; goto done; @@ -4960,41 +5670,28 @@ int main(int ac, char *av[]) // -------- // if (*av[i] == '-') { - if (!strncmp(av[i], "-dual_image", 10)) + int switchLen = strlen(av[i]); + + if (!strcmp(av[i], "-dual_image")) single_image_burn = false; else if (!strcmp(av[i], "-clear_semaphore")) { clear_semaphore = true; } - else if (!strncmp(av[i], "-d", 2)) { + else if (!strncmp(av[i], "-device", switchLen)) { NEXTS("-device"); device = av[i]; //f.reset( get_flash(device) ); - u_int32_t num_ports; - auto_ptr tmp( get_flash(device, num_ports)); - f = tmp; - - if (f.get() == NULL) { - printf("*** ERROR *** Can't get flash type using device %s\n", device); - rc = 1; goto done; - } - ops.SetNumPorts(num_ports); - - g_flash = f.get(); - if (!f->open(device, clear_semaphore)) { - printf("*** ERROR *** Can't open %s: %s\n", device, f->err()); - rc = 1; goto done; - } } else if (!strcmp(av[i], "-v") || !strcmp(av[i], "-vv")) { - printf("%s: Version %s .", + printf("%s: %s .", av[0], _versionID); if (!strcmp(av[i], "-vv")) { - printf(" CVS %s", _cvsID + 1); + printf(" SVN %s", _svnID + 1); } printf("\n"); @@ -5016,49 +5713,49 @@ int main(int ac, char *av[]) _byte_write = true; } else if (!strcmp(av[i], "-vsd")) { NEXTS("-vsd"); - vsd1 = av[i]; + user_vsd = av[i]; } // -vsd1 is an alias to -vsd, for backward compatibility. Can be removed in the future. else if (!strcmp(av[i], "-vsd1")) { NEXTS("-vsd1"); - vsd1 = av[i]; + user_vsd = av[i]; } else if (!strcmp(av[i], "-psid")) { NEXTS("-psid"); - psid = av[i]; + user_psid = av[i]; } // -vsd2 is an alias to psid, for backward compatibility. Can be removed in the future. else if (!strcmp(av[i], "-vsd2")) { NEXTS("-vsd2"); - psid = av[i]; + user_psid = av[i]; } else if (!strcmp(av[i], "-bsn")) { NEXTS("-bsn"); - GETBSN(av[i], &guids[0]); + GETBSN(av[i], &user_guids[0]); for (int i=1; i>32); - guids[i].l = (u_int32_t)g; + user_guids[i].h = (u_int32_t)(g>>32); + user_guids[i].l = (u_int32_t)g; } guids_specified = true; - } else if (!strncmp(av[i], "-i", 2)) { + } else if (!strncmp(av[i], "-image", switchLen)) { NEXTS("-image"); image_fname = av[i]; } else if (!strcmp(av[i], "-guid")) { NEXTS("-guid"); - GETGUID(av[i], &guids[0]); + GETGUID(av[i], &user_guids[0]); for (int i=1; i>32); - guids[i].l = (u_int32_t)g; + user_guids[i].h = (u_int32_t)(g>>32); + user_guids[i].l = (u_int32_t)g; } guids_specified = true; } else if (!strcmp(av[i], "-guids")) { NEXTS("-guids"); for (int j=0; j= ac) { printf("Exactly four GUIDs must be specified.\n"); rc = 1; goto done; @@ -5066,627 +5763,670 @@ int main(int ac, char *av[]) } i--; guids_specified = true; - } else if (!strncmp(av[i], "-s", 2)) + } else if (!strncmp(av[i], "-silent", switchLen)) silent = true; else if (!strncmp(av[i], "-use_image_ps", 2)) use_image_ps = true; else if (!strncmp(av[i], "-nofs", 5)) burn_failsafe = false; - else if (!strncmp(av[i], "-y", 2)) + else if (!strcmp(av[i], "-skip_is")) + ops.SetAllowSkipIs(true); + else if (!strncmp(av[i], "-yes", switchLen)) _assume_yes = true; + else if (!strcmp(av[i], "-byte_mode")) + ParallelFlash::set_byte_mode(true); else if (!strncmp(av[i], "-hh", 3) || !strncmp(av[i], "--hh", 4)) { usage(av[0], true); rc = 1; goto done; - } else if (!strncmp(av[i], "-h", 2) || !strncmp(av[i], "--h", 3)) { + } else if (!strncmp(av[i], "-help", switchLen) || !strncmp(av[i], "--h", 3)) { usage(av[0]); rc = 1; goto done; } else { - printf("Invalid switch \"%s\" is specified.\n", av[i]); + printf("*** ERROR *** Invalid switch \"%s\" is specified.\n", av[i]); rc = 1; goto done; } - } else { - // - // Commands - // -------- - // + } else { + // command + cmdStr = av[i]; + break; + } + } - if (clear_semaphore) { - printf("No command is allowed when -clear_semaphore flag is given.\n"); - rc = 1; goto done; - } - if (*av[i] == 'b') { - // - // BURN - // + // + // Commands + // -------- + // - bool burn_block = false; - if (!strcmp(av[i], "bb")) { - burn_block = true; - } + if (clear_semaphore) { + if (cmdStr) { + printf("*** ERROR *** No command is allowed when -clear_semaphore flag is given.\n"); + rc = 1; goto done; + } else { + cmdStr = "clear_semaphore"; + } + } - // Device - if (!device) { - printf("For %s command \"-device\" switch must be specified.\n", av[i]); - rc = 1; goto done; - } + if (!cmdStr) { + printf("*** ERROR *** No command given. See help for details.\n"); + rc = 1; goto done; + } - // Image - check, open and verify - if (!image_fname) { - printf("For %s command \"-image\" switch must be specified.\n", av[i]); - rc = 1; goto done; - } - FImage fim; - if (!fim.open(image_fname)) { - printf("*** ERROR *** Image file open failed: %s\n", fim.err()); - rc = 1; goto done; - } + // + // Check and parse command + // + cmd = ParseCommand(cmdStr); - if (!burn_block) { - // Make checks and replace vsd/guids. - - bool old_silent = _silent; - _silent = true; - if (!ops.Verify(fim)) { - printf("Not a valid image\n"); - rc = 1; goto done; - } - - // Check that the flash sector size is well defined in the image - if (fim.get_sector_size() && (fim.get_sector_size() != f->get_sector_size())) { - printf("Flash sector size(0x%x) differs from sector size defined in image (0x%x)\n", - f->get_sector_size(), - fim.get_sector_size()); - rc = 1; goto done; - } - - // Get GUID and VSD info from flash - memset(vsds, 0, VSD_LEN); - - bool read_guids = true; - bool read_ps = true; - - if (guids_specified) - read_guids = false; - - if ((vsd1 && psid) || use_image_ps) - read_ps = false; - - if (read_guids || read_ps) { - if (!ops.RevisionInfo(*f, guids, vsds, &fs_image, false, read_guids, read_ps )) { - printf("*** ERROR *** Can't extract "); - if (read_guids) { - printf("GUIDS "); - } - if (read_ps) { - if (read_guids) - printf("and "); - - printf("VSD/PSID "); - } - printf("info from flash. "); - printf("Please specify the missing info (using command line flags -guid(s) , -use_image_ps). "); - - if (burn_failsafe) { - printf("Can't burn in a failsafe mode. Please use \"-nofs\" flag to burn in a none failsafe mode..\n"); - } - rc = 1; goto done; - } - } - - - // Patch GUIDS - if (guids_specified) { - if (!ops.patchGUIDs(fim, guids, isatty(0) != 0)) { - rc = 1; goto done; - } - } else { - if (!ops.patchGUIDs(fim, guids, false)) { - rc = 1; goto done; - } - } + if (cmd == CMD_UNKNOWN) { + printf("*** ERROR *** Invalid command \"%s\".\n", av[i]); + rc = 1; goto done; + } - // Patch VSD - if (vsd1) - strncpy(&vsds[0], vsd1, VSD_OFFS); - //if (psid) - // strncpy(&vsds[VSD_OFFS], psid, VSD_LAST); - if (_image_is_full && !use_image_ps) - if (!ops.patchVSD(fim, &vsds[0], &vsds[VSD_OFFS], psid)) { - rc = 1; goto done; - } - - _silent = old_silent; - } else { - // BURN BLOCK: - burn_failsafe = false; - } + if (cmd == CMD_CLEAR_SEM) { + clear_semaphore = true; + } - // Burn it - if (burn_failsafe) { - // Failsafe burn - if (!_image_is_full) { - printf("*** ERROR *** Failsafe burn failed: FW Image on flash is short.\n"); - printf("It is impossible to burn a short image in a failsafe mode.\n"); - printf("If you want to burn in non failsafe mode, use the \"-nofs\" switch.\n"); - rc = 1; goto done; - } + if (!CheckCommandInputs(device, image_fname, cmd)) { + rc = 1; goto done; + } - // FS burn - if (!ops.FailSafe_burn(*f, - fim.getBuf(), - fim.getBufLength(), - single_image_burn, - !silent)) { - if (f->err()) { - // The error is in flash access: - printf("*** ERROR *** Flash access failed during burn: %s\n", f->err()); - } else { - // operation/ algorithm error: - printf("*** ERROR *** Failsafe burn failed: %s\n", ops.err()); - printf("It is impossible to burn this image in a failsafe mode.\n"); - printf("If you want to burn in non failsafe mode, use the \"-nofs\" switch.\n"); - } - rc = 1; goto done; - } - } else { - // - // Not failsafe (sequential) burn - // + if (!CheckMaxCmdArguments(cmd, ac - i - 1 )) { + rc = 1; goto done; + } - // Ask is it OK - printf("\n"); - if (burn_block) { - printf("Block burn: The given image will be burnt as is. No fields (such\n"); - printf("as GUIDS,VSD) are taken from current image on flash.\n"); - } - printf("Burn process will not be failsafe. No checks are performed.\n"); - printf("ALL flash, including Invariant Sector will be overwritten.\n"); - printf("If this process fails computer may remain in unoperatable state.\n"); - if (!ask_user("\nAre you sure ? (y/n) [n] : ")) { - rc = 1; goto done; - } + FBase* fbase; + char* cmdTarget; + char* cmdAccess; - // Non FS burn - if (!ops.write_image(*f, 0, fim.getBuf(), fim.getBufLength(), - !silent)) { - report("\n"); - printf("*** ERROR *** Non failsafe burn failed: %s\n", ops.err()); - rc = 1; goto done; - } - report("\n"); + if (device) { + // Open the device + + u_int32_t num_ports; + auto_ptr tmp( get_flash(device, num_ports)); + f = tmp; + + if (f.get() == NULL) { + printf("*** ERROR *** Can't get flash type using device %s\n", device); + rc = 1; goto done; + } + + ops.SetNumPorts(num_ports); + + g_flash = f.get(); + if (!f->open(device, clear_semaphore)) { + printf("*** ERROR *** Can't open %s: %s\n", device, f->err()); + rc = 1; goto done; + } + + cmdTarget = "Flash"; + cmdAccess = device; + fbase = f.get(); + } + + if (image_fname) { + if (!fim.open(image_fname)) { + printf("*** ERROR *** Image file open failed: %s\n", fim.err()); + rc = 1; goto done; + } + + cmdTarget = "Image file"; + cmdAccess = image_fname; + fbase = &fim; + } + + + + + + switch (cmd) { + case CMD_BURN: + case CMD_BURN_BLOCK: + { + + // + // BURN + // + + bool burn_block = (cmd == CMD_BURN_BLOCK); + + if (!burn_block) { + // Make checks and replace vsd/guids. + + Operations::ImageInfo fileInfo; + Operations::ImageInfo flashInfo; + + bool old_silent = _silent; + _silent = true; + if (!ops.Verify(fim) || !ops.QueryAll(fim, &fileInfo)) { + printf("*** ERROR *** %s: Not a valid image file (%s)\n", image_fname, ops.err()); + rc = 1; goto done; + } + + // Check that the flash sector size is well defined in the image + if (fim.get_sector_size() && (fim.get_sector_size() != f->get_sector_size())) { + printf("*** ERROR *** Flash sector size(0x%x) differs from sector size defined in the image (0x%x).\n" + " This means that the given FW file is not configured to work with the burnt HCA board type.\n", + f->get_sector_size(), + fim.get_sector_size()); + rc = 1; goto done; + } + + // Get GUID and VSD info from flash + + bool read_guids = true; + bool read_ps = true; + + // Flash query (unlike image file query) does not have to + // pass. E.G. blank flash and the user supplies the needed data (guids, vsd). + + bool flash_query_res = ops.QueryAll(*f, &flashInfo); + + if (guids_specified) + read_guids = false; + + if ((user_vsd && user_psid) || use_image_ps) + read_ps = false; + + if (read_guids && !flash_query_res) { + + if (read_guids && !flashInfo.imageOk) { + + printf("\n"); + printf("*** ERROR *** Can't extract GUIDS info from flash. " + "Please specify GUIDs (using command line flags -guid(s) ). \n"); } - } else if (*av[i] == 'e') { - // - // ERASE SECTOR - // Parameters: - // - u_int32_t addr; - char *endp; - - // Device - if (!device) { - printf("For erase command \"-device\" switch must be specified.\n"); - rc = 1; goto done; + + if (burn_failsafe) { + printf(" Can't burn in a failsafe mode. Please use \"-nofs\" flag to burn in a none failsafe mode.\n"); } + rc = 1; goto done; + } - // Address of sector to erase - NEXTC("", "erase"); - addr = strtoul(av[i], &endp, 0); - if (*endp) { - printf("Invalid address \"%s\"\n", av[i]); - rc = 1; goto done; - } + if (read_ps && !flashInfo.psOk) { + printf("\n"); + if (burn_failsafe) { - // Erase - if (!f->erase_sector(addr)) { - printf("*** ERROR *** Erase sector failed: %s\n", f->err()); - rc = 1; goto done; - } - } else if (*av[i] == 'q') { - // QUERY - if (device) { - if (!ops.RevisionInfo(*f, guids, 0, &fs_image)) { - printf("*** ERROR *** Flash query (through device %s) failed.\n", device); + printf("*** ERROR *** Can't extract VSD/PSID info from flash.\n" + " Can't burn in a failsafe mode. Please use \"-nofs\" flag to burn in a none failsafe mode.\n"); + rc = 1; goto done; + } else { + printf("*** WARNING *** Can't extract VSD/PSID info from flash.\n\n" + " To use a specific VSD, abort and re-burn specifying the\n" + " needed info (using command line flags -vsd / -use_image_ps).\n" + " You can also continue burn using blank VSD.\n"); + + if (!ops.ask_user("\n Continue burn using a blank VSD ? (y/n) ")) { rc = 1; goto done; - } - } else if (image_fname) { - FImage fim; - if (!fim.open(image_fname)) { - printf("*** ERROR *** Image file open failed. %s\n", fim.err()); - rc = 1; goto done; } - if (!ops.RevisionInfo(fim, guids, 0, &fs_image)) { - printf("*** ERROR *** Query image file %s failed.\n", image_fname); - rc = 1; goto done; - } - } else { - printf("For query command \"-device\" or \"-image\" switch must be specified.\n"); - rc = 1; goto done; } - } else if (!strcmp(av[i], "rb")) { - // READ BLOCK - // Parameters: [OUT_FILENAME] - // if OUT_FILENAME is given, binari read block is stored - // in the given file. Otherwise, data is printed to screen. - u_int32_t addr, length; - u_int8_t *data; - char *endp; - - bool to_file = false; + } + // Print FW versions: + printf(" Current FW version on flash: "); + if (flashInfo.infoFound[Operations::II_FwVersion]) { + printf("%d.%d.%d\n", flashInfo.fwVer[0], flashInfo.fwVer[1], flashInfo.fwVer[2]); + } else { + printf("N/A\n"); + } + + printf(" New FW version: "); + if (fileInfo.infoFound[Operations::II_FwVersion]) { + printf("%d.%d.%d\n", fileInfo.fwVer[0], fileInfo.fwVer[1], fileInfo.fwVer[2]); + } else { + printf("N/A\n"); + } - FImage fim; - FBase* target; - // Device - if (device) { - target = f.get(); - } else if (image_fname) { - if (!fim.open(image_fname)) { - printf("*** ERROR *** Image file open failed. %s\n", fim.err()); - rc = 1; goto done; - } - target = &fim; - } else { - printf("For rb command \"-device\" or \"-image\" switch must be specified.\n"); + // Patch GUIDS + if (guids_specified) { + if (!ops.patchGUIDs(fim, + user_guids, + flashInfo.imageOk ? flashInfo.guids : NULL, + isatty(0) != 0)) { rc = 1; goto done; } - - // Address and length - NEXTC("", "rb"); - addr = strtoul(av[i], &endp, 0); - if (*endp) { - printf("Invalid address \"%s\"\n", av[i]); - rc = 1; goto done; + } else { + if (!ops.patchGUIDs(fim, NULL, flashInfo.guids, false)) { + rc = 1; goto done; } - NEXTC("", "rb"); - length = strtoul(av[i], &endp, 0); - if (*endp) { - printf("Invalid length \"%s\"\n", av[i]); - rc = 1; goto done; + } + + if (_image_is_full && !use_image_ps) + if (!ops.patchVSD(fim, + user_vsd, + user_psid, + flashInfo.psOk ? flashInfo.vsd : NULL, + flashInfo.psOk ? flashInfo.psid : NULL, + fileInfo.psid )) { + rc = 1; goto done; } - data = new u_int8_t[length]; - // Output file - int fd = -1; + _silent = old_silent; + } else { + // BURN BLOCK: + burn_failsafe = false; + } - if (i + 2 == ac) - to_file = true; + // Burn it + if (burn_failsafe) { + // Failsafe burn + if (!_image_is_full) { + printf("*** ERROR *** Failsafe burn failed: FW Image on flash is short.\n"); + printf("It is impossible to burn a short image in a failsafe mode.\n"); + printf("If you want to burn in non failsafe mode, use the \"-nofs\" switch.\n"); + rc = 1; goto done; + } - if (to_file) { - NEXTC("", "rb"); - if ((fd = open(av[i], O_WRONLY | O_CREAT | O_BINARY, 0666)) < 0) { - fprintf(stderr, "Can't open "); - perror(av[i]); - rc = 1; goto done; - } - if (ftruncate(fd, 0) < 0) { - fprintf(stderr, "Can't truncate "); - perror(av[i]); - rc = 1; goto done; - } - } + // FS burn + if (!ops.FailSafe_burn(*f, + fim.getBuf(), + fim.getBufLength(), + single_image_burn, + !silent)) { + if (f->err()) { + // The error is in flash access: + printf("*** ERROR *** Flash access failed during burn: %s\n", f->err()); + } else { + // operation/ algorithm error: + printf("*** ERROR *** Failsafe burn failed: %s\n", ops.err()); + printf("If you want to burn in non failsafe mode, use the \"-nofs\" switch.\n"); + } + rc = 1; goto done; + } + } else { + // + // Not failsafe (sequential) burn + // - // Read flash - if (!target->read(addr, data, length)) { - printf("*** ERROR *** Flash read failed: %s\n", target->err()); - rc = 1; goto done; - } + // Ask is it OK + printf("\n"); + if (burn_block) { + printf("Block burn: The given image will be burnt as is. No fields (such\n"); + printf("as GUIDS,VSD) are taken from current image on flash.\n"); + } + printf("Burn process will not be failsafe. No checks are performed.\n"); + printf("ALL flash, including Invariant Sector will be overwritten.\n"); + printf("If this process fails computer may remain in unoperatable state.\n"); - if (to_file) { - // Write output - if (write(fd, data, length) != (int)length) { - perror("Write error"); - rc = 1; goto done; - } - close(fd); - } else { - for (u_int32_t i = 0; i < length ; i+=4) { - u_int32_t word = *((u_int32_t*)(data + i)); + if (!ops.ask_user("\nAre you sure ? (y/n) [n] : ")) { + rc = 1; goto done; + } - word = __be32_to_cpu(word); - printf("0x%08x ", word); - } - printf("\n"); - } - delete [] data; - } else if (!strcmp(av[i], "rw")) { - // READ DWORD - // Parameters: - u_int32_t data, addr; - char *endp; - - // Device - if (!device) { - printf("For rw command \"-device\" switch must be specified.\n"); - rc = 1; goto done; - } + // Non FS burn + if (!ops.write_image(*f, 0, fim.getBuf(), fim.getBufLength(), + !silent)) { + report("\n"); + printf("*** ERROR *** Non failsafe burn failed: %s\n", ops.err()); + rc = 1; goto done; + } + report("\n"); + } + } + break; - // Address - NEXTC("", "rw"); - addr = strtoul(av[i], &endp, 0); - if (*endp) { - printf("Invalid address \"%s\"\n", av[i]); - rc = 1; goto done; - } + case CMD_ERASE_SECT: + { + // + // ERASE SECTOR + // Parameters: + // + u_int32_t addr; + char *endp; - // Read - if (!f->read(addr, &data)) { - printf("*** ERROR *** Flash read failed: %s\n", f->err()); - rc = 1; goto done; - } - printf("0x%08x\n", (unsigned int)__cpu_to_be32(data)); - } else if (*av[i] == 'v') { - // VERIFY - if (device) - ops.Verify(*f); - else if (image_fname) { - FImage fim; - if (!fim.open(image_fname)) { - printf("*** ERROR *** Image file open failed: %s\n", fim.err()); - rc = 1; goto done; - } - ops.Verify(fim); - } else { - printf("For verify command \"-device\" or \"-image\" switch must be specified.\n"); - rc = 1; goto done; - } - - } else if (!strcmp(av[i], "dc")) { - // Dump conf - _silent = true; - - char* conf_file = NULL; - if (i + 2 <= ac) { - NEXTC("", "dc"); - conf_file = av[i]; - } + // Address of sector to erase + NEXTC("", "erase"); + addr = strtoul(av[i], &endp, 0); + if (*endp) { + printf("Invalid address \"%s\"\n", av[i]); + rc = 1; goto done; + } - if (device) - ops.Verify(*f); - else if (image_fname) { - FImage fim; - if (!fim.open(image_fname)) { - printf("*** ERROR *** Image file open failed: %s\n", fim.err()); - rc = 1; goto done; - } - ops.Verify(fim); - } else { - printf("For verify command \"-device\" or \"-image\" switch must be specified.\n"); - rc = 1; goto done; - } + // Erase + if (!f->erase_sector(addr)) { + printf("*** ERROR *** Erase sector failed: %s\n", f->err()); + rc = 1; goto done; + } + } + break; - if(!ops.DumpConf(conf_file)) { - printf("*** ERROR *** Failed dumping FW configuration: %s\n", ops.err()); - rc = 1; goto done; - } + case CMD_QUERY: + { + // QUERY + Operations::ImageInfo info; - } else if (!strcmp(av[i], "ri")) { - // Dump conf - _silent = true; + if (!ops.QueryAll(*fbase, &info)) { + printf("*** ERROR *** %s query (%s) failed: %s\n", cmdTarget , cmdAccess, ops.err()); + rc = 1; goto done; + } - char* img_file = NULL; - NEXTC("", "ri"); - img_file = av[i]; + ops.DisplayImageInfo(&info); + } + break; - if (device) { - ops.Verify(*f); - } else { - printf("For ri command \"-device\" switch must be specified.\n"); - rc = 1; goto done; - } + case CMD_READ_BLOCK: + { + // READ BLOCK + // Parameters: [OUT_FILENAME] + // if OUT_FILENAME is given, binari read block is stored + // in the given file. Otherwise, data is printed to screen. + u_int32_t addr, length; + u_int8_t *data; + char *endp; + + bool to_file = false; + + // Address and length + NEXTC("", "rb"); + addr = strtoul(av[i], &endp, 0); + if (*endp) { + printf("Invalid address \"%s\"\n", av[i]); + rc = 1; goto done; + } + NEXTC("", "rb"); + length = strtoul(av[i], &endp, 0); + if (*endp) { + printf("Invalid length \"%s\"\n", av[i]); + rc = 1; goto done; + } + data = new u_int8_t[length]; - //printf("Last addr: 0x%08x\n", ops._last_image_addr); + // Output file + FILE* fh; - u_int32_t length = ops._last_image_addr; - u_int8_t* data = new u_int8_t[length]; + if (i + 2 == ac) + to_file = true; + if (to_file) { + NEXTC("", "rb"); + if ((fh = fopen(av[i], "wb")) == NULL) { + fprintf(stderr, "Can't open "); + perror(av[i]); + rc = 1; goto done; + } + } - int fd = -1; + // Read flash + if (!fbase->read(addr, data, length)) { + printf("*** ERROR *** Flash read failed: %s\n", fbase->err()); + rc = 1; goto done; + } - if ((fd = open(av[i], O_WRONLY | O_CREAT | O_BINARY, 0666)) < 0) { - fprintf(stderr, "Can't open "); - perror(av[i]); - rc = 1; goto done; - } - if (ftruncate(fd, 0) < 0) { - fprintf(stderr, "Can't truncate "); - perror(av[i]); - rc = 1; goto done; - } + if (to_file) { + // Write output + if (fwrite(data, 1, length, fh) != length) { + perror("Write error"); + rc = 1; goto done; + } + fclose(fh); + } else { + for (u_int32_t i = 0; i < length ; i+=4) { + u_int32_t word = *((u_int32_t*)(data + i)); - // Read flash - if (!f->read(0, data, length)) { - printf("*** ERROR *** Flash read failed: %s\n", f->err()); - rc = 1; goto done; - } + word = __be32_to_cpu(word); + printf("0x%08x ", word); + } + printf("\n"); + } + delete [] data; + } + break; - // Write output - if (write(fd, data, length) != (int)length) { - perror("Write error"); - rc = 1; goto done; - } - close(fd); + case CMD_READ_WORD: + { + // READ DWORD + // Parameters: + u_int32_t data, addr; + char *endp; + + // Address + NEXTC("", "rw"); + addr = strtoul(av[i], &endp, 0); + if (*endp) { + printf("Invalid address \"%s\"\n", av[i]); + rc = 1; goto done; + } - delete [] data; + // Read + if (!f->read(addr, &data)) { + printf("*** ERROR *** Flash read failed: %s\n", f->err()); + rc = 1; goto done; + } + printf("0x%08x\n", (unsigned int)__cpu_to_be32(data)); - } else if (!strcmp(av[i], "wb")) { - // WRITE BLOCK - // Parameters: - u_int32_t addr, length; - u_int8_t *data; - char *endp; + } + break; - // Device - if (!device) { - printf("For wb command \"-device\" switch must be specified.\n"); - rc = 1; goto done; - } + case CMD_VERIFY: + { + // VERIFY + if (!ops.Verify(*fbase)) { + printf("\n*** ERROR *** FW Image verification failed. AN HCA DEVICE CAN NOT BOOT FROM THIS IMAGE.\n"); + rc = 1; goto done; + } else { + printf("\nFW Image verification succeeded. Image is OK.\n\n"); + } + } + break; - // Input file - int fd; - struct stat statbuf; - NEXTC("", "wb"); - if ((fd = ::open(av[i], O_RDONLY | O_BINARY), 0) < 0) { - fprintf(stderr, "Can't open "); - perror(av[i]); - rc = 1; goto done; - } - if (fstat(fd, &statbuf) < 0) { - fprintf(stderr, "Can't stat "); - perror(av[i]); - rc = 1; goto done; - } - length = statbuf.st_size; - data = new u_int8_t[length]; - - // Address - NEXTC("", "wb"); - addr = strtoul(av[i], &endp, 0); - if (*endp) { - printf("Invalid address \"%s\"\n", av[i]); - rc = 1; goto done; - } + case CMD_DUMP_CONF: + { + // Dump conf + _silent = true; - // Read file - if (read(fd, data, length) != (int)length) { - perror("Read error"); - rc = 1; goto done; - } + char* conf_file = NULL; + if (i + 2 <= ac) { + NEXTC("", "dc"); + conf_file = av[i]; + } - // Write flash - if (!ops.write_image(*f, addr, data, length, !silent)) { - printf("*** ERROR *** Flash write failed: %s\n", ops.err()); - rc = 1; goto done; - } + ops.Verify(*fbase); - close(fd); - delete [] data; - } else if (!strcmp(av[i], "ww")) { - // WRITE DWORD - // Parameters: - u_int32_t data, addr; - char *endp; - - // Device - if (!device) { - printf("For ww command \"-device\" switch must be specified.\n"); - rc = 1; goto done; - } + if(!ops.DumpConf(conf_file)) { + printf("*** ERROR *** Failed dumping FW configuration: %s\n", ops.err()); + rc = 1; goto done; + } + } + break; - // Address and data - NEXTC("", "ww"); - addr = strtoul(av[i], &endp, 0); - if (*endp) { - printf("Invalid address \"%s\"\n", av[i]); - rc = 1; goto done; - } - NEXTC("", "ww"); - data = __cpu_to_be32(strtoul(av[i], &endp, 0)); - if (*endp) { - printf("Invalid data \"%s\"\n", av[i]); - rc = 1; goto done; - } + case CMD_READ_IMAGE: + { + // Dump conf + _silent = true; - //f->curr_sector = 0xffffffff; // First time erase sector - if (!f->write(addr, data)) { - printf("*** ERROR *** Flash write failed: %s\n", f->err()); - rc = 1; goto done; - } - } else if (!strcmp(av[i], "wbne")) { - // WRITE DWORD WITHOUT ERASE - // Parameters: - u_int32_t size, addr; - char *endp; - - // Device - if (!device) { - printf("For wbne command \"-device\" switch must be specified.\n"); - rc = 1; goto done; - } + char* img_file = NULL; + NEXTC("", "ri"); + img_file = av[i]; - // Address and data - NEXTC("", "wbne"); - addr = strtoul(av[i], &endp, 0); - if (*endp) { - printf("Invalid address \"%s\"\n", av[i]); - rc = 1; goto done; - } - NEXTC("", "wbne"); - size = strtoul(av[i], &endp, 0); - if (*endp || size % 4) { - printf("Invalid size \"%s\"\n", av[i]); - rc = 1; goto done; - } - vector data_vec(size/4); - for (u_int32_t w = 0; w < size/4 ; w++) { - NEXTC("", "wbne"); - data_vec[w] = __cpu_to_be32(strtoul(av[i], &endp, 0)); - if (*endp) { - printf("Invalid data \"%s\"\n", av[i]); - rc = 1; goto done; - } + ops.Verify(*f); + + //printf("Last addr: 0x%08x\n", ops._last_image_addr); - //printf("-D- writing: %08x : %08x\n", addr + w*4 , data_vec[w]); - } + u_int32_t length = ops._last_image_addr; + u_int8_t* data = new u_int8_t[length]; - if (!f->write(addr, &data_vec[0], size, true, false)) { - printf("*** ERROR *** Flash write failed: %s\n", f->err()); - rc = 1; goto done; - } - } else if (!strcmp(av[i], "wwne")) { - // WRITE DWORD WITHOUT ERASE - // Parameters: - u_int32_t data, addr; - char *endp; - - // Device - if (!device) { - printf("For wwne command \"-device\" switch must be specified.\n"); - rc = 1; goto done; - } + FILE* fh; - // Address and data - NEXTC("", "wwne"); - addr = strtoul(av[i], &endp, 0); - if (*endp) { - printf("Invalid address \"%s\"\n", av[i]); - rc = 1; goto done; - } - NEXTC("", "wwne"); - data = __cpu_to_be32(strtoul(av[i], &endp, 0)); - if (*endp) { - printf("Invalid data \"%s\"\n", av[i]); - rc = 1; goto done; - } + if ((fh = fopen(av[i], "wb")) == NULL) { + fprintf(stderr, "Can't open "); + perror(av[i]); + rc = 1; goto done; + } - if (!f->write(addr, &data, 4, true, false)) { - printf("*** ERROR *** Flash write failed: %s\n", f->err()); - rc = 1; goto done; - } - } else if (!strcmp(av[i], "cfi")) { - // CFI (COMMON FLASH INTERFACE) QUERY + // Read flash + if (!f->read(0, data, length)) { + printf("*** ERROR *** Flash read failed: %s\n", f->err()); + rc = 1; goto done; + } + // Write output + if (fwrite(data, 1, length, fh) != length) { + perror("Write error"); + rc = 1; goto done; + } + fclose(fh); - // Device - if (!device) { - printf("For cfi command \"-device\" switch must be specified.\n"); - rc = 1; goto done; - } + delete [] data; + } + break; - if (!f->print_cfi_info()) { - printf("*** ERROR *** Cfi query failed: %s\n", f->err()); - rc = 1; goto done; - } - } else { - printf("Invalid command \"%s\".\n", av[i]); + case CMD_WRITE_BLOCK: + { + // WRITE BLOCK + // Parameters: + u_int32_t addr; + char *endp; + + char* fname; + + // Device + if (!device) { + printf("For wb command \"-device\" switch must be specified.\n"); + rc = 1; goto done; + } + + // Input file + FImage fim; + + NEXTC("", "wb"); + + fname = av[i]; + + // Address + NEXTC("", "wb"); + addr = strtoul(av[i], &endp, 0); + if (*endp) { + printf("Invalid address \"%s\"\n", av[i]); + rc = 1; goto done; + } + + if (!fim.open(image_fname)) { + printf("*** ERROR *** Image file open failed: %s\n", fim.err()); + rc = 1; goto done; + } + + // Write flash + if (!ops.write_image(*f, addr, fim.getBuf(), fim.getBufLength(), !silent)) { + printf("*** ERROR *** Flash write failed: %s\n", ops.err()); + rc = 1; goto done; + } + } + break; + + case CMD_WRITE_WORD: + { + // WRITE DWORD + // Parameters: + u_int32_t data, addr; + char *endp; + + // Address and data + NEXTC("", "ww"); + addr = strtoul(av[i], &endp, 0); + if (*endp) { + printf("Invalid address \"%s\"\n", av[i]); + rc = 1; goto done; + } + NEXTC("", "ww"); + data = __cpu_to_be32(strtoul(av[i], &endp, 0)); + if (*endp) { + printf("Invalid data \"%s\"\n", av[i]); + rc = 1; goto done; + } + + //f->curr_sector = 0xffffffff; // First time erase sector + if (!f->write(addr, data)) { + printf("*** ERROR *** Flash write failed: %s\n", f->err()); + rc = 1; goto done; + } + } + break; + + case CMD_WRITE_BLOCK_NE: + { + // WRITE DWORD WITHOUT ERASE + // Parameters: + u_int32_t size, addr; + char *endp; + + // Address and data + NEXTC("", "wbne"); + addr = strtoul(av[i], &endp, 0); + if (*endp) { + printf("Invalid address \"%s\"\n", av[i]); + rc = 1; goto done; + } + NEXTC("", "wbne"); + size = strtoul(av[i], &endp, 0); + if (*endp || size % 4) { + printf("Invalid size \"%s\"\n", av[i]); + rc = 1; goto done; + } + vector data_vec(size/4); + for (u_int32_t w = 0; w < size/4 ; w++) { + NEXTC("", "wbne"); + data_vec[w] = __cpu_to_be32(strtoul(av[i], &endp, 0)); + if (*endp) { + printf("Invalid data \"%s\"\n", av[i]); rc = 1; goto done; } + + //printf("-D- writing: %08x : %08x\n", addr + w*4 , data_vec[w]); + } + + if (!f->write(addr, &data_vec[0], size, true, false)) { + printf("*** ERROR *** Flash write failed: %s\n", f->err()); + rc = 1; goto done; } } + break; + + case CMD_WRITE_WORD_NE: + { + // WRITE DWORD WITHOUT ERASE + // Parameters: + u_int32_t data, addr; + char *endp; + + // Address and data + NEXTC("", "wwne"); + addr = strtoul(av[i], &endp, 0); + if (*endp) { + printf("Invalid address \"%s\"\n", av[i]); + rc = 1; goto done; + } + NEXTC("", "wwne"); + data = __cpu_to_be32(strtoul(av[i], &endp, 0)); + if (*endp) { + printf("Invalid data \"%s\"\n", av[i]); + rc = 1; goto done; + } + + if (!f->write(addr, &data, 4, true, false)) { + printf("*** ERROR *** Flash write failed: %s\n", f->err()); + rc = 1; goto done; + } + } + break; + + case CMD_CFI: + { + if (!f->print_cfi_info()) { + printf("*** ERROR *** Cfi query failed: %s\n", f->err()); + rc = 1; goto done; + } + } + break; + + case CMD_CLEAR_SEM: + // Do nothing - opening the device already cleared the semaphore. + break; + + default: + printf("*** INTERNAL ERROR *** Invalid command %d.\n", cmd); + rc = 1; goto done; + } done: @@ -5697,3 +6437,4 @@ done: return rc; } + -- 2.46.0