/**
 * Copyright (C) 2011 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Mobile Communication Division,
 * Digital Media & Communications Business, 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.
 *
 */

/**
 * @file tz_hdcp2.c
 * @author
 * @date
 * @brief This file contains all the function calls which are defined on SWD side.
 */

//#include <comdef.h>

#if !defined(CONFIG_MSM8996)&&!defined(CONFIG_MSM8998)
#include <rt_misc.h>
#endif /* !CONFIG_MSM8996 && !CONFIG_MSM8998 */

#include <string.h>
#include "tz_hdcp2.h"
#include "tz_hdcp2_crypto.h"

#ifdef CONFIG_MSM8998
#include "qsee_log.h"
#define QSEE_LOG  qsee_log
#endif /* CONFIG_MSM8998 */

#define HDCP2_SECBOOT_ENABLED	0x01

#ifdef USE_CHECK_SECBOOT
//QSEE OEM CMD ID
#define SECBOOT_IS_AUTH_ENABLED	0x10

// To check secure boot.
extern unsigned int qsee_oem_process_cmd(unsigned char *input, unsigned int input_len,
								unsigned char *output, unsigned int output_len);
#endif /* USE_CHECK_SECBOOT */

#ifdef CONFIG_HDCP_64BIT
const uint64_t g_tzt_heap_base = 0;
const uint64_t g_tzt_heap_end = 0;
#endif /* CONFIG_HDCP_64BIT */

/**
 * @fn int get_secboot_status();
 * @brief To check current status of secureboot.
 * @return status of secureboot
 */
int get_secboot_status()
{
	int status = HDCP2_SECBOOT_ENABLED;

#ifdef USE_CHECK_SECBOOT
	uint32_t oem_cmd_id = SECBOOT_IS_AUTH_ENABLED, oem_output = 0;
	status = qsee_oem_process_cmd((unsigned char *)&oem_cmd_id, sizeof(oem_cmd_id), (unsigned char *)&oem_output, sizeof(oem_output));
	if (status != HDCP2_SECBOOT_ENABLED) {
		QSEE_LOG(QSEE_LOG_MSG_ERROR, "secureboot is not enabled on device (%d)", status); 
		status = HDCP2_ERR_SECBOOT_DISABLED;
	}
#endif /* USE_CHECK_SECBOOT */

	return status;
}

/**
 * @fn void GetTimeStamp(timestamp_t *ts);
 * @brief To print the time stamp.
 * @return void
 */
void GetTimeStamp(timestamp_t *ts)
{
	QSEE_LOG(QSEE_LOG_MSG_ERROR, "GetTimeStamp not handled\n");
}

/**
 * SAMSUNG HDCP2.1 app name
 * Modify the app name to your specific app name
 */
char TZ_APP_NAME[] = {"sshdcpapp"};

/**
 * @fn void tz_app_init(void);
 * @brief Add any app specific initialization code here. QSEE will call this function after secure app is loaded andauthenticated
 * @return void
 */
void tz_app_init(void)
{
	QSEE_LOG(QSEE_LOG_MSG_ERROR, "SSHDCPAPP tz_app_init ");
}

/**
 * @fn void tz_app_cmd_handler(void* cmd, uint32 cmdlen, void* rsp, uint32 rsplen);
 * @brief App specific commands should be handled in this function.
 * @param cmd - Requested command structure
 * @param cmdlen- length of request commad struct
 * @param rsp - Resposnse structure
 * @param rsplen- length of response commad struct
 * @return void
 */
void tz_app_cmd_handler(void* cmd, uint32 cmdlen,
			void* rsp, uint32 rsplen)
{
	int ret = 0;
	HDCP_TZ_LOG(QSEE_LOG_MSG_ERROR, "tz_app_cmd_handler called\n");
	HDCP_TZ_LOG(QSEE_LOG_MSG_ERROR, " cmd:%#X, cmdlen:%u, rsp:%#X, rsplen:%u", cmd, cmdlen, rsp, rsplen);

	ret = TZ_COMMAND((const uint8_t)(*(u8*)cmd), (uint8_t*)cmd, cmdlen, (uint8_t*)rsp, (uint32_t *)&rsplen);
	memset((u8*)rsp + rsplen, 0, sizeof(int));

	if (ret < HDCP2_OK) {
		QSEE_LOG(QSEE_LOG_MSG_ERROR, "tz_app_cmd_handler cmd %d returns fail %d, rsplen %d", (int)*((uint8_t*)cmd), ret, rsplen);
#ifdef CONFIG_MSM8996
		memcpy((u8*)rsp + rsplen, &ret, sizeof(int));
#else
		(int)(*((u8*)rsp + rsplen)) = ret;
#endif /* CONFIG_MSM8996 */
	}
}

/**
 * @fn int TZ_COMMAND(const uint8_t command, uint8_t *request,const u32 req_size, uint8_t *response, uint32_t *res_size);
 * @brief The control comes to this function when secure world is entered and the command to be executed next is decided here only.
 * @param command - The command to be executed, sent from NWD
 * @param request- pointer to request
 * @param req_size - size of request
 * @param response- pointer to response
 * @param res_size - size of response
 * @return int - HDCP2_OK in case of success, else error code corresponding to the error
 */
int TZ_COMMAND(const uint8_t command, uint8_t *request, const u32 req_size,
			uint8_t *response, uint32_t *res_size)
{
	int ret = HDCP2_ERR_NOT_SUPPORTED_COMMAND;
	HDCP_TZ_LOG(QSEE_LOG_MSG_ERROR," TZ_COMMAND command = %d ",command);

	if (HDCP2_SECBOOT_ENABLED != get_secboot_status())
		return HDCP2_ERR_SECBOOT_DISABLED;

	switch (command) {
		case CMD_HDCP2_LOADKEY + CMD_RECEIVER:
		case CMD_HDCP2_LOADKEY_ODM + CMD_RECEIVER:
			ret = TZ_HDCP2_LOADKEY_R(command - CMD_RECEIVER, request, req_size,
						response, res_size);
			break;
		case CMD_AKE_INIT + CMD_RECEIVER:
			ret = TZ_AKE_Init_R(command - CMD_RECEIVER, request, req_size,
						response, res_size);
			break;
		case CMD_AKE_SEND_CERT + CMD_RECEIVER:
			ret = TZ_AKE_Send_Cert_R(command - CMD_RECEIVER, request, req_size,
						response, res_size);
			break;
		case CMD_AKE_NO_STORED_KM + CMD_RECEIVER:
			ret = TZ_AKE_No_Store_km_R(command - CMD_RECEIVER, request, req_size,
						response, res_size);
			break;
		case CMD_AKE_STORED_KM + CMD_RECEIVER:
			ret = TZ_AKE_Store_km_R(command - CMD_RECEIVER, request, req_size,
						response, res_size);
			break;
		case CMD_AKE_SEND_RRX + CMD_RECEIVER:
			ret = TZ_AKE_Send_rrx_R(command - CMD_RECEIVER, request, req_size,
						response, res_size);
			break;
		case CMD_AKE_SEND_H_PRIME + CMD_RECEIVER:
			ret = TZ_AKE_Send_h_prime_R(command - CMD_RECEIVER, request,
						req_size, response, res_size);
			break;
		case CMD_AKE_SEND_PAIRING_INFO + CMD_RECEIVER:
			ret = TZ_AKE_Send_Pairing_Info_R(command - CMD_RECEIVER, request,
						req_size, response, res_size);
			break;
		case CMD_LC_INIT + CMD_RECEIVER:
			ret = TZ_LC_Init_R(command - CMD_RECEIVER, request, req_size,
						response, res_size);
			break;
		case CMD_RTT_READY + CMD_RECEIVER:
			ret = TZ_RTT_READY_R(command - CMD_RECEIVER, request,
						req_size, response, res_size);
			break;
		case CMD_RTT_CHALLENGE + CMD_RECEIVER:
			ret = TZ_RTT_CHALLENGE_R(command - CMD_RECEIVER, request, req_size,
							response, res_size);
			break;
		case CMD_LC_SEND_L_PRIME + CMD_RECEIVER:
			ret = TZ_LC_Send_L_prime_R(command - CMD_RECEIVER, request,
						req_size, response, res_size);
			break;
		case CMD_SKE_SEND_EKS + CMD_RECEIVER:
			ret = TZ_SKE_Send_Eks_R(command - CMD_RECEIVER, request, req_size,
						response, res_size);
			break;
		case CMD_AKE_TRANSMITTER_INFO + CMD_RECEIVER:
			ret = TZ_AKE_Transmitter_Info_R(command - CMD_RECEIVER, request,
						req_size, response, res_size);
			break;
		case CMD_AKE_RECEIVER_INFO + CMD_RECEIVER:
			ret = TZ_AKE_Receiver_Info_R(command - CMD_RECEIVER, request,
						req_size, response, res_size);
			break;
		case CMD_REPEATERAUTH_SEND_RECEIVER_ID_LIST + CMD_RECEIVER:
			ret = TZ_RepeaterAuth_Send_ReceiverId_List_Rep(command - CMD_RECEIVER,
							request, req_size, response, res_size);
			break;
		case CMD_REPEATERAUTH_SEND_ACK + CMD_RECEIVER:
			ret = TZ_RepeaterAuth_Send_Ack_Rep(command - CMD_RECEIVER, request,
							req_size, response, res_size);
			break;
		case CMD_RECEIVER_AUTHSTATUS + CMD_RECEIVER:
			ret = TZ_Receiver_AuthStatus_Rep(command - CMD_RECEIVER, request,
							req_size, response, res_size);
			break;
		case CMD_REPEATERAUTH_STREAM_MANAGE+CMD_RECEIVER:
			ret = TZ_RepeaterAuth_Stream_Manage_Rep(command - CMD_RECEIVER, request,
							req_size, response, res_size);
			break;
		case CMD_REPEATERAUTH_STREAM_READY+CMD_RECEIVER:
			ret = TZ_RepeaterAuth_Stream_Ready_Rep(command - CMD_RECEIVER, request,
							req_size, response, res_size);
			break;
		case CMD_CIP_DEC_DATA + CMD_RECEIVER:
			ret = TZ_DEC_Data(command - CMD_RECEIVER, request, req_size,
							response, res_size);
			break;
		case CMD_CIP_DEC_DATA_ION + CMD_RECEIVER:
			ret = TZ_DEC_Data_ION(command - CMD_RECEIVER, request, req_size,
							response, res_size);
			break;
		case CMD_HDCP2_STOREKEY + CMD_RECEIVER:
			ret = TZ_HDCP2_STOREKEY_R(command - CMD_RECEIVER, request, req_size,
							response, res_size);
			break;
		case CMD_SET_HDCP_VERSION + CMD_RECEIVER:
			ret = TZ_SET_HDCP_VERSION_R(command - CMD_RECEIVER, request, req_size,
							response, res_size);
			break;
		case CMD_CIP_SPS_PPS_DATA + CMD_RECEIVER:
			ret = TZ_SPSPPS_COPY_R(command - CMD_RECEIVER, request, req_size, response, res_size);
			break;
		case CMD_HDCP2_LOADKEY + CMD_TRANSMITTER:
		case CMD_HDCP2_LOADKEY_ODM + CMD_TRANSMITTER:
			ret = TZ_HDCP2_LOADKEY_T(command - CMD_TRANSMITTER, request, req_size, response, res_size);
			break;
		case CMD_AKE_INIT + CMD_TRANSMITTER:
			ret = TZ_AKE_Init_T(command - CMD_TRANSMITTER, request, req_size, response, res_size);
			break;
		case CMD_AKE_SEND_CERT + CMD_TRANSMITTER:
			ret = TZ_AKE_Send_Cert_T(command - CMD_TRANSMITTER, request, req_size,
							response, res_size);
			break;
		case CMD_AKE_NO_STORED_KM + CMD_TRANSMITTER:
			ret = TZ_AKE_No_Store_km_T(command - CMD_TRANSMITTER, request,
							req_size, response, res_size);
			break;
		case CMD_AKE_STORED_KM + CMD_TRANSMITTER:
			ret = TZ_AKE_Store_km_T(command - CMD_TRANSMITTER, request, req_size,
							response, res_size);
			break;
		case CMD_AKE_SEND_RRX + CMD_TRANSMITTER:
			ret = TZ_AKE_Send_rrx_T(command - CMD_TRANSMITTER, request, req_size,
							response, res_size);
			break;
		case CMD_AKE_SEND_H_PRIME + CMD_TRANSMITTER:
			ret = TZ_AKE_Send_h_prime_T(command - CMD_TRANSMITTER, request,
							req_size, response, res_size);
			break;
		case CMD_AKE_SET_PAIRING_INFO + CMD_TRANSMITTER:
			ret = TZ_AKE_SET_PAIRING_INFO_T(command, request,
							req_size, response, res_size);
			break;
		case CMD_AKE_SEND_PAIRING_INFO + CMD_TRANSMITTER:
			ret = TZ_AKE_Send_Pairing_Info_T(command - CMD_TRANSMITTER, request,
							req_size, response, res_size);
			break;
		case CMD_LC_INIT + CMD_TRANSMITTER:
			ret = TZ_LC_Init_T(command - CMD_TRANSMITTER, request, req_size,
							response, res_size);
			break;
		case CMD_RTT_CHALLENGE + CMD_TRANSMITTER:
			ret = TZ_RTT_Challenge_T(command - CMD_TRANSMITTER, request, req_size,
							response, res_size);
			break;
		case CMD_LC_SEND_L_PRIME + CMD_TRANSMITTER:
			ret = TZ_LC_Send_L_prime_T(command - CMD_TRANSMITTER, request,
							req_size, response, res_size);
			break;
		case CMD_SKE_SEND_EKS + CMD_TRANSMITTER:
			ret = TZ_SKE_Send_Eks_T(command - CMD_TRANSMITTER, request, req_size,
							response, res_size);
			break;
		case CMD_AKE_TRANSMITTER_INFO + CMD_TRANSMITTER:
			ret = TZ_AKE_Transmitter_Info_T(command - CMD_TRANSMITTER, request,
							req_size, response, res_size);
			break;
		case CMD_AKE_RECEIVER_INFO + CMD_TRANSMITTER:
			ret = TZ_AKE_Receiver_Info_T(command - CMD_TRANSMITTER, request,
							req_size, response, res_size);
			break;
		case CMD_CIP_ENC_DATA + CMD_TRANSMITTER:
			ret = TZ_ENC_Data(command - CMD_TRANSMITTER, request, req_size,
							response, res_size);
			break;
		case CMD_REPEATERAUTH_SEND_RECEIVER_ID_LIST + CMD_TRANSMITTER:
			ret = TZ_RepeaterAuth_Send_ReceiverId_List_T(command - CMD_TRANSMITTER, request, req_size, response, res_size);
			break;
		case CMD_REPEATERAUTH_SEND_ACK + CMD_TRANSMITTER:
			ret = TZ_RepeaterAuth_Send_Ack_T(command - CMD_TRANSMITTER, request, req_size, response, res_size);
			break;
		case CMD_RECEIVER_AUTHSTATUS + CMD_TRANSMITTER:
			ret = TZ_Receiver_AuthStatus_T(command - CMD_TRANSMITTER, request, req_size, response, res_size);
			break;
		case CMD_REPEATERAUTH_STREAM_MANAGE + CMD_TRANSMITTER:
			ret = TZ_RepeaterAuth_Stream_Manage_T(command - CMD_TRANSMITTER, request, req_size, response, res_size);
			break;
		case CMD_REPEATERAUTH_STREAM_READY + CMD_TRANSMITTER:
			ret = TZ_RepeaterAuth_Stream_Ready_T(command - CMD_TRANSMITTER, request, req_size, response, res_size);
			break;
		case CMD_SET_HDCP_VERSION + CMD_TRANSMITTER:
			ret = TZ_SET_HDCP_VERSION_T(command - CMD_TRANSMITTER, request, req_size, response, res_size);
			break;
		default:
			break;
	}

	HDCP_TZ_LOG(QSEE_LOG_MSG_ERROR,"TZ_COMMAND collected return value: %d", ret);

	return ret;
}

/**
 * @fn void tz_app_shutdown(void);
 * @brief App specific shutdown code. App will be given a chance to shutdown gracefully
 * @return void
 */
void tz_app_shutdown(void)
{
	/* app specific shutdown code*/
	int HDCPflag = 0;

	HDCP_TZ_LOG(QSEE_LOG_MSG_ERROR, "SSHDCPAPP tz_app_shutdown  sshdcpapp");

	HDCPflag = qsee_get_global_flag();
	if (HDCPflag == 0x09) {
		HDCP_TZ_LOG(QSEE_LOG_MSG_ERROR, "qsee_get_global_flag returned 0x09 ..reset it ");
		qsee_set_global_flag(0);
	}
	/* Free resource */
	QSEE_LOG(QSEE_LOG_MSG_ERROR, "Free sourcode in Receiver");
	TZ_Free_Resource_R();

	QSEE_LOG(QSEE_LOG_MSG_ERROR, "Free sourcode in Transmitter");
	TZ_Free_Resource_T();

	QSEE_LOG(QSEE_LOG_MSG_ERROR, "tz_app_shutdown exit  ");

	return;
}

