/******************************************************************************/
/**
 * @file otsu_tctm_man.c
 *
 * @brief This file contains functions that provides demonstration of
 *        usage of telecommand/ telemetry encoding and decoding APIs
 *
 * The functions provided in the file provides demonstration on
 * usage of telecommand/ telemetry encoding and decoding APIs
 *
 * @copyright Copyright 2023 Antaris, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/******************************************************************************/




/******************************************************************************/
/*                      Include headers of the module                      */
/******************************************************************************/


#include "otsu_tctm_man.h"
#include "otsu_tctm_msg_def.h"
#include "version.h"
#include "message_frame_def.h"
#include "otsu.h"
#include "otsu_mem_def.h"
#include "otsu_tctm_msg_def.h"
#include "obc_main.h"
#include "obc_tc_tm.h"
#include "otsu_shutdown.h"
#include "nvm.h"
#include "logger.h"
#include "file_transfer.h"
#include "exo_tctm_ipc.h"
#include "btable_prepare.h"
#include "otsu_ftm.h"

/******************************************************************************/
/*                  Definition of local macros                 				  */
/******************************************************************************/


#define REBOOT_SHTDWN_WAIT_TIME_DEFAULT (uint16_t)20  // in milliseconds
#define FW_UPDATE_BY_GS_CTRL 0
#define FW_UPDATE_BY_AUTONOMOUS 1
#define OTSU_SCHEDULE_FUNC_TIMER_IN_SEC (30*1000)

/******************************************************************************/
/*                       Definition of local variables                        */
/******************************************************************************/


static s_string_info otfs_response;
static uint64_t otsu_schedule_boot_epoch_time;
static os_timer_handle_ptr  otsu_schedule_boot_time;


/******************************************************************************/
/*                     Definition of global varaibles                         */
/******************************************************************************/

s_otsu_fw_update_cfg_tc_encode_def fw_reboot_config;


/******************************************************************************/
/*                      Definition of exported variables                      */
/******************************************************************************/
extern uint8_t comms_gs_sunc_confirm_sts_otsu;
extern s_fw_flash_handle s_flash_hdle;
extern uint8_t otsu_sct_data_avail;
extern e_otsu_err_flag otsu_fw_error_flag;
extern firmware_upd_info_def fw_upd_info;
extern uint8_t comms_gscontact_confirm_status_flag;

/******************************************************************************/
/*                  Declaration of local function prototypes                  */
/******************************************************************************/
static void otsu_schedule_timeout_expired_call_back(void* args);




/**
 * @brief This function used to process the different integration test command
 * received from GS
 *
 * @param[in]  cmd : test command type
 *
 * @return none
 * @retval void : none
 */
static void otsu_integ_test_cmd_trigger(e_otsu_integ_test cmd);


/******************************************************************************/
/*                       Definition of local functions                        */
/******************************************************************************/


static void scheduled_boot_timer_expired(void)
{
    otsu_send_message_to_otsu_fsm(OTSU_SCHBOOT_TIMEOUT_BYOTSU, 0);
}



/**
 * @brief This function used to process the firmware update configuration
 * params, it will trigger firmware update options like scheduled boot and boot now
 *
 */
static void otsu_schedule_timeout_expired_call_back(void* args)
{
	/*
	 * 1. read current rtc in epoch time format
	 * 2. compare current rtc epoch with otsu schduled boot epoch time
	 * 3. if rtc epoch time elapsed otsu schduled time, trigger software update procces
	 */
	uint64_t rtc_epoch_time;

	rtc_epoch_time = get_rtc_tm_epoch();
	if(rtc_epoch_time >= otsu_schedule_boot_epoch_time)
	{
		scheduled_boot_timer_expired();
	}
	else
	{
		// do nothing
	}
}



/**
 * @brief This function used to process the different integration test command
 * received from GS
 *
 */
static void otsu_integ_test_cmd_trigger(e_otsu_integ_test cmd)
{
	switch(cmd)
	{
		case e_fw_val_pass:
			DEBUG_CPRINT(("Integ test cmd rcvd: e_fw_val_pass set\n"));
			log_id(LOG_INFO_L1,LOG_OTSU,INTEG_TEST_CMD_RCVD__E_FW_VAL_PASS_SET);
			otsu_new_fw_validation_status_update(new_fw_validate_pass);
			otsu_send_message_to_otsu_fsm(OTSU_GS_SYNC_RCV, new_fw_validate_pass);
		break;

		case e_fw_val_fail:
			DEBUG_CPRINT(("Integ test cmd rcvd: e_fw_val_fail set\n"));
			log_id(LOG_ERROR,LOG_OTSU,INTEG_TEST_CMD_RCVD__E_FW_VAL_FAIL_SET);
			otsu_new_fw_validation_status_update(new_fw_validate_fail);
			otsu_send_message_to_otsu_fsm(OTSU_GS_SYNC_RCV, new_fw_validate_fail);
		break;

		case e_fallback_1_fail:
			DEBUG_CPRINT(("Integ test cmd rcvd: e_fallback_1_fail set\n"));
			log_id(LOG_ERROR,LOG_OTSU,INTEG_TEST_CMD_RCVD__E_FALLBACK1_FAIL_SET);
			otsu_state_change(e_otsu_integ_test_fallback_corrupt);
			otsu_send_message_to_otsu_fsm(OTSU_FALLBACK_CORRUPT_TEST, e_fallback_1_fail);
		break;

		case e_fallback_2_fail:
			DEBUG_CPRINT(("Integ test cmd rcvd: e_fallback_2_fail set\n"));
			log_id(LOG_ERROR,LOG_OTSU,INTEG_TEST_CMD_RCVD__E_FALLBACK2_FAIL_SET);
			otsu_state_change(e_otsu_integ_test_fallback_corrupt);
			otsu_send_message_to_otsu_fsm(OTSU_FALLBACK_CORRUPT_TEST, e_fallback_2_fail);
		break;

		case e_fallback_3_fail:
			DEBUG_CPRINT(("Integ test cmd rcvd: e_fallback_3_fail set\n"));
			log_id(LOG_ERROR,LOG_OTSU,INTEG_TEST_CMD_RCVD__E_FALLBACK3_FAIL_SET);
			otsu_state_change(e_otsu_integ_test_fallback_corrupt);
			otsu_send_message_to_otsu_fsm(OTSU_FALLBACK_CORRUPT_TEST, e_fallback_3_fail);
		break;

		case e_fallback_4_fail:
			DEBUG_CPRINT(("Integ test cmd rcvd: e_fallback_4_fail set\n"));
			log_id(LOG_ERROR,LOG_OTSU,INTEG_TEST_CMD_RCVD__E_FALLBACK4_FAIL_SET);
			otsu_state_change(e_otsu_integ_test_fallback_corrupt);
			otsu_send_message_to_otsu_fsm(OTSU_FALLBACK_CORRUPT_TEST, e_fallback_4_fail);
		break;

		case e_sband_failure_on:
		case e_sband_failure_off:
			if(e_sband_failure_on == cmd)
			{
				ft_sband_manual_failure(1);
				DEBUG_CPRINT(("Integ test cmd rcvd: e_sband_failure_on set\n"));
			}
			else if(e_sband_failure_off == cmd)
			{
				ft_sband_manual_failure(0);
				DEBUG_CPRINT(("Integ test cmd rcvd: e_sband_failure_off set\n"));
			}
			else
			{

			}
			break;

		case e_ftds_ack_enable:
		case e_ftds_ack_disable:
			if(e_ftds_ack_enable == cmd)
			{
				ft_ftds_ack_enable_set(1);
				DEBUG_CPRINT(("Integ test cmd rcvd: e_ftds_ack_enable set\n"));
			}
			else if(e_ftds_ack_disable == cmd)
			{
				ft_ftds_ack_enable_set(0);
				DEBUG_CPRINT(("Integ test cmd rcvd: e_ftds_ack_disable set\n"));
			}
			else
			{

			}
		break;

		default:
			break;
	}
}




uint64_t calculate_eppoc_time_otsu(s_time_set_def *_utc_time,s_date_set_def *_utc_date)
{
	struct tm tm_time_date;
	uint64_t epoch_time;

	tm_time_date.tm_year = _utc_date->year - 1900;
	tm_time_date.tm_mon  = _utc_date->month -   1;
	tm_time_date.tm_mday = _utc_date->day;
	tm_time_date.tm_hour = _utc_time->hours;
	tm_time_date.tm_min  = _utc_time->min     ;
	tm_time_date.tm_sec  = _utc_time->sec    ;
	tm_time_date.tm_isdst = 0;
	epoch_time = mktime(&tm_time_date);
    // TODO:: need to check mktime return for failure case
	return epoch_time;
}



/******************************************************************************/
/*                      Definition of global functions                        */
/******************************************************************************/




void configure_reboot_schedule(tm_resp_enable_option gs_send)

//void configure_reboot_schedule(uint8_t gs_send)

{
	uint32_t *locptr1, *locptr2;
	uint32_t read_addr;
	uint8_t ret_sts;

	/* Reboot has postponed */
	if(fw_reboot_config.boot_operation_ctrl == BOOT_CONTROL_SCHEDULED)
	{
		/* UTC time available */
		locptr1 = (uint32_t*)&fw_reboot_config.schboot_utc_time;
		locptr2 = (uint32_t*)&fw_reboot_config.schboot_utc_date;

		if((*locptr1 != 0) && (*locptr2 != 0))
		{
			otsu_state_change(e_otsu_postponed_rtc_config);

			/*
			 * calculate epoch time for scheduled boot time
			 *
			 */
			log_id(LOG_INFO_L1,LOG_OTSU,BOOT_SCHEDULED);
			otsu_schedule_boot_epoch_time = calculate_eppoc_time_otsu(&fw_reboot_config.schboot_utc_time, &fw_reboot_config.schboot_utc_date);
			/* RUN timer TODO */
			 os_timer_create(&otsu_schedule_boot_time,"otsu_schedule_boot_tmr",PERIODIC,otsu_schedule_timeout_expired_call_back,NULL);
			 os_delay(100);
			 os_timer_start(otsu_schedule_boot_time,(os_tick_time_t)OTSU_SCHEDULE_FUNC_TIMER_IN_SEC);
			 if(gs_send == TM_RES_REQ)
			 {
				otsu_encode_tm(TM_OTSU_SEND_FW_UPDATE_BOOT_CFG, otfs_boot_scheduled, 0);
			 }
		}
		else
		{
			/* UTC time NOT available */
			/* TBD */   // read current RTC and
			log_id(LOG_INFO_L1,LOG_OTSU,BOOT_SCHEDULE_REJECTED_TIME_INVALID);
			otsu_state_change(e_otsu_postponed_boot);
			if(gs_send == TM_RES_REQ)
			{
				otsu_encode_tm(TM_OTSU_SEND_FW_UPDATE_BOOT_CFG, otfs_utc_time_invalid,s_flash_hdle.sw_version_bin);
			}
		}
	}
	else if(fw_reboot_config.boot_operation_ctrl == BOOT_CONTROL_NOW)
	{
		/* Immediate boot is initiated */
		read_addr = otsu_get_fw_storage_address();
		ret_sts = fimrware_integrity_check(read_addr, fw_reboot_config.sft_version);
		if(ret_sts == BOOT_CONTROL_FAIL_VERSION_MISMATCH)
		{
			DEBUG_CPRINT(("Software version mismatch in C and input version\n"));
			log_id(LOG_ERROR,LOG_OTSU,FW_UPDATE_CANCELED_cm_SOFTWARE_VERSION_MISSMATCHED);
			fw_reboot_config.boot_operation_ctrl = BOOT_CONTROL_FAIL_VERSION_MISMATCH;
			// TODO:: add logger
			if(gs_send == TM_RES_REQ)
			{
				otsu_encode_tm(TM_OTSU_SEND_FW_UPDATE_BOOT_CFG, otfs_sft_version_mismatch, 0x00);
			}
			otsu_state_change(e_otsu_boot_canceled_sw_version_mismatch);

		}
		else if(ret_sts == BOOT_CONTROL_FAIL_DWNLD_FW_CORRUPTD)
	    {
			DEBUG_CPRINT(("Firmware Integrity fail\n"));
			log_id(LOG_ERROR,LOG_OTSU,FIRMWARE_INTEGRITY_FAIL);
			// TODO:: add logger
			fw_reboot_config.boot_operation_ctrl = BOOT_CONTROL_FAIL_DWNLD_FW_CORRUPTD;
			if(gs_send == TM_RES_REQ)
			{
				otsu_encode_tm(TM_OTSU_SEND_FW_UPDATE_BOOT_CFG, otfs_downaloded_fw_integrity_fail, 0x00);
			}
			otsu_state_change(e_otsu_boot_canceled_dwld_sw_integrity_fail);
	    }
		else if(ret_sts == BOOT_CONTROL_NVM_FW_INTEGRITY_FAIL)
	    {
			DEBUG_CPRINT(("Firmware nvm Integrity fail\n"));
			log_id(LOG_ERROR,LOG_OTSU,FIRMWARE_INTEGRITY_FAIL);
			// TODO:: add logger
			fw_reboot_config.boot_operation_ctrl = BOOT_CONTROL_NVM_FW_INTEGRITY_FAIL;
			if(gs_send == TM_RES_REQ)
			{
				otsu_encode_tm(TM_OTSU_SEND_FW_UPDATE_BOOT_CFG, otfs_nvm_fw_integrity_fail, 0x00);
			}
			otsu_state_change(e_otsu_boot_canceled_nvm_intgrity_fail);
	    }

		else
		{
			if(gs_send == TM_RES_REQ)
			{
				otsu_encode_tm(TM_OTSU_SEND_FW_UPDATE_BOOT_CFG, otfs_boot_immediate, 0);
			}
			otsu_state_change(e_otsu_waitfor_obc_shutdown);
			fw_upd_info.tc_soft_reset_rqst = 0;
		}

	}
	else if(fw_reboot_config.boot_operation_ctrl == BOOT_CONTROL_POSTPONED)
	{
		/* GS control has requested */
		otsu_state_change(e_otsu_postponed_boot);
		log_id(LOG_INFO_L1,LOG_OTSU,BOOT_POSTPONED);
		/* report GS */
		if(gs_send == TM_RES_REQ)
		{
			otsu_encode_tm(TM_OTSU_SEND_FW_UPDATE_BOOT_CFG, otfs_boot_postponed, 0);
		}
	}
	else if(fw_reboot_config.boot_operation_ctrl == BOOT_CONTROL_FW_DWNLD)
	{
		/* report GS */
		if(gs_send == TM_RES_REQ)
		{
			otsu_encode_tm(TM_OTSU_SEND_FW_UPDATE_BOOT_CFG, otfs_ready_for_boot, 0);
		}

	}
}



/**
 * @brief This function used to decode the OTSU telecommand message
 * This telecommand used to set firmware update configuration params.
 * Also it used to read software version and firmware update configuration params
 */
/**
 * @brief This function used to encode the OTSU telecommand message
 * This telecommand used to encode software version and firmware update configuration params
 *
 */
void otsu_decode_tc (uint16_t tc_id, uint8_t *tc_data, uint8_t tc_len)
{
	e_otsu_tc_msg_id tc_msg;
	s_firmware_update_config_parms_def *fw_reboot_config_ptr;
	
	s_otsu_tc_integ_test_def *integ_test;
	uint16_t option;
	uint32_t gs_wait_time_in_min;
    uint32_t calc_checksum;

	tc_msg = tc_data[0] & 0x0F;
	switch(tc_id)
	{
		case TC_OTSU_GET_VERSION :
			option = tc_data[0];
			otsu_encode_tm(TM_OTSU_GET_VERSION, 0, option);
//			otsu_state_change(e_otsu_read_version);
			break;

		case TC_OTSU_CURRENT_STATUS :
			otsu_encode_tm(TM_OTSU_CURRENT_STATUS, 0, 0);
			break;


		case TC_OTSU_SEND_FW_UPDATE_BOOT_CFG :
			fw_reboot_config_ptr = (s_firmware_update_config_parms_def*)tc_data;
			fw_reboot_config.boot_operation_ctrl = fw_reboot_config_ptr->boot_type;
			fw_reboot_config.shutdwn_process_timeout = fw_reboot_config_ptr->shutdwn_timeout;
			fw_reboot_config.schboot_utc_time.hours = fw_reboot_config_ptr->utc_time_to_schboot.hours;
			fw_reboot_config.schboot_utc_time.min = fw_reboot_config_ptr->utc_time_to_schboot.min;
			fw_reboot_config.schboot_utc_time.sec = fw_reboot_config_ptr->utc_time_to_schboot.sec;
			fw_reboot_config.schboot_utc_date.day = fw_reboot_config_ptr->utc_date_to_schboot.day;
			fw_reboot_config.schboot_utc_date.month = fw_reboot_config_ptr->utc_date_to_schboot.month;
			fw_reboot_config.schboot_utc_date.year = fw_reboot_config_ptr->utc_date_to_schboot.year;

			fw_reboot_config.gs_cont_utc_time.hours = 0;
			fw_reboot_config.gs_cont_utc_time.min = 0;
			fw_reboot_config.gs_cont_utc_time.sec = 0;
			fw_reboot_config.gs_cont_utc_date.day = 0;
			fw_reboot_config.gs_cont_utc_date.month = 0;
			fw_reboot_config.gs_cont_utc_date.year = 0;
			fw_reboot_config.sft_version = fw_reboot_config_ptr->sft_ver;
			fw_reboot_config.gs_cont_failure_timeout = fw_reboot_config_ptr->gs_contact_wait_time;
			fw_reboot_config.gs_cont_fail_time_checksum = (fw_reboot_config_ptr->gs_contact_wait_time & 0xff) ^ ((fw_reboot_config_ptr->gs_contact_wait_time >> 8) & 0xff);
			shtdwn_time_config(fw_reboot_config.shutdwn_process_timeout);
			{
				// TODO :: check integrity of Location C, if fail send status to GS

				/* OTSU has been waiting for GS command to resume boot */
				configure_reboot_schedule(TM_RES_REQ);
				/* store boot congif param in NVM */
				nvm_parameter_write(NVM_DATA,NVM_OTSU_REBOOT_CONFIG,(uint8_t*)&fw_reboot_config);

				gs_wait_time_in_min = fw_reboot_config.gs_cont_failure_timeout;
				calc_checksum = gs_wait_time_in_min & 0xFF;
				calc_checksum ^= (gs_wait_time_in_min >> 8) & 0xFF;
				calc_checksum ^= (gs_wait_time_in_min >> 16) & 0xFF;
				gs_wait_time_in_min = gs_wait_time_in_min | (calc_checksum << 24);
				nvm_parameter_write(NVM_DATA,NVM_OTSU_GSCONT_FAIL_TIMEOUT,(uint8_t*)&gs_wait_time_in_min);
			}
			break;


		case TC_OTSU_INTEGERATION_TEST_CMD :
			integ_test = (s_otsu_tc_integ_test_def*)tc_data;
			otsu_integ_test_cmd_trigger((e_otsu_integ_test)integ_test->integ_test_cmd);
			otsu_encode_tm(TM_OTSU_CURRENT_STATUS, 0, 0);
			break;

		case TC_OTSU_GET_FW_UPDATE_STS :
			otsu_encode_tm(TC_OTSU_GET_FW_UPDATE_STS,0, 0);
			break;
		case TC_OTSU_GET_BOOT_CFG_INFO :
			otsu_encode_tm(TM_OTSU_GET_BOOT_CFG_INFO,0, 0);
			break;

		case TC_OTSU_READ_GSCONATCT_WAIT_TIME :
			otsu_encode_tm(TM_OTSU_READ_GSCONATCT_WAIT_TIME,0, 0);
			break;

		case TC_OTSU_SET_GSCONATCT_WAIT_TIME :
			gs_wait_time_in_min = *((uint32_t*)&tc_data[0]);
			calc_checksum = gs_wait_time_in_min & 0xFF;
			calc_checksum ^= (gs_wait_time_in_min >> 8) & 0xFF;
			calc_checksum ^= (gs_wait_time_in_min >> 16) & 0xFF;
			gs_wait_time_in_min = gs_wait_time_in_min | (calc_checksum << 24);
			nvm_parameter_write(NVM_DATA,NVM_OTSU_GSCONT_FAIL_TIMEOUT,(uint8_t*)&gs_wait_time_in_min);
			otsu_encode_tm(TM_OTSU_SET_GSCONATCT_WAIT_TIME,0, 0);
			break;

		case TC_OTSU_READ_BOOTABLE_BLT1 :
			otsu_encode_tm(TM_OTSU_READ_BOOTABLE_BLT1,0, 0);
			break;

		case TC_OTSU_READ_BOOTABLE_BLT2 :
			otsu_encode_tm(TM_OTSU_READ_BOOTABLE_BLT2,0, 0);
			break;

		case TC_OTSU_GET_NVM_FW_VERSION :
			option = tc_data[0];
			otsu_encode_tm(TM_OTSU_GET_NVM_FW_VERSION,0, option);

		default:
			log_id_with_one_arg(LOG_ERROR,LOG_OTSU,INVALID_TC_RCVED_u8_,tc_msg);
			break;
	}
}



void otsu_encode_tm(uint16_t tm_id, uint8_t response, uint16_t option)
{
	//otsu_firmware_sts *fw_sts;

	uint8_t tm_set=0;
	uint32_t frmwr_address=0;
	s_string_info bt_conf;
	s_firmware_update_config_parms_def *fw_config_params;
	uint16_t sw_ver = 0xffff;
	nvm_firmware_info_def nvm_info;

	{
		switch(tm_id)
		{
			case TM_OTSU_GET_VERSION:
				otfs_response.size = 3;
				otfs_response.str_ptr = os_malloc_eram(otfs_response.size);
				DEBUG_CPRINT(("Software version read for loc = %d\n", sw_ver));
				log_id_with_one_arg(LOG_INFO_L1,LOG_OTSU,SOFTWARE_VERSION_READ_FOR_LOC_eq__u16_,sw_ver);

				switch(option)
				{
				case 1:
					frmwr_address = get_fw_execution_address();
					break;
				case 2:
					frmwr_address = get_previous_fwstored_address();
					break;
				case 3:
					frmwr_address = otsu_get_fw_storage_address();
					break;
				case 4:
					frmwr_address = get_factory_fwstored_address();
					break;

				default:
					frmwr_address = otsu_get_fw_storage_address();
					break;
				}
				otfs_response.str_ptr[0] = prepare_boottable_setup_for_module(frmwr_address,INTG_TEST, SET_CLEAR_UNDEF);
				sw_ver = getVersion_downloaded_bin(frmwr_address);
				otfs_response.str_ptr[1] = sw_ver & 0xff;
				otfs_response.str_ptr[2] = (sw_ver >> 8) & 0xff;
				tm_set = 1;
				break;


			case TM_OTSU_CURRENT_STATUS:
				otfs_response.size = 2;
				otfs_response.str_ptr = os_malloc_eram(otfs_response.size);
				tm_set = 1;
				otfs_response.str_ptr[0] = get_otsu_state();
				otfs_response.str_ptr[1] = comms_gscontact_confirm_status_flag;
				break;

			case TM_OTSU_SET_GSCONATCT_WAIT_TIME:
				otfs_response.size = 1;
				otfs_response.str_ptr = os_malloc_eram(otfs_response.size);
				tm_set = 1;
				otfs_response.str_ptr[0] = 1;
				break;


			case TM_OTSU_GET_BOOT_CFG_INFO:
				otfs_response.str_ptr = os_malloc_eram(sizeof(s_firmware_update_config_parms_def));
				tm_set = 1;
				bt_conf.str_ptr= (uint8_t*)(otfs_response.str_ptr);
				if(bt_conf.str_ptr != NULL)
				{
					fw_config_params = (s_firmware_update_config_parms_def*)bt_conf.str_ptr;
					fw_config_params->boot_type = fw_reboot_config.boot_operation_ctrl;
					fw_config_params->sft_ver = fw_reboot_config.sft_version;
					fw_config_params->shutdwn_timeout = fw_reboot_config.shutdwn_process_timeout;

					fw_config_params->utc_time_to_schboot.hours = fw_reboot_config.schboot_utc_time.hours;
					fw_config_params->utc_time_to_schboot.min = fw_reboot_config.schboot_utc_time.min;
					fw_config_params->utc_time_to_schboot.sec = fw_reboot_config.schboot_utc_time.sec;
					fw_config_params->utc_date_to_schboot.day = fw_reboot_config.schboot_utc_date.day;
					fw_config_params->utc_date_to_schboot.month = fw_reboot_config.schboot_utc_date.month;
					fw_config_params->utc_date_to_schboot.year = fw_reboot_config.schboot_utc_date.year;

					fw_config_params->gs_contact_wait_time = fw_reboot_config.gs_cont_failure_timeout;

					otfs_response.size = sizeof(otsu_firmware_sts) + sizeof(s_firmware_update_config_parms_def);
				}
				else
				{
					DEBUG_CPRINT(("OTSU TC : malloc error"));
				}
				break;

			case TM_OTSU_GET_FW_UPDATE_STS:
				otfs_response.size = 3;
				otfs_response.str_ptr = os_malloc_eram(otfs_response.size);
				otfs_response.str_ptr[0] = otsu_sct_data_avail;
				otfs_response.str_ptr[1] = fw_upd_info.nw_frmw_avail_sts;
				otfs_response.str_ptr[2] = fw_upd_info.new_fw_loaded;
				tm_set = 1;
				break;


			case TM_OTSU_SEND_FW_UPDATE_BOOT_CFG:
				switch(response)
				{
				case otfs_nvm_fw_integrity_fail:
				case otfs_downaloded_fw_integrity_fail:
				case otfs_boot_postponed:
				case otfs_boot_scheduled:
				case otfs_boot_immediate:
				case otfs_sft_version_mismatch:
				case otfs_boot_initiated:
				case otfs_utc_time_invalid:
					otfs_response.size = 1;
					otfs_response.str_ptr = os_malloc_eram(otfs_response.size);
					otfs_response.str_ptr[0] = response;
					tm_set = 1;
					break;

				default:
					break;
				}

				break;

			case TM_OTSU_READ_GSCONATCT_WAIT_TIME:
				otfs_response.size = 4;
				otfs_response.str_ptr = os_malloc_eram(otfs_response.size);
			    nvm_parameter_read(NVM_DATA,NVM_OTSU_GSCONT_FAIL_TIMEOUT,(uint8_t*)&frmwr_address);
				memcpy(otfs_response.str_ptr, &frmwr_address, 4);
				tm_set = 1;
				break;

			case TM_OTSU_READ_BOOTABLE_BLT1:
				otfs_response.size = 1;
				otfs_response.size += otsu_get_btable_size();
				otfs_response.str_ptr = os_malloc_eram(otfs_response.size);
				otfs_response.str_ptr[0] = otsu_get_btable_size();
				otsu_copy_btable_data(0, &otfs_response.str_ptr[1]);
				tm_set = 1;
				break;

			case TM_OTSU_READ_BOOTABLE_BLT2:
				otfs_response.size = 1;
				otfs_response.size += otsu_get_btable_size();
				otfs_response.str_ptr = os_malloc_eram(otfs_response.size);
				otfs_response.str_ptr[0] = otsu_get_btable_size();
				otsu_copy_btable_data(1, &otfs_response.str_ptr[1]);
				tm_set = 1;
				break;


			case TM_OTSU_GET_NVM_FW_VERSION:
				otfs_response.size = 3;
				otfs_response.str_ptr = os_malloc_eram(otfs_response.size);
				DEBUG_CPRINT(("NVM Software version read for loc = %d\n", sw_ver));
				log_id_with_one_arg(LOG_INFO_L1,LOG_OTSU,SOFTWARE_VERSION_READ_FOR_LOC_eq__u16_,sw_ver);

				switch(option)
				{
				case 1:
					frmwr_address = (uint32_t)nvm_get_nvm_fwupd_memory_partition_address(NVM_STORAGE_BANK1);
					break;

				case 2:
					frmwr_address = (uint32_t)nvm_get_nvm_fwupd_memory_partition_address(NVM_STORAGE_BANK2);
					break;

				case 3:
					frmwr_address = (uint32_t)nvm_get_nvm_fwupd_memory_partition_address(NVM_FW_UPDATE_LOC_A);
					break;
				case 4:
					frmwr_address = (uint32_t)nvm_get_nvm_fwupd_memory_partition_address(NVM_FW_UPDATE_LOC_B);
					break;
				case 5:
					frmwr_address = (uint32_t)nvm_get_nvm_fwupd_memory_partition_address(NVM_FW_UPDATE_LOC_C);
					break;
				case 6:
					frmwr_address = (uint32_t)nvm_get_nvm_fwupd_memory_partition_address(NVM_FW_UPDATE_LOC_D);
					//nvm_fw_update(NVM_FW_UPDATE_TRIGGER);
					send_ftm_dwld_msg();
					break;

				case 7:
					frmwr_address = (uint32_t)nvm_get_nvm_fwupd_memory_partition_address(NVM_STORAGE_RAM);
					break;


				default:
					frmwr_address = (uint32_t)nvm_get_nvm_fwupd_memory_partition_address(NVM_FW_UPDATE_LOC_A);
					break;
				}
				otfs_response.str_ptr[0] = nvm_get_nvm_bin_info((uint8_t*)frmwr_address, &nvm_info);
				otfs_response.str_ptr[1] = nvm_info.version_number_major;
				otfs_response.str_ptr[2] = nvm_info.version_number_minor;
				tm_set = 1;
				break;


			case TM_OTSU_NOTIFICATION:
				switch(response)
				{
				case otfs_flash_copy_fail:
				case otfs_ready_for_boot:
				case otfs_ack:
				case otfs_nack:
				case otfs_boot_pass:
				case otfs_boot_fail:
					otfs_response.size = 1;
					otfs_response.str_ptr = os_malloc_eram(1);
					otfs_response.str_ptr[0] = response;
					tm_set = 1;
					break;

				case otfs_sft_ver_exists:
					otfs_response.size = 3;
					otfs_response.str_ptr = os_malloc_eram(3);
					otfs_response.str_ptr[0] = response;
					memcpy(otfs_response.str_ptr+4, &option, 2);
					tm_set = 1;
					break;

				}

				case otfs_response_max:
					break;

				default:
					break;
			break;
		}

		if(tm_set ==1)
		{
			otsu_payload_transmitter_to_obc(tm_id, otfs_response.str_ptr, otfs_response.size);
		}

		os_free(otfs_response.str_ptr);
		otfs_response.str_ptr = NULL;
	}

}




void otsu_stop_schduled_boot_timer(void)
{
	os_timer_stop(otsu_schedule_boot_time);
}
