/*
 * Copyright (C) Jan 2013 Mellanox Technologies Ltd. All rights reserved.
 * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef FS2_OPS_
#define FS2_OPS_

#include "fw_ops.h"
#define FULL_VERIFY 0xff

class Fs2Operations : public FwOperations
{
public:
    Fs2Operations(FBase* ioAccess) : FwOperations(ioAccess), _burnBlankGuids(false), _isFullVerify(false){};

    virtual ~Fs2Operations(){};
    // virtual void print_type() {};
    virtual bool FwQuery(fw_info_t* fwInfo,
                         bool readRom = true,
                         bool isStripedImage = false,
                         bool quickQuery = true,
                         bool ignoreDToc = false,
                         bool verbose = false);
    virtual bool FwVerify(VerifyCallBack verifyCallBackFunc,
                          bool isStripedImage = false,
                          bool showItoc = false,
                          bool ignoreDToc = false);

    virtual bool
      FwBurn(FwOperations* imageOps, u_int8_t forceVersion, ProgressCallBack progressFunc = (ProgressCallBack)NULL);
    virtual bool FwBurnAdvanced(FwOperations* imageOps, ExtBurnParams& burnParams);
    virtual bool FwBurnBlock(FwOperations* imageOps, ProgressCallBack progressFunc);

    virtual bool FwBurnRom(FImage* romImg,
                           bool ignoreProdIdCheck = false,
                           bool ignoreDevidCheck = false,
                           ProgressCallBack progressFunc = (ProgressCallBack)NULL);
    virtual bool FwDeleteRom(bool ignoreProdIdCheck, ProgressCallBack progressFunc = (ProgressCallBack)NULL);

    // virtual bool FwSetGuids(std::vector<guid_t>& userGuids, std::vector<guid_t>& userMacs, bool updateCrc=true,
    // PrintCallBack callBackFunc=(PrintCallBack)NULL);
    virtual bool FwSetGuids(sg_params_t& sgParam,
                            PrintCallBack callBackFunc = (PrintCallBack)NULL,
                            ProgressCallBack progressFunc = (ProgressCallBack)NULL);

    virtual bool FwSetMFG(fs3_uid_t baseGuid, PrintCallBack callBackFunc = (PrintCallBack)NULL);
    virtual bool FwSetMFG(guid_t baseGuid, PrintCallBack callBackFunc = (PrintCallBack)NULL);
    virtual bool FwSetVSD(char* vsdStr,
                          ProgressCallBack progressFunc = (ProgressCallBack)NULL,
                          PrintCallBack printFunc = (PrintCallBack)NULL);
    virtual bool FwSetVPD(char* vpdFileStr, PrintCallBack callBackFunc = (PrintCallBack)NULL);
    virtual bool FwSetAccessKey(hw_key_t userKey, ProgressCallBack progressFunc = (ProgressCallBack)NULL);
    virtual bool FwShiftDevData(PrintCallBack progressFunc = (PrintCallBack)NULL);
    virtual bool FwResetNvData();
    virtual const char* FwGetResetRecommandationStr();

    virtual bool FwGetSection(u_int32_t sectType, std::vector<u_int8_t>& sectInfo, bool stripedImage = false);

    virtual u_int8_t FwType();
    virtual bool FwInit();
    virtual bool FwReadData(void* image, u_int32_t* image_size, bool verbose = false);
    virtual bool FwReadRom(std::vector<u_int8_t>& romSect);
    virtual bool FwCalcMD5(u_int8_t md5sum[16]);

    bool FwCheckIfWeCanBurnWithFwControl(FwOperations*) { return false; }

private:
    enum Fs2ImageInfoTags
    {
        II_IiFormatRevision = 0,
        II_FwVersion = 1,
        II_FwBuildTime = 2,
        II_DeviceType = 3,
        II_PSID = 4,
        II_VSD = 5,
        II_SuppurtedPsids = 6,
        II_ProductVer = 7,
        II_VsdVendorId = 8,
        II_IsGa = 9,
        II_HwDevsId = 10,
        II_MicVersion = 11,
        II_MinFitVersion = 12,
        II_HwAccessKey = 13,
        II_PROFILES_LIST = 14,
        II_SUPPORTED_PROFS = 15,
        II_CONFIG_INFO = 16,
        II_TLVS_FORMAT = 17,
        II_TRACER_HASH = 18,
        II_ConfigArea = 19,
        II_PSInfo = 20,
        II_Last, // Mark the end of used tag ids
        II_End = 0xff
    };
    struct Fs2ImgInfo
    {
        // Constructor for accurate initialization
        // Since this struct includes vectors it raises a warning when using memset on it
        Fs2ImgInfo() :
            psOk(0),
            defPorfile(0),
            configAddr1(0),
            configAddr2(0),
            configSize(0),
            isConfigurable(0),
            infoSectPtr(0),
            guidPtr(0),
            fw_sector_size(0)
        {
            memset(&ext_info, 0, sizeof(ext_info));
            memset(infoOffs, 0, sizeof(infoOffs));
        }
        fs2_info_t ext_info;
        u_int32_t infoOffs[II_Last];
        bool psOk;
        // Configuration info
        std::vector<u_int8_t> profListSectZipped;
        std::vector<u_int8_t> TlvFormatSectZipped;
        std::vector<u_int8_t> TracerHashSectZipped;
        std::vector<u_int32_t> supportedProfList;
        u_int32_t defPorfile;
        u_int32_t configAddr1;
        u_int32_t configAddr2;
        u_int32_t configSize;
        bool isConfigurable;
        u_int32_t infoSectPtr;
        u_int32_t guidPtr;
        u_int32_t fw_sector_size;
    };

    bool Fs2Verify(VerifyCallBack verifyCallBackFunc = (VerifyCallBack)NULL,
                   bool is_striped_image = false,
                   bool both_images = false,
                   bool only_get_start = false,
                   bool ignore_full_image_crc = false,
                   bool force_no_striped_image = false);
    bool Fs2Query();
    bool Fs2Burn(Fs2Operations& imageOps, ExtBurnParams& burnParams);

    bool CntxGetFsData(u_int32_t fs_info_word, bool& fs_en, u_int32_t& log2chunk_size);
    bool checkList(u_int32_t offs,
                   u_int32_t fw_start,
                   const char* pref,
                   VerifyCallBack verifyCallBackFunc = (VerifyCallBack)NULL);
    bool checkGen(u_int32_t beg,
                  u_int32_t offs,
                  u_int32_t& next,
                  const char* pref,
                  VerifyCallBack verifyCallBackFunc = (VerifyCallBack)NULL);
    bool ParseInfoSect(u_int8_t* buff, u_int32_t byteSize);
    bool Fs2IntQuery(bool readRom = true, bool isStripedImage = false);
    u_int32_t getDefaultSectorSz();
    bool GetMaxImageSize(u_int32_t flash_size,
                         bool image_is_fs,
                         u_int32_t imgConfigSectors,
                         u_int32_t imgFwSectorSz,
                         u_int32_t& max_image_size);
    bool UpdateFullImageCRC(u_int32_t* buff, u_int32_t size, bool blank_guids);
    bool Fs2FailSafeBurn(Fs2Operations& imageOps, ExtBurnParams& burnParams);
    bool ModifyGuidSection(guid_t* user_guids, ProgressCallBack progressFunc = (ProgressCallBack)NULL);
    bool preFS2PatchGUIDs(bool patch_macs,
                          bool user_guids,
                          bool user_macs,
                          guid_t new_guids[MAX_GUIDS],
                          guid_t old_guids[MAX_GUIDS],
                          guid_t** used_guids_p,
                          u_int32_t num_of_old_guids);
    bool patchGUIDs(Fs2Operations& imageOps,
                    bool patch_macs,
                    bool user_guids,
                    bool user_macs,
                    guid_t new_guids[MAX_GUIDS],
                    guid_t old_guids[MAX_GUIDS],
                    u_int32_t num_of_old_guids);
    void patchGUIDsSection(u_int32_t* buf, u_int32_t ind, guid_t guids[MAX_GUIDS], int nguids);
    bool patchImageVsd(Fs2Operations& imgFwOps, const char* userVsd = (char*)NULL);
    void PatchInfoSect(u_int8_t* rawSect, u_int32_t vsdOffs, const char* vsd);
    void initSectToRead(int imp_index);
    // needed for fs2burn
    bool IntegrateDevRomInImage(Fs2Operations& imgFwOps);
    bool
      UpdateRomInImage(u_int8_t* new_image, u_int8_t* old_image, u_int8_t* rom_data, int rom_size, int* new_image_size);
    bool AddNewSect(u_int8_t*& new_image_p, u_int8_t* data, GPH gph, u_int32_t* last_next);
    bool CopyBoot2(u_int8_t*& new_image_p, u_int8_t*& old_image_p);
    bool CopyData(u_int8_t*& new_image, u_int8_t*& old_image, int copy_size);

    bool ModifyKeySection(guid_t access_key, ProgressCallBack callBackFunc = (ProgressCallBack)NULL);
    void PatchKeySect(u_int32_t* buff, u_int32_t keyOff, guid_t hw_key);

    bool ModifyVSDSection(const char* vsd, ProgressCallBack callBackFunc = (ProgressCallBack)NULL);
    bool
      ReburnNewImage(u_int8_t* data, const char* feature_name, ProgressCallBack callBackFunc = (ProgressCallBack)NULL);
    bool packStripedImageData(u_int8_t* striped_data,
                              u_int8_t* normal_data,
                              u_int32_t length,
                              u_int32_t& striped_length,
                              bool needs_repack,
                              u_int32_t cntxLog2ChunkSize);
    bool Fs2SetGuids(sg_params_t& sgParam,
                     PrintCallBack callBackFunc = (PrintCallBack)NULL,
                     ProgressCallBack progressFunc = (ProgressCallBack)NULL);
    bool Fs2SetGuidsForBlank(sg_params_t& sgParam);
    bool getRunningFwVer();

    Fs2ImgInfo _fs2ImgInfo;
    bool _burnBlankGuids;
    bool _isFullVerify;
};

#endif // FS2_OPS_o
