/*
@file app_grdm.c
@brief Contains test code for most of the QSEE fuse APIs.

*/
/*===========================================================================
   Copyright (c) 2011 by Qualcomm Technologies, Incorporated.  All Rights Reserved.
===========================================================================*/

/*===========================================================================

                            EDIT HISTORY FOR FILE
  $Header:
  $DateTime:
  $Author: pwbldsvc $

# when       who     what, where, why
# 2019-03-15 sh4615.lee first implement

===========================================================================*/

#include <stdbool.h>
//#include "qsee_log.h"

#include <app_grdm.h>

#include <ese_api.h>
#include <grdm_bl.h>
#include <star_api.h>

#include <grdm_common.h>
#include <grdm_fw.h>
#include <grdm_internal.h>
#include <grdm_log.h>
#include <grdm_transport.h>

GRDM_RESULT grdm_FWupgrade_Header(uint8_t *fw_header, grdm_fw_info_t* fw_info)
{
	GRDM_RESULT grdm_ret = GRDM_NO_ERROR;
	uint8_t *data = NULL;
	uint32_t data_size = 0;

	GRDM_RESULT ret = GRDM_NO_ERROR;

	LOG_E("grdm_FWupgrade_Header :\n");
#if 1
	grdm_ret = grdm_openLogicalChannel();
	if (grdm_ret != GRDM_NO_ERROR) {
		LOG_E("grdm_openLogicalChannel failed : %d\n", grdm_ret);
		return grdm_ret;
	}
#endif
	data_size = GRDM_IMAGE_HEADER_SIZE;

	data = MALLOC(data_size);
	if (data == NULL) {
		LOG_E("grdm_FWupgrade_Header : failed to malloc\n");
		grdm_ret = GRDM_UNKNOWN_ERROR;
		goto exit;
	}

	memset((void *)data, 0, data_size);
	memcpy((void *)data, fw_header, data_size);

	grdm_ret = grdm_FW_checkImage(data, data_size, &fw_info->fw_start_addr, &fw_info->target_size);
	if (grdm_ret < 0) {
		LOG_E("grdm_FWupgrade_Start : failed to checkImage : %d(0x%x)\n", grdm_ret, grdm_ret);
		fw_info->fw_start_addr = 0x0;
		fw_info->target_size = 0x0;
		//if (grdm_ret == GRDM_FW_ALREADY_UPDATED)
		//	grdm_ret = GRDM_NO_ERROR;
	}

	LOG_E("grdm_FW_checkImage fw_start_addr : 0x%x, target_size : 0x%x\n", fw_info->fw_start_addr, fw_info->target_size);
	FREE(data);
exit:
#if 0
	ret = grdm_closeLogicalChannel();
	if (ret != GRDM_NO_ERROR) {
		LOG_E("grdm_closeLogicalChannel failed : %d\n", ret);
	}
#endif

	return grdm_ret;
}

GRDM_RESULT grdm_FWupgrade_Start(uint8_t *fw_data)
{
	GRDM_RESULT grdm_ret = GRDM_NO_ERROR;

	unsigned char *data = NULL;
	unsigned int data_size = 0;

	LOG_E("grdm_FWupgrade_Start :\n");
	data = MALLOC(GRDM_FW_START_DATA_SIZE);
	if (data == NULL) {
		LOG_E("grdm_FWupgrade_Start : failed to malloc\n");
		grdm_ret = GRDM_UNKNOWN_ERROR;
		goto exit;
	}

	data_size = GRDM_FW_START_DATA_SIZE;
	memset((void *)data, 0, GRDM_FW_START_DATA_SIZE);
	memcpy((void *)data, fw_data, data_size);

	grdm_ret = grdm_FW_startUpgrade(data, data_size);
	if (grdm_ret < 0) {
		LOG_E("grdm_FWupgrade_Start : failed to startUpgrade\n");
		FREE(data);
		goto exit;
	}
	FREE(data);

exit:
	return grdm_ret;
}


GRDM_RESULT grdm_FWupgrade_Data(uint8_t *fw_data, uint32_t *next_size)
{
	GRDM_RESULT grdm_ret = GRDM_NO_ERROR;

	unsigned char *data = NULL;
	unsigned int data_size = 0;
	unsigned int ret_size = 0;

//	LOG_E("grdm_FWupgrade_Data :\n");
	data = MALLOC(GRDM_SECTOR_SIZE);
	if (data == NULL) {
		LOG_E("grdm_FWupgrade_Data : failed to malloc\n");
		grdm_ret = GRDM_UNKNOWN_ERROR;
		goto exit;
	}
	memset((void *)data, 0, GRDM_SECTOR_SIZE);
	memcpy((void *)data, fw_data, GRDM_SECTOR_SIZE);

	data_size = GRDM_SECTOR_HEADER_SIZE;
	grdm_ret = grdm_FW_checkHeader(data, data_size, &data_size);
	if (grdm_ret < 0) {
		LOG_E("grdm_FWupgrade_Data : failed to checkHeader\n");
		FREE(data);
		goto exit;
	}
	//LOG_E("grdm_FW_checkHeader : data_size: 0x%x\n", data_size);
	*next_size = data_size;

	grdm_ret = grdm_FW_updateUpgrade(data, data_size);
	if (grdm_ret < 0) {
		LOG_E("grdm_FWupgrade_Start : failed to updateUpgrade \n");
		FREE(data);
		goto exit;
	}

	FREE(data);

exit:
	return grdm_ret;
}

GRDM_RESULT grdm_FWupgrade_Finish(uint8_t* fw_version)
{
	GRDM_RESULT grdm_ret = GRDM_NO_ERROR;
	unsigned char version[4];
	unsigned int version_len = 4;
	LOG_E("grdm_FWupgrade_Finish :\n");

	grdm_ret = grdm_FW_finishUpgrade(version, &version_len);
	if (grdm_ret < 0) {
		LOG_E("grdm_FWupgrade_Finish : failed to finishUpgrade \n");
		memset(fw_version, 0xff, 4);
	}
	else {
		memcpy(fw_version, version, 4);
	}

	grdm_ret = grdm_closeLogicalChannel();
	if (grdm_ret != GRDM_NO_ERROR) {
		LOG_E("grdm_closeLogicalChannel failed : %d\n", grdm_ret);
	}
	LOG_E("grdm_closeLogicalChannel : %d\n", grdm_ret);
	return grdm_ret;
}


GRDM_RESULT grdm_get_fw_version(grdm_fw_info_t* fw_info)
{
	GRDM_RESULT grdm_ret = GRDM_NO_ERROR;
	GRDM_RESULT ret = GRDM_NO_ERROR;
	uint8_t version[8] = {0x0,};
	uint32_t version_size = 8;
	uint8_t partition = 0x0;

	LOG_E("grdm_get_fw_version :\n");

	grdm_ret = grdm_openLogicalChannel();
	if (grdm_ret != GRDM_NO_ERROR) {
		LOG_E("grdm_openLogicalChannel failed : %d\n", grdm_ret);
		return grdm_ret;
	}
	grdm_ret = grdm_FW_readVersion(version, &version_size, &partition);
	if (grdm_ret < 0) {
		LOG_E("grdm_get_fw_version : failed to read Version\n");
		memset(fw_info->fw_version, 0xff, 8);
		fw_info->partition = 0xff;
		goto exit;
	}
	memcpy(fw_info->fw_version, version, 8);
	fw_info->partition =  partition;
exit:
	ret = grdm_closeLogicalChannel();
	if (ret != GRDM_NO_ERROR) {
		LOG_E("grdm_closeLogicalChannel failed : %d\n", ret);
	}

	return grdm_ret;
}
