
/*
 * =====================================================================================
 *
 *       Filename:  app_main.c
 *
 *    Description:  TUI main
 *
 *        Version:  1.0
 *       Revision:  none
 *       Compiler:  gcc
 *
 *        Company:  Samsung Electronics
 *        Copyright (c) 2020 by Samsung Electronics, All rights reserved.
 *
 * =====================================================================================
 */

/** Inlcudes */
#include "process_cmd.h"
#include <comdef.h>
#include "qsee_log.h"
#include "tui_defs.h"
#include "tui_vendor.h"
#include "tci.h"
#include "SecureUI.h"
#include "SecureUILib.h"
#include "TZ_Vendor_tl.h"
#include "tui_vendor_impl.h"

#define MSG_ALIGN_SIZE	0x40
#define MSG_ALIGN_MASK	(MSG_ALIGN_SIZE - 1)
#define MSG_ALIGN(x)    ((x + MSG_ALIGN_SIZE) & (~MSG_ALIGN_MASK))

/** App Name */
char TZ_APP_NAME[] = {"mpostui"};

#if defined(SM8350)
#include "qsee_access_control.h"

#define TUI_TA_OFFSET            0x02000000
#define CMD_ID_TUI_START         ( 1 | TUI_TA_OFFSET)
#define CMD_ID_TUI_STOP          ( 2 | TUI_TA_OFFSET)

#define MAX_TEST_NAME 128
#define SECURE_UI_SERVICE               0x4000
#define TUI_SERVICE_2_0                 0x4001

struct __attribute__ ((__packed__)) send_cmd {
    uint32_t cmd_id;
    uint8_t useSecureIndicator;
    uint8_t cmd_data[MAX_TEST_NAME];
};

struct send_cmd_rsp{
  int32_t status;
};
#endif

/**
 * @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) {
	/* App specific initialization code */
	qsee_log_set_mask(QSEE_LOG_MSG_ERROR | QSEE_LOG_MSG_FATAL | QSEE_LOG_MSG_DEBUG);
	qsee_log(QSEE_LOG_MSG_DEBUG, "TZ_TUI Init");
}
static void * g_cmd_buffer = NULL;

// local copy of NW data
static uint8_t g_msg[MSG_ALIGN(sizeof(tciMessage_t))];

/**
 * @brief
 * App specific command handler
 * App executes code based on input command
 *
 * @param[in] cmd     - command
 * @param[in] cmdlen  - command length
 * @param[out] *rsp   - response
 * @param[out] rsplen - response length
 */
void tz_app_cmd_handler(void *cmd, uint32 cmdlen, void *rsp, uint32 rsplen) {
	tui_return_code_t ret = TUI_STATUS_SUCCESS;
	uint32_t commandId = 0;
	uint32_t retval = 0;
	tciMessage_t *sendmsg;
	tciMessage_t *respmsg;

	// 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) {
		return;
	}

	uint32_t g_msg_len = sizeof(g_msg);
	TUI_LOG_DEBUG("%s: cmd buffer=%p - len: %d", TAG, g_cmd_buffer, g_msg_len);
	TUI_LOG_DEBUG("%s: input(from nwd) len = %d", TAG, cmdlen);
	TUI_LOG_DEBUG("%s: tcibuffer(calcurated in ta) len = %d", TAG, g_msg_len);

	retval = secUiProcessCmd(cmd, cmdlen, rsp, rsplen);
	if (retval > 0) {
		return;
	}

#if defined(SM8350)
	// [fixme]don't know why input cmd len(from nwd) has extra 64byte
	// I guess extra header is attached in TUI HLOS20
	if (cmdlen > g_msg_len + 64) {
		TUI_LOG("%s Error: input buf size %d > max %d ", __func__,cmdlen, g_msg_len);
		return;
	}
#else
	if (cmdlen > g_msg_len) {
		TUI_LOG("%s Error: input buf size %d > max %d ", __func__,cmdlen, g_msg_len);
		return;
	}
#endif

	TZ_bzero(&g_msg, g_msg_len); 
	memcpy(&g_msg, cmd, cmdlen);

#if defined(SM8350)
	struct send_cmd *cmd_ptr = (struct send_cmd *)cmd;
	struct send_cmd_rsp *rsp_ptr = (struct send_cmd_rsp *)rsp;
	int32_t sec_ui_retval = 0;

	TUI_LOG("TUI_SERVICE_2_0");
	secure_ui_service = TUI_SERVICE_2_0;

	if (((unsigned long)cmd_ptr + cmdlen < (unsigned long)cmd_ptr) || ((unsigned long)rsp_ptr + rsplen < (unsigned long)rsp_ptr)){
		TUI_LOG("cmd_ptr/rsp_ptr overflow detected");
		return;
	}

	if ((cmdlen < sizeof(cmd_ptr->cmd_id)) || (rsplen < sizeof(*rsp_ptr)) ) {
		TUI_LOG("cmd handler received too short cmd/rsp buffers %d vs %d, %d vs %d",
			cmdlen, sizeof(cmd_ptr->cmd_id), rsplen,
			sizeof(*rsp_ptr));
		return;
	}

	TUI_LOG("[tui20] cmd_id = %08X", cmd_ptr->cmd_id);

	//secure_memset(rsp, 0, rsplen);
	//TZ_bzero(&rsp, rsplen);
	rsp_ptr->status = 0;

	if (cmd_ptr->cmd_id == CMD_ID_TUI_START) {
		rsp_ptr->status = 0;
		TUI_LOG("CMD_ID_TUI_START String : %s",(const char *)cmd_ptr->cmd_data);
		return;

	} else if (cmd_ptr->cmd_id == CMD_ID_TUI_STOP) {
		closeTuiSessionImpl();
		return;
	}

	TZ_bzero(&g_msg, g_msg_len);
	memcpy(&g_msg, cmd + 4, cmdlen - 4);
#endif

	sendmsg = (tciMessage_t *) g_msg;
	respmsg = (tciMessage_t *) rsp;

	if (NULL == cmd || NULL == rsp
	    || ((cmd < rsp) && ((void *)((uint8_t *)cmd + cmdlen) > rsp))
	    || ((rsp < cmd) && ((void *)((uint8_t *)rsp + rsplen) > cmd))) {
		TUI_LOG_DEBUG("APP_MAIN: cmd or rsp buffer too small, exiting from TA - %d,%d,%d", cmdlen, rsplen, sizeof(tciMessage_t));
		TUI_LOG_DEBUG("APP_MAIN: or cmd overlap with resp - %p,%d,%p,%d", cmd, cmdlen, rsp, rsplen);
		TUI_LOG("APP_MAIN: fail to setup command handler");

		ret = TUI_STATUS_FAIL;
		goto exit;
	}

	commandId = sendmsg->header.id;
	TUI_LOG_DEBUG("command id - %08X", commandId);

	if (!IS_CMD(commandId)) {
		TUI_LOG("Invalid command id, exiting!");

		ret = TUI_STATUS_FAIL;
		goto exit;
	}

	ret = process_cmd(commandId, sendmsg, cmdlen, respmsg, rsplen);

exit:
	respmsg->header.id = RSP_ID(commandId);
	respmsg->header.status = ret;

	//TEE_MemMove(cmd, &sendmsg, sizeof(tciMessage_t));
	TEE_MemMove(rsp, respmsg, sizeof(tciMessage_t));
	TZ_bzero(&g_msg, g_msg_len);

	/*TODO: HVC */
}


/**
 * @brief
 * App specific shutdown
 * App will be given a chance to shutdown gracefully
 */
void tz_app_shutdown(void) {
	/* app specific shutdown code*/
	qsee_log(QSEE_LOG_MSG_DEBUG, "TZ_TUI shutdown");
	secUiTouchStop();
	sec_ui_stop_disp();
	sec_ui_free_app_buffer();
	return;
}
