/*
 *
 * (c) Copyright 2018 Samsung Research America, Inc.
 *                  All rights reserved
 *
 *                  MCL-B2B Lab
 *
 *
 * File: process_cmd.c
 * Author: r.kadir@samsung.com
 * Creation Date: Nov, 2018
 *
 */
/**
* Copyright (C) 2018 Samsung Electronics Co., Ltd. All rights reserved.
*
* Mobile Platform & Solutions Lab (MPS Lab),
* Samsung Electronics Co., Ltd.
*
* This software and its documentation are confidential and proprietary
* information of Samsung Electronics Co., Ltd.  No part of the software and
* documents may be copied, reproduced, transmitted, translated, or reduced to
* any electronic medium or machine-readable form without the prior written
* consent of Samsung Electronics.
*
* Samsung Electronics makes no representations with respect to the contents,
* and assumes no responsibility for any errors that might appear in the
* software and documents. This publication and the contents hereof are subject
* to change without notice.
*/
#include "process_cmd_private.h"
#include "tci.h"
#include "utils.h"
#include "dualdar_globals.h"
#include "dualdar_init_tl.h"
////////////////////////////

static uint32_t process_cmd_internal(
	uint32_t commandId,
	tciMessage_t * sendmsg,
	uint32_t sendmsg_len,
	tciMessage_t * respmsg,
	uint32_t respmsg_len
);
///////////////////////

uint32_t process_cmd(
	uint32_t commandId,
	tciMessage_t * sendmsg,
	uint32_t sendmsg_len,
	tciMessage_t * respmsg,
	uint32_t respmsg_len
)
{
	uint32_t ret = DUALDAR_OK;

	LOGSTARTTIME();

	DUALDAR_REL("DUALDAR - process_cmd: %d", commandId);

	// [SI-16417] Security misconfiguration in DualDAR TA
	// Trusted boot status should be checked before processing internal command.
	// TA should exit and return error in case of trusted boot status failure.
	ret = verify_trusted_boot();
	if (ret == TZ_DUALDAR_INIT_OK) {
		DUALDAR_REL("trusted boot verification completed successfully");
		gDualDarData.initialized = true;
	} else {
		DUALDAR_ERROR("trusted boot initialized failed");
		DUALDAR_ERROR("Command %08X failed with error code: %d", commandId, ret);
		gDualDarData.initialized = false;
	}

	if (gDualDarData.initialized == true) {
		ret =
			process_cmd_internal(commandId, sendmsg, sendmsg_len, respmsg,
					respmsg_len);
		if (ret != DUALDAR_OK) {
			DUALDAR_ERROR("Error: process_cmd_internal failed");
		}
	} else {
		DUALDAR_ERROR("trusted boot verification failed");
	}

	respmsg->dualdarhdr.header.id = RSP_ID(commandId);
	respmsg->dualdarhdr.header.status = ret;

	DUALDAR_LOG("Trustlet respmsg->dualdarhdr.header.id = 0x%08X", respmsg->dualdarhdr.header.id);
	DUALDAR_LOG("Trustlet respmsg->dualdarhdr.header.status = 0x%08X", respmsg->dualdarhdr.header.status);
	DUALDAR_LOG("Returning = 0x%08X", ret);

	DUALDAR_REL("DUALDAR - process_cmd ends");

	LOGTIMETAKEN();

	return ret;
}

#define PROCESS_CMD(sendmsg,sendmsg_len,respmsg,respmsg_len,cmdname) { \
	DUALDAR_REL("\nDUALDAR - PROCESS_CMD: = %s",  #cmdname); \
	LOG_CMD(sendmsg_len, tz_##cmdname##_msg_cmd_t, respmsg_len, tz_##cmdname##_msg_resp_t); \
	if(!IS_VALID_BUFFER(sendmsg_len, tz_##cmdname##_msg_cmd_t, respmsg_len, tz_##cmdname##_msg_resp_t)) { \
		DUALDAR_ERROR("\nError: Received Length is less than expected Length"); \
		return DUALDAR_INVALID_INPUT_PARAM; \
	} \
	DUALDAR_LOG("\nprocess_"#cmdname"_cmd in tl - start"); \
	memcpy(&gDualDarData.tmp_data.secureReqMsg.payload.cmdname##_cmd, \
			&sendmsg->payload.cmdname##_cmd, sizeof(tz_##cmdname##_msg_payload_t)); \
   	memset(&gDualDarData.tmp_data.secureRespMsg.payload.cmdname##_cmd, 0, \
   	       sizeof(tz_##cmdname##_msg_payload_t)); \
	ret = process_##cmdname##_cmd(&gDualDarData.tmp_data.secureReqMsg.payload.cmdname##_cmd, &gDualDarData.tmp_data.secureRespMsg.payload.cmdname##_cmd); \
	memcpy(&respmsg->payload.cmdname##_cmd.payload.resp, \
	       &gDualDarData.tmp_data.secureRespMsg.payload.cmdname##_cmd. \
	       payload.resp, sizeof(tz_##cmdname##_msg_resp_t)); \
	respmsg->dualdarhdr.header.len =  sizeof(tz_##cmdname##_msg_resp_t); \
	DUALDAR_LOG("\nprocess_"#cmdname"_cmd in tl - end"); \
	respmsg->payload.cmdname##_cmd.payload.resp.return_code = ret; \
	memset(&gDualDarData.tmp_data, 0, sizeof(gDualDarData.tmp_data)); \
	ret = DUALDAR_OK; \
}

uint32_t process_cmd_internal(
	uint32_t commandId,
	tciMessage_t * sendmsg,
	uint32_t sendmsg_len,
	tciMessage_t * respmsg,
	uint32_t respmsg_len
)
{
	uint32_t ret = DUALDAR_OK;

	DUALDAR_REL("DUALDAR - process_cmd_internal: 0x%08X", commandId);

	switch (commandId) {

	case CMD_DUALDAR_INIT:
		PROCESS_CMD(sendmsg, sendmsg_len, respmsg, respmsg_len,
			    init);
		break;

	case CMD_DUALDAR_SETUP_PASSWORD:
		PROCESS_CMD(sendmsg, sendmsg_len, respmsg, respmsg_len,
			    setup_password);
		break;


	case CMD_DUALDAR_CHANGE_PASSWORD:
		PROCESS_CMD(sendmsg, sendmsg_len, respmsg, respmsg_len,
			    change_password);
		break;


	case CMD_DUALDAR_AUTHENTICATE:
		PROCESS_CMD(sendmsg, sendmsg_len, respmsg, respmsg_len,
			    authenticate);
		break;



	default:
		DUALDAR_REL("DUALDAR - process_cmd_internal: UNKNOWN_CMD = 0x%08X",
			 commandId);
		ret = DUALDAR_UNKNOWN_CMD;
		break;
	}

	return ret;
}