/*
 * @file adcs_ftm.c
 *
 * @brief This file contains file transfer manager related functions for ADCS
 *
 * @copyright Copyright 2023 Antaris, Inc.
 */

#include "exo_common.h"
#include "exo_types.h"
#include "file_integrity_check.h"
#include "nvm.h"
#include "adcs_ftm.h"
#include "adcs_vapi_fw.h"
#include "ft_dwnld.h"
#include "otsu.h"
#include "crc_cal.h"
#include "logger.h"
#include "exo_tctm_ipc.h"
#include "adcs_va.h"

#ifndef LINUX_TEMP_PORT
typedef struct memcpy_info_save_def
{
    uint32 src_addrs;
    uint32 des_addrs;
    uint32 size;
    uint32 checksum;
}memcpy_info_save;

static memcpy_info_save adcs_memcpy_inf;
#endif

/* @brief Handle of contex info
 * structure to handle file data stored in NOR flash when save context mode
 * is triggered by FTM
 * structure size is 12 bytes = 12B
 * it has to be stored in NVM memory
 */
typedef struct nor_savecontxt_info_def
{
    uint32_t file_size_stored; /*!< Size of firmware */
    uint32_t file_checksum;    /*!< Checksum of firmware  */
    uint32_t reserv3;          /*!< unused */
    uint32_t file_stored_sts;  /*!< Status of context info; it tells
                                 NORflash has data */
}nor_savecontxt_info;

#ifndef LINUX_TEMP_PORT
//uint8_t sct_data_avail;
static uint8_t ftm_nor_write_avail;

#define ADCS_FIRMWARE_STORAGE_MEM (512*1024)
/*
 * This function will be invoked by memcopy module once firmware fully
 * moved from SDRAM to permanent storage memory NOR flash
 *
 * @param[in] sts      : memcpy status.
 *
 */
static void adcs_sdram_nor_cpy_completed(uint8 sts,\
        memcpy_info_save *s_adcs_ftm_handle);

static uint8_t adcs_ftmSaveConext_read_file_from_nor(
        ft_contextsave_info* c_info_ptr);

static void adcs_ftm_savecontext_nor_copy_compld_cblk(uint8_t cpy_sts);

static void adcs_ftm_savecontext_sdram_copy_compld_cblk(uint8_t cpy_sts,\
        memcpy_info_save *memcpy_inf_ptr);

static uint8_t adcs_ftmSaveConext_read_file_from_nor(
        ft_contextsave_info* c_info_ptr)
{
    uint8_t ret_sts =0;
    memcpy_info_save a_memcpy_inf;

    //ft_contextsave_info* c_info_ptr;

    //c_info_ptr = (ft_contextsave_info*)a_savecontext_ptr;

    /* read NVM flash */
    nor_savecontxt_info *nor_info_nvm_data =
        (nor_savecontxt_info*) os_malloc(sizeof(nor_savecontxt_info));
    nvm_parameter_read(NVM_DATA,NVM_ADCS_FTM_FILE_CONTXT_DATA,\
            (uint8_t*)nor_info_nvm_data);

    if(c_info_ptr->bulkdata_len == nor_info_nvm_data->file_size_stored &&\
       c_info_ptr->bulkdata_len != 0 && c_info_ptr->bulkdata_len != 0xFFFFFFFF)
    {
        if(c_info_ptr->bulkdata_checksum == 
                nor_info_nvm_data->file_checksum &&\
                c_info_ptr->bulkdata_checksum != 0 &&\
                c_info_ptr->bulkdata_checksum != 0xFFFFFFFF)
        {
            /* NOR flash is having file data,so memcpy can be done from
             * NOR to SDARM */
            a_memcpy_inf.des_addrs = 
                (uint32_t)adcs_get_sdram_storage_address();
            a_memcpy_inf.src_addrs = (uint32_t)adcs_get_nor_flash_address();
            a_memcpy_inf.size = nor_info_nvm_data->file_size_stored;
            a_memcpy_inf.checksum = nor_info_nvm_data->file_checksum;
            /*DEBUG_CPRINT(("Src addr: %lux\nDsc addr: %lux\nSize:\
            %lu\nChecksum: %lux\n",a_memcpy_inf.src_addrs,\
            a_memcpy_inf.des_addrs,a_memcpy_inf.size,a_memcpy_inf.checksum));*/
            ret_sts = os_memcpy_extmem((uint8_t*)a_memcpy_inf.des_addrs,\
                    (uint8_t*)a_memcpy_inf.src_addrs, a_memcpy_inf.size, NULL,\
                    1,1);
            adcs_ftm_savecontext_sdram_copy_compld_cblk(ret_sts, \
                    &a_memcpy_inf);
            //          sct_data_avail = 1;
            ret_sts =1;
        }
        else
        {
            DEBUG_CPRINT(("[FTM savecontxt]NOR data not avail"
                        " checksumFail\n"));
            log_id(LOG_ERROR,LOG_ADCS,FTM_NOR_data_not_avail_checksumFail);
            //otsu_encode_tm(otfs_flash_copy_fail,0xCD);
        }
    }
    else
    {
        DEBUG_CPRINT(("[FTM savecontxt] NOR data not avail\n"));
        log_id(LOG_ERROR,LOG_ADCS,FTM_NOR_data_not_avail);

        //otsu_encode_tm(otfs_flash_copy_fail,0xCD);
    }
    os_free(nor_info_nvm_data);
    nor_info_nvm_data = NULL;
    return ret_sts;
}

static void adcs_ftm_savecontext_sdram_copy_compld_cblk(uint8_t cpy_sts,\
        memcpy_info_save *memcpy_inf_ptr)
{
    uint32_t cal_checksum;


    DEBUG_CPRINT(("[FTM savecontxt] SDRAM flash  callback called\n"));
    log_id(LOG_INFO_L1,LOG_ADCS,FTM_SDRAM_flash_callback_called);

    if(cpy_sts == 0)
    {
        cal_checksum = calc_checksum_memory(
                (uint8_t*)memcpy_inf_ptr->des_addrs,memcpy_inf_ptr->size);
        if(cal_checksum == memcpy_inf_ptr->checksum)
        {
            /* Notify GS that SDRAM is ready to resume download */
            DEBUG_CPRINT(("[FTM savecontxt] SDRAM flash CRC pass\n"));
            log_id(LOG_INFO_L1,LOG_ADCS,FTM_SDRAM_flash_CRC_pass);
        }
        else
        {
            DEBUG_CPRINT(("[FTM savecontxt] SDRAM flash CRC FAIL\n"));
            log_id(LOG_ERROR,LOG_ADCS,FTM_SDRAM_flash_CRC_fail);

        }
    }
    else
    {
        DEBUG_CPRINT(("[FTM savecontxt] NOR flash callback called - Fail\n"));
        log_id(LOG_ERROR,LOG_ADCS,\
                FTM_savecontext_NOR_flash_callback_called_fail);
    }
}

static void adcs_ftm_savecontext_nor_copy_compld_cblk(uint8_t cpy_sts)
{
    uint32_t cal_checksum;
    nor_savecontxt_info nor_info_nvm_data;


    DEBUG_CPRINT(("[FTM savecontxt] NOR flash  callback called\n"));
    log_id(LOG_INFO_L1,LOG_ADCS,\
            FTM_savecontext_NOR_flash_callback_called);
    e_sus_res_state sus_state;

    sus_state =  ft_get_suspend_resume_sts();
    if(sus_state == no_suspend_reusume)
    {
        DEBUG_CPRINT(("FTM savecontext NOR cpy /nvm store discarded \n"));
        log_id(LOG_INFO_L1,LOG_ADCS,\
                FTM_savecontext_NOR_cpy_nvm_store_discarded);
    }
    else
    {
        if(cpy_sts == 0)
        {

            /* if discovery board has used, checksum cal function will not
             * directly read data from QSPI flash so memcpy is required to
             * read back content from qspi to sdram
             */
#ifdef COREBOARD
            cal_checksum = calc_checksum_memory(
                    (uint8_t*)adcs_memcpy_inf.des_addrs,adcs_memcpy_inf.size);
#else
            os_memcpy_extmem((uint8_t*)adcs_memcpy_inf.src_addrs,\
                    (uint8_t*)adcs_memcpy_inf.des_addrs, adcs_memcpy_inf.size,\
                    NULL, 1,1);
            cal_checksum = calc_checksum_memory(
                    (uint8_t*)adcs_memcpy_inf.src_addrs,adcs_memcpy_inf.size);
#endif
            if(cal_checksum == adcs_memcpy_inf.checksum)
            {
                nor_info_nvm_data.file_size_stored = adcs_memcpy_inf.size;
                nor_info_nvm_data.file_checksum = adcs_memcpy_inf.checksum;
                nor_info_nvm_data.file_stored_sts = 1;
                /* store in NVM */
                /*nvm_parameter_write(NVM_DATA,NVM_MAGIC_NUM,\
                        (uint8_t*)&nvm_wr_magic_num);
                nvm_parameter_write(NVM_DATA,NVM_VERSION,\
                        (uint8_t*)&nvm_wr_vrsn);*/
                nvm_parameter_write(NVM_DATA,NVM_ADCS_FTM_FILE_CONTXT_DATA,\
                        (uint8_t*)&nor_info_nvm_data);
                //              sct_data_avail = 1;
                //nvm_commit();
                DEBUG_CPRINT(("[FTM savecontxt] NOR flash CRC pass\n"));
                log_id(LOG_INFO_L1,LOG_ADCS,FTM_saveontext_NOR_flash_CRC_PASS);
                /*
                 * GS notify is required ?
                 */
            }
            else
            {
                DEBUG_CPRINT(("[FTM savecontxt] NOR flash CRC FAIL\n"));
                log_id(LOG_ERROR,LOG_ADCS,FTM_saveontext_NOR_flash_CRC_FAIL);

            }
        }
        else
        {
            DEBUG_CPRINT(("[FTM savecontxt] NOR MEMCPY copy  - Fail\n"));
            log_id(LOG_ERROR,LOG_ADCS,FTM_saveontext_NOR_memcpy_FAIL);
        }
    }
}


/**
 * @brief This function used to calculate CRC by applying CRC32 algorithm
 */
uint32 ftm_crc32(uint32 Crc, uint32 Data)
{
  uint8 index;

  Crc = Crc ^ Data;

  for(index=0; index<32; index++)
  {
    if (Crc & 0x80000000)
      Crc = (Crc << 1) ^ 0x04C11DB7; // Polynomial used in STM32
    else
      Crc = (Crc << 1);
  }
  return(Crc);
}


/**
 * @brief This function used to calculate integrity and
 * return the calculated CRC
 */
uint32 ftm_calc_checksum(uint8 *data_buf,uint32 length)
{
    uint32 read_buffer = 0xffffffff;
    uint32 calc_CRC;
    uint32 buf_inc;

    // checking if the file exist or not
    if (data_buf == NULL)
    {
                DEBUG_CPRINT(("INTG | Buffer ptr Null  !\n"));
                log_id(LOG_ERROR, LOG_ADCS, INTG_Buffer_ptr_Null);
        return 0;
    }
    buf_inc = 0;
    calc_CRC = 0xFFFFFFFF;
    while (length > 3)
    {
        memcpy(&read_buffer,&data_buf[buf_inc],4);
        calc_CRC = ftm_crc32(calc_CRC, read_buffer);
        length -= 4;
        buf_inc +=4;
    }

    return calc_CRC;
}

/*
 * This function will be invoked by memcopy module once firmware fully
 * moved from SDRAM to permanent storage memory NOR flash
 */
static void adcs_sdram_nor_cpy_completed(uint8 sts, \
        memcpy_info_save *s_adcs_ftm_handle)
{
    uint32 cal_checksum;
    uint8 adcs_fw_status = 0;
    uint16 adcs_fw_crc;

    if(sts == 0)
    {
        /*
         * fw_flash copy from SDRAM to flash has completed calculate CRC for
         * flash memory
         */
#ifdef COREBOARD
        cal_checksum = ftm_calc_checksum((uint8*)s_adcs_ftm_handle->des_addrs,\
                s_adcs_ftm_handle->size);
#else
        cal_checksum = ftm_calc_checksum((uint8*)s_adcs_ftm_handle->src_addrs,\
                s_adcs_ftm_handle->size);
#endif

        // Verify CRC are same and update firmware available status
        if(cal_checksum == s_adcs_ftm_handle->checksum)
        {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
            DEBUG_CPRINT(("ADCS FW copied in NOR at Address:0x%X of"
                        " Size %lukb\n",\
                        s_adcs_ftm_handle->des_addrs,s_adcs_ftm_handle->size));
            log_id_with_two_arg(LOG_INFO_L1, LOG_ADCS,\
                    ADCS_FW_copied_in_NOR_at_Address_0x_hex_of_Size_u32_kb,\
                s_adcs_ftm_handle->des_addrs,s_adcs_ftm_handle->size);
#pragma GCC diagnostic pop

            adcs_fw_status = ADCS_FW_AVAILABLE;

            adcs_fw_crc = adcs_crc_calc((uint8*)s_adcs_ftm_handle->src_addrs,\
                    s_adcs_ftm_handle->size);

            nvm_parameter_write(NVM_DATA, NVM_ADCS_FW_SIZE,\
                    (uint8 *)&s_adcs_ftm_handle->size);
            nvm_parameter_write(NVM_DATA, NVM_ADCS_FW_CRC,\
                    (uint8 *)&adcs_fw_crc);
            nvm_parameter_write(NVM_DATA, NVM_ADCS_FW_STATUS,\
                    (uint8 *)&adcs_fw_status);

        }
        else
        {
            DEBUG_CPRINT(("ADCS FW copied at NOR Fail\n"));
            log_id(LOG_ERROR, LOG_ADCS, ADCS_FW_copied_at_NOR_Fail);
            nvm_parameter_write(NVM_DATA, NVM_ADCS_FW_STATUS,\
                    (uint8 *)&adcs_fw_status);
        }
    }
    else
    {
        DEBUG_CPRINT(("ADCS FW copied at memcpy Fail\n"));
        log_id(LOG_ERROR, LOG_ADCS, ADCS_FW_copied_at_memcpy_Fail);
        nvm_parameter_write(NVM_DATA, NVM_ADCS_FW_STATUS,\
                (uint8 *)&adcs_fw_status);
    }
}
#endif

/*
 * @brief Application API which will be invoked during file transmission by
 * FT framework it handles all FTM related notification published by
 * FTM module
 */
void adcs_ft_receiver_notificataion_clbk(ft_notification_info *ft_sts)
{

    /*
     * THis callback service function should not wait for long time
     */
    uint16 u16cnt;
    uint8 ret_sts;
    UNUSED(ret_sts);
#ifndef LINUX_TEMP_PORT
    e_avtive_type node_act_type;
    static uint8_t nack_test = 1;
    uint8_t *a_savecontext_ptr;
    memcpy_info_save s_adcs_ftm_handle;
#endif
    DEBUG_CPRINT((" FTM for ADCS module >> notification API invoked !!!!\n"));
    log_id(LOG_INFO_L1,LOG_ADCS,FTM_for_ADCS_module_notification_API_invoked);

    if(ft_sts->status == transfer_download_success)
    {
        DEBUG_CPRINT(("1. download success\n"));
        log_id(LOG_INFO_L1,LOG_ADCS,download_success);

        if(ft_sts->dwld_info.tx_mode == 1)
        {

        }
        else
        {
            DEBUG_CPRINT(("2. Transfer mode : FILE\n"));
            log_id(LOG_INFO_L1,LOG_ADCS,Transfer_mode_FILE);
            DEBUG_CPRINT(("3. File name : "));
            for (u16cnt = 0; u16cnt < \
            ft_sts->dwld_info.path_filename_buf_length; u16cnt++)
            {
                DEBUG_CPRINT(("%c",\
                    ft_sts->dwld_info.storage_path_and_File_name[u16cnt]));
                log_id_with_one_arg(LOG_INFO_L1,LOG_ADCS,File_name__s8_,\
                        ft_sts->dwld_info.storage_path_and_File_name[u16cnt]);
            }
#ifndef LINUX_TEMP_PORT
            DEBUG_CPRINT(("\n4. File size : %ldkb",\
                                ft_sts->dwld_info.size_file_or_data));
            log_id_with_one_arg(LOG_INFO_L1,LOG_ADCS,\
                    File_size__u32__cm__NOR_copy_initiated,\
                    ft_sts->dwld_info.size_file_or_data);
            DEBUG_CPRINT(("\nNOR copy initiated !!!\n"));

            /* copy downloaded firmware to external nor flash */
            s_adcs_ftm_handle.src_addrs = \
                    (uint32)ft_sts->dwld_info.bulkdata_ptr;
            s_adcs_ftm_handle.size = ft_sts->dwld_info.size_file_or_data;
            s_adcs_ftm_handle.checksum = ft_sts->dwld_info.checksum;
            s_adcs_ftm_handle.des_addrs = (uint32)adcs_get_nor_flash_address();
            ret_sts = os_memcpy_extmem((uint8*)s_adcs_ftm_handle.des_addrs,\
                    (uint8*)s_adcs_ftm_handle.src_addrs, \
                    s_adcs_ftm_handle.size, NULL, 1, 1);
            adcs_sdram_nor_cpy_completed(ret_sts, &s_adcs_ftm_handle);
#endif
        }
    }
    else if(ft_sts->status == crc_error)
    {
        DEBUG_CPRINT(("1. download failed/ CRC error\n"));
        log_id(LOG_ERROR,LOG_ADCS,download_failed__cm__CRC_error);
    }
    else if(ft_sts->status == transfer_suspended)
    {
        DEBUG_CPRINT(("1. download suspended by sender [Timeout mode]\n"));
        log_id(LOG_INFO_L1,LOG_ADCS,download_suspended_by_sender_Timeout_mode);
    }

    else if(ft_sts->status == transfer_suspended_savecontext ||
            ft_sts->status == transfer_suspended_auto_savecontext ||
            ft_sts->status == transfer_suspend_savecontext_accepeted ||
            ft_sts->status == transfer_suspended_savecontext_etended_sts)
    {
#ifndef LINUX_TEMP_PORT
        if(ft_sts->status != transfer_suspended_savecontext_etended_sts)
        {
            if(ft_sts->status == transfer_suspended_savecontext)
            {
                DEBUG_CPRINT(("1. download suspended by sender\
                            [Save Context Mode]\n"));
                log_id(LOG_INFO_L1,LOG_ADCS,\
                        dwnld_suspended_by_sender_save_context_mode);
            }
            else if(ft_sts->status == transfer_suspended_auto_savecontext)
            {
                DEBUG_CPRINT(("1. Auto [Save Context Mode] activated\n"));
                log_id(LOG_INFO_L1,LOG_ADCS,Auto_Save_Context_Mode_activated);
            }
            else if(ft_sts->status == transfer_suspend_savecontext_accepeted)
            {
                DEBUG_CPRINT(("1. Manual [Save Context Mode] activated\n"));
                log_id(LOG_INFO_L1,LOG_ADCS,\
                        Manual_Save_Context_Mode_activated);
            }
            else
            {

            }

            DEBUG_CPRINT(("2. malloc req: %d \n",\
                        ft_sts->context_info.context_info_size));
            log_id_with_one_arg(LOG_INFO_L1,LOG_ADCS,Malloc_req__u16_,\
                    ft_sts->context_info.context_info_size);
            //a_savecontext_ptr = os_malloc(
            //ft_sts->context_info.context_info_size);
            a_savecontext_ptr = os_malloc(200);
            if(a_savecontext_ptr != NULL)
            {
                memset(a_savecontext_ptr,0,200);
                DEBUG_CPRINT(("2. context data size: %d\n",\
                            ft_sts->context_info.context_info_size));
                log_id_with_one_arg(LOG_INFO_L1,LOG_ADCS,\
                        context_data_size__u16_,\
                        ft_sts->context_info.context_info_size);
                DEBUG_CPRINT(("3. context data : "));
                for (u16cnt = 0;
                    u16cnt < ft_sts->context_info.context_info_size; u16cnt++)
                {
                    a_savecontext_ptr[u16cnt] =
                        ft_sts->context_info.context_info_buf_ptr[u16cnt];
                    //DEBUG_CPRINT(("%x ",a_savecontext_ptr[u16cnt]));
                }
                /* send ack */

                display_context_info();

                node_act_type = ft_get_master_slave_status();
                if(node_act_type == sus_res_slave)
                {
                    if(ft_sts->status == transfer_suspended_savecontext)
                    {
                        if(nack_test != 0)
                        {
                            ft_transfer_request(Suspend_Savecontext_ack_rqst,\
                                    0);
                            //file_tx_running = 0;
                        }
                        else
                        {
                            ft_transfer_request(Suspend_Savecontext_nack_rqst,\
                                    0);
                            nack_test = 1;
                        }
                    }
                    else
                    {
                        // do nothing
                        // skip response frame if auto suspend is actiavted
                    }
                    /* store FTM structure/global variables in NVM */

                    /* TODO */
                    nvm_parameter_write(NVM_DATA,NVM_ADCS_FTM_CONTXT_DATA,\
                            a_savecontext_ptr);
                    os_free(a_savecontext_ptr);
                    a_savecontext_ptr = NULL;
                    /*initiate NOR copy to save file which is stored in SDRAM*/
                    adcs_memcpy_inf.src_addrs =
                        ft_sts->context_info.bulkdata_mem_addr & 0xffffffff;
                    adcs_memcpy_inf.des_addrs =
                        (uint32_t)adcs_get_nor_flash_address();
                    adcs_memcpy_inf.size = ft_sts->context_info.bulkdata_len;
                    adcs_memcpy_inf.checksum =
                        ft_sts->context_info.bulkdata_checksum;
                    ftm_nor_write_avail = 1;
                }
            }
        }
        else
        {
            DEBUG_CPRINT(("FTM - SCT 100%% completed <<<\n"));
            log_id(LOG_INFO_L1,LOG_ADCS,FTM_SCT_100_per_completed);
            if(ft_sts->status == transfer_suspended_savecontext_etended_sts)
            {
                if(ftm_nor_write_avail == 1)
                {
                    DEBUG_CPRINT(("NOR copy initiated\n"));
                    log_id(LOG_INFO_L1,LOG_ADCS,NOR_copy_initiated);
                    ret_sts = os_memcpy_extmem(\
                            (uint8_t*)adcs_memcpy_inf.des_addrs,\
                            (uint8_t*)adcs_memcpy_inf.src_addrs, \
                            adcs_memcpy_inf.size, NULL, 1,1);
                    adcs_ftm_savecontext_nor_copy_compld_cblk(ret_sts);
                    ftm_nor_write_avail = 0;
                }
                else
                {
                    DEBUG_CPRINT(("NOR copy not initiated.\n"));
                    log_id(LOG_WARNING,LOG_ADCS,NOR_copy_not_initiated);
                }
            }
            else
            {
                DEBUG_CPRINT(("0. Invalid case ??? \n"));
                log_id(LOG_ERROR,LOG_ADCS,Invalid_case);
            }
        }
#endif
    }

    else if(ft_sts->status == transfer_resumed)
    {
        DEBUG_CPRINT(("1. downloading resumed by sender\n"));
        log_id(LOG_INFO_L1,LOG_ADCS,dwnld_resumed_by_sender);
    }
    else if(ft_sts->status == transfer_resume_accepted)
    {
        DEBUG_CPRINT(("1. downloading resumed back by sender\n"));
        log_id(LOG_INFO_L1,LOG_ADCS,dwnld_resumed_back_by_sender);
    }
    else if(ft_sts->status == tx_terminated_suspend_timeout_expired)
    {
        DEBUG_CPRINT(("1.dwnld Terminated due to suspend timeout expired\n"));
        log_id(LOG_INFO_L1,LOG_ADCS,\
                dwnld_terminated_due_to_suspend_timeout_expired);
    }
    else if(ft_sts->status == transfer_suspend_accepted)
    {
        DEBUG_CPRINT(("1.dwnld Suspend - Timeout mode Accepted by Sender\n"));
        log_id(LOG_INFO_L1,LOG_ADCS,\
                dwnld_suspend_timeout_mode_accepted_by_sender);

    }
    else if(ft_sts->status == transfer_suspend_savecontext_accepeted)
    {

    }
    else if(ft_sts->status == transfer_resumed_restorecontext)
    {
#ifndef LINUX_TEMP_PORT
        ftm_nor_write_avail = 0;
        DEBUG_CPRINT(("1. Download Resume Savecontext mode Requested"
                    " by Sender\n"));
        log_id(LOG_INFO_L1,LOG_ADCS,\
                Dwnld_Resume_Savecontext_mode_Req_by_Sender);


        DEBUG_CPRINT(("\r\nResume-SaveContext mode [Bulkdata] selected \r\n"));
        log_id(LOG_INFO_L1,LOG_ADCS,Resume_Savecontext_mode_Bulkdata_selected);

        /*
         * Read FTM context info in NVM
         *
         */
        a_savecontext_ptr = os_malloc(200);
        if(a_savecontext_ptr != NULL)
        {
            nvm_parameter_read(NVM_DATA,NVM_ADCS_FTM_CONTXT_DATA,\
                    a_savecontext_ptr);
            ft_contextsave_info *c_inf =
                (ft_contextsave_info*)a_savecontext_ptr;
            //          if(c_inf->tx_mode == 1)
            {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
                DEBUG_CPRINT(("Mem address passing 0x%lux of size %lu \n",\
                            c_inf->bulkdata_mem_addr,c_inf->bulkdata_len));
                log_id_with_two_arg(LOG_INFO_L1,LOG_ADCS,\
                        Mem_addr_passing_0x_u32_x_of_size__u32_,\
                        c_inf->bulkdata_mem_addr,c_inf->bulkdata_len);
#pragma GCC diagnostic pop
                ft_config_receiver_node_storage_address(
                        c_inf->bulkdata_mem_addr&0xffffffff);
            }



            ret_sts = ft_resume_context(a_savecontext_ptr,\
                    c_inf->context_info_size);
            if(ret_sts == 0)
            {
                /* resume context success */
                nor_savecontxt_info *nor_info_nvm_data =\
                (nor_savecontxt_info*) os_malloc(sizeof(nor_savecontxt_info));
                os_memset(a_savecontext_ptr,0,200);
                os_memset(&nor_info_nvm_data,0,sizeof(nor_info_nvm_data));
                nvm_parameter_write(NVM_DATA,NVM_ADCS_FTM_CONTXT_DATA,\
                        a_savecontext_ptr);
                nvm_parameter_write(NVM_DATA,NVM_ADCS_FTM_FILE_CONTXT_DATA,\
                        (uint8_t*)&nor_info_nvm_data);
                //sct_data_avail = 0;
                os_free(a_savecontext_ptr);
                a_savecontext_ptr = NULL;
                os_free(nor_info_nvm_data);
                nor_info_nvm_data = NULL;
            }
            else
            {
                /* resume fail */
                if(ret_sts == 0x04)
                {
                    /*
                     * error code : 0x04 >> SDRAM copy is not valid ,
                     *     so need to prepare SDRAM with NOR flash content file
                     * data before that it need to confirm that is NOR location
                     * has really having file data
                     */
                    ret_sts = adcs_ftmSaveConext_read_file_from_nor(
                            (ft_contextsave_info*)a_savecontext_ptr);
                    if(ret_sts == 1)
                    {
                        /* NOR flash is having file data , so memcpy
                         * can be done from NOR to SDARM */
                    }
                    else
                    {

                    }


                }
                DEBUG_CPRINT(("Resume-SaveContext Error %d\n",ret_sts));
                log_id_with_one_arg(LOG_ERROR,LOG_ADCS,\
                        Resume_SaveContext_Error__u8_,ret_sts);
            }
        }
#endif
    }
    else if(ft_sts->status == transfer_download_ready)
    {
        DEBUG_CPRINT(("1. Download request received for EPS \n"));
        log_id(LOG_INFO_L1,LOG_ADCS,Dwnld_req_recv_for_EPS);
        if(ft_sts->dwld_info.tx_mode == 1)
        {
            DEBUG_CPRINT(("2. Transfer mode : DATA\n"));
            log_id(LOG_INFO_L1,LOG_ADCS,Transfer_mode_DATA);
        }
        else
        {
            DEBUG_CPRINT(("2. Transfer mode : FILE\n"));
            log_id(LOG_INFO_L1,LOG_ADCS,Transfer_mode_FILE);
#ifndef LINUX_TEMP_PORT
            DEBUG_CPRINT(("3. File size: %ld\n",\
                        ft_sts->dwld_info.size_file_or_data));
            log_id_with_one_arg(LOG_INFO_L1,LOG_ADCS,File_size__u32_,\
                    ft_sts->dwld_info.size_file_or_data);

			if((ft_sts->dwld_info.size_file_or_data) < (ADCS_FIRMWARE_STORAGE_MEM))
			{

				ft_config_receiver_node_storage_address(
                    (uint32)adcs_get_sdram_storage_address());

			}
			else
			{
				// dont allocate memory if requested size is not in range, so FTM will discard download request

			}
#endif
        }
    }
    else if(ft_sts->status == transfer_resume_savecontext_accepeted)
    {
        DEBUG_CPRINT(("1.dwnld Resume-Savecontext mode Accepted by Sender\n"));
        log_id(LOG_INFO_L1,LOG_ADCS,\
                dwnld_Resume_Savecontext_mode_Accepted_by_Sender);
    }
    else if(ft_sts->status == transmission_terminated_by_rx_node)
    {
        DEBUG_CPRINT(("1. download Terminated by Receiver node\n"));
        log_id(LOG_INFO_L1,LOG_ADCS,dwnld_Terminated_by_Recv_node);
    }
    else if(ft_sts->status == transfer_suspend_tout_not_accepted)
    {
        DEBUG_CPRINT(("1. suspend timeout request not completed\n"));
        log_id(LOG_ERROR,LOG_ADCS,suspend_timeout_req_not_completed);
    }
    else if(ft_sts->status == transfer_suspend_savecontext_failed)
    {
        DEBUG_CPRINT(("1. suspend savecontxt request not completed\n"));
        log_id(LOG_ERROR,LOG_ADCS,suspend_savecontext_req_not_completed);
    }
    else if(ft_sts->status == transfer_rseume_tout_not_accepted)
    {
        DEBUG_CPRINT(("1. resume timeout request not completed\n"));
        log_id(LOG_ERROR,LOG_ADCS,resume_timeout_req_not_completed);
    }
    else if(ft_sts->status == transfer_resume_restorecontext_failed)
    {
        DEBUG_CPRINT(("1. resume savecontxt request not completed\n"));
        log_id(LOG_ERROR,LOG_ADCS,resume_savecontext_req_not_completed);
    }
    else
    {
        DEBUG_CPRINT(("Invalid Notification not processed\n"));
        log_id(LOG_ERROR,LOG_ADCS,Invalid_Notification_not_processed);
    }

    DEBUG_CPRINT(("\n-------------/End/---------------\n\n"));
    log_id(LOG_INFO_L1,LOG_ADCS,END);

}

/*
 * @brief This API register FTM service for ADCS
 */
void adcs_fw_init(void)
{
    ft_register_receiver_app(TC_DST_FTM_OBC_ADCS,
            adcs_ft_receiver_notificataion_clbk);
    DEBUG_CPRINT(("ADCS FTM REGISTRATION"));
    log_id(LOG_INFO_L1,LOG_ADCS,ADCS_FTM_REGISTRATION);
}
