/*!
 * \file    init_tl.c
 * \brief   process_init implementation
 * \author  Shyam Prasad
 * \date    11/15/2013
 *
 * <hr>
 * \section LICENSE
 * Copyright Samsung Electronics, Co. Ltd. B2B TIMA team. 2013 04
 * <hr>
 */

#include "TZ_Vendor_tl.h"

#include "init_tl.h"
#include "process_msr.h"
#include "tlc_tz_common.h"
#if ICCC_FEATURE
#ifndef TZ_ICCC
#include "tz_iccc_comdef.h"
#else
#include "iccc_core.h"
#endif
#endif
#include "tima_config.h"

#define MEASUREMENT_SIZE 32

extern uint32_t check_license_kap(
	void
);

void printbuf(
	uint8_t * buf
)
{
	int i = 0;
	TTY_LOG("TZ_COMMON: BUFFER START--------------------------");
	while (i < (TIMA_NUM_OF_MEASUREMENTS * MEASUREMENT_SIZE)) {
		TTY_LOG
		    ("TZ_COMMON: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
		     buf[i], buf[i + 1], buf[i + 2], buf[i + 3], buf[i + 4],
		     buf[i + 5], buf[i + 6], buf[i + 7], buf[i + 8], buf[i + 9],
		     buf[i + 10], buf[i + 11], buf[i + 12], buf[i + 13],
		     buf[i + 14], buf[i + 15]);
		i += (MEASUREMENT_SIZE / 2);
	}

	TTY_LOG("TZ_COMMON: BUFFER END--------------------------");

}

TZ_Result process_init(
	tz_init_payload_t * sendmsg,
	tz_init_payload_t * respmsg
)
{
	TZ_Result ret = TZ_COMMON_INIT_ERROR;
	uint8_t boot_msrs[TIMA_MSR_MAX_SIZE];
	uint8_t golden_msrs[TIMA_MSR_MAX_SIZE];
	uint16_t msr_size;
	uint32_t tb_flag = TEXT_TRUSTBOOT_FAILURE;
	int32_t is_svb = 0;

	is_svb = is_svb_enabled();
#ifndef TEMP_DEV_SKIP_MSR_COMPARE
	if (is_tamper_fuse_bit_set()) {
		TTY_LOG("TZ_COMMON: Initialize failed - tamper fuse set");
		ret = TZ_COMMON_INIT_ERROR_TAMPER_FUSE_FAIL;
		goto exit;
	}	

	if (is_svb < 0) { // failure
		TTY_LOG("TZ_COMMON: SVB MAGIC read failed");
		ret = TZ_COMMON_INIT_ERROR;
		goto exit;
	}

	if (is_svb == 1) { // SVB_MAGIC match suing SVB instead of Trust boot
#ifdef TZ_ICCC
		if (ICCC_SUCCESS == Iccc_Core_ReadData_TA(TRUSTBOOT_FLAG, &tb_flag)) {
#else
		if (ICCC_SUCCESS == Iccc_ReadData_TA(TRUSTBOOT_FLAG, &tb_flag)) {
#endif
			if (tb_flag == TEXT_TRUSTBOOT_SUCCESS) {
				TTY_LOG("TZ_COMMON: Measurements match(svb1.0) - Initialization complete");
				ret = TZ_COMMON_OK;
			}
			else {
				TTY_LOG("TZ_COMMON: Initialize failed(svb1.0) - SVB measurements mismatch");
				ret = TZ_COMMON_INIT_MSR_MISMATCH;
				goto exit;
			}
		}
		else {
			TTY_LOG("TZ_COMMON: ICCC failure for TB");
			ret = TZ_COMMON_INIT_ERROR;
			goto exit;
		}
	}
	else // if (is_svb == 0) 
	{
		// SVB_MAGIC not match using Trustboot
		if (0 == sendmsg->payload.cmd.msr_size) {
			if (read_golden_measurement(golden_msrs, &msr_size)) {
				TTY_LOG("TZ_COMMON: Uninitialized secure memory");
				ret = TZ_COMMON_INIT_UNINITIALIZED_SECURE_MEM;
				goto exit;
			}
		} else {
			if (read_measurement((void *)sendmsg->payload.cmd.msr_buf,
					     sendmsg->payload.cmd.msr_size, golden_msrs,
					     &msr_size)) {
				TTY_LOG
				    ("TZ_COMMON: Initialize failed - Read measurements failed");
#ifdef DEBUG_LOG_ENABLE	
				TTY_LOG
				    ("TZ_COMMON: Golden Measurements from tima_measurement_info file");
				printbuf(golden_msrs);
#endif				
				ret = TZ_COMMON_INIT_MSR_MODIFIED;
				goto exit;
			}

			/* after verifying the golden measurements, initialize the 
			   measurements in the secure memory */

			if (init_golden_measurement(golden_msrs, msr_size)) {
				TTY_LOG
				    ("TZ_COMMON: Failed to initialize golden measurements");
				ret = TZ_COMMON_INIT_ERROR;
				goto exit;
			}
		}

		TTY_LOG("TZ_COMMON: Read boot time measurement");

		if (boot_measurement(boot_msrs, msr_size)) {
			TTY_LOG("TZ_COMMON: Failed to read the boot-time measurements");
			ret = TZ_COMMON_INIT_ERROR;
			goto exit;
		}

		TTY_LOG("TZ_COMMON: compare measurements from boot and golden_msrs");

		if (memcmp(boot_msrs, golden_msrs, msr_size)) {
			TTY_LOG
			    ("TZ_COMMON: Initialize failed - Boot-time measurements mismatch");
#ifdef DEBUG_LOG_ENABLE
			TTY_LOG("TZ_COMMON: Golden msrs from secure memory: ");
			printbuf(golden_msrs);
			TTY_LOG("TZ_COMMON: Boot msrs from secure memory: ");
			printbuf(boot_msrs);
#endif			
			ret = TZ_COMMON_INIT_MSR_MISMATCH;
			goto exit;
		}
	}

	TTY_LOG("TZ_COMMON: Measurements match, now check for license nad kap fuse status");
	ret = check_license_kap();
	if (ret) {
		TTY_LOG("TZ_COMMON: license and kap check failed");
		ret = TZ_COMMON_INIT_LICENSE_KAP_CHK_FAIL;
		goto exit;
	}
	ret = TZ_COMMON_OK;
	TTY_LOG("TZ_COMMON: Measurements match - Initialization complete");
#else
	ret = TZ_COMMON_OK;
	TTY_LOG("TZ_COMMON: TEMP_DEV_SKIP_MSR_COMPARE -- initi_tl: Measurements match - Initialization complete");
#endif
exit:
#if ICCC_FEATURE
	if(ret != TZ_COMMON_INIT_UNINITIALIZED_SECURE_MEM) {
		if (is_svb == 0) { // SVB_MAGIC not match using Trustboot
			uint32_t trustboot_result;
			if(ret == TZ_COMMON_OK) {
#ifdef TZ_ICCC
				trustboot_result = TEXT_TRUSTBOOT_SUCCESS;
				Iccc_Core_SaveData_TA(TRUSTBOOT_FLAG, &trustboot_result);
			} else {
				trustboot_result = TEXT_TRUSTBOOT_FAILURE;
				Iccc_Core_SaveData_TA(TRUSTBOOT_FLAG, &trustboot_result);
			}
#else
				trustboot_result = TEXT_TRUSTBOOT_SUCCESS;
				Iccc_SaveData_TA(TRUSTBOOT_FLAG, &trustboot_result);
			} else {
				trustboot_result = TEXT_TRUSTBOOT_FAILURE;
				Iccc_SaveData_TA(TRUSTBOOT_FLAG, &trustboot_result);
			}
#endif
		}
	}
#endif
	respmsg->payload.resp.return_code = ret;
	return TZ_COMMON_OK;
}

TZ_Result process_init_early_boot(
	uint8_t *p_msr_buf,
	uint32_t p_msr_size
)
{
	TZ_Result ret = TZ_COMMON_INIT_ERROR;
	uint8_t boot_msrs[TIMA_MSR_MAX_SIZE];
	uint8_t golden_msrs[TIMA_MSR_MAX_SIZE];
	uint16_t msr_size;
	uint32_t tb_flag = TEXT_TRUSTBOOT_FAILURE;
	int32 is_svb = 0;

	is_svb = is_svb_enabled();
#ifndef TEMP_DEV_SKIP_MSR_COMPARE
	if (is_tamper_fuse_bit_set()) {
		TTY_LOG("TZ_COMMON: Initialize failed - tamper fuse set");
		ret = TZ_COMMON_INIT_ERROR_TAMPER_FUSE_FAIL;
		goto exit;
	}

	TTY_LOG("TZ_COMMON: tamper_fuse_good - process_init, msr_size: %d", p_msr_size);

	if (is_svb < 0) { // failure
		TTY_LOG("SVB MAGIC read failed");
		ret = TZ_COMMON_INIT_ERROR;
		goto exit;
	}

	if (is_svb == 1) { // SVB_MAGIC match suing SVB instead of Trust boot
#ifdef TZ_ICCC
		if (ICCC_SUCCESS == Iccc_Core_ReadData_TA(TRUSTBOOT_FLAG, &tb_flag)) {
#else
		if (ICCC_SUCCESS == Iccc_ReadData_TA(TRUSTBOOT_FLAG, &tb_flag)) {
#endif
			if (tb_flag == TEXT_TRUSTBOOT_SUCCESS) {
				TTY_LOG("TZ_COMMON: Measurements match(svb1.0) - Initialization complete");
				ret = TZ_COMMON_OK;
			}
			else {
				TTY_LOG("TZ_COMMON: Initialize failed(svb1.0) - SVB measurements mismatch");
				ret = TZ_COMMON_INIT_MSR_MISMATCH;
				goto exit;
			}
		}
		else {
			TTY_LOG("TZ_COMMON: ICCC failure");
			ret = TZ_COMMON_INIT_ERROR;
			goto exit;
		}
	}
	else // if (is_svb == 0)
	{
		// SVB_MAGIC not match using Trustboot
		if (0 == p_msr_size) {
			if (read_golden_measurement(golden_msrs, &msr_size)) {
				TTY_LOG("TZ_COMMON: Uninitialized secure memory");
				ret = TZ_COMMON_INIT_UNINITIALIZED_SECURE_MEM;
				goto exit;
			}
		} else {
			if (read_measurement((void *)p_msr_buf,
					     p_msr_size, golden_msrs,
					     &msr_size)) {
				TTY_LOG
				    ("TZ_COMMON: Initialize failed - Read measurements failed");
#ifdef DEBUG_LOG_ENABLE					
				TTY_LOG
				    ("TZ_COMMON: Golden Measurements from tima_measurement_info file");
				printbuf(golden_msrs);
#endif				
				ret = TZ_COMMON_INIT_MSR_MODIFIED;
				goto exit;
			}

			/* after verifying the golden measurements, initialize the 
			   measurements in the secure memory */

			if (init_golden_measurement(golden_msrs, msr_size)) {
				TTY_LOG
				    ("TZ_COMMON: Failed to initialize golden measurements");
				ret = TZ_COMMON_INIT_ERROR;
				goto exit;
			}
		}

		TTY_LOG("TZ_COMMON: Read boot time measurement");

		if (boot_measurement(boot_msrs, msr_size)) {
			TTY_LOG("TZ_COMMON: Failed to read the boot-time measurements");
			ret = TZ_COMMON_INIT_ERROR;
			goto exit;
		}

		TTY_LOG("TZ_COMMON: compare measurements from boot and golden_msrs");

		if (memcmp(boot_msrs, golden_msrs, msr_size)) {
			TTY_LOG
			    ("TZ_COMMON: Initialize failed - Boot-time measurements mismatch");
#ifdef DEBUG_LOG_ENABLE
			TTY_LOG("TZ_COMMON: Golden msrs from secure memory: ");
			printbuf(golden_msrs);
			TTY_LOG("TZ_COMMON: Boot msrs from secure memory: ");
			printbuf(boot_msrs);
#endif			
			ret = TZ_COMMON_INIT_MSR_MISMATCH;
			goto exit;
		}
	}

	TTY_LOG("TZ_COMMON: Measurements match, now check for license nad kap fuse status");
	ret = check_license_kap();
	if (ret) {
		TTY_LOG("TZ_COMMON: license and kap check failed");
		ret = TZ_COMMON_INIT_LICENSE_KAP_CHK_FAIL;
		goto exit;
	}
	ret = TZ_COMMON_OK;
	TTY_LOG("TZ_COMMON: Measurements match - Initialization complete");
#else
	ret = TZ_COMMON_OK;
	TTY_LOG("TZ_COMMON: TEMP_DEV_SKIP_MSR_COMPARE -- initi_tl: Measurements match - Initialization complete");
#endif
exit:
#if ICCC_FEATURE
	if(ret != TZ_COMMON_INIT_UNINITIALIZED_SECURE_MEM) {
		if (is_svb == 0) { // SVB_MAGIC not match using Trustboot
			uint32_t trustboot_result;
			if(ret == TZ_COMMON_OK) {
#ifdef TZ_ICCC
				trustboot_result = TEXT_TRUSTBOOT_SUCCESS;
				Iccc_Core_SaveData_TA(TRUSTBOOT_FLAG, &trustboot_result);
			} else {
				trustboot_result = TEXT_TRUSTBOOT_FAILURE;
				Iccc_Core_SaveData_TA(TRUSTBOOT_FLAG, &trustboot_result);
			}
#else
				trustboot_result = TEXT_TRUSTBOOT_SUCCESS;
				Iccc_SaveData_TA(TRUSTBOOT_FLAG, &trustboot_result);
			} else {
				trustboot_result = TEXT_TRUSTBOOT_FAILURE;
				Iccc_SaveData_TA(TRUSTBOOT_FLAG, &trustboot_result);
			}
#endif
		}
	}
#endif
	TTY_LOG("TZ_COMMON: End of process_init_early_boot, ret=%x", ret);
	return ret;
}
