/*
@file app_main.c
*/

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stringl.h>

#include "qsee_core.h"
#include "qsee_fs.h"
#include "qsee_log.h"
#include "qsee_heap.h"
#include "qsee_services.h"
#include "qsee_timer.h"
#include "tci.h"
#include "process_cmd.h"
#include "dualdar_init_tl.h"
#include "validate_cmd.h"
#include "utils.h"

#define TAG "TL_DUALDAR_MAIN"
#define ENABLE_QSEE_LOG_MSG_DEBUG 1

char TZ_APP_NAME[] = {TRUSTED_APP_NAME};
static bool initialized = false;

/**
  @brief
    Add any app specific initialization code here
    QSEE will call this function after secure app is loaded and
    authenticated
 */

void tz_app_init(void)
{
#ifdef ENABLE_DUALDAR_LOG
	qsee_log_set_mask(QSEE_LOG_MSG_DEBUG | QSEE_LOG_MSG_ERROR);
#else
	qsee_log_set_mask(QSEE_LOG_MSG_ERROR);
#endif
	/*  App specific initialization code*/
	DUALDAR_LOG("%s: Init ", TAG);
	/* Call TA specific initialization function */

#ifdef TA_VERSION
    DUALDAR_LOG("TA VERSION is: %s", TA_VERSION);
#else
    DUALDAR_LOG("TA VERSION is UNKNOWN");
#endif
}

static void * g_cmd_buffer = NULL;
void tz_app_cmd_handler(void* cmd, uint32_t cmdlen, void* resp, uint32_t rsplen)
{
	uint32_t commandId = 0;

	uint32_t ret = TZ_DUALDAR_INIT_ERROR;

	// to avoid an attack: multiple NW clients talk to the same TA
	if (g_cmd_buffer == NULL) {
		g_cmd_buffer = cmd;
	} else if (g_cmd_buffer != cmd) {
		DUALDAR_ERROR("%s: cmd buffer= %p", TAG, g_cmd_buffer);
		goto error;
	}

	DUALDAR_LOG("%s: cmd buffer=%p", TAG, g_cmd_buffer);

	tciMessage_t *sendmsg = (tciMessage_t *) cmd;
	tciMessage_t *respmsg = (tciMessage_t *) resp;

    DUALDAR_LOG("sendmsg = %p", cmd);
    DUALDAR_LOG("sendmsg_len = %d", cmdlen);
    DUALDAR_LOG("respmsg = %p", resp);
    DUALDAR_LOG("respmsg_len = %d", rsplen);

	DUALDAR_LOG("tciMessage_t size? = %lu", sizeof(tciMessage_t));
	DUALDAR_LOG("sendmsg size? = %lu", sizeof(sendmsg));
	DUALDAR_LOG("respmsg size? = %lu", sizeof(respmsg));

	if (NULL == cmd || NULL == resp
			|| ((0xffff) == cmdlen && (0xffff) == rsplen)
			|| ((cmd < resp) && ((void *)((uint8_t *)cmd + cmdlen) > resp))
			|| ((resp < cmd) && ((void *)((uint8_t *)resp + rsplen) > cmd))) {
		DUALDAR_ERROR("%s: APP_MAIN: cmd or rsp buffer too small, exiting from TA - %d,%d,%lu", TAG, cmdlen, rsplen, sizeof(tciMessage_t));
		DUALDAR_ERROR("%s: APP_MAIN: or cmd overlap with resp - %p,%d,%p,%d", TAG, cmd, cmdlen, resp, rsplen);
		goto error;
	}

	commandId = sendmsg->dualdarhdr.header.id;
	DUALDAR_LOG("%s: Command id - %08X", TAG, commandId);

	if (!IS_CMD(commandId)) {
		DUALDAR_ERROR("%s: Invalid command id, exiting!", TAG);
		goto error;
	}

	// [SI-17526] Input validation Vulnerability for all CMDs
	if (validate_cmd(commandId, sendmsg, cmdlen, respmsg, rsplen) != DUALDAR_OK) {
		DUALDAR_ERROR("%s: validate cmd failed!", TAG);
		goto error;
	}

	ret = process_cmd(commandId, sendmsg, cmdlen, respmsg, rsplen);
	if (ret != DUALDAR_OK) {
		DUALDAR_ERROR("%s: process_cmd, failed!", TAG);
		goto error;
	}

	DUALDAR_LOG("%s: cmd done.", TAG);
	return;

error:
	DUALDAR_LOG("%s: cmd handle error!.", TAG);
	return;
}

/**
  @brief
    App specific shutdown
    App will be given a chance to shutdown gracefully
 */
void tz_app_shutdown(void)
{
	/* app specific shutdown code*/
	DUALDAR_LOG("%s: TZ DUALDAR_COMMON_ENTRY shutdown", TAG);
	initialized = 0;
	return;
}
