* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
- * Version: $Id: flint.cpp 6984 2011-05-02 12:21:00Z mohammad $
+ * Version: $Id: flint.cpp 7187 2011-07-05 11:53:16Z orenk $
*
*/
#include <fcntl.h>
#include <assert.h>
#include <time.h>
+#include <termios.h>
+
#include "tools_version.h"
#ifndef FLINT_NAME
#ifdef __GNUC__
- #define FLINT_NAME "%1$s"
+ #define FLINT_NAME "flint"
#else
- #define FLINT_NAME "./flint"
+ #define FLINT_NAME "flint"
#endif
#endif
u_int32_t h;
u_int32_t l;
} guid_t;
+typedef guid_t hw_key_t;
static inline void be_guid_to_cpu(guid_t* to, guid_t* from) {
to->h=__be32_to_cpu(from->h);
FBase(true),
_mfl(0),
_curr_sector(0xffffffff),
- _port_num(0)
+ _port_num(0),
+ _cr_space_locked(0)
{}
virtual ~Flash() { close();};
u_int32_t get_dev_id () {return _attr.hw_dev_id; }
u_int32_t get_rev_id () {return _attr.rev_id; }
u_int32_t get_port_num () {return _port_num;}
+ u_int8_t get_cr_space_locked () {return _cr_space_locked;}
bool sw_reset();
virtual bool write (u_int32_t addr,
u_int32_t data);
+ virtual bool enable_hw_access(u_int64_t key);
+
+ virtual bool disable_hw_access();
+
bool print_attr();
- bool print_attr_old_format();
enum {
TRANS = 4096
u_int32_t _curr_sector;
u_int32_t _port_num;
+ u_int8_t _cr_space_locked;
};
rc = mf_open_ignore_lock(_mfl);
}
- if (rc == MFE_SEM_LOCKED) {
- return errmsg("Can not obtain Flash semaphore (63). You can run \"flint -clear_semaphore -d <device>\" to force semaphore unlock. See help for details.");
- } else
- if (rc != MFE_OK) {
+ if (rc != MFE_OK) {
+ if (rc == MFE_SEM_LOCKED) {
+ return errmsg("Can not obtain Flash semaphore (63). You can run \"flint -clear_semaphore -d <device>\" to force semaphore unlock. See help for details.");
+ }
+ if (rc == MFE_LOCKED_CRSPACE) {
+ _cr_space_locked = 1;
+ return errmsg("HW access is disabled on the device.\n-E- Run \"flint -d %s hw_access enable\" in order to enable HW access.", device);
+ }
+ if (rc == MFE_REG_ACCESS_MAD_NOT_SUPPORTED) {
+ return errmsg("The target device FW does not support flash access commands.\n-E- Please use the -override_cache_replacement option in order to access the flash directly.");
+ }
+ if (rc == MFE_DIRECT_FW_ACCESS_DISABLED) {
+ return errmsg(" Flash cache replacement is active.\n-E- Please use the -override_cache_replacement option in order to access the flash directly.");
+ }
+
return errmsg("%s %s", errno == 0 ? "" : strerror(errno), mf_err2str(rc));
}
return true;
}
+bool Flash::enable_hw_access(u_int64_t key)
+{
+ int rc;
+ rc = mf_enable_hw_access(_mfl, key);
+
+ if (rc != MFE_OK) {
+ return errmsg("Enable HW access failed: %s", mf_err2str(rc));
+ }
+ return true;
+}
+
+bool Flash::disable_hw_access(void)
+{
+ int rc;
+ rc = mf_disable_hw_access(_mfl);
+
+ if (rc != MFE_OK) {
+ return errmsg("Disable HW access failed: %s", mf_err2str(rc));
+ }
+ return true;
+
+}
+
bool Flash::sw_reset() {
- if (_attr.hw_dev_id != 435 || _attr.hw_dev_id == SWITCHX_HW_ID) {
- return errmsg("operation supported only for InfiniScale4 switch over IB interface");
+ if (_attr.hw_dev_id != 435 && _attr.hw_dev_id != SWITCHX_HW_ID) {
+ return errmsg("operation supported only for InfiniScale4 switch and SwitchX over IB interface");
}
int rc = mf_sw_reset(_mfl);
if (rc != MFE_OK) {
- return errmsg("%s %s", errno == 0 ? "" : strerror(errno), mf_err2str(rc));
+ return errmsg("%s (%s)", errno == 0 ? "" : strerror(errno), mf_err2str(rc));
}
return true;
}
bool Flash::print_attr() {
printf("Flash attributes:\n");
printf(" HwDevId %d\n", _attr.hw_dev_id);
+ printf(" HwRevId 0x%x\n", _attr.rev_id);
printf(" TotalSize 0x%x\n", _attr.size);
printf(" Banks 0x%x\n", _attr.size/_attr.bank_size );
printf(" SectorSize 0x%x\n", _attr.sector_size );
return true;
}
-bool Flash::print_attr_old_format() {
- // Needed for some old tools which parce the size section of the CFI query in oder flint versions:
-
- int i;
- printf("\n----Sector Organization Parameters-------------------\n\n");
-
- printf("%-50s ", "Device size:");
- printf("[%8li] bytes, or [%2i] Mbit\n",
- (long int)_attr.size,
- (int) (_attr.size/((long)0x20000)));
-
- printf("%-50s ", "Number of erase block regions:");
- printf("%d\n", _attr.num_erase_blocks);
-
- for (i = 0; i < _attr.num_erase_blocks; i++) {
- printf(" Size:[%8lx] bytes, Mask [%08x], [Number:[%4i]\n",
- _attr.erase_block[i].sector_size,
- _attr.erase_block[i].sector_mask,
- _attr.erase_block[i].num_sectors);
- }
- return true;
-}
////////////////////////////////////////////////////////////////////////
CMD_BURN_ROM,
CMD_REMOVE_ROM,
CMD_READ_ROM,
+ CMD_SET_KEY,
+ CMD_HW_ACCESS,
};
struct CommandInfo {
{ CMD_BURN_BLOCK , "bb" ,true , 0, CI_IMG_AND_DEV , ""},
{ CMD_SET_GUIDS , "sg" ,true , 1, CI_IMG_OR_DEV , ""},
{ CMD_SET_VSD , "sv" ,true , 0, CI_IMG_OR_DEV , ""},
+ { CMD_SET_KEY , "set_key" ,true , 1, CI_DEV_ONLY , ""},
{ CMD_QUERY_FORCE , "qf" ,true , 0, CI_IMG_OR_DEV , ""},
{ CMD_QUERY , "query" ,false , 1, CI_IMG_OR_DEV , ""},
{ CMD_QUERY_ROM , "qrom" ,true , 0, CI_IMG_ONLY , ""},
{ CMD_BURN_ROM , "brom" ,true , 1, CI_DEV_ONLY , ""},
{ CMD_REMOVE_ROM , "drom" ,true , 0, CI_DEV_ONLY , ""},
{ CMD_READ_ROM , "rrom" ,true , 1, CI_DEV_ONLY , ""},
+ { CMD_HW_ACCESS , "hw_access" , true , 2, CI_DEV_ONLY , ""},
+
};
// Burn Operations functions
//
////////////////////////////////////////////////////////////////////////
-#define FULL_VERIFY 0xff
-#define FREE_STR_MAX_LEN 256
+#define FULL_VERIFY 0xff
+#define FREE_STR_MAX_LEN 256
#define MAX_ROM_ERR_MSG_LEN 256
+#define MAX_ROMS_NUM 5
+#define ROM_INFO_SIZE 12
+
class Operations : public ErrMsg {
public:
Operations() :
II_HwDevsId = 10,
II_MicVersion = 11,
II_MinFitVersion = 12,
- II_Last = 13, // Mark the end of used tag ids
+ II_HwAccessKey = 13,
+ II_Last = 14, // Mark the end of used tag ids
II_End = 0xff
};
};
struct ImageInfo;
+ struct RomInfo;
// Burn operations:
bool write_image (Flash& f, u_int32_t addr, void *data, int cnt, bool need_report, const char* message,
bool ReburnNewImage(u_int8_t *data, FBase *fbase, Operations::ImageInfo *info, char *image_fname, bool silent, char *feature_name);
bool ModifyGuidSection(FBase *fbase, Operations::ImageInfo *info, guid_t *user_guids, char *image_fname, bool silent);
bool ModifyVSDSection(FBase *fbase, Operations::ImageInfo *info, char *vsd, char *image_fname, bool silent);
+ bool ModifyKeySection(FBase *fbase, Operations::ImageInfo *info, guid_t key_str, char *image_fname, bool silent);
+
bool PrepareBurnErr(Flash& f);
bool LoadAsExpRom (FBase& f, ImageInfo* info);
bool DumpConf (const char* conf_file = NULL, SectionType sect_type = H_FW_CONF);
+ bool GetExpRomVerForOneRom(ImageInfo* info, u_int32_t ver_offset);
+
+
bool GetExpRomVersion(ImageInfo* info);
bool GetExpRomVersionWrapper(ImageInfo* info);
- bool DisplayExpRomInfo(ImageInfo* info, bool print_pre = true);
+ bool DisplayOneExpRomInfo(RomInfo* info);
+ bool DisplayExpRomInfo(ImageInfo* info, char *pre_str = "");
bool DisplayImageInfo (ImageInfo* info, bool full_query = false);
bool GetExpRomStrVer(Operations::ImageInfo* info, char* version);
QueryImage(f, info);}
bool getBSN (char *s, guid_t *guid);
- bool getGUID (const char *s, guid_t *guid);
+ bool getGUID (const char *s, guid_t *guid, char *filed_type = "");
bool getFlashParams(char *flash_arg, flash_params_t *flash_params);
bool patchVSD (FImage& f,
const char *curr_psid,
const char *image_psid);
+ bool patchHwAccessKey(FImage& f, ImageInfo& flash_info, ImageInfo& imageinfo);
+
// Misc operations
void SetDevFlags(u_int16_t devType, bool& ib_dev, bool& eth_dev);
bool CheckGuidsFlags(u_int16_t devType,
guid_t old_guids[MAX_GUIDS],
u_int32_t num_of_old_guids);
+ bool preFS2PatchGUIDs(bool patch_macs,
+ bool patch_uids,
+ bool user_guids,
+ bool user_macs,
+ bool user_uids,
+ guid_t new_guids[MAX_GUIDS],
+ guid_t old_guids[MAX_GUIDS],
+ guid_t **used_guid_p,
+ u_int32_t num_of_old_guids);
+
bool PrintMacLine (guid_t* new_guids, guid_t* old_guids, int mac_index);
bool PrintBxMacs (guid_t* new_guids, guid_t* old_guids, int index, int num_of_guids, const char* pre_str);
bool PrintGuidLine (guid_t* new_guids, guid_t* old_guids, int guid_index);
void SetFs2Mode (bool fs2_mode) {_is_fs2 = fs2_mode;}
void SetIgnoreTty (bool ignore_tty) {_ignore_tty = ignore_tty;}
void SetFs2StripedImage(bool si) {_cntx_striped_image = si;}
+ bool GetFs2StripedImage() {return _cntx_striped_image;}
bool IsFs2 () {return _is_fs2;}
bool CheckMac (u_int64_t mac);
// _last_image_addr is set by the Verify() op
u_int32_t _last_image_addr;
+ struct RomInfo {
+ bool expRomValidVersion;
+ u_int16_t expRomProductId; // 0 - invalid.
+ u_int16_t expRomVer[3];
+ u_int16_t expRomDevId;
+ u_int8_t expRomPort;
+ u_int8_t expRomProto;
+ char expRomFreestr[FREE_STR_MAX_LEN];
+ };
+
//
// 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
u_int32_t supportedHwId[MAX_NUM_SUPP_HW_IDS];
int supportedHwIdNum;
+ u_int8_t accessKeyExists;
+ guid_t accessKeyValue;
+
u_int32_t imageSize;
u_int32_t infoOffs[II_Last]; // Offset of the tag data inside the info section data.
// Can not be 0 (because of tag header) - 0 means not found.
- bool expRomFound;
- bool expRomValidVersion;
- u_int16_t expRomProductId; // 0 - invalid.
- u_int16_t expRomVer[3];
- u_int16_t expRomDevId;
- u_int8_t expRomPort;
- u_int8_t expRomProto;
- char expRomFreestr[FREE_STR_MAX_LEN];
- bool expRomWarning;
- char expRomWarningMsg[MAX_ROM_ERR_MSG_LEN];
- bool expRomErrMsgValid;
- char expRomErrMsg[MAX_ROM_ERR_MSG_LEN];
-
- bool magicPatternFound;
- std::vector<u_int8_t> _rom_sect;
+ // Can not be 0 (because of tag header) - 0 means not found.
+ bool expRomFound;
+ u_int8_t numOfExpRom;
+ bool noRomChecksum;
+ bool expRomValidVersion;
+ u_int16_t expRomComDevid;
+ bool expRomWarning;
+ char expRomWarningMsg[MAX_ROM_ERR_MSG_LEN];
+ bool expRomErrMsgValid;
+ char expRomErrMsg[MAX_ROM_ERR_MSG_LEN];
+ struct RomInfo romInfo[MAX_ROMS_NUM];
+ std::vector<u_int8_t> _rom_sect;
+
+ bool magicPatternFound;
};
enum {
void PatchInfoSect (u_int8_t* rawSect,
u_int32_t vsdOffs,
const char* vsd);
+ void PatchKeySect(u_int32_t* buff, u_int32_t keyOff, guid_t hw_key);
+
private:
bool FailSafe_burn_image (Flash& f,
return true;
}
+#define MISS_MATCH_DEV_ID 0xffff
+#define EXP_ROM_GEN_DEVID 0
+
bool Operations::CheckMatchingExpRomDevId(Operations::ImageInfo* info) {
- if (info->expRomFound &&
- info->expRomValidVersion &&
- info->expRomProductId >= 0x10 &&
- info->infoOffs[II_DeviceType] &&
- info->expRomDevId != 0 &&
- info->devType != info->expRomDevId) {
- return errmsg("FW is for device %d, but Exp-ROM is for device %d",
- info->devType,
- info->expRomDevId);
+ if (info->expRomFound && info->numOfExpRom && info->infoOffs[II_DeviceType]
+ && info->expRomComDevid != EXP_ROM_GEN_DEVID && info->expRomComDevid != MISS_MATCH_DEV_ID
+ && info->devType != info->expRomComDevid) {
+ return errmsg("FW is for device %d, but Exp-ROM is for device %d",
+ info->devType, info->expRomComDevid);
}
return true;
}
+bool Operations::ModifyKeySection(FBase *fbase, Operations::ImageInfo *info, guid_t access_key, char *image_fname, bool silent)
+{
+
+ u_int32_t length = info->imageSize;
+ vector<u_int8_t> data(length);
+
+ // Read the image.
+ if (!fbase->read(0, (u_int8_t*)(&data[0]), length)) {
+ return errmsg("Flash/Image read failed: %s\n", fbase->err());
+ }
+
+ // Change the VSD
+ PatchKeySect((u_int32_t*)(&data[0] + info->infoSectPtr - sizeof(GPH)),
+ info->infoOffs[Operations::II_HwAccessKey],
+ access_key);
+ // Re-burn the new Image after modifying the VSD
+ return ReburnNewImage((u_int8_t*)(&data[0]), fbase, info, image_fname, silent, (char*)"HW Key");
+}
+
+
bool Operations::Verify(FBase& f, Operations::ImageInfo* info, bool both_images)
{
u_int32_t prim_ptr, scnd_ptr;
return true;
}
-bool Operations::GetExpRomVersion(ImageInfo* info) {
- const char* magic_string = "mlxsign:";
- u_int32_t magic_len = strlen(magic_string);
- u_int32_t i;
- bool magic_found = false;
- u_int32_t ver_offset;
- u_int32_t rom_checksum_range;
-
- // Init some
- info->expRomValidVersion = false;
- info->expRomWarning = false;
- info->expRomErrMsgValid = false;
-
- if (info->_rom_sect.empty()) {
- return errmsg("Expansion Rom section not found.");
- }
- // When checking the version of the expansion rom, only the first image has
- // to be checked. This is because the second image the uefi image does not
- // have to comply with checksumming to 0. To do this you have to read byte
- // 2 (third) of the image and multiply by 512 to get the size of the x86
- // image.
-
- // Checksum:
- if (info->_rom_sect.size() < 4) {
- return errmsg("ROM size (0x%x) is too small", (u_int32_t)info->_rom_sect.size());
- }
-
- // restore endianess.
- TOCPUn(&(info->_rom_sect[0]), info->_rom_sect.size()/4);
-/* // FOR WE DON'T CHECKSUM UNTIL WE DECIDED REGARDING THE NEW FORMAT.
-*/
- // We will look for the magic string in whole ROM instead of the first part of it.
- rom_checksum_range = info->_rom_sect.size();
-
- for (i = 0 ; i < rom_checksum_range; i++) {
- for (u_int32_t j = 0; j < magic_len; j++) {
- if (info->_rom_sect[i+j] != magic_string[j]) {
- break;
- } else if (j == magic_len - 1) {
- magic_found = true;
- }
- }
+bool Operations::GetExpRomVerForOneRom(ImageInfo* imageInfo, u_int32_t ver_offset) {
- if (magic_found) {
- break;
- }
+ u_int32_t tmp;
+ RomInfo *romInfo;
+
+ if (imageInfo->numOfExpRom == MAX_ROMS_NUM) {
+ imageInfo->expRomWarning = true;
+ snprintf(imageInfo->expRomWarningMsg,
+ MAX_ROM_ERR_MSG_LEN,
+ "Number of exp ROMs exceeds the maximum allowed number: %d",
+ MAX_ROMS_NUM);
+ return true;
}
+ romInfo = &(imageInfo->romInfo[imageInfo->numOfExpRom]);
- if (magic_found) {
- ver_offset = i + magic_len;
- } else {
- return errmsg("Cannot get ROM version. Signature not found.");
- }
// Following mlxsign:
// 31:24 0 Compatible with UEFI
// 8:11 Reserved
// 0:7 Protocol type: 0=IB 1=ETH 2=VPI
- u_int32_t tmp;
// Get expansion rom product ID
- tmp = __le32_to_cpu(*((u_int32_t*) &info->_rom_sect[ver_offset]));
- info->expRomProductId = tmp >> 16;
- info->expRomVer[0] = tmp & 0xffff;
-
- // Check sum for expansion ROM
- if (info->expRomProductId != 0x11) { // No need for checksum on UEFI
- u_int8_t rom_checksum = 0;
- rom_checksum_range = info->_rom_sect[2] * 512 ;
- if (rom_checksum_range > info->_rom_sect.size()) {
- return errmsg("ROM size field (0x%2x) is larger than actual ROM size (0x%x)",
- rom_checksum_range ,
- (u_int32_t)info->_rom_sect.size());
- } else if (rom_checksum_range == 0) {
- return errmsg("ROM size field is 0. Unknown ROM format or corrupted ROM.");
- }
+ tmp = __le32_to_cpu(*((u_int32_t*) &imageInfo->_rom_sect[ver_offset]));
+ romInfo->expRomProductId = tmp >> 16;
+ romInfo->expRomVer[0] = tmp & 0xffff;
- for (i = 0; i < rom_checksum_range; i++) {
- rom_checksum += info->_rom_sect[i];
- }
-
- if (rom_checksum != 0) {
- info->expRomWarning = true;
- snprintf(info->expRomWarningMsg, MAX_ROM_ERR_MSG_LEN,
- "Bad ROM Checksum (0x%02x), ROM info may not be displayed correctly.", rom_checksum);
- }
+ if (romInfo->expRomProductId == 0x11) {
+ imageInfo->noRomChecksum = true;
}
- if (info->expRomProductId >= 0x10) {
- tmp = __le32_to_cpu(*((u_int32_t*) &info->_rom_sect[ver_offset + 4]));
- info->expRomVer[1] = tmp >> 16;
- info->expRomVer[2] = tmp & 0xffff;
- tmp = __le32_to_cpu(*((u_int32_t*) &info->_rom_sect[ver_offset + 8]));
- info->expRomDevId = tmp >> 16;
- info->expRomPort = (tmp >> 12) & 0xf;
- info->expRomProto = tmp & 0xff;
- } else if (info->expRomProductId == 0xf) {
+ if (romInfo->expRomProductId >= 0x10) {
+ tmp = __le32_to_cpu(*((u_int32_t*) &imageInfo->_rom_sect[ver_offset + 4]));
+ romInfo->expRomVer[1] = tmp >> 16;
+ romInfo->expRomVer[2] = tmp & 0xffff;
+
+ tmp = __le32_to_cpu(*((u_int32_t*) &imageInfo->_rom_sect[ver_offset + 8]));
+ romInfo->expRomDevId = tmp >> 16;
+ romInfo->expRomPort = (tmp >> 12) & 0xf;
+ romInfo->expRomProto = tmp & 0xff;
+ } else if (romInfo->expRomProductId == 0xf) {
// get string length
- u_int32_ba tmp_ba= *((u_int32_t*) &info->_rom_sect[ver_offset + 0xc]);
+ u_int32_ba tmp_ba = *((u_int32_t*) &imageInfo->_rom_sect[ver_offset + 0xc]);
u_int32_t str_len = u_int32_t(tmp_ba.range(15, 8));
- u_int32_t sign_length = u_int32_t(tmp_ba.range(7, 0));
- u_int32_t dws_num = ((str_len + 3 ) / 4) + 4;
+ u_int32_t sign_length = u_int32_t(tmp_ba.range(7, 0));
+ u_int32_t dws_num = ((str_len + 3) / 4) + 4;
if (sign_length < dws_num) {
- return errmsg("The Signature length (%d) and the ROM version string length (%d) are not coordinated",
- sign_length, str_len);
+ return errmsg(
+ "The Signature length (%d) and the ROM version string length (%d) are not coordinated",
+ sign_length, str_len);
}
// copy str
- strncpy(info->expRomFreestr, (char*)&info->_rom_sect[ver_offset + 0x10], str_len);
- info->expRomFreestr[str_len] = '\0';
+ strncpy(romInfo->expRomFreestr,
+ (char*) &imageInfo->_rom_sect[ver_offset + 0x10], str_len);
+ romInfo->expRomFreestr[str_len] = '\0';
-
- tmp_ba = __le32_to_cpu(*((u_int32_t*) &info->_rom_sect[0x18]));
+ tmp_ba = __le32_to_cpu(*((u_int32_t*) &imageInfo->_rom_sect[0x18]));
u_int32_t dev_id_off = u_int32_t(tmp_ba.range(15, 0)) + 4;
-
- if (dev_id_off >= info->_rom_sect.size()) {
- return errmsg("The device ID offset %#x is out of range. ROM size: %#x", dev_id_off,
- (u_int32_t)info->_rom_sect.size());
+ if (dev_id_off >= imageInfo->_rom_sect.size()) {
+ return errmsg(
+ "The device ID offset %#x is out of range. ROM size: %#x",
+ dev_id_off, (u_int32_t) imageInfo->_rom_sect.size());
}
// get devid
- tmp_ba = __le32_to_cpu(*((u_int32_t*) &info->_rom_sect[dev_id_off]));
- info->expRomDevId = u_int32_t(tmp_ba.range(31, 16));
+ tmp_ba = __le32_to_cpu(*((u_int32_t*) &imageInfo->_rom_sect[dev_id_off]));
+ romInfo->expRomDevId = u_int32_t(tmp_ba.range(31, 16));
u_int32_t vendor_id = u_int32_t(tmp_ba.range(15, 0));
- if ( vendor_id != MELLANOX_VENDOR_ID) {
- info->expRomWarning = true;
- snprintf(info->expRomWarningMsg, MAX_ROM_ERR_MSG_LEN,
- "The Exp-ROM PCI vendor ID: %#x does not match the expected value: %#x.", vendor_id,
- MELLANOX_VENDOR_ID);
+
+ if (vendor_id != MELLANOX_VENDOR_ID) {
+ imageInfo->expRomWarning = true;
+ snprintf(imageInfo->expRomWarningMsg,
+ MAX_ROM_ERR_MSG_LEN,
+ "The Exp-ROM PCI vendor ID: %#x does not match the expected value: %#x.",
+ vendor_id, MELLANOX_VENDOR_ID);
+ }
+
+ }
+ return true;
+}
+
+
+bool Operations::GetExpRomVersion(ImageInfo* info) {
+ const char* magic_string = "mlxsign:";
+ u_int32_t magic_len = strlen(magic_string);
+ u_int32_t i;
+ bool magic_found = false;
+ u_int32_t ver_offset;
+ u_int32_t rom_checksum_range;
+
+ // Init some
+ info->expRomValidVersion = false;
+ info->numOfExpRom = 0;
+ info->expRomComDevid = 0;
+
+ info->expRomWarning = false;
+ info->expRomErrMsgValid = false;
+
+ if (info->_rom_sect.empty()) {
+ return errmsg("Expansion Rom section not found.");
+ }
+ // When checking the version of the expansion rom, only the first image has
+ // to be checked. This is because the second image the uefi image does not
+ // have to comply with checksumming to 0. To do this you have to read byte
+ // 2 (third) of the image and multiply by 512 to get the size of the x86
+ // image.
+
+ // Checksum:
+ if (info->_rom_sect.size() < 4) {
+ return errmsg("ROM size (0x%x) is too small",
+ (u_int32_t) info->_rom_sect.size());
+ }
+
+ // restore endianess.
+ TOCPUn(&(info->_rom_sect[0]), info->_rom_sect.size()/4);
+ /* // FOR WE DON'T CHECKSUM UNTIL WE DECIDED REGARDING THE NEW FORMAT.
+ */
+ // We will look for the magic string in whole ROM instead of the first part of it.
+ rom_checksum_range = info->_rom_sect.size();
+
+ for (i = 0; i < rom_checksum_range; i++) {
+ for (u_int32_t j = 0; j < magic_len; j++) {
+ if (info->_rom_sect[i + j] != magic_string[j]) {
+ break;
+ } else if (j == magic_len - 1) {
+ magic_found = true;
+ }
+ }
+
+ if (magic_found) {
+ // Get the ROM info after the mlxsign
+ bool rc;
+ RomInfo *currRom;
+
+ if (info->numOfExpRom == MAX_ROMS_NUM) {
+ info->expRomWarning = true;
+ snprintf(info->expRomWarningMsg,
+ MAX_ROM_ERR_MSG_LEN,
+ "Number of exp ROMs exceeds the maximum allowed number (%d)",
+ MAX_ROMS_NUM);
+ // Here we want to warn regarding this issue without checksum.
+ return true;
+ }
+
+ currRom = &(info->romInfo[info->numOfExpRom]);
+ ver_offset = i + magic_len;
+ rc = GetExpRomVerForOneRom(info, ver_offset);
+ if (rc != true) {
+ return rc;
+ }
+
+ // Get the device ID and check if it mismatches with other ROMs
+ if (info->expRomComDevid != MISS_MATCH_DEV_ID) { // When the DevId is already mismatched, no end to any check
+ if (currRom->expRomDevId != EXP_ROM_GEN_DEVID) { // When we have a device ID on the ROM
+ if (info->expRomComDevid == EXP_ROM_GEN_DEVID) { // Update the common DevId at the first time we find ID
+ info->expRomComDevid = currRom->expRomDevId;
+ } else { // Check if we have the same IDs, if yes, continue
+ if (currRom->expRomDevId != info->expRomComDevid) { // There is a mismatch between ROMs
+ info->expRomComDevid = MISS_MATCH_DEV_ID;
+ info->expRomWarning = true;
+ snprintf(info->expRomWarningMsg,
+ MAX_ROM_ERR_MSG_LEN,
+ "The device IDs of the ROMs mismatched.");
+ }
+ }
+ }
+ }
+
+ magic_found = false; // Clean the magic_found to start search for another magic string
+ i += (ROM_INFO_SIZE - 1); // Increase the index to point to the end of the ROM info.
+ info->numOfExpRom++;
}
+ }
+ // TODO: ADD CHECKSUM CHECK
+ if (!info->numOfExpRom) {
+ return errmsg("Cannot get ROM version. Signature not found.");
}
- info->expRomValidVersion = true;
+
+ if (info->noRomChecksum == 0) { // No need for checksum on some ROMs like uEFI
+ u_int8_t rom_checksum = 0;
+ rom_checksum_range = info->_rom_sect[2] * 512;
+ if (rom_checksum_range > info->_rom_sect.size()) {
+ return errmsg(
+ "ROM size field (0x%2x) is larger than actual ROM size (0x%x)",
+ rom_checksum_range, (u_int32_t) info->_rom_sect.size());
+ } else if (rom_checksum_range == 0) {
+ return errmsg(
+ "ROM size field is 0. Unknown ROM format or corrupted ROM.");
+ }
+
+ for (i = 0; i < rom_checksum_range; i++) {
+ rom_checksum += info->_rom_sect[i];
+ }
+
+ if (rom_checksum != 0) {
+ info->expRomWarning = true;
+ snprintf(
+ info->expRomWarningMsg,
+ MAX_ROM_ERR_MSG_LEN,
+ "Bad ROM Checksum (0x%02x), ROM info may not be displayed correctly.",
+ rom_checksum);
+ }
+ }
+
return true;
}
////////////////////////////////////////////////////////////////////////
#define GETGUID(s, g) do { if (!ops.getGUID(s,g)) return 1; } while (0)
#define GETBSN(s, g) do { if (!ops.getBSN(s,g)) return 1; } while (0)
+#define GETKEY(s, g) do { if (!ops.getGUID(s,g, "Invalid Key syntax, it should contain only hexa numbers.")) return 1; } while (0)
#define GET_FLASH_PARAMS(a, fp) do { if (!ops.getFlashParams(a, fp)) return 1; } while (0)
#define BSN_RET do { \
return true;
}
-bool Operations::getGUID(const char *s, guid_t *guid)
+bool Operations::getGUID(const char *s, guid_t *guid, char *err_msg)
{
char* endp;
u_int64_t g;
g = strtoull(s, &endp, 16);
if (*endp || (g == 0xffffffffffffffffULL && errno == ERANGE)) {
- report_err(_err_msg, "Invalid GUID syntax (%s) %s \n",
- s,
- errno ? strerror(errno) : "" );
+ if (!strcmp(err_msg, "")) {
+ report_err(_err_msg, "Invalid GUID syntax (%s) %s \n", s, errno ? strerror(errno) : "" );
+ } else {
+ report_err(_err_msg, "%s\n", err_msg);
+ }
return false;
}
guid->h = (u_int32_t)(g >> 32);
+void Operations::PatchKeySect(u_int32_t* buff, u_int32_t keyOff, guid_t hw_key)
+{
+ u_int32_t infoSize = __be32_to_cpu(*(buff + 1));
+ u_int32_t sectSize = sizeof(GPH) + infoSize * 4;
+
+ u_int32_t realKeyoff = (keyOff + sizeof(GPH)) / 4;
+
+ // Update the key in the buffer which is supposed to be burnt into the flash
+ buff[realKeyoff] = __cpu_to_be32(hw_key.h);
+ buff[realKeyoff + 1] = __cpu_to_be32(hw_key.l);
+
+ recalcSectionCrc((u_int8_t*)buff, sectSize);
+ return;
+}
//
// PatchInfoSect() :
// This func assumes it gets a pointer (rawSect) to a valid info sect.
// It patches the it with the given data, recalculated CRC ,
-// and copies it back to the geven data
+// and copies it back to the given data
//
void Operations::PatchInfoSect(u_int8_t* rawSect,
// byte size;
infoSize *= 4;
- //printf("-D- vsdOffs=%x, vsdSize=%x, infoSize=%x\n", vsdOffs,vsdSize, infoSize );
if (vsd) {
u_int32_t len = strlen(vsd);
if (len > vsdSize) {
- report("Warning: The given VSD length is too large (%d chars). Truncating to %d chars.\n", len, vsdSize);
+ report_warn("The given VSD length is too large (%d chars). Truncating to %d chars.\n", len, vsdSize);
len = vsdSize;
}
recalcSectionCrc((u_int8_t *)ps, sizeof(PS) - 4);
}
+bool Operations::patchHwAccessKey(FImage& f, ImageInfo& flash_info, ImageInfo& image_info)
+{
+ u_int32_t key_supported_flash = flash_info.infoOffs[Operations::II_HwAccessKey];
+ u_int32_t key_supported_image = image_info.infoOffs[Operations::II_HwAccessKey];
+
+ if (key_supported_image) {
+ hw_key_t key_to_burn;
+ u_int32_t *buff = f.getBuf();
+ u_int32_t *infoSectBuff = (u_int32_t*)((u_int8_t*)buff + image_info.infoSectPtr - sizeof(GPH));
+ u_int32_t keyOff = image_info.infoOffs[II_HwAccessKey];
+
+ if (key_supported_flash) {
+ // Image file : HW access Key exists
+ // Flash : HW access Key exists
+ // Behavior: Save the burnt key in the flash.
+ key_to_burn = flash_info.accessKeyValue;
+ } else {
+ // Image file : HW access Key exists
+ // Flash : No HW access Key
+ // Behavior: Just create a zero Key even if the image contains an activated key
+ key_to_burn.l = 0;
+ key_to_burn.h = 0;
+ }
+ PatchKeySect(infoSectBuff, keyOff, key_to_burn);
+ } else {
+ if (key_supported_flash) {
+ // Image file : No HW access Key
+ // Flash : HW access Key exists
+ // Behavior: In this case we will warn the user that he's going to remove the HW access Key
+ printf("\n NOTE: You are about to burn a FW that does not support HW access enable/disable.\n");
+ printf(" If you already have an activated key it will be removed.\n");
+ if (! ask_user()) {
+ return false;
+ }
+ } else {
+ // Image file : No HW access Key
+ // Flash : No HW access Key
+ // Behavior: Do nothing
+ return true;
+ }
+ }
+ return true;
+}
////////////////////////////////////////////////////////////////////////
//Note that vsd1 is a string of bytes.
bool print_guids, bool print_macs, bool print_uids)
{
- printf(" You are about to change the Guids/Macs/Uids on the device:\n");
+ printf(" You are about to change the Guids/Macs/Uids on the device:\n\n");
printf(" New Values " GUID_SPACES "Current Values\n");
if (print_uids) {
PrintUids(new_guids, old_guids );
return true;
}
-
-
-////////////////////////////////////////////////////////////////////////
-bool Operations::patchGUIDs (FImage& f,
- ImageInfo* info,
- bool patch_macs,
- bool patch_uids,
- bool user_guids,
- bool user_macs,
- bool user_uids,
- guid_t new_guids[MAX_GUIDS],
- guid_t old_guids[MAX_GUIDS],
- u_int32_t num_of_old_guids)
+bool Operations::preFS2PatchGUIDs(bool patch_macs,
+ bool patch_uids,
+ bool user_guids,
+ bool user_macs,
+ bool user_uids,
+ guid_t new_guids[MAX_GUIDS],
+ guid_t old_guids[MAX_GUIDS],
+ guid_t **used_guids_p,
+ u_int32_t num_of_old_guids)
{
- guid_t* used_guids = old_guids ? old_guids : new_guids;
- u_int32_t *buf = f.getBuf();
int i;
- bool old_guids_fmt = info->guidNum < GUIDS;
+ guid_t* used_guids;
+ *used_guids_p = old_guids ? old_guids : new_guids;
- // Print old GUIDs and get confirmation
if (new_guids) {
- if (old_guids_fmt)
- printf(" Old image!!!! Only %d GUIDs may be set.\n", info->guidNum);
// if only guids or only macs are specified by user, keep the other
// as currently set of flash. This is in order to simplify transitions between
// burning IB and ETH FW.
}
}
}
- used_guids = new_guids;
+ *used_guids_p = new_guids;
}
-
+ used_guids = *used_guids_p;
if (!patch_uids) {
if (patch_macs) {
}
}
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+bool Operations::patchGUIDs (FImage& f,
+ ImageInfo* info,
+ bool patch_macs,
+ bool patch_uids,
+ bool user_guids,
+ bool user_macs,
+ bool user_uids,
+ guid_t new_guids[MAX_GUIDS],
+ guid_t old_guids[MAX_GUIDS],
+ u_int32_t num_of_old_guids)
+{
+ guid_t* used_guids;
+ u_int32_t *buf = f.getBuf();
+ bool old_guids_fmt = info->guidNum < GUIDS;
+
+ // Print old GUIDs and get confirmation
+ if (new_guids) {
+ if (old_guids_fmt) {
+ printf(" Old image!!!! Only %d GUIDs may be set.\n", info->guidNum);
+ }
+ }
+ // Call common function
+ if (!preFS2PatchGUIDs(patch_macs, patch_uids, user_guids, user_macs, user_uids, new_guids, old_guids, &used_guids, num_of_old_guids)) {
+ return false;
+ }
// Path GUIDs section
if (info->guidPtr) {
patchGUIDsSection(buf, info->imgStart + info->guidPtr, used_guids, info->guidNum);
patchGUIDsSection(buf, info->allImgStart[1] + info->guidPtr, used_guids, info->guidNum);
}
}
-
return true;
} // patchGUIDs
}
info->supportedHwIdNum = tagSize / 4;
break;
-
+ case II_HwAccessKey: {
+ info->accessKeyValue.h = __be32_to_cpu(*(p + 1));;
+ info->accessKeyValue.l = __be32_to_cpu(*(p + 2));;
+ info->accessKeyExists= 1;
+ }
+ break;
case II_End:
endFound = true;
return true;
}
-bool Operations::GetExpRomStrVer(Operations::ImageInfo* info, char* version)
-{
- if (info->expRomProductId >= 0x10) {
- sprintf(version, "%d.%d.%d", info->expRomVer[0], info->expRomVer[1], info->expRomVer[2]);
+bool Operations::GetExpRomStrVer(Operations::ImageInfo* info, char* version) {
+ if (info->romInfo[0].expRomProductId >= 0x10) {
+ sprintf(version, "%d.%d.%d", info->romInfo[0].expRomVer[0], info->romInfo[0].expRomVer[1],
+ info->romInfo[0].expRomVer[2]);
} else {
- sprintf(version, "%d", info->expRomVer[0]);
+ sprintf(version, "%d", info->romInfo[0].expRomVer[0]);
}
return true;
}
-bool Operations::DisplayExpRomInfo(Operations::ImageInfo* info, bool print_pre) {
- if (print_pre) {
- report("Rom Info: ");
- }
- if (info->expRomValidVersion) {
- if (info->expRomProductId == 0xf) {
- report("devid=%d version_id=%s", info->expRomDevId, info->expRomFreestr);
- } else {
- report("type=");
- switch (info->expRomProductId) {
- case 1 : report("CLP1 "); break;
- case 2 : report("CLP2 "); break;
- case 3 : report("CLP3 "); break;
- case 4 : report("CLP4 "); break;
- case 0x10: report("PXE "); break;
- case 0x11: report("UEFI "); break;
- default: report("0x%x - Unknown ROM product ID\n", info->expRomProductId); return true;
- }
-
- report("version=%d", info->expRomVer[0]);
- if (info->expRomProductId >= 0x10) {
- report(".%d.%d",
- info->expRomVer[1],
- info->expRomVer[2]);
-
- if (info->expRomDevId) {
- // Do not display if 0 - ROM is the same for all device IDs
- report(" devid=%d", info->expRomDevId);
- }
- if (info->expRomPort) {
- // Do not display if 0 - port independent
- report(" port=%d", info->expRomPort);
- }
+bool Operations::DisplayOneExpRomInfo(RomInfo* info) {
- report(" proto=");
- switch (info->expRomProto) {
- case ER_IB: report("IB"); break;
- case ER_ETH: report("ETH"); break;
- case ER_VPI: report("VPI"); break;
- default: report("0x%x", info->expRomProto);
- }
- }
- }
- if (info->expRomWarning) {
- report(" (-W- %s)", info->expRomWarningMsg);
- }
- report("\n");
+ if (info->expRomProductId == 0xf) {
+ report("devid=%d version_id=%s", info->expRomDevId,
+ info->expRomFreestr);
} else {
+ report("type=");
+ switch (info->expRomProductId) {
+ case 1:
+ report("CLP1 ");
+ break;
+ case 2:
+ report("CLP2 ");
+ break;
+ case 3:
+ report("CLP3 ");
+ break;
+ case 4:
+ report("CLP4 ");
+ break;
+ case 0x10:
+ report("PXE ");
+ break;
+ case 0x11:
+ report("UEFI ");
+ break;
+ default:
+ report("0x%x - Unknown ROM product ID\n", info->expRomProductId);
+ return true;
+ }
+
+ report("version=%d", info->expRomVer[0]);
+ if (info->expRomProductId >= 0x10) {
+ report(".%d.%d", info->expRomVer[1], info->expRomVer[2]);
+
+ if (info->expRomDevId != EXP_ROM_GEN_DEVID) {
+ // Do not display if 0 - ROM is the same for all device IDs
+ report(" devid=%d", info->expRomDevId);
+ }
+ if (info->expRomPort) {
+ // Do not display if 0 - port independent
+ report(" port=%d", info->expRomPort);
+ }
+
+ report(" proto=");
+ switch (info->expRomProto) {
+ case ER_IB:
+ report("IB");
+ break;
+ case ER_ETH:
+ report("ETH");
+ break;
+ case ER_VPI:
+ report("VPI");
+ break;
+ default:
+ report("0x%x", info->expRomProto);
+ }
+ }
+ }
+ return true;
+
+}
+bool Operations::DisplayExpRomInfo(Operations::ImageInfo* info, char *pre_str) {
+ int i;
+ int str_len = strlen(pre_str);
+
+ if (info->numOfExpRom > 0) {
+ for (i = 0; i < info->numOfExpRom; i++) {
+
+ // Print the pre string or spaces
+ if (i == 0) {
+ report("%s", pre_str);
+ } else {
+ int j;
+ for ( j = 0; j < str_len; j++) {
+ printf("%s", " ");
+ }
+ }
+ // Display a ROM info
+ DisplayOneExpRomInfo(&(info->romInfo[i]));
+ if (i != info->numOfExpRom - 1) { // Don't print new line after the info of the last ROM
+ report("\n");
+ }
+ }
+ if (info->expRomWarning) {
+ report(" (-W- %s)", info->expRomWarningMsg);
+ }
+ report("\n");
+ } else {
+ report("%s", pre_str);
report("N/A");
if (info->expRomErrMsgValid) {
report(" (-E- %s)", info->expRomErrMsg);
return true;
}
-
-
bool Operations::ReportBxGuidsQuery(guid_t* guids, int base1, int guids_num, int index, const char* pre_str)
{
int i, first_index, base, wwnns_index;
}
if (info->expRomFound) {
- DisplayExpRomInfo(info);
+ DisplayExpRomInfo(info, "Rom Info: ");
}
if (info->isFailsafe && !IsFs2()) {
}
}
- report("Chip Revision: %X\n", info->devRev);
+ if (info->accessKeyExists) {
+ report("HW Access Key: ");
+ if (info->accessKeyValue.l || info->accessKeyValue.h) {
+ report("Enabled\n");
+ } else {
+ report("Disabled\n");
+ }
+
+ }
// GUIDS:
// TODO: Handle case where devtype not found.
if (!ib_dev) {
report("Description:%s Port1 Port2\n", mac_indent);
} else if (IsSX(info->devType)) {
- report("\nDescription: Base Switch\n");
+ report("\nDescription: Base Switch\n");
} else {
printf("\n");
}
// sed -e 's/"/\\"/g' < flint.txt | perl -pe 's/^(.*)$/"$1\\n"/'
void usage(const char *sname, bool full = false)
{
+#ifdef FOR_MAN
+ #define MAN_BR ".br\n"
+
+ #define QUOTE(s) #s
+ #define MAN_SH(name) ".SH " #name "\n"
+ #define MAN_SS(name) ".SS " #name "\n"
+ #define MAN_FS
+#else
+ #define MAN_BR
+ #define MAN_SH(name) name "\n"
+ #define MAN_SS(name) name "\n"
+ #define MAN_FS(name) " " name "\n"
+#endif
+
+
const char *descr =
+#ifdef FOR_MAN
+ ".TH \"flint\" \"\" \"Jul 2011\" \"MFT 2.7.0\" \"Administration\"\n"
+ MAN_SH("NAME")
+#endif
"\n"
" FLINT - FLash INTerface\n"
+
"\n"
- "FW (firmware) burning and flash memory operations tool for\n"
- "Mellanox Infiniband HCAs and Ethernet NIC cards.\n"
- "\n"
- "Usage:\n"
- "------\n"
- "\n"
+ MAN_SH("SYNOPSIS")
" " FLINT_NAME " [switches...] <command> [parameters...]\n"
+// "Switches summary:\n"
+// "-----------------\n"
"\n"
+ MAN_SH("DESCRIPTION")
+ " "FLINT_NAME " is a FW (firmware) burning and flash memory operations tool for\n"
+ " Mellanox Infiniband HCAs, Ethernet NIC cards, and switch devices.\n"
"\n"
- "Switches summary:\n"
- "-----------------\n"
-// " -bsn <BSN> - Mellanox Board Serial Number (BSN).\n"
-// " Valid BSN format is:\n"
-// " MTxxxxx[-]R[xx]ddmmyy-nnn[-cc]\n"
-// " Commands affected: burn\n"
-// "\n"
-// " -crc - Print out each section CRC.\n"
-// " Commands affected: verify\n"
+ MAN_SS("OPTIONS")
"\n"
" -d[evice] <device> - Device flash is connected to.\n"
" Commands affected: all\n"
" malfunction. Use only if you know what you are doing\n"
"\n"
" -override_cache_replacement\n"
- " - Allow Accessing the flash even if the cache replacement mode is enabled.\n"
- " NOTE: This flag is intended for advanced users usage.\n"
+ " - On SwitchX devices:\n"
+MAN_BR
+ " Allow accessing the flash even if the cache replacement mode is enabled.\n"
+ " NOTE: This flag is intended for advanced users only.\n"
" Running in this mode may cause the firmware to hang.\n"
"\n"
" -skip_is - Allow burning the FW image without updating the invariant sector,\n"
" -use_image_guids - Burn (guids/uids/macs) as appears in the given image.\n"
" Commands affected: burn\n"
"\n"
- "\n"
" -use_image_rom - Do not save the ROM which exists in the device.\n"
" Commands affected: burn\n"
"\n"
" default failsafe burn process burns a single image (in alternating locations).\n"
" Commands affected: burn\n"
"\n"
+ " -striped_image - Use this flag to indicate that the given image file is in a \"striped image\" format.\n"
+ " Commands affected: query verify\n"
+ "\n"
" -banks <banks>\n"
" - Set the number of attached flash devices (banks)\n"
"\n"
" - Use the given parameters to access the flash instead of reading them from the flash.\n"
" Supported parameters:\n"
// TODO: Get the supported type list from the mflash library.
- " Type: The type of the flash, such as: M25PXxx, M25Pxx, SST25VFxx.\n"
+ " Type: The type of the flash, such as: M25PXxx, M25Pxx, SST25VFxx, W25QxxBV.\n"
" log2size: The log2 of the flash size.\n"
" num_of_flashes: the number of the flashes connected to the device.\n"
"\n"
" -v - Version info.\n"
"\n"
- "Commands summary (use -hh flag for full commands description):\n"
- "-----------------\n"
+ MAN_SS("COMMANDS SUMMARY")
+#ifndef FOR_MAN
+ "\n(use -hh flag for full commands description):\n"
+#else
+ "\n"
+#endif
+ "\n"
+ "Common FW Update and Query:\n"
" b[urn] - Burn flash\n"
" q[uery] [full] - Query misc. flash/firmware characteristics, use \"full\" to get more information.\n"
" v[erify] - Verify entire flash\n"
+ " swreset - SW reset the target un-managed switch device. This command\n"
+ " is supported only in the In-Band access method.\n"
+ "\n"
+ "Expansion ROM Update:\n"
+ " brom <ROM-file> - Burn the specified ROM file on the flash.\n"
+ " drom - Remove the ROM section from the flash.\n"
+ " rrom <out-file> - Read the ROM section from the flash.\n"
+ "\n"
+ "Initial Burn, Production:\n"
" bb - Burn Block - Burns the given image as is. \n"
" No checks are done.\n"
" sg [nocrc] - Set GUIDs.\n"
" sv - Set the VSD.\n"
+ "\n"
+ "Misc FW Image operations:\n"
" ri <out-file> - Read the fw image on the flash.\n"
" dc [out-file] - Dump Configuration: print fw configuration file\n"
" for the given image.\n"
" dh [out-file] - Dump Hash: print hash file\n"
" for the given image.\n"
+ "\n"
+ "HW Access Key:\n"
+ " set_key [key] - Set/Update the HW access key which is used to enable/disable access to HW.\n"
+ " The key can be provided in the command line or interactively typed after\n"
+ " the command is given\n"
+ " NOTE: The new key is activated only after the device is reset.\n"
+ " hw_access <enable|disable> [key]\n"
+ " - Enable/disable the access to the HW.\n"
+ " The key can be provided in the command line or interactively typed after\n"
+ " the command is given\n"
+ "\n"
+ "Low Level Flash Operations:\n"
+ " cfi - Query flash device parameters\n"
" e[rase] <addr> - Erase sector\n"
" rw <addr> - Read one dword from flash\n"
" ww <addr> < data> \n"
" - Write a data block to flash without sector erase\n"
" rb <addr> <size> [out-file]\n"
" - Read a data block from flash\n"
- " swreset - SW reset the target InfniScale IV device. This command\n"
- " is supported only in the In-Band access method.\n"
- " brom <ROM-file> - Burn the specified ROM file on the flash.\n"
- " rrom <out-file> - Read the ROM section from the flash.\n"
- " drom - Remove the ROM section from the flash.\n"
"\n"
" Return values:\n"
" 0 - Successful completion\n"
const char* full_descr =
"\n"
- "Command descriptions:\n"
- "----------------------------\n"
+ MAN_SS("COMMAND DESCRIPTION")
"\n"
"* Burn flash\n"
- " Burns entire flash from raw binary image.\n"
+ " Performs failsafe FW update from a raw binary image.\n"
"\n"
" Command:\n"
" b[urn]\n"
" " FLINT_NAME " -d " DEV_MST_EXAMPLE2 " -guid 0x2c9000100d050 -i image1.bin b\n"
"\n"
"\n"
+ "* Query miscellaneous FW and flash parameters\n"
+ " Display FW Version, GUIDs, PSID, and other info\n"
+ "\n"
+ " Command:\n"
+ " q[uery]\n"
+ " Parameters:\n"
+ " None\n"
+ " Example:\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " query\n"
+ "\n"
+ "\n"
+ "* Verify entire flash.\n"
+ "\n"
+ " Command:\n"
+ " v[erify]\n"
+ " Parameters:\n"
+ " None\n"
+ " Example:\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " v\n"
+ "\n"
+ "\n"
+ "* Burn the specified exp-ROM on the flash.\n"
+ "\n"
+ " Command:\n"
+ " brom\n"
+ " Parameters:\n"
+ " file - The exp-ROM file.\n"
+ " Example:\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " brom exp-rom.rom\n"
+ "\n"
+ "* Remove the exp-ROM from the flash if it is existing.\n"
+ "\n"
+ " Command:\n"
+ " drom\n"
+ " Example:\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " drom\n"
+ "\n"
+ "* Read the exp-ROM from the flash if it is existing.\n"
+ "\n"
+ " Command:\n"
+ " rrom\n"
+ " file - filename to write the exp-ROM to.\n"
+
+ " Example:\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rrom exp-rom.rom\n"
+ "\n"
"* Burn Block\n"
- " Burns entire flash from raw binary image as is. No checks are done on the flash or\n"
+ " Burns entire flash verbatim from raw binary image. No checks are done on the flash or\n"
" on the given image file. No fields (such as VSD or Guids) are read from flash. \n"
"\n"
" Command:\n"
" the full image crc after changing the guids\n"
" Examples:\n"
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " -guid 0x0002c9000100d050 sg\n"
- "\n"
- "\n"
-
"\n"
"\n"
"* Set VSD\n"
"\n"
"\n"
- "* Erase sector.\n"
- " Erases a sector that contains specified address.\n"
+ "* Print (to screen or to a file) the FW 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"
- " e[rase]\n"
+ " dc\n"
" Parameters:\n"
- " addr - address of word in sector that you want\n"
- " to erase.\n"
+ " file - (optional) filename to write the dumped configuration to. If not given, the data\n"
+ " is printed to screen\n"
" Example:\n"
- " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " erase 0x10000\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " dc\n"
"\n"
+ "* Print (to screen or to a file) the HASH text file used by the FW.\n"
+ " This command would fail if the image does not contain a Hash file.\n"
"\n"
- "* Query miscellaneous FW and flash parameters\n"
+ " Command:\n"
+ " dh\n"
+ " Parameters:\n"
+ " file - (optional) filename to write the dumped hash to. If not given, the data\n"
+ " is printed to screen\n"
+ " Example:\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " dh\n"
+ "\n"
+
+ "\n"
+ "* Set/Update the HW access key which is used to enable/disable access to HW.\n"
"\n"
" Command:\n"
- " q[uery]\n"
+ " set_key\n"
" Parameters:\n"
- " None\n"
+ " key - (optional) The new key you intend to set (in hex).\n"
" Example:\n"
- " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " query\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " set_key 1234deaf5678\n"
"\n"
+
+ "* Enable/disable the access to the HW.\n"
"\n"
+ " Command:\n"
+ " hw_access\n"
+ " Parameters:\n"
+ " <enable/disable> - Specify if you intend to disable or enable the HW access.\n"
+ " You will be asked to type a key when you try to enable HW access.\n"
+ " key - (optional) The key you intend to use for enabling the HW access.\n"
+
+ " Example:\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " hw_access enable\n"
+ "\n"
+
"* Query flash device parameters (Common Flash Interface)\n"
"\n"
" Command:\n"
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " cfi\n"
"\n"
"\n"
- "* Read one dword from flash.\n"
+ "* Erase sector.\n"
+ " Erases a sector that contains specified address.\n"
"\n"
" Command:\n"
- " rw\n"
+ " e[rase]\n"
" Parameters:\n"
- " addr - address of word to read\n"
+ " addr - address of word in sector that you want\n"
+ " to erase.\n"
" Example:\n"
- " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rw 0x20\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " erase 0x10000\n"
"\n"
"\n"
- "* Verify entire flash.\n"
+
+ "* Read one dword from flash.\n"
"\n"
" Command:\n"
- " v[erify]\n"
+ " rw\n"
" Parameters:\n"
- " None\n"
+ " addr - address of word to read\n"
" Example:\n"
- " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " v\n"
+ " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rw 0x20\n"
"\n"
"\n"
"* Write one dword to flash.\n"
" Example:\n"
" " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " wbne 0x10000 12 0x30000 0x76800 0x5a445a44\n"
"\n"
- "* Print (to screen or to a file) the FW 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"
- " file - (optional) filename to write the dumped configuration to. If not given, the data\n"
- " is printed to screen\n"
- " Example:\n"
- " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " dc\n"
- "\n"
- "* Print (to screen or to a file) the HASH text file used by the FW.\n"
- " This command would fail if the image does not contain a Hash file.\n"
- "\n"
- " Command:\n"
- " dh\n"
- " Parameters:\n"
- " file - (optional) filename to write the dumped hash to. If not given, the data\n"
- " is printed to screen\n"
- " Example:\n"
- " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " dh\n"
- "\n"
- "* Burn the specified exp-ROM on the flash.\n"
- "\n"
- " Command:\n"
- " brom\n"
- " Parameters:\n"
- " file - The exp-ROM file.\n"
- " Example:\n"
- " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " brom exp-rom.rom\n"
- "\n"
- "* Remove the exp-ROM from the flash if it is existing.\n"
- "\n"
-
- " Command:\n"
- " drom\n"
- " Example:\n"
- " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " drom\n"
- "\n"
- "* Read the exp-ROM from the flash if it is existing.\n"
+ MAN_SH("RETURN VALUES")
"\n"
- " Command:\n"
- " rrom\n"
- " file - filename to write the exp-ROM to.\n"
-
- " Example:\n"
- " " FLINT_NAME " -d " DEV_MST_EXAMPLE1 " rrom exp-rom.rom\n"
- "\n";
-
+ " 0 - Successful completion\n"
+ " 1 - An error has occurred\n"
+ " 7 - For burn command - FW already updated - burn was aborted.\n"
+#ifdef FOR_MAN
+ MAN_SH("KNOWN ISSUES")
+ "If flint is forcefully killed without giving it a chance to clean up,\n"
+ "the HCA internal flash semaphore may not be released, and prevent further\n"
+ "activation of flint. Use the -clear_semaphore flag to force clearing of\n"
+ "this semaphore."
+#endif
+;
printf(descr, sname);
if (full) {
SIGINT,
#ifndef _WIN32
SIGHUP,
+ SIGPIPE,
#endif
SIGTERM
};
#define SETERR(args) do { printf("*** ERROR *** "); printf args; printf("\n"); return 1; } while(0)
+#define GET_PASSWORD_FROM_USER(pre_str, key_struct_p) {\
+ char key_arr[MAX_PASSWORD_LEN];\
+ GetPasswordFromUser(pre_str, key_arr);\
+ GETKEY(key_arr, key_struct_p);\
+}
+
+#define GET_KEY_FROM_USER(command, key_struct_p, from_password_p) {\
+ if (i + 2 == ac) {\
+ NEXTC("<HW_ACCESS_KEY>", command);\
+ GETKEY(av[i], key_struct_p);\
+ *from_password_p = 0;\
+ } else {\
+ GET_PASSWORD_FROM_USER("Enter key ", key_struct_p);\
+ *from_password_p = 1;\
+ }\
+}
+
+int mygetch(void)
+{
+ struct termios oldt,
+ newt;
+ int ch;
+ tcgetattr( STDIN_FILENO, &oldt );
+ newt = oldt;
+ newt.c_lflag &= ~( ICANON | ECHO );
+ tcsetattr( STDIN_FILENO, TCSANOW, &newt );
+ ch = getchar();
+ tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
+ return ch;
+}
+#define MAX_PASSWORD_LEN 256
+// TODO: Move this function to the tools common file.
+int GetPasswordFromUser(char *pre_str, char buffer[MAX_PASSWORD_LEN])
+{
+ char c;
+ int pos = 0;
+
+ printf("%s: ", pre_str);
+ do {
+ c = mygetch();
+
+ if( ((pos < MAX_PASSWORD_LEN - 1)) && isprint(c) ) {
+ buffer[ pos++ ] = c;
+ printf("%c", '*');
+ } else if( (c == 8 || c == 127) && pos ) {
+ buffer[ pos-- ] = '\0';
+ printf("%s", "\b \b");
+ }
+ } while( c != '\n' );
+ printf("\n");
+ buffer[pos] = '\0';
+ return true;
+}
int main(int ac, char *av[])
{
bool fs2_image = false;
bool fs2_device = false;
-
-
+ u_int8_t is_cr_space_locked = 0;
//
// Map termination signal handlers
//
g_flash = f.get();
if (!f->open(device, clear_semaphore, false, num_of_banks, flash_params_p, ignoreCasheRepGuard)) {
- report_err(ops._err_msg, "Can not open %s: %s\n", device, f->err());
- rc = 1; goto done;
+ is_cr_space_locked = f->get_cr_space_locked();
+
+ // We will ignore this failure when we want to disable/enable the HW access
+ if (!(is_cr_space_locked && cmd == CMD_HW_ACCESS)) {
+ report_err(ops._err_msg, "Can not open %s: %s\n", device, f->err());
+ rc = 1; goto done;
+ }
+
}
ops.SetNumPorts(f->get_port_num());
if (!burn_block) {
+ if (ops.GetFs2StripedImage()) {
+ report_err(ops._err_msg, "The -striped_image cannot be used with the burn command\n");
+ rc = 1; goto done;
+ }
+
if (fs2_image != fs2_device) {
report_err(ops._err_msg, "The given device %s a FS2 image type, but the given image file %s a FS2 FW image\n",
fs2_device ? "requires" : "does not require",
// 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).
" Select \"yes\" to use the ROM from the given image file.\n"
" Select \"no\" to keep the existing ROM in the flash\n");
_silent = false;
- printf("\n Current ROM info on flash: ");
- ops.DisplayExpRomInfo(&flashInfo, false);
- printf(" ROM info from image file : ");
- ops.DisplayExpRomInfo(&tmpFileInfo, false);
+ ops.DisplayExpRomInfo(&flashInfo, " Current ROM info on flash: ");
+ ops.DisplayExpRomInfo(&tmpFileInfo, " ROM info from image file : ");
_silent = true;
if (!ops.ask_user("Use the ROM from the image file")) {
bool ib_dev;
bool eth_dev;
bool bx_dev;
-
+ // Get the FW types
bx_dev = ops.IsBridgeX(fileInfo.devType);
ops.SetDevFlags(fileInfo.devType, ib_dev, eth_dev);
- if ((user_vsd && user_psid) || use_image_ps)
- read_ps = false;
-
+ // Check if there is a need to read guids
if (use_image_guids || ops.GetBurnBlankGuids() || (guids_specified && ib_dev) ||
(macs_specified && eth_dev) || (uids_specified && bx_dev)) {
read_guids = false;
}
-
+ // Check if the burnt FW is ok and readable in order to get the GUIDs later
if (read_guids && !flash_query_res) {
ops.PrintMissGuidErr(ib_dev, eth_dev, bx_dev);
if (burn_failsafe) {
bool is_guids_specified = guids_specified || macs_specified || uids_specified;
// Patch GUIDS
if (is_guids_specified) {
- if (!ops.CheckGuidsFlags(fileInfo.devType, guids_specified, macs_specified, uids_specified)) {
+ if (!ops.CheckGuidsFlags(fileInfo.devType, guids_specified, macs_specified, uids_specified)) {
report_err(ops._err_msg, "%s\n", ops.err());
rc = 1; goto done;
}
}
}
}
+ if (!ops.patchHwAccessKey(fim, flashInfo, fileInfo)) {
+ rc = 1; goto done;
+ }
// Check PSID and ib -> eth change.
-
if (fileInfo.infoOffs[Operations::II_PSID] &&
flashInfo.infoOffs[Operations::II_PSID] &&
strncmp( fileInfo.psid, flashInfo.psid, PSID_LEN)) {
case CMD_BURN_ROM:
{
char *rom_file = NULL;
- int rom_size;
- FILE *fh_rom;
-
NEXTC("<ROM_FILE>", "brom");
rom_file = av[i];
_silent = true;
// Open Rom file, get its size and read it
- fh_rom = fopen(rom_file, "rb");
- if (!fh_rom) {
- report_err(ops._err_msg, "Can not open file \"%s\" - %s\n", rom_file, strerror(errno));
- rc = 1; goto done;
+ FImage rom_image;
+ if (!rom_image.open(rom_file, true)) {
+ report_err(ops._err_msg, "ROM file open failed: %s\n", rom_image.err());
+ rc = 1; goto done;
}
- if (!ops.GetFileSize(fh_rom, rom_file, rom_size)) {
- report_err(ops._err_msg, "Failed to get ROM file size: %s.\n", ops.err());
- fclose(fh_rom);
+
+ if (rom_image.getBufLength() == 0) {
+ report_err(ops._err_msg, "Bad ROM file: Empty file.\n");
rc = 1; goto done;
}
- vector<u_int8_t> rom_data(rom_size);
- // Read rom data.
- if (fread((u_int8_t*)(&rom_data[0]), 1, rom_size, fh_rom) != (unsigned)rom_size) {
- report_err(ops._err_msg, "Failed to read ROM file \"%s\": %s\n", rom_file, strerror(errno));
- fclose(fh_rom);
+ Operations::ImageInfo dummy_info;
+ if (ops.VerifyFs2(rom_image, &dummy_info)) {
+ // Note that if this check passes it means that a FW image was
+ // erroneously provided as an expansion ROM
+ report_err(ops._err_msg, "File \"%s\" is a Mellanox FW image. Expecting an expansion ROM image.\n", rom_file);
rc = 1; goto done;
}
- fclose(fh_rom);
Operations::ImageInfo file_info;
Operations::ImageInfo flash_info;
u_int32_t length = ops._last_image_addr;
- u_int32_t new_data_size = length + TOTAL_SEC_SIZE(rom_size);
+ u_int32_t new_data_size = length + TOTAL_SEC_SIZE(rom_image.getBufLength());
vector<u_int8_t> data(length);
vector<u_int8_t> new_data(new_data_size);
// Insert the rom to the image.
if(!ops.UpdateRomInImage((u_int8_t*)(&new_data[0]), (u_int8_t*)(&data[0]),
- (u_int8_t*)(&rom_data[0]), rom_size, &new_image_size)) {
+ (u_int8_t*)rom_image.getBuf(), rom_image.getBufLength(),
+ &new_image_size)) {
report_err(ops._err_msg, "Burning ROM Failed: %s\n", f->err());
rc = 1; goto done;
}
}
_silent = false;
char rom_ver1[50], rom_ver2[50];
- printf("\n Current ROM info on flash: ");
+ printf("\n");
+ char *info_str = " Current ROM info on flash: ";
+ char *info_str2 = " New ROM info: ";
if (!ops.IsRomEmpty(&flash_info)) {
- ops.DisplayExpRomInfo(&flash_info, false);
+ ops.DisplayExpRomInfo(&flash_info, info_str);
ops.GetExpRomStrVer(&flash_info, rom_ver1);
-
} else {
+ printf("%s", info_str);
sprintf(rom_ver1, "N/A");
printf("%s\n", rom_ver1);
}
- printf(" New ROM info: ");
- ops.DisplayExpRomInfo(&file_info, false);
+ ops.DisplayExpRomInfo(&file_info, info_str2);
ops.GetExpRomStrVer(&file_info, rom_ver2);
-
- print_line_to_log("Current ROM version on flash: %s, New ROM version: %s\n", rom_ver1, rom_ver2);
-
+ print_line_to_log(
+ "Current ROM version on flash (1st ROM of %d): %s, New ROM version (1st ROM of %d): %s\n",
+ flash_info.numOfExpRom, rom_ver1, file_info.numOfExpRom, rom_ver2);
// Print the ROM versin of the curerrent and the new ROM.
bool ret = ops.CntxFailSafeBurn(*f, fim, !silent, &flash_info, &flash_info, true, "Burning ROM image");
FImage fim1;
Operations::ImageInfo info;
- Operations::ImageInfo new_info;
if (user_vsd == NULL) {
report_err(ops._err_msg, "For set_vsd command, please specify the VSD (using command flag -vsd).\n");
if (!ops.ModifyVSDSection(fbase, &info, user_vsd, image_fname, silent)) {
report_err(ops._err_msg, "Failed to set the VSD: %s.\n", ops.err());
rc = 1; goto done;
+ }
+ }
+ break;
+
+ case CMD_SET_KEY:
+ {
+
+ FImage fim1;
+ Operations::ImageInfo info;
+ hw_key_t key;
+ u_int8_t got_pass;
+ GET_KEY_FROM_USER("set_key", &key, &got_pass);
+
+ // As the user to confirm the key
+ if (got_pass) {
+ hw_key_t second_key;
+ GET_PASSWORD_FROM_USER("Verify key", &second_key);
+ if (key.l != second_key.l || key.h != second_key.h) {
+ report_err(ops._err_msg, "Failed to set the HW access key: The keys you entered did not match.\n");
+ rc = 1; goto done;
+ }
+ }
+ _silent = true;
+ if (!ops.CheckDevImage(*fbase, info)) {
+ report_err(ops._err_msg, "Failed to set the HW access key: %s\n", ops.err());
+ rc = 1; goto done;
+ }
+ _silent = false;
+
+ // Check if we have info section in the image.
+ if (!info.infoOffs[Operations::II_HwAccessKey]) {
+ report_err(ops._err_msg, "Failed to set the HW access key: The image does not support this operation.\n");
+ rc = 1; goto done;
+ }
+
+ if (!ops.ModifyKeySection(fbase, &info, key, image_fname, silent)) {
+ report_err(ops._err_msg, "Failed to set the HW access key: %s.\n", ops.err());
+ rc = 1; goto done;
}
}
break;
+
+ case CMD_HW_ACCESS:
+ {
+ char *operation;
+
+ NEXTC("<disable/enable>", "hw_access");
+ operation = av[i];
+
+ if (!strcmp(operation, "disable")) {
+ if (is_cr_space_locked) {
+ printf("-I- HW access already disabled\n");
+ } else {
+ if (!f->disable_hw_access()) {
+ report_err(ops._err_msg, "%s\n", f->err());
+ rc = 1; goto done;
+ }
+ }
+ } else if (!strcmp(operation, "enable")) {
+ u_int64_t key;
+
+ if (is_cr_space_locked == 0) {
+ printf("-I- HW access already enabled\n");
+ } else {
+ hw_key_t key_struct;
+ u_int8_t got_pass;
+ GET_KEY_FROM_USER("hw_access", &key_struct, &got_pass);
+ key = ((u_int64_t)key_struct.h << 32) | key_struct.l;
+ if (!f->enable_hw_access(key)) {
+ report_err(ops._err_msg, "%s\n", f->err());
+ rc = 1; goto done;
+ }
+ }
+ } else {
+ report_err(ops._err_msg, "Bad option (%s). You can use enable or disable as options for hw_access.\n", operation);
+ rc = 1; goto done;
+ }
+
+
+ }
+ break;
case CMD_SET_GUIDS:
{
Operations::ImageInfo info;
} else {
// 1- FS2 image
// 2- FS2 device with no blank guids
+ guid_t *used_guids;
// Check the guid given by the user
if (!ops.CheckSetGuidsFlags(&info, macs_specified, guids_specified, uids_specified)) {
}
if (image_fname == NULL) {
// 2- FS2 device with no blank Guids
- report_warn("GUIDs are already set, re-burning image with the new GUIDs ...");
+ report_warn("GUIDs are already set, re-burning image with the new GUIDs ...\n");
+ }
+
+ bool ib_dev, eth_dev, bx_dev;
+
+ // Get the FW types
+ bx_dev = ops.IsBridgeX(info.devType);
+ ops.SetDevFlags(info.devType, ib_dev, eth_dev);
+ guid_t* old_guids = info.imageOk ? info.guids : NULL;
+
+ // Patch the GUIDs and prints any needed warnings
+ if (!ops.preFS2PatchGUIDs(eth_dev, bx_dev, guids_specified, macs_specified, uids_specified, user_guids,
+ old_guids, &used_guids, info.guidNum)) {
+ rc = 1; goto done;
}
- if (!ops.ModifyGuidSection(fbase, &info, user_guids, image_fname, silent)) {
+ // Report the changes in the GUIDs
+ if (!ops.reportGuidChaneges(&info, used_guids, old_guids, ib_dev, eth_dev, bx_dev)) {
+ rc = 1; goto done;
+ }
+ // Modify the guids in the burnt image and re-burn it
+ if (!ops.ModifyGuidSection(fbase, &info, used_guids, image_fname, silent)) {
report_err(ops._err_msg, "GUIDs set failed: %s\n", ops.err());
rc = 1; goto done;
}
}
break;
- case CMD_QUERY_ROM:
- {
- Operations::ImageInfo info;
- if (!ops.LoadAsExpRom(*fbase, &info) ||
- !ops.GetExpRomVersion(&info) ||
- !ops.DisplayExpRomInfo(&info)) {
- report_err(ops._err_msg, "%s rom query (%s) failed: %s\n", cmdTarget , cmdAccess, ops.err());
- rc = 1; goto done;
- }
+ case CMD_QUERY_ROM: {
+ Operations::ImageInfo info;
+ if (!ops.LoadAsExpRom(*fbase, &info) ||
+ !ops.GetExpRomVersion(&info) ||
+ !ops.DisplayExpRomInfo(&info, "Rom Info: ")) {
+
+ report_err(ops._err_msg, "%s rom query (%s) failed: %s\n",
+ cmdTarget, cmdAccess, ops.err());
+ rc = 1;
+ goto done;
}
+ }
break;
case CMD_READ_BLOCK:
{
case CMD_CFI:
{
- if (!f->print_attr() || !f->print_attr_old_format()) {
+ if (!f->print_attr()) {
report_err(ops._err_msg, "Cfi query failed: %s\n", f->err());
rc = 1; goto done;
}
#define MERGE_C(rsrc1,rsrc2,start,len) ((((rsrc2)<<(start)) & (MASK32((start),(len)))) | ((rsrc1) & (~MASK32((start),(len)))))
#define MERGE(rsrc1,rsrc2,start,len) (((len)==32)?(rsrc2):MERGE_C(rsrc1,rsrc2,start,len))
+#define ONES64(size) ((size)?(0xffffffffffffffffULL>>(64-(size))):0)
+#define MASK64(offset,size) (ONES64(size)<<(offset))
+
+#define EXTRACT_C64(source,offset,size) ((((unsigned long long)(source))>>(offset)) & ONES64(size))
+#define EXTRACT64(src,start,len) (((len)==64)?(src):EXTRACT_C64(src,start,len))
+
+#define MERGE_C64(rsrc1,rsrc2,start,len) ((((u_int64_t)(rsrc2)<<(start)) & (MASK64((start),(len)))) | ((rsrc1) & (~MASK64((start),(len)))))
+#define MERGE64(rsrc1,rsrc2,start,len) (((len)==64)?(rsrc2):MERGE_C64(rsrc1,rsrc2,start,len))
#ifndef __WIN__
//typedef struct mflash *mflash;
typedef int (*f_mf_lock) (mflash* mfl, int lock_state);
-typedef int (*f_mf_unlock) (mflash* mfl);
typedef int (*f_mf_set_bank) (mflash* mfl, u_int32_t bank);
typedef int (*f_mf_read) (mflash* mfl, u_int32_t addr, u_int32_t len, u_int8_t* data);
typedef int (*f_mf_reset) (mflash* mfl);
typedef int (*f_st_spi_status)(mflash* mfl, u_int8_t op_type, u_int8_t* status);
-typedef int (*f_mf_get_info) (mflash* mfl, int bank_num, unsigned *type_index, int *log2size, u_int8_t *no_flash);
+typedef int (*f_mf_get_info) (mflash* mfl, unsigned *type_index, int *log2size, u_int8_t *no_flash);
// This is an interface function when running in IRISC
int mf_open_fw(mflash* mfl, flash_params_t* flash_params);
// Functions:
f_mf_lock f_lock;
- f_mf_unlock f_unlock;
+
f_mf_set_bank f_set_bank;
f_mf_get_info f_get_info;
#else
#define MREAD4(offs, val) do { if (mread4 (mfl->mf, offs, val) != 4) { \
fprintf(stderr, "-E- Cr read (0x%08x) failed: %s(%d)\n", (u_int32_t)(offs), strerror(errno), (u_int32_t)errno); \
- exit(2); } \
+ exit(2); } /*printf("-D- mread4: offs = %#x, val = %#x\n", offs, val);*/ \
} while (0)
#define MWRITE4(offs, val) do { if (mwrite4(mfl->mf, offs, val) != 4) { \
fprintf(stderr, "-E- Cr write (0x%08x, 0x%08x) failed: %s(%d)\n", (u_int32_t)(offs), (u_int32_t)(val), strerror(errno), (u_int32_t)errno); \
- mclose(mfl->mf); exit(2); } \
+ mclose(mfl->mf); exit(2); } /*printf("-D- %s mwrite4: offs = %#x, val = %#x\n", __FUNCTION__, offs, val);*/ \
} while (0)
#endif
} flash_info_t;
#define SST_FLASH_NAME "SST25VFxx"
+#define WINBOND_NAME "W25QxxBV"
#define FMT_ST_M25P_NAME
typedef enum flash_vendor {
- FV_ST = 0x20,
- FV_SST = 0xbf,
+ FV_ST = 0x20,
+ FV_SST = 0xbf,
+ FV_WINBOND = 0xef,
} flash_vendor_t;
typedef enum flash_memory_type {
FMT_ST_M25P = 0x20,
FMT_ST_M25PX = 0x71,
FMT_SST_25 = 0x25,
+ FMT_WINBOND = 0x40,
} flash_memory_type;
flash_info_t g_flash_info_arr[] =
{
- {"M25PXxx", FV_ST, FMT_ST_M25PX, MCS_STSPI, SFC_SSE, 0x1000},
- {"M25Pxx", FV_ST, FMT_ST_M25P, MCS_STSPI, SFC_SE, 0x10000},
- {SST_FLASH_NAME, FV_SST, FMT_SST_25, MCS_SSTSPI, SFC_SE, 0x10000},
+ {"M25PXxx", FV_ST, FMT_ST_M25PX, MCS_STSPI, SFC_SSE, 0x1000},
+ {"M25Pxx", FV_ST, FMT_ST_M25P, MCS_STSPI, SFC_SE, 0x10000},
+ {SST_FLASH_NAME, FV_SST, FMT_SST_25, MCS_SSTSPI, SFC_SE, 0x10000},
+ {WINBOND_NAME, FV_WINBOND, FMT_WINBOND, MCS_STSPI, SFC_SSE, 0x1000},
+
};
int cntx_sst_get_log2size(u_int8_t capacity, int* log2spi_size)
return MFE_OK;
}
-int cntx_get_flash_info(mflash* mfl, int bank_num, unsigned *type_index, int *log2size, u_int8_t *no_flash)
+int cntx_get_flash_info(mflash* mfl, unsigned *type_index, int *log2size, u_int8_t *no_flash)
{
int rc, res_rc;
u_int8_t type = 0, capacity = 0, vendor = 0, no_flash_res = 0, no_flash_rdid = 0;
*no_flash = 0;
rc = cntx_spi_get_type(mfl, SFC_JEDEC, &vendor, &type, &capacity); CHECK_RC(rc);
- //printf("-D- vendor = %#x, type = %#x, capacity = %#x, rc1 = %d.\n", vendor, type, capacity, rc);
no_flash_rdid = is_no_flash_detected(type, vendor, capacity);
if (get_type_index_by_vendor_and_type(vendor, type, type_index) == MFE_OK) {
// RDID Succeded.
// Get the capacity
if (get_log2size_by_capcity(*type_index, capacity, log2size) != MFE_OK) {
- printf("-E- SST SPI flash #%d (vendor: %#x, type: %#x, capacity:%#x) is not supported.\n", bank_num, vendor,
+ printf("-E- SST SPI flash #%d (vendor: %#x, type: %#x, capacity:%#x) is not supported.\n", mfl->curr_bank, vendor,
type, capacity);
return MFE_UNSUPPORTED_FLASH_TOPOLOGY;
}
*no_flash = 1;
} else {
// 3- Flash is not supported
- printf("-E- SPI flash #%d (vendor: %#x, memory type: %#x) is not supported.\n", bank_num, vendor, type);
+ printf("-E- SPI flash #%d (vendor: %#x, memory type: %#x) is not supported.\n", mfl->curr_bank, vendor, type);
rc = MFE_UNSUPPORTED_FLASH_TYPE;
}
}
rc = res_rc;
if (rc == MFE_UNSUPPORTED_FLASH_TYPE) {
// 3- Flash is not supported
- printf("-E- SPI flash #%d (vendor: %#x, memory type: %#x, es: %#x) is not supported.\n", bank_num, vendor, type, es);
+ printf("-E- SPI flash #%d (vendor: %#x, memory type: %#x, es: %#x) is not supported.\n", mfl->curr_bank, vendor, type, es);
}
// when rc != MFE_UNSUPPORTED_FLASH_TYPE, "RES failed due to cr-space error."
}
return rc;
}
-int ih3lx_get_flash_info(mflash* mfl, int bank_num, unsigned *type_index, int *log2size, u_int8_t *no_flash)
+int ih3lx_get_flash_info(mflash* mfl, unsigned *type_index, int *log2size, u_int8_t *no_flash)
{
int rc;
unsigned char es;
rc = get_flash_info_by_res(mfl, type_index, log2size, no_flash, &es);
if (rc == MFE_UNSUPPORTED_FLASH_TYPE) {
- printf("-E- SPI flash #%d (electric signature: %#x) is not supported.\n", bank_num, es);
+ printf("-E- SPI flash #%d (electric signature: %#x) is not supported.\n", mfl->curr_bank, es);
}
return rc;
}
int log2size;
u_int8_t no_flash = 0;
char *type_name;
-
rc = set_bank(mfl, spi_sel); CHECK_RC(rc);
- rc = mfl->f_get_info(mfl, spi_sel, type_index, &log2size, &no_flash); CHECK_RC(rc);
+ rc = mfl->f_get_info(mfl, type_index, &log2size, &no_flash); CHECK_RC(rc);
+ //printf("-D- spi_sel = %d, num_of_flashes = %d, rc = %d, no_flash = %d\n", spi_sel, num_of_flashes, rc, no_flash);
+
if (no_flash == 1) {
// This bank is empty and also the following banks will be empty.
if (flash_params->num_of_flashes == 0) {
}
-int ih3lx_st_spi_reset (mflash* mfl) {
+int empty_reset (mflash* mfl) {
mfl = NULL;
return MFE_OK;
}
rc = st_spi_fill_attr(mfl, NULL); CHECK_RC(rc);
if (mfl->attr.command_set == MCS_STSPI) {
- mfl->f_reset = ih3lx_st_spi_reset;
+ mfl->f_reset = empty_reset;
mfl->f_write_blk = ih3lx_st_spi_block_write;
mfl->f_write = write_chunks;
mfl->f_erase_sect = ih3lx_st_spi_erase_sect;
HBS_GPIO_CS = 4
};
-int cntx_set_bank(mflash* mfl, u_int32_t bank) {
+int empty_set_bank(mflash* mfl, u_int32_t bank) {
// NULL function - No actual work here - in ConnectX the curr_bank is written in the command word.
mfl = NULL; // Compiler warning
bank = 0; // Compiler warning
}
+int is_sx(u_int32_t dev_id) {
+ if (dev_id == SWITCHX_HW_ID) {
+ return 1;
+ }
+ return 0;
+}
int is_is4_family(u_int32_t dev_id) {
if (dev_id == 435 || // InfiniScaleIV
- dev_id == 6100 || // BridgeX
- dev_id == SWITCHX_HW_ID) { // SwitchX
+ dev_id == 6100) { // BridgeX
return 1;
}
return 0;
}
+int is_4th_gen_switch_family(u_int32_t dev_id) {
+ if (is_is4_family(dev_id) ||
+ is_sx(dev_id)) {
+ return 1;
+ }
+ return 0;
+}
int cntx_exec_cmd(mflash* mfl, u_int32_t gw_cmd, char* msg) {
- if (is_is4_family(mfl->attr.hw_dev_id)) {
+ if (is_4th_gen_switch_family(mfl->attr.hw_dev_id)) {
// For Infiniscale4 and BridgeX: keep the GW locked during flash ops
gw_cmd = MERGE(gw_cmd, 1, 31, 1);
}
gw_cmd = MERGE(gw_cmd, (u_int32_t)mfl->curr_bank,
HBO_CHIP_SELECT, HBS_CHIP_SELECT);
MWRITE4(CR_FLASH_GW, gw_cmd);
-
return ih3lx_wait_ready(mfl, msg);
}
return MFE_OK;
}
+int get_info_from_jededc_id(u_int32_t jededc_id, u_int8_t *vendor, u_int8_t* type, u_int8_t* capacity)
+{
+ *vendor = EXTRACT(jededc_id, 0, 8);
+ *type = EXTRACT(jededc_id, 8, 8);
+ *capacity = EXTRACT(jededc_id, 16, 8);
+ return MFE_OK;
+}
+
int cntx_spi_get_type(mflash* mfl, u_int8_t op_type, u_int8_t *vendor, u_int8_t* type, u_int8_t* capacity) {
u_int32_t flash_data = 0;
int rc;
rc = cntx_int_spi_get_status_data(mfl, op_type, &flash_data, 3); CHECK_RC(rc);
flash_data = __be32_to_cpu(flash_data);
- // printf("-D- cntx_spi_get_type: flash_data = %#x\n", flash_data);
-
- *vendor = EXTRACT(flash_data, 0, 8);
- *type = EXTRACT(flash_data, 8, 8);
- *capacity = EXTRACT(flash_data, 16, 8);
+ // Get type and some other info from jededc_id
+ get_info_from_jededc_id(flash_data, vendor, type, capacity);
return MFE_OK;
}
int cntx_sst_spi_write_status_reg(mflash* mfl)
return atol(mflash_env);
}
- return 4;
+ return -1;
+}
+
+int spi_update_num_of_banks(mflash* mfl, int prev_num_of_flashes)
+{
+ int num_of_banks;
+
+ num_of_banks = spi_get_num_of_flashes(prev_num_of_flashes);
+ if (num_of_banks == -1) {
+ mfl->opts[MFO_NUM_OF_BANKS] = 4;
+ mfl->opts[MFO_USER_BANKS_NUM] = 0;
+ } else {
+ mfl->opts[MFO_NUM_OF_BANKS] = num_of_banks;
+ mfl->opts[MFO_USER_BANKS_NUM] = 1;
+ }
+ return MFE_OK;
}
return MFE_OK;
}
+int get_flash_offset(u_int32_t addr, int log2_bank_size, u_int32_t *flash_addr_p)
+{
+ *flash_addr_p = addr & ONES32(log2_bank_size);
+ return MFE_OK;
+}
+
int cntx_st_spi_block_read_ex (mflash* mfl, u_int32_t blk_addr, u_int32_t blk_size, u_int8_t* data, u_int8_t is_first, u_int8_t is_last) {
int rc;
u_int32_t i;
gw_cmd = MERGE(gw_cmd, 1 , HBO_ADDR_PHASE, 1);
gw_cmd = MERGE(gw_cmd, SFC_READ , HBO_CMD, HBS_CMD);
- gw_addr = blk_addr & ONES32(mfl->attr.log2_bank_size);
+ rc = get_flash_offset(blk_addr, mfl->attr.log2_bank_size, &gw_addr); CHECK_RC(rc);
+ //printf("-D- cntx_st_spi_block_read_ex: write to gateway\n");
MWRITE4(HCR_FLASH_ADDR, gw_addr);
+
}
//printf("-D- gw_addr = %#x, gw_cmd = %#x, blk_addr = %#x, mfl->attr.log2_bank_size = %#x\n", gw_addr, gw_cmd, blk_addr, mfl->attr.log2_bank_size);
if (!is_last) {
mfl->f_read = read_chunks;
mfl->f_read_blk = cntx_st_spi_block_read;
mfl->f_lock = ihst_flash_lock; // Flash lock has same address and functionality as in InfiniHost.
- mfl->f_set_bank = cntx_set_bank;
+ mfl->f_set_bank = empty_set_bank;
mfl->f_get_info = cntx_get_flash_info;
rc = st_spi_fill_attr(mfl, flash_params); CHECK_RC(rc);
if (mfl->attr.command_set == MCS_STSPI || mfl->attr.command_set == MCS_SSTSPI) {
- mfl->f_reset = ih3lx_st_spi_reset; // Null func - same as in ih3lx
+ mfl->f_reset = empty_reset; // Null func - same as in ih3lx
mfl->f_write_blk = get_write_blk_func(mfl->attr.command_set);
mfl->attr.page_write = 256;
mfl->is_locked = (lock_state != 0);
return MFE_OK;
}
+#define SX_CS_SUPPORT_ADDR 0xF0420
+
+int sx_init_cs_support(mflash* mfl) {
+ if (is_sx(mfl->attr.hw_dev_id)) {
+ u_int8_t cs_support_mask = 0;
+ u_int32_t data;
+ if (mfl->opts[MFO_USER_BANKS_NUM] == 0) {
+ // We assume we have only 2 flashes on SX
+ mfl->opts[MFO_NUM_OF_BANKS] = 2;
+ }
+ // Prepare the bit mask of the banks number
+ cs_support_mask = (1 << mfl->opts[MFO_NUM_OF_BANKS]) - 1;
+
+ // Read Modify write the cs support field
+ MREAD4(SX_CS_SUPPORT_ADDR, &data);
+ data = MERGE(data, cs_support_mask, 0, 4);
+ MWRITE4(SX_CS_SUPPORT_ADDR, data);
+ }
+ return 0;
+}
+
+#define HW_DEV_ID 0xf0014
+#define CACHE_REP_OFF 0xf0408
+#define CASHE_REP_CMD 0xf040c
+
+int check_cache_replacement_gaurd(mflash* mfl, u_int8_t *needs_cache_replacement)
+{
+ *needs_cache_replacement = 0;
+
+ if (mfl->opts[MFO_IGNORE_CASHE_REP_GUARD] == 0) {
+ u_int32_t off, cmd, data;
+
+ // Read the Cache replacement offset
+ MREAD4(CACHE_REP_OFF, &data);
+ off = EXTRACT(data, 0, 26);
+ // Read the Cache replacement cmd
+ MREAD4(CASHE_REP_CMD, &data);
+ cmd = EXTRACT(data, 16, 8);
+ // Check if the offset and cmd are zero in order to continue burning.
+ if (cmd != 0 || off != 0) {
+ *needs_cache_replacement = 1;
+ // HACK - This error value should not be displayed on new MFT.
+ /*
+ printf("-E- Can not access flash - SwitchX cache replacement is active."
+ " The current version of this tool does not support this mode\n");
+ return MFE_ERROR;
+ */
+ }
+ } else {
+ // Here we ignore the cache replacement check
+ // We need to execute a write in order to do any needed cache replacement
+ // Reset the HW ID which is read only register.
+ MWRITE4(HW_DEV_ID, 0);
+ }
+
+ return MFE_OK;
+}
+
+int mfl_com_lock(mflash* mfl)
+{
+ int rc;
+ rc = mfl->f_lock(mfl, 1);
+ if (!mfl->opts[MFO_IGNORE_SEM_LOCK]) {
+ CHECK_RC(rc);
+ } else {
+ mfl->is_locked = 1;
+ }
+ return MFE_OK;
+}
// ConnectX and Shaldag flash interfaces are identical (except lock function)
// Use same functions
mfl->f_read = read_chunks;
mfl->f_read_blk = cntx_st_spi_block_read;
mfl->f_lock = is4_flash_lock;
- mfl->f_set_bank = cntx_set_bank;
+ mfl->f_set_bank = empty_set_bank;
mfl->f_get_info = cntx_get_flash_info;
- rc = mfl->f_lock(mfl, 1);
- if (!mfl->opts[MFO_IGNORE_SEM_LOCK]) {
- CHECK_RC(rc);
- } else {
- mfl->is_locked = 1;
- }
-
- //HACK - Not yet implemented, but should work without it also
- //rc = is4_init_gpios(mfl); CHECK_RC(rc);
+ rc = mfl_com_lock(mfl); CHECK_RC(rc);
+ if (is_sx(mfl->attr.hw_dev_id)) {
+ // Update the chip_select_support according to the banks number of cs.
+ rc = sx_init_cs_support(mfl); CHECK_RC(rc);
+ }
mfl->f_spi_status = cntx_st_spi_get_status;
rc = st_spi_fill_attr(mfl, flash_params); CHECK_RC(rc);
if (mfl->attr.command_set == MCS_STSPI || mfl->attr.command_set == MCS_SSTSPI) {
- mfl->f_reset = ih3lx_st_spi_reset; // Null func - same as in ih3lx
+ mfl->f_reset = empty_reset; // Null func - same as in ih3lx
//mfl->f_write_blk = cntx_st_spi_block_write;
mfl->f_write_blk = get_write_blk_func(mfl->attr.command_set);
mfl->attr.page_write = 256;
return MFE_OK;
}
+int sx_flash_init_direct_access(mflash* mfl, flash_params_t* flash_params)
+{
+ return is4_flash_init(mfl, flash_params);
+}
+
+int mfl_get_bank_info(mflash *mfl, u_int32_t addr, u_int32_t *flash_off_p, int *bank_p)
+{
+ int rc;
+ // Get the bank number
+ rc = set_bank(mfl, addr); CHECK_RC(rc);
+ *bank_p = mfl->curr_bank;
+ // Get the offset in the flash
+ rc = get_flash_offset(addr, mfl->attr.log2_bank_size, flash_off_p); CHECK_RC(rc);
+ return MFE_OK;
+}
+
+
+#ifdef NO_INBAND_ACCESS
+
+int sx_get_flash_info(mflash* mfl, unsigned *type_index, int *log2size, u_int8_t *no_flash)
+{
+ mfl = NULL;
+ type_index = NULL;
+ log2size = NULL;
+ no_flash = NULL;
+ return MFE_NOT_SUPPORTED_OPERATION;
+}
+
+int sx_block_read(mflash* mfl, u_int32_t blk_addr, u_int32_t blk_size, u_int8_t* data)
+{
+ mfl = NULL;
+ blk_addr = 0;
+ blk_size = 0;
+ data = NULL;
+
+ return MFE_NOT_SUPPORTED_OPERATION;
+}
+
+int sx_block_write(mflash* mfl, u_int32_t addr, u_int32_t size, u_int8_t* data)
+{
+ mfl = NULL;
+ addr = 0;
+ size = 0;
+ data = NULL;
+ return MFE_NOT_SUPPORTED_OPERATION;
+}
+
+int sx_flash_lock(mflash* mfl, int lock_state)
+{
+ mfl = NULL;
+ lock_state = 0;
+ return MFE_NOT_SUPPORTED_OPERATION;
+}
+
+int sx_erase_sect(mflash* mfl, u_int32_t addr)
+{
+ mfl = NULL;
+ addr = 0;
+ return MFE_NOT_SUPPORTED_OPERATION;
+}
+
+#else
+
+#include "mflash_inband.h"
+
+int sx_get_flash_info(mflash* mfl, unsigned *type_index, int *log2size, u_int8_t *no_flash)
+{
+ int rc;
+ u_int8_t vendor, type, capacity;
+ u_int32_t jedec_id;
+
+ rc = mfi_get_jedec(mfl->mf, mfl->curr_bank, &jedec_id); CHECK_RC(rc);
+ rc = get_info_from_jededc_id(jedec_id, &vendor, &type, &capacity); CHECK_RC(rc);
+
+ // Return there is no flash when all the params are 0xff
+ if (vendor == 0xff && type == 0xff && capacity == 0xff) {
+ *no_flash = 1;
+ return MFE_OK;
+ }
+ rc = get_type_index_by_vendor_and_type(vendor, type, type_index); CHECK_RC(rc);
+ rc = get_log2size_by_capcity(*type_index, capacity, log2size); CHECK_RC(rc);
+ return MFE_OK;
+
+}
+
+int sx_block_read(mflash* mfl, u_int32_t blk_addr, u_int32_t blk_size, u_int8_t* data)
+{
+ int rc, bank;
+ u_int32_t flash_offset;
+ if (blk_size > (u_int32_t)mfl->attr.block_write || blk_size < 4) {
+ return MFE_BAD_PARAMS;
+ }
+ rc = mfl_get_bank_info(mfl, blk_addr, &flash_offset, &bank); CHECK_RC(rc);
+ return mfi_read_block(mfl->mf, flash_offset, bank, blk_size, data);
+}
+int sx_block_write(mflash* mfl, u_int32_t addr, u_int32_t size, u_int8_t* data)
+{
+ int rc, bank;
+ u_int32_t flash_offset;
+
+ CHECK_ALLIGN(addr, mfl->attr.block_write, size);
+ rc = mfl_get_bank_info(mfl, addr, &flash_offset, &bank); CHECK_RC(rc);
+ return mfi_write_block(mfl->mf, flash_offset, bank, size, data);
+}
+
+int sx_flash_lock(mflash* mfl, int lock_state)
+{
+ return mfi_flash_lock(mfl->mf, lock_state);
+}
+
+int sx_erase_sect(mflash* mfl, u_int32_t addr)
+{
+ int rc, bank;
+ u_int32_t flash_addr;
+
+ rc = mfl_get_bank_info(mfl, addr, &flash_addr, &bank); CHECK_RC(rc);
+ return mfi_erase_sector(mfl->mf, flash_addr, bank);
+}
+
+#endif
+
+
+int sx_flash_init_inband_access(mflash* mfl, flash_params_t* flash_params)
+{
+ int rc;
+
+ mfl->f_read = read_chunks;
+ mfl->f_write = write_chunks;
+
+ mfl->f_reset = empty_reset;
+ mfl->f_set_bank = empty_set_bank;
+
+
+ mfl->f_get_info = sx_get_flash_info;
+ mfl->f_lock = sx_flash_lock;
+ mfl->f_erase_sect = sx_erase_sect;
+ mfl->f_write_blk = sx_block_write;
+ mfl->f_read_blk = sx_block_read;
+
+
+ // Lock the FW semaphore which synchronizes between multiple processes
+ rc = mfl_com_lock(mfl); CHECK_RC(rc);
+ // Get the flash attribute
+ rc = st_spi_fill_attr(mfl, flash_params); CHECK_RC(rc);
+
+ mfl->attr.block_write = 32;
+ mfl->attr.page_write = 32;
+
+ return MFE_OK;
+}
+
+int sx_flash_init_fw_access(mflash* mfl, flash_params_t* flash_params)
+{
+ // This function checks the access type in order to select the access functions
+ u_int32_t dev_flags = 0;
+ int rc;
+
+ // TODO: Check that the flags is indeed set with the true value.
+#ifndef NO_INBAND_ACCESS
+ rc = mget_mdevs_flags(mfl->mf, &dev_flags); CHECK_RC(rc);
+ if (dev_flags & MDEVS_IB) {
+ rc = sx_flash_init_inband_access(mfl, flash_params); CHECK_RC(rc);
+ } else {
+ return MFE_DIRECT_FW_ACCESS_DISABLED;
+ }
+#endif
+ return MFE_OK;
+}
+
+int sx_flash_init(mflash* mfl, flash_params_t* flash_params)
+{
+ int rc;
+ u_int8_t needs_cache_replacement;
+
+ rc = check_cache_replacement_gaurd(mfl, &needs_cache_replacement); CHECK_RC(rc);
+
+ if (needs_cache_replacement) {
+ rc = sx_flash_init_fw_access(mfl, flash_params); CHECK_RC(rc);
+ } else {
+ rc = sx_flash_init_direct_access(mfl, flash_params); CHECK_RC(rc);
+ }
+ return MFE_OK;
+}
//
return mf_open_fw(mfl, NULL);
}
-#define HW_DEV_ID 0xf0014
-#define CACHE_REP_OFF 0xf0408
-#define CASHE_REP_CMD 0xf040c
-
-int check_cache_replacement_gaurd(mflash* mfl)
-{
- if (mfl->attr.hw_dev_id == SWITCHX_HW_ID && mfl->opts[MFO_IGNORE_CASHE_REP_GUARD] == 0) {
- u_int32_t off, cmd, data;
- // Read the Cache replacement offset
- MREAD4(CACHE_REP_OFF, &data);
- off = EXTRACT(data, 0, 26);
- // Read the Cache replacement cmd
- MREAD4(CASHE_REP_CMD, &data);
- cmd = EXTRACT(data, 16, 8);
- // Check if the offset and cmd are zero in order to continue burning.
- if (cmd != 0 || off != 0) {
- printf("-E- Can not access flash - SwitchX cache replacement is active."
- " The current version of this tool does not support this mode\n");
- return MFE_ERROR;
- }
- }
- return MFE_OK;
-}
+#define CR_LOCK_HW_ID 0xbad0cafe
//Caller must zero the mflash struct before calling this func.
int mf_open_fw(mflash* mfl, flash_params_t* flash_params)
MREAD4(HW_DEV_ID, &dev_id);
+ if (dev_id == CR_LOCK_HW_ID) {
+ return MFE_LOCKED_CRSPACE;
+ }
mfl->attr.rev_id = (dev_id & 0xff0000) >> 16;
mfl->attr.hw_dev_id = dev_id;
mfl->curr_bank = -1;
+
//printf("-D- read dev id: %d, rev_id: %#x\n", mfl->attr.hw_dev_id, mfl->attr.rev_id);
- rc = check_cache_replacement_gaurd(mfl); CHECK_RC(rc);
if (dev_id == 23108 || dev_id == 25208) {
rc = cntx_flash_init(mfl, flash_params);
} else if (is_is4_family(dev_id)) {
rc = is4_flash_init(mfl, flash_params);
+ } else if (is_sx(dev_id)) {
+ rc = sx_flash_init(mfl, flash_params);
} else if (dev_id == 0xffff) {
printf("-E- Read a corrupted device id (0x%x). Probably HW/PCI access problem\n", dev_id);
rc = MFE_CR_ERROR;
memset(*pmfl, 0, sizeof(mflash));
(*pmfl)->mf = (mfile*)mf;
(*pmfl)->opts[MFO_NUM_OF_BANKS] = spi_get_num_of_flashes(num_of_banks);
+
+ rc = spi_update_num_of_banks((*pmfl), num_of_banks); CHECK_RC(rc);
+
(*pmfl)->opts[MFO_IGNORE_CASHE_REP_GUARD] = ignore_cache_rep_guard;
rc = mf_open_fw(*pmfl, flash_params);
return MFE_OK;
}
+int release_semaphore(mflash* mfl) {
+ int rc;
+ if (mfl->is_locked && mfl->f_lock) {
+ rc = mfl->f_lock(mfl, 0); CHECK_RC(rc);
+ }
+ return MFE_OK;
+}
+
int mf_close (mflash* mfl) {
if (!mfl) {
return MFE_BAD_PARAMS;
set_bank(mfl, 0);
}
- if (mfl->is_locked && mfl->f_lock) {
- mfl->f_lock(mfl, 0);
- }
+ release_semaphore(mfl);
if (mfl->mf && (mfl)->opts[MFO_CLOSE_MF_ON_EXIT]) {
mclose(mfl->mf);
if (msw_reset(mfl->mf)) {
if (errno == EPERM) {
return MFE_CMD_SUPPORTED_INBAND_ONLY;
+ } else if (errno == EOPNOTSUPP) {
+ return MFE_MANAGED_SWITCH_NOT_SUPPORTED;
} else {
+
return MFE_ERROR;
}
}
"MFE_NOMEM",
"MFE_OUT_OF_RANGE",
"MFE_CMD_SUPPORTED_INBAND_ONLY",
- "MFE_NO_FLASH_DETECTED"
+ "MFE_NO_FLASH_DETECTED",
+ "MFE_HW_ACCESS_DISABLED",
+ "MFE_CMDIF_BAD_STATUS_ERR",
+ "MFE_CMDIF_TIMEOUT_ERR",
+ "MFE_CMDIF_GO_BIT_BUSY",
+ "MFE_MISMATCH_KEY",
+ "MFE_UNKNOWN_REG",
+ "MFE_REG_ACCESS_FAILED",
+ "MFE_REG_ACCESS_MAD_BAD_STATUS",
+ "MFE_REG_ACCESS_MAD_NOT_SUPPORTED",
+ "MFE_DIRECT_FW_ACCESS_DISABLED",
+ "MFE_MANAGED_SWITCH_NOT_SUPPORTED",
+ "MFE_NOT_SUPPORTED_OPERATION",
};
return err_code < (int)ARRSIZE(mf_err_str) ? mf_err_str[err_code] : NULL;
}
return MFE_OK;
}
+/**********************************************************************************************/
+/// THIS PART SHOULD BE MOVED TO A COMMON PLACE - CMDIF LIB
+
+#define TOOLS_HCR_ADDR 0x80780
+#define IF_CMD_UNLOCK_CR_SPACE 0x60
+#define CMD_IF_SIZE 28
+#define CMD_IF_WAIT_GO 2000
+
+typedef struct mf_cmd_if {
+ u_int64_t in_param;
+ u_int64_t out_param;
+ u_int32_t input_modifier;
+ u_int16_t token;
+ u_int16_t opcode;
+ u_int8_t opcode_modifier;
+ u_int8_t t;
+ u_int8_t e;
+ u_int8_t go;
+ u_int8_t status;
+} mf_cmd_if_t;
+
+static void cmd_if_pack(mf_cmd_if_t* cmd, u_int32_t* buf) {
+ memset((char*)buf, 0, sizeof(mf_cmd_if_t));
+ buf[0] = EXTRACT64(cmd->in_param, 32, 32);
+ buf[1] = EXTRACT64(cmd->in_param, 0, 32);
+ buf[2] = cmd->input_modifier;
+ // out h
+ // out l
+ buf[5] = MERGE(buf[5], cmd->token, 16, 16);
+ buf[6] = MERGE(buf[6], cmd->opcode, 0, 12);
+ buf[6] = MERGE(buf[6], cmd->opcode_modifier, 12, 4);
+ buf[6] = MERGE(buf[6], cmd->e, 22, 1);
+}
+
+static void cmd_if_unpack(mf_cmd_if_t* cmd, u_int32_t* buf) {
+ memset(cmd, 0, sizeof(mf_cmd_if_t));
+
+ cmd->in_param = MERGE64(cmd->in_param, buf[0], 32, 32);
+ cmd->in_param = MERGE64(cmd->in_param, buf[1], 0, 32);
+ cmd->input_modifier = buf[2];
+ cmd->out_param = MERGE64(cmd->out_param, buf[3], 32, 32);
+ cmd->out_param = MERGE64(cmd->out_param, buf[4], 0, 32);
+ cmd->opcode = EXTRACT(buf[6], 0, 12);
+ cmd->opcode_modifier= EXTRACT(buf[6], 12, 4);
+
+ cmd->status = EXTRACT(buf[6], 24, 8);
+}
+
+static int cmd_if_wait_go(mflash* mfl, int* retries)
+{
+ int i;
+ u_int8_t go_bit;
+
+ for (i = 0; i < CMD_IF_WAIT_GO; i++) {
+ u_int32_t word;
+ MREAD4(TOOLS_HCR_ADDR + CMD_IF_SIZE - 4, &word);
+ /*
+ if (mread4( mf, TOOLS_HCR_ADDR + CMD_IF_SIZE - 4, &word) != 4) {
+ return 3;
+ }
+ */
+ go_bit = EXTRACT(word, 23, 1);
+ if (!go_bit) {
+ if (retries) {
+ *retries = i;
+ }
+ return 0;
+ }
+ }
+ return MFE_CMDIF_GO_BIT_BUSY;
+}
+
+static int cmd_if_send(mflash* mfl, mf_cmd_if_t* cmd)
+{
+
+ u_int32_t raw_cmd[CMD_IF_SIZE/4];
+ int act_retries;
+ int rc;
+
+ // Check if the go BIT is ready
+ rc = cmd_if_wait_go(mfl, NULL);
+ if (rc) {
+ //printf("cmd_if_send: GO bit set before command issued (rc=%d)\n", rc);
+ return MFE_CMDIF_GO_BIT_BUSY;
+ }
+ // Prepare the date of the command we're gonna execute
+ cmd_if_pack(cmd, raw_cmd);
+
+ if (mwrite4_block(mfl->mf, TOOLS_HCR_ADDR, raw_cmd, CMD_IF_SIZE) != CMD_IF_SIZE) {
+ return MFE_CR_ERROR;
+ }
+
+ raw_cmd[6] = MERGE(raw_cmd[6], 1, 23, 1); // go
+ MWRITE4(TOOLS_HCR_ADDR + 24, raw_cmd[6]);
+
+ rc = cmd_if_wait_go(mfl, &act_retries);
+ if (rc) {
+ return MFE_CMDIF_TIMEOUT_ERR;
+ }
+
+ if (mread4_block(mfl->mf, TOOLS_HCR_ADDR, raw_cmd, CMD_IF_SIZE) != CMD_IF_SIZE) {
+ return MFE_CR_ERROR;
+ }
+
+ cmd_if_unpack(cmd, raw_cmd);
+
+ if (cmd->status) {
+ //printf("-E- CMD IF Bad status. Op: 0x%x Status: 0x%x\n", cmd->opcode, cmd->status);
+ return MFE_CMDIF_BAD_STATUS_ERR; // TODO - Special return code here - needs a specific attention
+ }
+ return MFE_OK;
+}
+
+#define MISMATCH_KEY_RC 0x3
+int cmdif_hw_access_int(mflash* mfl, u_int64_t key, u_int8_t opcode_modifier)
+{
+ mf_cmd_if_t cmd;
+ int rc;
+
+ my_memset(&cmd, 0, sizeof(cmd));
+
+ // Prepare CMD IF
+ cmd.opcode = IF_CMD_UNLOCK_CR_SPACE;
+ // Determine if we want to lock (1) or unlock (0)
+ cmd.opcode_modifier = opcode_modifier;
+ // Setting the given key
+ cmd.in_param = key;
+
+ rc = cmd_if_send(mfl, &cmd);
+
+ // Special case
+ if (rc == MFE_CMDIF_BAD_STATUS_ERR && cmd.opcode_modifier == 0) {
+ if (cmd.status == MISMATCH_KEY_RC) {
+ return MFE_MISMATCH_KEY;
+ }
+ }
+ return rc;
+}
+
+int mf_enable_hw_access(mflash* mfl, u_int64_t key)
+{
+ return cmdif_hw_access_int(mfl, key, 0 /* Unlock */);
+
+}
+
+int mf_disable_hw_access(mflash* mfl)
+{
+ int rc;
+ // We need to release the semaphore because we will not have any access to semaphore after disabling the HW access
+ rc = release_semaphore(mfl); CHECK_RC(rc);
+ return cmdif_hw_access_int(mfl, 0, 1 /* Lock */);
+}
+
+/**********************************************************************************************/
+