#include "drStd.h"
#include "DrApi/DrApi.h"
#include "DrApi/DrApiMm.h"
#if TBASE_API_LEVEL >= 5
#include "DrApi/DrApiMmExt.h"
#include "DrApi/DrApiError.h"
#endif
#include "DrApi/DrApiThread.h"
#include "DrApi/DrApiIpcMsg.h"
#include "TlApiMarshalDrTima.h"
#include "TlApiDrTimaError.h"
#include "drTimaMm.h"
#include "DrApi/DrApiHeap.h"
// for HDM
#include "DrApi/DrApiFastCall.h"
#include "DrApi/DrApiMcSystem.h"

#include "dbg.h"

#include "sha1.h"
#include "drMobicore.h"
#include "drLog.h"
#include "dashboard.h"
#include "rtic_secdrv.h"
#ifdef CONFIG_MST_DRV
#include "mst_secdrv.h"
#endif
#if defined(CONFIG_RUNTIME_SKIP_MSR)
#include "rt_ks_skip.h"
#endif

#include "allowlist.h"
#ifdef USE_SCRYPTO
#include "openssl/crypto.h"
#include <locale.h>
#if !defined(CONFIG_SMDK8895) && !defined(CONFIG_SMDK9810) && !defined(CONFIG_SMDK7870) && !defined(CONFIG_SMDK7885)
extern void FINGERPRINT_premain(void);
#endif
#include "process_scrypto.h"
#endif

char g_log_msg[LOG_MSG_SIZE];

DECLARE_DRIVER_MAIN_STACK(0x20000);

#if TBASE_API_LEVEL <= 10
/** Root id for system applications. */
static const uint32_t MC_ROOTID_SYSTEM = 0xFFFFFFFE;
/** SPID for system applications. */
static const uint32_t MC_SPID_SYSTEM = 0xFFFFFFFE;
#endif

log_info_t sec_log_info, dbg_log_info;

#if defined(CONFIG_SMDK9810) || defined(CONFIG_SMDK7885)
char TZ_APP_NAME[] = {"drTima"};
#endif

#ifdef CONFIG_MST_DRV
char mst_track_data[TRACK_DATA_SIZE];
#endif

#ifdef TIMA_ADDRESS_CHECK
#include "regs-tzasc.h"
#include "fcTIMA.h"
#define SEC_MEM_TIMA_SIZE (1U << 20)
#define IRAM_TIMA_SIZE (1U << 11)
#define DRAM_TIMA_SIZE (1U << 21)
#if defined(CONFIG_MT6768)
#define sec_mem_base_pa         0x4CE61000
#else
uint32_t sec_mem_base_pa = 0;
#endif
#endif

#ifdef CONFIG_PKM_SHA256
#define SHA256_HASH_SIZE	32
#endif

/*addr_t drApiAddrTranslateAndCheckBuffer(addr_t adr, uint32_t len);
drApiResult_t drApiGetClientProperty(const threadid_t  client, const property_t  property,
        const addr_t      buffer, uint32_t          *bufferLen); */
#if TBASE_API_LEVEL >= 5
addr_t tima_dashboard_va, tima_sec_log_va, tima_dbg_log_va;
addr_t tima_sfr_va, tima_measurement_va, tima_mst_data_va;

void InitializeVirtAddr(
	void
)
{
	drApiResult_t ret = DRAPI_OK;
    TTY_LOG("drTima: In InitializeVirtAddr");
	ret = drApiMapPhysicalBuffer((uint64_t)TIMA_DASHBOARD_PADDR,
			SIZE_4KB,
			MAP_READABLE | MAP_WRITABLE | MAP_UNCACHED,
			(void **)&tima_dashboard_va);
    TTY_LOG("drTima: In InitializeVirtAddr after drApiMapPhysicalBuffer 1");
	if (ret != DRAPI_OK) {
		//ERR_LOG("drTima: Cannot map tima_dashboard_va: %x", ret);
        TTY_LOG("drTima: In InitializeVirtAddr ret != DRAPI_OK---1");
		return;
	}

#ifndef CONFIG_MT6768
    TTY_LOG("drTima: In InitializeVirtAddr in #ifndef CONFIG_MT6768");
	ret = drApiMapPhysicalBuffer((uint64_t)TIMA_SEC_LOG_PADDR,
			SIZE_4KB,
			MAP_READABLE | MAP_WRITABLE | MAP_UNCACHED,
			(void **)&tima_sec_log_va);
    TTY_LOG("drTima: In InitializeVirtAddr after drApiMapPhysicalBuffer 2");	
	if (ret != DRAPI_OK) {
		//ERR_LOG("drTima: Cannot map tima_sec_log_va: %x", ret);
        TTY_LOG("drTima: In InitializeVirtAddr  ret != DRAPI_OK---2");
		return;
	}
    TTY_LOG("drTima: In InitializeVirtAddr before memset --1");
	memset((void *)tima_sec_log_va, 0, TIMA_LOG_MAP_SIZE);
    TTY_LOG("drTima: In InitializeVirtAddr after memset");

	ret = drApiMapPhysicalBuffer((uint64_t)TIMA_DBG_LOG_PADDR,
			SIZE_4KB,
			MAP_READABLE | MAP_WRITABLE | MAP_UNCACHED,
			(void **)&tima_dbg_log_va);
    TTY_LOG("drTima: In InitializeVirtAddr after drApiMapPhysicalBuffer 3");
	if (ret != DRAPI_OK) {
		//ERR_LOG("drTima: Cannot map tima_dbg_log_va: %x", ret);
        TTY_LOG("drTima: In InitializeVirtAddr  ret != DRAPI_OK---3");
		return;
	}
    TTY_LOG("drTima: In InitializeVirtAddr before memset --2");
	memset((void *)tima_dbg_log_va, 0, TIMA_LOG_MAP_SIZE);
#endif

#if defined(CONFIG_SMDK7885) || defined(CONFIG_SMDK7870)
    TTY_LOG("drTima: In InitializeVirtAddr in #if defined(CONFIG_SMDK7885) || defined(CONFIG_SMDK7870)");
	ret = drApiMapPhysicalBuffer((uint64_t)TZASC0_SFR_BASE,
			SIZE_4KB,
			MAP_READABLE | MAP_WRITABLE | MAP_IO,
			(void **)&tima_sfr_va);
    TTY_LOG("drTima: In InitializeVirtAddr after drApiMapPhysicalBuffer 4");
#elif defined(CONFIG_MT6768)
	ret = DRAPI_OK;
#else
    TTY_LOG("drTima: In InitializeVirtAddr before drApiMapPhysicalBuffer 5");
	ret = drApiMapPhysicalBuffer((uint64_t)TZASC0_SFR_BASE,
			SIZE_4KB,
			MAP_READABLE | MAP_WRITABLE | MAP_UNCACHED,
			(void **)&tima_sfr_va);
    TTY_LOG("drTima: In InitializeVirtAddr after drApiMapPhysicalBuffer 5");
#endif
	if (ret != DRAPI_OK) {
        TTY_LOG("drTima: In InitializeVirtAddr  ret != DRAPI_OK---4");
		//ERR_LOG("drTima: Cannot map tima_sfr_va: %x", ret);
		return;
	}
}
#endif

void InitialiseTIMADriver(
	void
)
{
	drApiResult_t drRet;

#ifdef USE_SCRYPTO
#if !defined(CONFIG_SMDK8895) && !defined(CONFIG_SMDK9810) && !defined(CONFIG_SMDK7870) && !defined(CONFIG_SMDK7885)
	FINGERPRINT_premain();
#endif
	setlocale(LC_ALL, "C");
#endif

#if TBASE_API_LEVEL >= 5
	dashboard_init();
#else
	/* Initialize dashboard memory */
	drRet = drApiMapPhys((addr_t) TIMA_DASHBOARD_VADDR, TIMA_LOG_MAP_SIZE,
			     (addr_t) TIMA_DASHBOARD_PADDR,
			     MAP_READABLE | MAP_WRITABLE | MAP_UNCACHED);
	if (E_OK != drRet) {
		ERR_LOG("drTima: Cannot map dashboard hdr");
		return;
	}
	dashboard_init();
#endif
	//sec_tz_protect(sec_log_info.log_start_paddr, sec_log_info.log_size);

#ifndef CONFIG_MT6768
	sec_log_info.log_start_paddr = TIMA_SEC_LOG_PADDR;
	sec_log_info.log_size = TIMA_SEC_LOG_SIZE;
	dbg_log_info.log_start_paddr = TIMA_DBG_LOG_PADDR;
	dbg_log_info.log_size = TIMA_DBG_LOG_SIZE;
#endif

#if TBASE_API_LEVEL >= 5

#ifdef RTIC_FEATURE_USED
	drRet = rtic_init();
	if (E_OK != drRet) {
		TTY_LOG("drTima: RTIC init failed");
		return;
	}
#endif

#if TBASE_API_LEVEL <= 10
#ifdef TIMA_ADDRESS_CHECK
#if defined(CONFIG_SMDK4X12) || defined(CONFIG_SMDK3470) || defined(CONFIG_SMDK4415)
	sec_mem_base_pa = read_sfr_value((uint32_t)tima_sfr_va - ((uint32_t)(tima_sfr_va) & (SIZE_4KB - 1)) + (TZRS_LOW3 & (SIZE_4KB - 1)));
#elif defined(CONFIG_SMDK8890) || defined(CONFIG_SMDK8895) || defined(CONFIG_SMDK9810) // flagship
	sec_mem_base_pa = read_sfr_value((uint32_t)tima_sfr_va - ((uint32_t)(tima_sfr_va) & (SIZE_4KB - 1)) + (TZRS_LOW0 & (SIZE_4KB - 1)))
						<< TZ_INTERLEAVING_SHIFT;
#else //middle-segment
	sec_mem_base_pa = read_sfr_value((uint32_t)tima_sfr_va - ((uint32_t)(tima_sfr_va) & (SIZE_4KB - 1)) + (TZRS_LOW1 & (SIZE_4KB - 1)))
						<< TZ_INTERLEAVING_SHIFT;
#endif

/* for the below chipset(middle segment), it requires 12 bit shift more */
#if defined(CONFIG_SMDK7570) || defined(CONFIG_SMDK7870) || defined(CONFIG_SMDK7880) || defined(CONFIG_SMDK7885)
		sec_mem_base_pa = sec_mem_base_pa << 12;
#endif

	drRet = drApiUnmapBuffer(tima_sfr_va);
	if (drRet != DRAPI_OK) {
		ERR_LOG("drTima: Cannot unmap tima_sfr_va: %x", drRet);
		return;
	}
#endif
#endif

#ifndef CONFIG_MT6768
	sec_log_info.log_hdr_vaddr = (uint32_t)(uint32_t *)tima_sec_log_va;
	dbg_log_info.log_hdr_vaddr = (uint32_t)(uint32_t *)tima_dbg_log_va;
#endif

#else //TBASE_API_LEVEL >= 5

#ifndef CONFIG_MT6768
	sec_log_info.log_hdr_vaddr = TIMA_SEC_LOG_VADDR;
	sec_log_info.log_data_vaddr = TIMA_SEC_LOG_PAGE;

	/* Initialize sec_log memory */
	drRet = drApiMapPhys((addr_t) TIMA_SEC_LOG_VADDR, TIMA_LOG_MAP_SIZE,
			     (addr_t) TIMA_SEC_LOG_PADDR,
			     MAP_READABLE | MAP_WRITABLE | MAP_UNCACHED);
	if (E_OK != drRet) {
		ERR_LOG("drTima: Cannot map sec_log hdr");
		return;
	}
	//sec_tz_protect(sec_log_info.log_start_paddr, sec_log_info.log_size);

	memset((void *)TIMA_SEC_LOG_VADDR, 0, TIMA_LOG_MAP_SIZE);

	dbg_log_info.log_hdr_vaddr = TIMA_DBG_LOG_VADDR;
	dbg_log_info.log_data_vaddr = TIMA_DBG_LOG_PAGE;

	/* Initialize dbg_log memory */
	drRet = drApiMapPhys((addr_t) TIMA_DBG_LOG_VADDR, TIMA_LOG_MAP_SIZE,
			     (addr_t) TIMA_DBG_LOG_PADDR,
			     MAP_READABLE | MAP_WRITABLE | MAP_UNCACHED);
	if (E_OK != drRet) {
		ERR_LOG("drTima: Cannot map dbg_log hdr");
		return;
	}

	memset((void *)TIMA_DBG_LOG_VADDR, 0, TIMA_LOG_MAP_SIZE);
#endif

#ifdef RTIC_FEATURE_USED
	drRet = rtic_init();
	if (E_OK != drRet) {
		//ERR_LOG("drTima: RTIC init failed");
		return;
	}
#endif

ENG_LOG("sec_log_info.log_start_paddr1 is 0x%x", sec_log_info.log_start_paddr);
ENG_LOG("sec_log_info.log_size1 is 0x%x", sec_log_info.log_size);
ENG_LOG("sec_log_info.log_hdr_vaddr1 is 0x%x", sec_log_info.log_hdr_vaddr);
ENG_LOG("sec_log_info.log_data_vaddr1 is 0x%x", sec_log_info.log_data_vaddr);

ENG_LOG("dbg_log_info.log_start_paddr1 is 0x%x", dbg_log_info.log_start_paddr);
ENG_LOG("dbg_log_info.log_size1 is 0x%x", dbg_log_info.log_size);
ENG_LOG("dbg_log_info.log_hdr_vaddr1 is 0x%x", dbg_log_info.log_hdr_vaddr);
ENG_LOG("dbg_log_info.log_data_vaddr1 is 0x%x", dbg_log_info.log_data_vaddr);

#ifdef TIMA_ADDRESS_CHECK
	/* Get physical address of hash table */
	sec_map(TIMA_SFR_VADDR, TZASC0_SFR_BASE, SIZE_4KB);
#if defined(CONFIG_SMDK4X12) || defined(CONFIG_SMDK3470) || defined(CONFIG_SMDK4415)
	sec_mem_base_pa = read_sfr_value((uint32_t)(TIMA_SFR_VADDR + TZRS_LOW3));
#elif defined(CONFIG_SMDK8890) || defined(CONFIG_SMDK8895) || defined(CONFIG_SMDK9810)
	sec_mem_base_pa = read_sfr_value((uint32_t)(TIMA_SFR_VADDR + TZRS_LOW0));
#else
	sec_mem_base_pa = read_sfr_value((uint32_t)(TIMA_SFR_VADDR + TZRS_LOW1))
						<< TZ_INTERLEAVING_SHIFT;
#endif

	/* for the below chipset, it requires 12 bit shift more */
#if defined(CONFIG_SMDK7570) || defined(CONFIG_SMDK7870) || defined(CONFIG_SMDK7880) || defined(CONFIG_SMDK7885)
	sec_mem_base_pa = sec_mem_base_pa << 12;
#endif

	sec_unmap(TIMA_SFR_VADDR, SIZE_4KB);
	//ENG_LOG("sec_mem_base_pa is: %x", sec_mem_base_pa);
#endif

#endif //TBASE_API_LEVEL >= 5

ENG_LOG("sec_log_info.log_start_paddr2 is 0x%x", sec_log_info.log_start_paddr);
ENG_LOG("sec_log_info.log_size2 is 0x%x", sec_log_info.log_size);
ENG_LOG("sec_log_info.log_hdr_vaddr2 is 0x%x", sec_log_info.log_hdr_vaddr);
ENG_LOG("sec_log_info.log_data_vaddr2 is 0x%x", sec_log_info.log_data_vaddr);

ENG_LOG("dbg_log_info.log_start_paddr2 is 0x%x", dbg_log_info.log_start_paddr);
ENG_LOG("dbg_log_info.log_size2 is 0x%x", dbg_log_info.log_size);
ENG_LOG("dbg_log_info.log_hdr_vaddr2 is 0x%x", dbg_log_info.log_hdr_vaddr);
ENG_LOG("dbg_log_info.log_data_vaddr2 is 0x%x", dbg_log_info.log_data_vaddr);

#ifndef CONFIG_MT6768
log_init(sec_log_info);
log_init(dbg_log_info);
#endif

ENG_LOG("sec_log_info.log_start_paddr3 is 0x%x", sec_log_info.log_start_paddr);
ENG_LOG("sec_log_info.log_size3 is 0x%x", sec_log_info.log_size);
ENG_LOG("sec_log_info.log_hdr_vaddr3 is 0x%x", sec_log_info.log_hdr_vaddr);
ENG_LOG("sec_log_info.log_data_vaddr3 is 0x%x", sec_log_info.log_data_vaddr);

ENG_LOG("dbg_log_info.log_start_paddr3 is 0x%x", dbg_log_info.log_start_paddr);
ENG_LOG("dbg_log_info.log_size3 is 0x%x", dbg_log_info.log_size);
ENG_LOG("dbg_log_info.log_hdr_vaddr3 is 0x%x", dbg_log_info.log_hdr_vaddr);
ENG_LOG("dbg_log_info.log_data_vaddr3 is 0x%x", dbg_log_info.log_data_vaddr);
}

int check_mem_access(uintptr_t addr_pa, uint32_t len, Action_t action)
{
#ifdef TIMA_ADDRESS_CHECK
	if (addr_pa + len < addr_pa) {
		TTY_LOG("addr_pa + len overflow");
		return 1;
	}
	if (action == PHYS_READ) {
		if ((addr_pa >= sec_mem_base_pa) && (addr_pa + len <= sec_mem_base_pa + SEC_MEM_TIMA_SIZE)
				|| (addr_pa >= DDR_MEM_BASE_ADDR) && (addr_pa + len <= DDR_MEM_BASE_ADDR + DRAM_TIMA_SIZE)
				|| (addr_pa >= SRAM_HASH_TABLE_PA) && (addr_pa + len <= SRAM_HASH_TABLE_PA + IRAM_TIMA_SIZE)
				|| (addr_pa >= DDR_MEM_BASE_ADDR) && (addr_pa + len <=sec_mem_base_pa)) {
			return 0;
		} else {
			ENG_LOG("OMG!!! physical address %x is not allowed for reading", addr_pa);
			return 1;
		}
	} else if (action == PHYS_WRITE) {
		/* only allow write permission for golden MSR in TIMA secure memory */
		if ((addr_pa >= sec_mem_base_pa + TIMA_GOLDEN_MSR_ADDR_OFFSET) && (addr_pa + len <= sec_mem_base_pa + SEC_MEM_TIMA_SIZE)) {
			return 0;
#ifdef ICCC_SECURE_PARAMETERS_AREA
		} else if((addr_pa >= sec_mem_base_pa + ICCC_SECURE_PARAMETERS_OFFSET) && (addr_pa + len <= sec_mem_base_pa + ICCC_LOCK_FLAG_OFFSET + sizeof(uint32_t))) {
			return 0;
#endif
#ifdef PAY_MINI_IN_SERVER_SIGNED_NONCE
		} else if((addr_pa >= (sec_mem_base_pa + PAY_MINI_SERVER_SIGNED_NONCE_OFFSET)) && ((addr_pa + len) <= (sec_mem_base_pa + PAY_MINI_SERVER_SIGNED_NONCE_OFFSET + PAY_MINI_SERVER_SIGNED_NONCE_SIZE))) {
			return 0;
#endif
		}
#ifdef CONFIG_ENABLE_EPKM
		else if ((addr_pa >= sec_mem_base_pa + TIMA_BOOT_MSR_ADDR) && ((addr_pa + len) <= (sec_mem_base_pa + TIMA_BOOT_MSR_ADDR + TIMA_BOOT_MSR_MAX_SIZE))) {
			return 0;
		}
#endif
			else {
			ENG_LOG("OMG!!! physical address %x is not allowed for writing", addr_pa);
			return 1;
		}
	}
	TTY_LOG("OMG!!! non-supported action");
	return 1;
#else
	return 0;
#endif
}

int check_nwd(uintptr_t addr_pa, uint32_t len) {
#ifdef TIMA_ADDRESS_CHECK
	if (addr_pa + len < addr_pa) {
		TTY_LOG("addr_pa + len overflow");
		return 1;
	}
	if ((addr_pa > DDR_MEM_BASE_ADDR) && (addr_pa < sec_mem_base_pa) && (addr_pa + len <= sec_mem_base_pa )) {
		return 0;
	}
	TTY_LOG("OMG!!! not NWD");
	return 1;
#else
	return 0;
#endif
}

typedef enum {
	TIMA_ALLOWLIST = 0,
	MST_ALLOWLIST = 1,
	PKM_ALLOWLIST = 2
} allowlist_type;

bool check_uuid_allowlist (threadid_t ipcClient, allowlist_type type)
{
	uint8_t uuid[UUID_LENGTH];
	uint32_t uuid_len = sizeof(uuid);
	bool check_result = false;

	memset(uuid, 0, sizeof(uuid));

	if (E_OK != drApiGetClientProperty(ipcClient, PROPERTY_UUID, uuid, &uuid_len)) {
		TTY_LOG("drTima: failed to get client UUID");
		return false;
	}

	switch (type) {
	case TIMA_ALLOWLIST:
		check_result = in_uuid_allowlist(uuid, uuid_len);
		break;
	case MST_ALLOWLIST:
		check_result = in_mst_allowlist(uuid, uuid_len);
		break;
	case PKM_ALLOWLIST:
		check_result = in_pkm_allowlist(uuid, uuid_len);
		break;
	default:
		TTY_LOG("drTima: wrong allowlist type");
		check_result = false;
	}

	if (check_result == false) {
		if (uuid_len == UUID_LENGTH) {
			DEBUG_LOG("drTima: uuid[%d] ", UUID_LENGTH);
			for (int i = 0; i < UUID_LENGTH; i++) {
				DEBUG_LOG("%02x", uuid[i]);
			}
			TTY_LOG("drTima: this uuid is not in allowlist");
		} else {
			TTY_LOG("drTima: illegal uuid length (%d)", uuid_len);
		}
		return false;
	}

	return true;
}

bool check_cncc_uuid (threadid_t ipcClient)
{
	static const uint8_t cncc_uuid[UUID_LENGTH] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32};
	uint8_t uuid[UUID_LENGTH];
	uint32_t uuid_len = sizeof(uuid);

	memset(uuid, 0, sizeof(uuid));

	if (E_OK != drApiGetClientProperty(ipcClient, PROPERTY_UUID, uuid, &uuid_len)) {
		TTY_LOG("drTima: failed to get client UUID");
		return false;
	}

	if (memcmp(cncc_uuid, uuid, uuid_len)) {
		TTY_LOG("drTima: not CNCC UUID");
		return false;
	}

	return true;
}

/* Main routine for the example driver.
   Initializes the Api data structures and starts the required threads.
*/
_DRAPI_ENTRY void drMain(
	const addr_t dciBuffer,
	const uint32_t dciBufferLen
)
{
	TTY_LOG("drTima: starting main driver thread");
#if TBASE_API_LEVEL >= 5
	InitializeVirtAddr();
#endif
	for (;;) {
		/* Initialise Driver */
		InitialiseTIMADriver();

		INFO_LOG("drTima: main driver thread started");

		/* Become IPC Handler, this will not return */
		TIMADriverIPC_Handler();
	}
}

/* IPC handler that will take care of communication with trustlet.*/
_NORETURN static void TIMADriverIPC_Handler(
	void
)
{
	// Set IPC parameters for initial MSG_RD to IPCH
	threadid_t ipcClient = NILTHREAD;
	message_t ipcMsg = MSG_RD;
	uint32_t ipcData = 0;
	tlApiResult_t tlapiRet = TLAPI_OK;
	drApiResult_t ret = DRAPI_OK;
	TimaMarshalingParam_ptr pMarshal;
	uint32_t offset = 0;
	uint32_t mapLen = SIZE_4KB;
	int tail = 0;
#if TBASE_API_LEVEL >= 5
	uint8_t *mappedPhysAddr;
#else
	uint8_t *mappedPhysAddr = (uint8_t *) TIMA_MEASUREMENT_VADDR;
#endif
	DigestData_ptr pData;
#ifndef RTIC_FEATURE_USED
	SHA1Context sha;
#endif
	uint8_t *pDigest;
	addr_t physAddr;
	PhysMemAccessData_ptr pAccessData;
	char *tlAddr;
	Action_t action = PHYS_READ;
	uint32_t mem_access_len = 0;
#ifdef CONFIG_MST_DRV
	uint64_t mstPhysAddr;
	uint32_t mstOffset = 0;
#endif

#ifdef USE_SCRYPTO
	SCrypto_ptr pSCrypto;
#endif

	SetHdmPolicy_ptr pPolicy;
	atfCallRegCtx_t atfReg;

	struct update_allowlist_t *pwl;
	uint8_t *wl_addr = NULL;
	uint32_t wl_version = 0;
	uint32_t wl_len = 0;

	for (;;) {
		/* When called first time sends ready message to IPC server and waits for
		 * client request. Otherwise wait for another client request.
		 */
		drApiIpcCallToIPCH(&ipcClient, &ipcMsg, &ipcData);
		DETAIL_LOG("drTima: ipcClient = 0x%x, ipcMsg = 0x%x", ipcClient,
			   ipcMsg);

		// dispatch request
		switch (ipcMsg) {
		case MSG_CLOSE_TRUSTLET:
			ipcMsg = MSG_CLOSE_TRUSTLET_ACK;
			ipcData = 0;
			break;

		case MSG_CLOSE_DRIVER:
			DEBUG_LOG("drTima: MSG_CLOSE_DRIVER call");
			ipcMsg = MSG_CLOSE_DRIVER_ACK;
			ipcData = 0;
			break;

		default:
			/* init tlRet value */
			tlapiRet = TLAPI_OK;

			uint32_t rootId, spId;

			/* Try to get the rootId and spid of the calling client */
			if (E_OK !=
			    drApiGetClientRootAndSpId(&rootId, &spId,
						      ipcClient)) {
				TTY_LOG("drTima: Rejecting IPC request: failed to get rootid");
				ipcMsg = (message_t) MSG_RS;
				ipcData = 0;
				continue;
			}

			/* We only allow system trustlets to run, anything else is undefined */
			if (rootId != MC_ROOTID_SYSTEM
			    || spId != MC_SPID_SYSTEM) {
				/* The message cannot be handled, continue */
				TTY_LOG("drTima: Rejecting IPC request, rootId = 0x%x",rootId);
				TTY_LOG("drTima: spId = 0x%x", spId);
				ipcMsg = (message_t) MSG_RS;
				ipcData = 0;
				continue;
			}
//API not present in old SDK. 5260 uses T200
#ifndef CONFIG_SMDK5260
			if (check_uuid_allowlist(ipcClient, TIMA_ALLOWLIST) == false) {
				ipcMsg = (message_t) MSG_RS;
				ipcData = 0;
				continue;
			}
#endif
			/* Map requesting client so we can access the data in the request */
#if TBASE_API_LEVEL >= 5
			ret = drApiMapTaskBuffer(
					THREADID_TO_TASKID(ipcClient),
					(addr_t)ipcData,
					sizeof(TimaMarshalingParam_t),
					MAP_READABLE | MAP_WRITABLE,
					(void **)&pMarshal);
			if (ret != DRAPI_OK) {
				ipcMsg = (message_t) MSG_RS;
				ipcData = 0;
				TTY_LOG
					("drTima: drApiMapTaskBuffer error for ipcData: %x", ret);
				continue;
			}
#else

			pMarshal =
			    (TimaMarshalingParam_ptr)
			    drApiMapClientAndParams(ipcClient, ipcData);
#endif
			if (NULL == pMarshal) {
				TTY_LOG("drTima: drApiMapClientAndParams returned NULL");
				ipcData = 0;
				ipcMsg = (message_t) MSG_RS;
				continue;
			}
			/* Process the request */
			/* Get function ID and call corresponding driver function */
			switch (pMarshal->functionId) {
#ifdef CONFIG_MST_DRV
			case TIMA_DRIVER_MST:

				if (check_uuid_allowlist(ipcClient, MST_ALLOWLIST) == false) {
					ERR_LOG("drTima: mst allowlist check failed");
					tlapiRet = E_DRAPI_DRV_TIMA;
					break;
				}

				mstPhysAddr = (sec_mem_base_pa + MST_TRACK_DATA_OFFSET);

				mstOffset = (uintptr_t) mstPhysAddr & (SIZE_4KB - 1); //4KB align

#if TBASE_API_LEVEL >= 5
				ret = drApiMapPhysicalBuffer((uintptr_t)mstPhysAddr - mstOffset,
						SIZE_4KB,
						MAP_READABLE | MAP_WRITABLE | MAP_IO,
						(void **)&tima_mst_data_va);
				if (ret != DRAPI_OK) {
					ERR_LOG("drTima: Cannot map tima_mst_data_va: %x", ret);
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
					break;
				}
#if defined(CONFIG_MT6768)
				// FIXME : memcpy failed case -  when size is 512(TRACK_DATA_SIZE)
				memcpy((char *)(tima_mst_data_va) + mstOffset, pMarshal->payload.mst_track_data, TRACK_DATA_SIZE / 2);
#else
				memcpy((char *)(tima_mst_data_va) + mstOffset, pMarshal->payload.mst_track_data, TRACK_DATA_SIZE);
#endif
				tlapiRet = mst_transmit(mst_track_data, mstPhysAddr);

				ret = drApiUnmapBuffer(tima_mst_data_va);
				if (ret != DRAPI_OK) {
					ERR_LOG("drTima: Cannot unmap tima_mst_data_va: %x", ret);
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
				}
#else
				if (sec_map
				    ((uintptr_t) TIMA_MST_DATA_VADDR,
				     (uintptr_t) mstPhysAddr - mstOffset, SIZE_4KB)) {
					ERR_LOG
					    ("mstTima: physical to virtual mapping error");
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
					break;
				}

				memcpy((char *)(TIMA_MST_DATA_VADDR) + mstOffset, pMarshal->payload.mst_track_data, TRACK_DATA_SIZE);

				tlapiRet = mst_transmit(mst_track_data, mstPhysAddr);

				if (sec_unmap
				    ((uintptr_t) TIMA_MST_DATA_VADDR,
				     SIZE_4KB)) {
					TTY_LOG("mstTima: physical to virtual unmapping error");
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
				}
#endif
				break;
#endif

#if defined(CONFIG_RUNTIME_SKIP_MSR)
			case TIMA_DRIVER_GET_SECURE_BOOT_STATUS:
				tlapiRet = get_secure_boot_status();
				break;
#endif

			case TIMA_DRIVER_GENERATE_DIGEST:
				//DEBUG_LOG("drTima: processing TIMA_DRIVER_GENERATE_DIGEST");

				if (check_uuid_allowlist(ipcClient, PKM_ALLOWLIST) == false) {
					ERR_LOG("drTima: PKM allowlist check failed");
					tlapiRet = E_DRAPI_DRV_TIMA;
					break;
				}
#if TBASE_API_LEVEL >= 5
				ret = drApiMapTaskBuffer(
						THREADID_TO_TASKID(ipcClient),
						pMarshal->payload.pDigestData,
						sizeof(DigestData_t),
						MAP_READABLE | MAP_WRITABLE,
						(void **)&pData);
				if (ret != DRAPI_OK) {
					ERR_LOG
					    ("drTima: drApiMapTaskBuffer error for pDigestData: %x", ret);
					tlapiRet =
						E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}

#ifdef CONFIG_PKM_SHA256
				ret = drApiMapTaskBuffer(
						THREADID_TO_TASKID(ipcClient),
						pData->pDigest,
						SHA256_HASH_SIZE,
						MAP_READABLE | MAP_WRITABLE,
						(void **)&pDigest);
#else
				ret = drApiMapTaskBuffer(
						THREADID_TO_TASKID(ipcClient),
						pData->pDigest,
						sizeof(SHA1HashSize),
						MAP_READABLE | MAP_WRITABLE,
						(void **)&pDigest);
#endif
				if (ret != DRAPI_OK) {
					ERR_LOG
					    ("drTima: drApiMapTaskBuffer error for pDigest: %x", ret);
					tlapiRet =
						E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}
#else
				if (NULL ==
				    (pData =
				     (DigestData_ptr)drApiAddrTranslateAndCheckBuffer(pMarshal->
								payload.
								pDigestData,
								sizeof(DigestData_t)))) {
					tlapiRet =
					    E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}

#ifdef CONFIG_PKM_SHA256
				if (NULL ==
				    (pDigest =
				     (uint8_t *)drApiAddrTranslateAndCheckBuffer(pData->
								pDigest,
								SHA256_HASH_SIZE))) {
#else
				if (NULL ==
				    (pDigest =
				     (uint8_t *)drApiAddrTranslateAndCheckBuffer(pData->
								pDigest,
								SHA1HashSize))) {
#endif
					tlapiRet =
					    E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}
#endif
				physAddr = pData->physAddr;
				mem_access_len = pData->len;
				offset = (uintptr_t) physAddr & (SIZE_4KB - 1);

#if !(defined(CONFIG_SMDK3475) || defined(CONFIG_SMDK5430) || defined(CONFIG_SMDK5433))
				// Fix Riscue F-006: block must be greater or equal to page size and page aligned
				if (offset || mem_access_len < SIZE_4KB){
					ERR_LOG("drTima: incorrect physical address");
					tlapiRet = E_DRAPI_DRV_TIMA_ALIGNMENT_ERROR;
					break;
				}
#endif

				mapLen = mem_access_len + offset;

				tail = mapLen % TIMA_LOG_MAP_SIZE;

				if (tail) {
					mapLen =
					    mapLen - tail + TIMA_LOG_MAP_SIZE;
				}

#ifdef TIMA_ADDRESS_CHECK
				/* only normal world access is OK */

				if (check_nwd((uintptr_t)physAddr, mem_access_len)) {
					ERR_LOG("drTima: Only non-secure memory is allowed for TIMA_DRIVER_GENERATE_DIGEST CMD");
					tlapiRet = E_DRAPI_DRV_TIMA;
					break;
				}
#endif

#ifndef RTIC_FEATURE_USED
#if TBASE_API_LEVEL >= 5
				ret = drApiMapPhysicalBuffer((uintptr_t)physAddr - offset,
						mapLen,
						MAP_READABLE | MAP_WRITABLE | MAP_IO,
						(void **)&tima_measurement_va);
				if (ret != DRAPI_OK) {
					ERR_LOG("drTima: Cannot map tima_measurement_va: %x", ret);
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
					break;
				}

				mappedPhysAddr =
				    (uint8_t *)((uintptr_t)tima_measurement_va - ((uintptr_t)(tima_measurement_va) & (SIZE_4KB - 1)) + offset);
#else
				if (sec_map
				    ((uintptr_t) TIMA_MEASUREMENT_VADDR,
				     (uintptr_t) physAddr - offset, mapLen)) {
					ERR_LOG
					    ("drTima: physical to virtual mapping error");
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
					break;
				}

				mappedPhysAddr =
				    (uint8_t *) (TIMA_MEASUREMENT_VADDR +
						 offset);
#endif
				DETAIL_LOG("drTima: data_len = %d = 0x%x",
					   mem_access_len, mem_access_len);

				if ((pData->status = SHA1Reset(&sha)) != 0) {
					ERR_LOG
					    ("drTima: SHA1Reset Error: status = 0x%x",
					     pData->status);
					tlapiRet = E_DRAPI_DRV_TIMA;
					goto unmap;
				}

				if ((pData->status =
				     SHA1Input(&sha, mappedPhysAddr,
					       mem_access_len)) != 0) {
					ERR_LOG
					    ("drTima: SHA1Input Error: status = 0x%x",
					     pData->status);
					tlapiRet = E_DRAPI_DRV_TIMA;
					goto unmap;
				}

				if ((pData->status =
				     SHA1Result(&sha, pDigest)) != 0) {
					ERR_LOG
					    ("drTima: SHA1Reset Error: status = 0x%x",
					     pData->status);
					tlapiRet = E_DRAPI_DRV_TIMA;
					goto unmap;
				}

unmap:
#if TBASE_API_LEVEL >= 5
				ret = drApiUnmapBuffer(tima_measurement_va);
				if (ret != DRAPI_OK) {
					ERR_LOG("drTima: Cannot unmap tima_measurement_va: %x", ret);
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
				}
#else
				if (sec_unmap
				    ((uintptr_t) TIMA_MEASUREMENT_VADDR,
				     mapLen)) {
					ERR_LOG
					    ("drTima: physical to virtual unmapping error");
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
				}
#endif
#else //RTIC_FEATURE_USED
				pData->status = rtic_get_hash((uint32_t)physAddr, (uint32_t)mem_access_len, (uint8_t *)pDigest);
				if (pData->status != 0) {
					ERR_LOG
						("drTima: rtic_get_hash: status = 0x%x", pData->status);
					tlapiRet = E_DRAPI_DRV_TIMA;
				}

#endif //RTIC_FEATURE_USED

				break;

			case TIMA_DRIVER_PHYS_MEM_ACCESS_COPY:
//				DEBUG_LOG
//				    ("drTima: processing TIMA_DRIVER_PHYS_MEM_ACCESS_COPY");
#if TBASE_API_LEVEL >= 5
				ret = drApiMapTaskBuffer(
						THREADID_TO_TASKID(ipcClient),
						pMarshal->payload.pPhysMemAccessData,
						sizeof(PhysMemAccessData_t),
						MAP_READABLE | MAP_WRITABLE,
						(void **)&pAccessData);
				if (ret != DRAPI_OK) {
					ERR_LOG
					    ("drTima: drApiMapTaskBuffer error for pPhysMemAccessData: %x", ret);
					tlapiRet =
						E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}
#else
				if (NULL ==
				    (pAccessData =
				     (PhysMemAccessData_ptr)drApiAddrTranslateAndCheckBuffer(pMarshal->
								payload.
								pPhysMemAccessData,
								sizeof(PhysMemAccessData_t))))
				{
					TTY_LOG("drTima: drApiAddrTranslateAndCheckBuffer error for pPhysMemAccessData ");
					tlapiRet =
					    E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}
#endif
				physAddr = pAccessData->physAddr;
				mem_access_len = pAccessData->len;
				action = pAccessData->action;
				offset = (uintptr_t) physAddr & (SIZE_4KB - 1);
				mapLen = mem_access_len + offset;
				tail = mapLen % TIMA_LOG_MAP_SIZE;

				if (((uintptr_t) physAddr & TIMA_ALIGNMENT_TEST)
				    || (offset & TIMA_ALIGNMENT_TEST)
				    || (mapLen & TIMA_ALIGNMENT_TEST)) {
					tlapiRet =
					    E_DRAPI_DRV_TIMA_ALIGNMENT_ERROR;
					DEBUG_LOG
					    ("drTima: alignment error physaddr: %x, offset: %x, maplen: %x. len = %d",
					     ((uintptr_t) physAddr &
					      TIMA_ALIGNMENT_TEST),
					     (offset & TIMA_ALIGNMENT_TEST),
					     (mapLen & TIMA_ALIGNMENT_TEST),
					     pAccessData->len);
					break;
				}

				if (tail) {
					mapLen =
					    mapLen - tail + TIMA_LOG_MAP_SIZE;
				}

				/* check address range */
				if (check_mem_access((uintptr_t)physAddr, mem_access_len, action)) {
					DEBUG_LOG("address %x not allowed for action %x", physAddr, action);
					tlapiRet = E_DRAPI_DRV_TIMA;
					break;
				}
#if TBASE_API_LEVEL >= 5
				ret = drApiMapTaskBuffer(
						THREADID_TO_TASKID(ipcClient),
						pAccessData->tlAddr,
						mem_access_len,
						MAP_READABLE | MAP_WRITABLE,
						(void **)&tlAddr);
				if (ret != DRAPI_OK) {
					ERR_LOG
					    ("drTima: drApiMapTaskBuffer error for tlAddr: %x", ret);
					tlapiRet =
						E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}

				ret = drApiMapPhysicalBuffer((uintptr_t)physAddr - offset,
						mapLen,
						MAP_READABLE | MAP_WRITABLE | MAP_IO,
						(void **)&tima_measurement_va);
				if (ret != DRAPI_OK) {
					ERR_LOG("drTima: Cannot map tima_measurement_va: %x", ret);
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
					break;
				}

				mappedPhysAddr =
				    (uint8_t *)((uintptr_t)tima_measurement_va - ((uintptr_t)(tima_measurement_va) & (SIZE_4KB - 1)) + offset);
#else
				if (NULL ==
				    (tlAddr =
				     (char *)
				     drApiAddrTranslateAndCheckBuffer(pAccessData->
								tlAddr,
								mem_access_len))) {
					TTY_LOG("drTima: drApiAddrTranslateAndCheckBuffer error for tlAddr ");
					tlapiRet =
					    E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}

				if (sec_map
				    ((uintptr_t) TIMA_MEASUREMENT_VADDR,
				     (uintptr_t) physAddr - offset, mapLen)) {
					TTY_LOG("drTima: physical to virtual mapping error");
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
					break;
				}

				mappedPhysAddr =
				    (uint8_t *) (TIMA_MEASUREMENT_VADDR +
						 offset);

#endif

//				DEBUG_LOG("drTima: data_len = %d = 0x%x",
//					  pAccessData->len, pAccessData->len);

				switch (action) {
				case PHYS_READ:
					memcpy(tlAddr, mappedPhysAddr,
					       mem_access_len);
					pAccessData->status = TLAPI_OK;
					break;
				case PHYS_WRITE:
					memcpy(mappedPhysAddr, tlAddr,
					       mem_access_len);
					pAccessData->status = TLAPI_OK;
					break;
				default:
					DEBUG_LOG("drTima: action can be PHYS_READ or PHYS_WRITE only");
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
					pAccessData->status =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
					break;
				}
#if TBASE_API_LEVEL >= 5
				ret = drApiUnmapBuffer(tima_measurement_va);
				if (ret != DRAPI_OK) {
					ERR_LOG("drTima: Cannot unmap tima_measurement_va: %x", ret);
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
				}
#else
				if (sec_unmap
				    ((uintptr_t) TIMA_MEASUREMENT_VADDR,
				     mapLen)) {
					ERR_LOG("drTima: physical to virtual unmapping error");
					tlapiRet =
					    E_DRAPI_DRV_TIMA_MAPPING_ERROR;
				}
#endif
				break;

#ifndef CONFIG_MT6768
			case TIMA_DRIVER_DBG_LOG:
				log_msg(dbg_log_info,
					pMarshal->payload.log_msg);
				break;

			case TIMA_DRIVER_SEC_LOG:
				dashboard_update(pMarshal->payload.
						 dashboard_entry_type);
				snprintf(g_log_msg, LOG_MSG_SIZE - 1,
					 dashboard_lookup_msg_type(pMarshal->
								   payload.
								   dashboard_entry_type));
				g_log_msg[LOG_MSG_SIZE - 1] = '\0';
				log_msg(sec_log_info, g_log_msg);
				//dashboard_dump();
				break;
#endif
#ifdef USE_SCRYPTO
			case TIMA_DRIVER_SCRYPTO:
#if TBASE_API_LEVEL >= 5
				ret = drApiMapTaskBuffer(
						THREADID_TO_TASKID(ipcClient),
						pMarshal->payload.pSCrypto,
						sizeof(SCrypto_t),
						MAP_READABLE | MAP_WRITABLE,
						(void **)&pSCrypto);
				if (ret != DRAPI_OK) {
					ERR_LOG
					    ("drTima: drApiMapTaskBuffer error for pSCrypto: %x", ret);
					tlapiRet =
						E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}
				pSCrypto->ret_val = process_scrypto(pSCrypto, ipcClient);
#else
				if (NULL ==
				    (pSCrypto =
				     drApiAddrTranslateAndCheckBuffer(pMarshal->
								payload.
								pSCrypto,
								sizeof(SCrypto_t)))) {
					tlapiRet =
					    E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}
				pSCrypto->ret_val = process_scrypto(pSCrypto);
#endif
				break;
#endif
			case TIMA_DRIVER_ALLOWLIST:
				/* only CNCC TA can call this ipc call */
				DEBUG_LOG("drTima: TIMA_DRIVER_ALLOWLIST");

				if (!check_cncc_uuid(ipcClient)) {
					tlapiRet = E_DRAPI_DRV_TIMA;
					break;
				}
#if TBASE_API_LEVEL >= 5
				ret = drApiMapTaskBuffer(
						THREADID_TO_TASKID(ipcClient),
						pMarshal->payload.wl,
						sizeof(struct update_allowlist_t),
						MAP_READABLE | MAP_WRITABLE,
						(void **)&pwl);
				if (ret != DRAPI_OK) {
					ERR_LOG
					    ("drTima: drApiMapTaskBuffer error for wl: %x", ret);
					tlapiRet =
						E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}
				wl_version = pwl->wl_version;
				wl_len = pwl->wl_len;
				if (wl_len != 0) {
					ret = drApiMapTaskBuffer(
						THREADID_TO_TASKID(ipcClient),
						pwl->wl_addr,
						wl_len,
						MAP_READABLE | MAP_WRITABLE,
						(void **)&wl_addr);
					if (ret != DRAPI_OK) {
						ERR_LOG
							("drTima: drApiMapTaskBuffer error for wl_addr: %x", ret);
						tlapiRet =
							E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
						break;
					}
				}
#else
				if (NULL ==
				    (pwl =
				     (struct update_allowlist_t *)drApiAddrTranslateAndCheckBuffer(pMarshal->payload.wl,
								sizeof(struct update_allowlist_t)))) {
					tlapiRet =
					    E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					TTY_LOG("failed to translate payload");
					break;
				}
				wl_version = pwl->wl_version;
				wl_len = pwl->wl_len;
				if (wl_len != 0) {
					wl_addr = (uint8_t *)drApiAddrTranslateAndCheckBuffer(pwl->wl_addr, wl_len);
					if (NULL == wl_addr) {
						tlapiRet = E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
						TTY_LOG("failed to translate wl_addr");
						break;
					}
				}
#endif
				pwl->ret_val = process_update_allowlist(
						wl_version,
						wl_addr, wl_len);
				break;

			case TIMA_DRIVER_SET_HDM_POLICY:
#if TBASE_API_LEVEL >= 5
				ret = drApiMapTaskBuffer(
						THREADID_TO_TASKID(ipcClient),
						pMarshal->payload.policy,
						sizeof(SetHdmPolicy_t),
						MAP_READABLE | MAP_WRITABLE,
						(void **)&pPolicy);
				if (ret != DRAPI_OK) {
					ERR_LOG
					    ("drTima: drApiMapTaskBuffer error for setting hdm policy: %x", ret);
					tlapiRet =
						E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}

				atfReg.r[0] = 0xC2000822; //MTK_SIP_HYP_SMC_TO_EL2_RKP_AARCH64
				atfReg.r[1] = pPolicy->r1;
				atfReg.r[2] = pPolicy->r2;
				atfReg.r[3] = pPolicy->r3;
				ret = drApiCallTrustedFirmware(&atfReg);

				pPolicy->ret_val = ret;
#else
				if (NULL ==
				    (pPolicy =
				     (SetHdmPolicy_ptr)drApiAddrTranslateAndCheckBuffer(pMarshal->
								payload.policy,
								sizeof(SetHdmPolicy_t)))) {
					tlapiRet =
					    E_DRAPI_DRV_TIMA_ADDRESS_TRANSLATION_ERROR;
					break;
				}
				atfReg.r[0] = 0xC2000822; //MTK_SIP_HYP_SMC_TO_EL2_RKP_AARCH64
				atfReg.r[1] = pPolicy->r1;
				atfReg.r[2] = pPolicy->r2;
				atfReg.r[3] = pPolicy->r3;

				ret = drApiCallTrustedFirmware(&atfReg);
				pPolicy->ret_val = ret;
#endif
				break;
			default:	/* Could not find function ID */
				ERR_LOG
				    ("drTima: Unknown function id: 0x%x, ipcClient = 0x%x",
				     pMarshal->functionId, ipcClient);
				tlapiRet = E_TLAPI_UNKNOWN_FUNCTION;
				break;
			}	// end switch (mParam->functionId)

			/* prepare response message */
			ipcMsg = MSG_RS;
			pMarshal->payload.retVal = tlapiRet;
			break;
		}		// end switch (ipcMsg)
#if TBASE_API_LEVEL >= 5
		ret = drApiUnmapTaskBuffers(THREADID_TO_TASKID(ipcClient));
		if (ret != DRAPI_OK) {
			ERR_LOG("drTima: failed to UnmapTaskBuffers: %x", ret);
			break;
		}
#endif

	}			// end for (;;)
}

/** @} */
