/*
 * =====================================================================================
 *
 *       Filename:  qseeAppMain.c
 *
 *    Description:  Entry point of QSEE trustzone app.
 *
 *        Version:  1.0
 *        Created:  04/26/2017 05:19:18 PM
 *       Compiler:  armcc
 *
 *         Author:  Dongwook Shim (), dw.shim@samsung.com
 *        Company:  Samsung Electronics
 *
 *        Copyright (c) 2017 by Samsung Electronics, All rights reserved. 
 *
 * =====================================================================================
 */

#include "qsee_core.h"

#include "commonConfig.h"
#include "cryptoEngine.h"
#include "log.h"
#include "secMemoryManager.h"
#include "teeCmdExecuter.h"
#include "version.h"
#include "qseeSecureState.h"

#ifndef DISABLE_LOG_ENCRYPTION
#include "logEncryptor.h"
#endif  // End of DISABLE_LOG_ENCRYPTION

char TZ_APP_NAME[] = "skm";

void tz_app_init(void)
{
	VERSIONIZE(TRUSTLET_TAG);
}

void tz_app_shutdown(void)
{
	LOGD("Unloading %s trustlet...", TRUSTLET_TAG);
}

void tz_app_cmd_handler(void *req, uint32_t reqLen, void *rsp, uint32_t rspLen)
{
	int32_t ret;
	CmdReq_t reqBuf;
	CmdRsp_t rspBuf;

	if(req == NULL || rsp == NULL)
	{
		LOGE("Buffer is invalid.");
		return;
	}

	if(qsee_is_ns_range(req, reqLen) || qsee_is_ns_range(rsp, rspLen))
	{
		LOGE("Buffer is located at non-secure memory.");
		((CmdPtrRsp_t *)rsp)->status = ERR_TA_NOT_SECURE;
		return;
	}

	if(!checkBspSecureState())
	{
		((CmdPtrRsp_t *)rsp)->status = ERR_SECURE_BOOT_DISABLED;
		return;
	}

	// Allocator initialize.
	if((ret = secMemoryManagerInit()) != NOT_ERROR)
	{
		((CmdPtrRsp_t *)rsp)->status = ret;
		return;
	}

	// crypto engine init
	CRYPTO_init();
	
	memset(&reqBuf, 0, sizeof(reqBuf));
	memset(&rspBuf, 0, sizeof(rspBuf));

	memcpy(&reqBuf, req, (reqLen < sizeof(reqBuf)) ? reqLen : sizeof(reqBuf));
	rspBuf.dataLen = sizeof(rspBuf.data);

	LOGE("Received Cmd = 0x%x with %d bytes in request buffer.", reqBuf.cmdId, reqLen);

	if((rspBuf.status = taCmdExecute(reqBuf.cmdId, reqBuf.data, reqBuf.dataLen, rspBuf.data, &(rspBuf.dataLen))) != NOT_ERROR)
	{
		LOGE("Invoke Command data caused error! Ret = %d", rspBuf.status);
#ifndef DISABLE_LOG_ENCRYPTION
		if((ret = logEncrypt(rspBuf.data, sizeof(rspBuf.data))) > 0) {
			rspBuf.dataLen = (uint32_t)ret;
        } else
		{
			LOGE("Failed to log encryption with error %d.", ret);
			rspBuf.dataLen = 0;
		}
#else
		((CmdRsp_t *)rsp)->status = rspBuf.status;
		goto cleanup;
#endif  // End of DISABLE_LOG_ENCRYPTION
	}

	// Treat out buffer size equal to max shared buffer length.
	if(rspBuf.dataLen > sizeof(rspBuf.data))
	{
		LOGE("Wrapped data is too big (%d bytes)", rspBuf.dataLen);
		((CmdRsp_t *)rsp)->status = ERR_TA_BUFFER_OVERFLOW;
		goto cleanup;
	}

	//  Copy out data from temp static buffer to shared buffer.
	memcpy((char *)rsp, &rspBuf, (rspLen < sizeof(rspBuf)) ? rspLen : sizeof(rspBuf));

cleanup:
	LOGE("Respond from Cmd = 0x%x return %d in Cmd Buffer", reqBuf.cmdId, rspBuf.status);
	memset(&reqBuf, 0, sizeof(reqBuf));
	memset(&rspBuf, 0, sizeof(rspBuf));
}
