#include "em_common.h"

#if defined(EMAS) && !defined(EMLITE)
static int em_context_marchal_rsp_payload(uint8_t *rsp_buf, em_rsp_payload *rsp)
{
	int ret, i;
	uint32_t offset = 0;

	EM_CHECK_NULL(__func__, EM_ERR_EM_CONTEXT_MARCHAL_RSP_PAYLOAD, rsp_buf, rsp);

	em_set_data_to_raw((uint8_t *)&(rsp->ret), sizeof(uint32_t), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
	em_set_data_to_raw((uint8_t *)&(rsp->version), sizeof(uint8_t), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(uint8_t));

	/* Marchal Primary */
	em_set_data_to_raw((uint8_t *)&(rsp->primary.cmd), sizeof(uint32_t), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(uint32_t));


	for (i = 0; i < EM_LEN_PAYLOAD_FLAGS; i++) {
		em_set_data_to_raw((uint8_t *)&(rsp->primary.flags[i]), sizeof(uint64_t), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(uint64_t));
	}

	em_set_data_to_raw((uint8_t *)&(rsp->primary.keep), sizeof(em_keeping_item), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(em_keeping_item));

	for (i = 0; i < EM_LEN_GET_MODES_BIT_BUFFER; i++) {
		em_set_data_to_raw((uint8_t *)&(rsp->primary.mode_bits[i]), sizeof(uint64_t), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(uint64_t));
	}

	em_set_data_to_raw(rsp->primary.priority, sizeof(rsp->primary.priority), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(rsp->primary.priority));

	em_set_data_to_raw(rsp->primary.reserved, sizeof(rsp->primary.reserved), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(rsp->primary.reserved));
	/* END_Marchal Primary */

	/* Unmarchal Secondary */
	for (i = 0; i < EM_LEN_PAYLOAD_FLAGS; i++) {
		em_set_data_to_raw((uint8_t *)&(rsp->secondary.flags[i]), sizeof(uint64_t), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(uint64_t));
	}

	if (rsp->secondary.flags[1] & EM_FLAGS_1_EXIST_RETURN_ESI)
		em_set_data_to_raw(rsp->secondary.esi, EM_LEN_ESI, rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, EM_LEN_ESI);
	else
		offset += EM_LEN_ESI;

	if (rsp->secondary.flags[1] & EM_FLAGS_1_EXIST_RETURN_TOKEN)
		em_set_data_to_raw(rsp->secondary.token, EM_LEN_TOKEN, rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, EM_LEN_TOKEN);
	else
		offset += EM_LEN_TOKEN;

	em_set_data_to_raw((uint8_t *)&(rsp->secondary.type_message), sizeof(uint32_t), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(uint32_t));

	if (rsp->secondary.flags[1] & EM_FLAGS_1_EXIST_RETURN_MESSAGE) {
		em_set_data_to_raw((uint8_t *)&(rsp->secondary.len_message), sizeof(uint32_t), rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
		em_set_data_to_raw(rsp->secondary.message, EM_LEN_MESSAGE, rsp_buf, EM_STRUCT_RSP_PAYLOAD_SIZE, &offset, EM_LEN_MESSAGE);
	} else
		offset += (sizeof(uint32_t) + EM_LEN_MESSAGE);
	/* END_Unmarchal Secondary */

	ret = EM_SUCCESS;
out:
	return ret;
}

static int em_context_unmarchal_req_payload(uint8_t *req_buf, em_req_payload *req)
{
	int ret, i;
	uint32_t offset = 0;

	EM_CHECK_NULL(__func__, EM_ERR_EM_CONTEXT_UNMARCHAL_REQ_PAYLOAD, req_buf, req);

	req->version = req_buf[0];
	offset = sizeof(uint8_t);

	/* Unmarchal Primary */
	em_get_data_from_raw((uint8_t *)&(req->primary.cmd), sizeof(uint32_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint32_t));

	for (i = 0; i < EM_LEN_PAYLOAD_FLAGS; i++)
		em_get_data_from_raw((uint8_t *)&(req->primary.flags[i]), sizeof(uint64_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint64_t));

	em_get_data_from_raw(req->primary.did, EM_LEN_DID, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_DID);
	em_get_data_from_raw(req->primary.imei, EM_LEN_IMEI, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_IMEI);
	em_get_data_from_raw(req->primary.single_id, EM_LEN_SINGLE_ID, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_SINGLE_ID);
	em_get_data_from_raw(req->primary.model_name, EM_LEN_MODEL_NAME, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_MODEL_NAME);
	em_get_data_from_raw(req->primary.otp, EM_LEN_OTP, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_OTP);
	em_get_data_from_raw(req->primary.date, EM_LEN_DATE, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_DATE);
	em_get_data_from_raw(req->primary.client_proc_name, EM_LEN_CLIENT_PROC_NAME, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_CLIENT_PROC_NAME);
	em_get_data_from_raw(req->primary.client_pkg_name, EM_LEN_CLIENT_PKG_NAME, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_CLIENT_PKG_NAME);
	em_get_data_from_raw((uint8_t *)&(req->primary.client_uid), sizeof(uint32_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
	em_get_data_from_raw((uint8_t *)&(req->primary.client_signature), sizeof(uint32_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
	em_get_data_from_raw((uint8_t *)&(req->primary.cnt_mode), sizeof(uint16_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint16_t));

	for (i = 0; i < EM_LEN_MODE_BUFFER; i++)
		em_get_data_from_raw((uint8_t *)&(req->primary.modes[i]), sizeof(uint16_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint16_t));

	em_get_data_from_raw((uint8_t *)&(req->primary.cnt_validity), sizeof(uint32_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
	em_get_data_from_raw(req->primary.osversion, EM_LEN_OSVERSION, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_OSVERSION);
	em_get_data_from_raw(req->primary.swversion, EM_LEN_SWVERSION, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_SWVERSION);
	em_get_data_from_raw(req->primary.blversion, EM_LEN_BLVERSION, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_BLVERSION);
	em_get_data_from_raw((uint8_t *)&(req->primary.tss), sizeof(uint32_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
	em_get_data_from_raw((uint8_t *)&(req->primary.activated), sizeof(uint32_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
	em_get_data_from_raw(req->primary.serial, EM_LEN_UNIQUE, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_UNIQUE);
	em_get_data_from_raw(req->primary.smsn, EM_LEN_SMSN, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_SMSN);
	em_get_data_from_raw((uint8_t *)&(req->primary.keep), sizeof(em_keeping_item), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(em_keeping_item));
	em_get_data_from_raw((uint8_t *)&(req->primary.req_cnt), sizeof(uint32_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
	em_get_data_from_raw(req->primary.fuse, EM_LEN_FUSE, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_FUSE);
	em_get_data_from_raw(req->primary.openday, EM_LEN_OPENDAY, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_OPENDAY);
	em_get_data_from_raw(req->primary.iin, EM_LEN_IIN, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_IIN);
	em_get_data_from_raw(req->primary.priority, EM_LEN_PRIORITY_TIME, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_PRIORITY_TIME);
	em_get_data_from_raw(req->primary.omc_id, EM_LEN_OMC_ID, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_OMC_ID);
	em_get_data_from_raw(req->primary.reserved, sizeof(req->primary.reserved), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(req->primary.reserved));
	/* END_Unmarchal Primary */

	/* Unmarchal Secondary */

	for (i = 0; i < EM_LEN_PAYLOAD_FLAGS; i++)
		em_get_data_from_raw((uint8_t *)&(req->secondary.flags[i]), sizeof(uint64_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint64_t));

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_TOKEN)
		em_get_data_from_raw(req->secondary.token, EM_LEN_TOKEN, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_TOKEN);
	else
		offset += EM_LEN_TOKEN;

	if ((req->secondary.flags[0] & EM_FLAGS_0_EXIST_MESSAGE) || (req->secondary.flags[0] & EM_FLAGS_0_EXIST_RECOVERY_MESSAGE)) {
		em_get_data_from_raw((uint8_t *)&(req->secondary.len_message), sizeof(uint32_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
		em_get_data_from_raw(req->secondary.message, EM_LEN_MESSAGE, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_MESSAGE);
	} else
		offset += (sizeof(uint32_t) + EM_LEN_MESSAGE);

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_CERT) {
		em_get_data_from_raw((uint8_t *)&(req->secondary.len_cert), sizeof(uint32_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
		em_get_data_from_raw(req->secondary.cert, EM_LEN_CERTIFICATE, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_CERTIFICATE);
	} else
		offset += (sizeof(uint32_t) + EM_LEN_CERTIFICATE);

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_ESS_PREFIXBODY) {
		em_get_data_from_raw((uint8_t *)&(req->secondary.len_ess_prefixbody), sizeof(uint32_t), req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, sizeof(uint32_t));
		em_get_data_from_raw(req->secondary.ess_prefixbody, EM_LEN_ESS_PREFIX_BODY, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_ESS_PREFIX_BODY);
	} else
		offset += (sizeof(uint32_t) + EM_LEN_ESS_PREFIX_BODY);

	em_get_data_from_raw(req->secondary.ess_nonce, EM_LEN_NONCE, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_NONCE);

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_ESS_IV_B64)
		em_get_data_from_raw(req->secondary.ess_iv_b64, EM_LEN_ESS_IV_B64, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_ESS_IV_B64);
	else
		offset += EM_LEN_ESS_IV_B64;

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_ESI)
		em_get_data_from_raw(req->secondary.esi, EM_LEN_ESI, req_buf, EM_STRUCT_REQ_PAYLOAD_SIZE, &offset, EM_LEN_ESI);
	else
		offset += EM_LEN_ESI;

	/* END_Unmarchal Secondary */

	ret = EM_SUCCESS;
out:
	return ret;
}
#endif

static int em_context_set_manadatory_fields(em_req_payload *req, em_context *ctx)
{
	int ret, i;

	EM_CHECK_NULL(__func__, EM_ERR_EM_CONTEXT_SET_MAN_FIELD, req, ctx);

	ctx->cmd = req->primary.cmd;
	for (i = 0; i < EM_LEN_PAYLOAD_FLAGS; i++) {
		ctx->flags[i] = req->primary.flags[i];
	}
	memcpy(ctx->did, req->primary.did, EM_LEN_DID);
	memcpy(ctx->imei, req->primary.imei, EM_LEN_IMEI);
	memcpy(ctx->single_id, req->primary.single_id, EM_LEN_SINGLE_ID);
	memcpy(ctx->model_name, req->primary.model_name, EM_LEN_MODEL_NAME);
	memcpy(ctx->otp, req->primary.otp, EM_LEN_OTP);
	memcpy(ctx->date, req->primary.date, EM_LEN_DATE);
	memcpy(ctx->client_proc_name, req->primary.client_proc_name, EM_LEN_CLIENT_PROC_NAME);
	memcpy(ctx->client_pkg_name, req->primary.client_pkg_name, EM_LEN_CLIENT_PKG_NAME);
	ctx->client_uid = req->primary.client_uid;
	ctx->client_signature = req->primary.client_signature;
	ctx->cnt_mode = req->primary.cnt_mode;
	for (i = 0; i < EM_LEN_MODE_BUFFER; i++) {
		ctx->modes[i] = req->primary.modes[i];
	}
	ctx->cnt_validity = req->primary.cnt_validity;
	memcpy(ctx->osversion, req->primary.osversion, EM_LEN_OSVERSION);
	memcpy(ctx->swversion, req->primary.swversion, EM_LEN_SWVERSION);
	memcpy(ctx->blversion, req->primary.blversion, EM_LEN_BLVERSION);
	ctx->tss = req->primary.tss;
	ctx->activated = req->primary.activated;
	memcpy(ctx->serial, req->primary.serial, EM_LEN_UNIQUE);
	memcpy(ctx->smsn, req->primary.smsn, EM_LEN_SMSN);
	memcpy(ctx->fuse, req->primary.fuse, EM_LEN_FUSE);
	memcpy(ctx->openday, req->primary.openday, EM_LEN_OPENDAY);
	memcpy(ctx->omc_id, req->primary.omc_id, EM_LEN_OMC_ID);

	ret = EM_SUCCESS;
out:
	return ret;
}

int em_context_make_request(uint8_t *req_buf, em_context *ctx)
{
	int ret, i = 0;
	uint8_t req_payload_ver;
	em_req_payload *req = NULL;

	EM_CHECK_NULL(__func__, EM_ERR_EM_CONTEXT_MAKE_REQUEST, req_buf, ctx);

	req_payload_ver = req_buf[0];
	if (req_payload_ver != EM_PAYLOAD_VERSION) {
		LOGE("payload version isn't matched(%02x/%02x)\n", req_payload_ver, EM_PAYLOAD_VERSION);
		ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_VERSION;
		goto out;
	}

#if defined(EMAS) && !defined(EMLITE)
	req = (em_req_payload *)em_calloc(1, sizeof(em_req_payload));
	if (req == NULL) {
		LOGE("Failed to allocate req buf\n");
		ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_ALLOC_REQ;
		goto out;
	}

	ret = em_context_unmarchal_req_payload(req_buf, req);
	if (ret != EM_SUCCESS) {
		LOGE("Failed to unmarchal req payload(0x%08x)\n", ret);
		goto out;
	}
#else
	req = (em_req_payload *)req_buf;
#endif

	LOGW("EM C/C : %08x/%08x\n", req->primary.cmd, req->primary.req_cnt);

#ifndef EMLITE
	ret = em_check_provision();
	if (ret != EM_SUCCESS) {
		if (ret != (int)EM_ERR_EM_CHECK_PROVISION_NOT_PROVISION) {
			LOGE("Rpmb can't be used(0x%08x)\n", ret);
			goto out;
		}
		LOGI("RPMB isn't provisioned\n");
	} else {
		ctx->is_provision = 1;
	}
#endif

	ret = em_context_set_manadatory_fields(req, ctx);
	if (ret != EM_SUCCESS) {
		LOGE("Failed to set mandatory fields(0x%08x)\n", ret);
		goto out;
	}

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_TOKEN) {
		memcpy(ctx->token, req->secondary.token, EM_LEN_TOKEN);
	}

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_MESSAGE) {
		ctx->len_message = req->secondary.len_message;
		if (ctx->len_message > EM_LEN_MESSAGE || ctx->len_message <= 0) {
			LOGE("please check message length(%u)\n", ctx->len_message);
			ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_LEN_MESSAGE;
			goto out;
		}
		memcpy(ctx->message, req->secondary.message, ctx->len_message);
	}

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_RECOVERY_MESSAGE) {
		ctx->len_message = req->secondary.len_message;
		if (ctx->len_message > EM_LEN_RECOVERY_DATA || ctx->len_message <= 0) {
			LOGE("please check recovery message length(%u)\n", ctx->len_message);
			ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_LEN_RECOVERY_MESSAGE;
			goto out;
		}
		memcpy(ctx->recovery_data, req->secondary.message, ctx->len_message);
	}

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_CERT) {
		ctx->len_cert = req->secondary.len_cert;
		if (ctx->len_cert > EM_LEN_CERTIFICATE || ctx->len_cert <= 0) {
			LOGE("please check certificate length(%u)\n", ctx->len_cert);
			ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_LEN_CERT;
			goto out;
		}
		memcpy(ctx->cert, req->secondary.cert, ctx->len_cert);
	}

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_ESS_PREFIXBODY) {
		ctx->len_ess_prefixbody = req->secondary.len_ess_prefixbody;
		if (ctx->len_ess_prefixbody > EM_LEN_ESS_PREFIX_BODY || ctx->len_ess_prefixbody <= 0) {
			LOGE("please check ess prefixbody length(%u)\n", ctx->len_ess_prefixbody);
			ret = EM_ERR_EM_CONTEXT_MAKE_REQUEST_LEN_ESS_PREFIXBODY;
			goto out;
		}
		memcpy(ctx->ess_prefixbody, req->secondary.ess_prefixbody, ctx->len_ess_prefixbody);
	}

	if (req->primary.flags[0] & EM_FLAGS_0_EXIST_KEEPING_ITEM)
		memcpy(&ctx->keep, &req->primary.keep, sizeof(em_keeping_item));

	if (req->primary.flags[0] & EM_FLAGS_0_EXIST_IIN)
		memcpy(ctx->iin, req->primary.iin, EM_LEN_IIN);

	if (req->primary.flags[0] & EM_FLAGS_0_EXIST_PRIORITY_TIME)
		memcpy(ctx->priority, req->primary.priority, EM_LEN_PRIORITY_TIME);

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_ESI)
		memcpy(ctx->esi, req->secondary.esi, EM_LEN_ESI);

	if (req->secondary.flags[0] & EM_FLAGS_0_EXIST_ESS_IV_B64)
		memcpy(ctx->ess_iv_b64, req->secondary.ess_iv_b64, EM_LEN_ESS_IV_B64);

	for (i = 0; i < EM_LEN_PAYLOAD_FLAGS; i++)
		ctx->flags[i] = (ctx->flags[i] | req->primary.flags[i]) | req->secondary.flags[i];

	if (ctx->cmd == EM_CMD_ESS) {
		ret = em_ess_get_command_type(ctx);
		if (ret != EM_SUCCESS) {
			LOGE("Failed to get command type(0x%08x)\n", ret);
		} else {
			LOGI("Converted cmd type 0x%08x\n", ctx->cmd);
		}
	}

	ret = EM_SUCCESS;
out:
#if defined(EMAS) && !defined(EMLITE)
	if (req)
		em_free(req);
#else
	req = NULL;
#endif

	LOGW("\n");
	return ret;
}

int em_context_make_response(uint8_t *rsp_buf, em_context *ctx, uint32_t result)
{
	int ret;
	uint32_t offset = 0;
	uint8_t *raw_core_v20 = NULL;
	em_rsp_payload *rsp = NULL;
	(void)offset;

	EM_CHECK_NULL(__func__, EM_ERR_EM_CONTEXT_MAKE_RESPONSE, rsp_buf, ctx);

#if defined(EMAS) && !defined(EMLITE)
	rsp = (em_rsp_payload *)em_calloc(1, sizeof(em_rsp_payload));
	if (rsp == NULL) {
		LOGE("Failed to allocate rep buf\n");
		ret = EM_ERR_EM_CONTEXT_MAKE_RESPONSE_ALLOC_RSP;
		goto out;
	}
#else
	rsp = (em_rsp_payload *)rsp_buf;
#endif

	rsp->ret = result;
	rsp->version = EM_PAYLOAD_VERSION;

	if (ctx->cmd == EM_CMD_GET_TUC)
		rsp->ret = ctx->ret_temp;

	rsp->primary.cmd = ctx->cmd;

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_TOKEN) {
		rsp->secondary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_TOKEN;
		memcpy(rsp->secondary.token, ctx->token, EM_LEN_TOKEN);
	}

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_MESSAGE) {
		rsp->secondary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_MESSAGE;
		rsp->secondary.len_message = ctx->len_message;
		if (rsp->secondary.len_message > EM_LEN_MESSAGE || rsp->secondary.len_message <= 0) {
			LOGE("%s : please check message length(%u)\n", __func__, ctx->len_message);
			ret = EM_ERR_EM_CONTEXT_MAKE_RESPONSE_LEN_MESSAGE;
			goto out;
		}
		memcpy(rsp->secondary.message, ctx->message, ctx->len_message);
	}

#ifndef EMLITE
	if (!(ctx->flags[2] & EM_FLAGS_2_ENABLED_LSEC_TOKEN)) {
		if (ctx->flags[1] & EM_FLAGS_1_WRITE_CORE && result == EM_SUCCESS) {

			raw_core_v20 = (uint8_t *)em_calloc(1, EM_LEN_CORE_V20);
			if (raw_core_v20 == NULL) {
				LOGE("Failed to allocate raw core buf\n");
				ret = EM_ERR_EM_CONTEXT_MAKE_RESPONSE_ALLOC_CORE;
				goto out;
			}

			em_set_data_to_raw(ctx->core_v20.magic, EM_LEN_MAGIC_CORE_V20, raw_core_v20, EM_LEN_CORE_V20,
					   &offset, EM_LEN_MAGIC_CORE_V20);
			em_set_data_to_raw(ctx->core_v20.gcm_tag, EM_LEN_GCM_TAG_CORE_V20, raw_core_v20,
					   EM_LEN_CORE_V20, &offset, EM_LEN_GCM_TAG_CORE_V20);
			em_set_data_to_raw(ctx->core_v20.key, EM_LEN_KEY_CORE_V20, raw_core_v20, EM_LEN_CORE_V20,
					   &offset, EM_LEN_KEY_CORE_V20);
			em_set_data_to_raw((uint8_t *)&(ctx->core_v20.esi_ctr), (uint32_t)sizeof(uint32_t),
					   raw_core_v20, EM_LEN_CORE_V20, &offset, (uint32_t)sizeof(uint32_t));
			em_set_data_to_raw((uint8_t *)&(ctx->core_v20.flags), (uint32_t)sizeof(uint32_t), raw_core_v20,
					   EM_LEN_CORE_V20, &offset, (uint32_t)sizeof(uint32_t));
			em_set_data_to_raw((uint8_t *)&(ctx->core_v20.recovery_ctr), (uint32_t)sizeof(uint32_t),
					   raw_core_v20, EM_LEN_CORE_V20, &offset, (uint32_t)sizeof(uint32_t));
			em_set_data_to_raw(ctx->core_v20.iin, EM_LEN_IIN, raw_core_v20, EM_LEN_CORE_V20, &offset,
					   EM_LEN_IIN);
			em_set_data_to_raw((uint8_t *)&(ctx->core_v20.ta_rp), (uint32_t)sizeof(uint32_t), raw_core_v20,
					   EM_LEN_CORE_V20, &offset, (uint32_t)sizeof(uint32_t));

			ret = em_write_core(raw_core_v20, EM_LEN_CORE_V20);
			if (ret != EM_SUCCESS) {
				LOGE("Failed to write core(0x%08x)\n", ret);
				ret = EM_ERR_EM_CONTEXT_MAKE_RESPONSE_WRITE_CORE;
				goto out;
			}
		}

		if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_ESI && result == EM_SUCCESS) {
			rsp->secondary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_ESI;
			memcpy(rsp->secondary.esi, ctx->esi, EM_LEN_ESI);
		}
	}
#endif

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_KEEPING_ITEM) {
		rsp->primary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_KEEPING_ITEM;
		memcpy(&rsp->primary.keep, &ctx->keep, sizeof(em_keeping_item));
	}

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_MODES_BIT) {
		rsp->primary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_MODES_BIT;
		memcpy(rsp->primary.mode_bits, ctx->mode_bits, EM_LEN_GET_MODES_BIT_BUFFER * sizeof(uint64_t));
	}

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_PRIORITY_TIME) {
		rsp->primary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_PRIORITY_TIME;
		memcpy(rsp->primary.priority, ctx->priority, EM_LEN_PRIORITY_TIME);
	}

	if (ctx->flags[1] & EM_FLAGS_1_NEED_RECOVERY_ESI)
		rsp->primary.flags[1] |= EM_FLAGS_1_NEED_RECOVERY_ESI;

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_TOKEN_REMOVE)
		rsp->primary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_TOKEN_REMOVE;

	if (ctx->flags[1] & EM_FLAGS_1_DO_INIT_CORE)
		rsp->primary.flags[1] |= EM_FLAGS_1_DO_INIT_CORE;

	if (ctx->flags[1] & EM_FLAGS_1_EXIST_RETURN_TOKEN_EXPIRED)
		rsp->primary.flags[1] |= EM_FLAGS_1_EXIST_RETURN_TOKEN_EXPIRED;

	if (ctx->flags[1] & EM_FLAGS_1_LTS_INSTALL_TOKEN)
		rsp->primary.flags[1] |= EM_FLAGS_1_LTS_INSTALL_TOKEN;

	if (ctx->flags[1] & EM_FLAGS_1_LTS_REMOVE_TOKEN)
		rsp->primary.flags[1] |= EM_FLAGS_1_LTS_REMOVE_TOKEN;

#if defined(EMAS) && !defined(EMLITE)
	ret = em_context_marchal_rsp_payload(rsp_buf, rsp);
	if (ret != EM_SUCCESS) {
		LOGE("Failed to marchal rsp payload(0x%08x)\n", ret);
		goto out;
	}
#endif

	ret = EM_SUCCESS;
out:
	memset(&ctx->core_v20, 0, sizeof(em_core_v20));

	if (raw_core_v20) {
		memset(raw_core_v20, 0, EM_LEN_CORE_V20);
		em_free(raw_core_v20);
	}

	if (ctx->parsed_token) {
		em_free(ctx->parsed_token);
		ctx->parsed_token = NULL;
	}

#if defined(EMAS) && !defined(EMLITE)
	if (rsp)
		em_free(rsp);
#else
	rsp = NULL;
#endif

	LOGW("\n");
	return ret;
}
