/*
 * Copyright (c) 2022-2023, MediaTek Inc. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <errno.h>
#if MTK_SIP_KERNEL_BOOT_ENABLE
#include <cold_boot.h>
#endif
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <lib/mtk_init/mtk_init.h>
#include <mtk_sip_svc.h>

#define SMC_HANDLER_DEBUG(...) VERBOSE(__VA_ARGS__)
#define SMC_HANDLER_DEBUG_NOT_IMP_MSG "%s[0x%x] smc handler not implemented\n"
#define SMC_HANDLER_DEBUG_START_MSG "%s[0x%x] smc handler start, smc desc. index:%d\n"
#define SMC_HANDLER_DEBUG_END_MSG "%s[0x%x] smc handler end\n"

/*
 * These macros below are used to identify SIP calls from Kernel,
 * Hypervisor, or 2ndBootloader
 */
#define SIP_FID_ORI_MASK	(0xc000)
#define SIP_FID_ORI_SHIFT	(14)
#define SIP_FID_KERNEL		(0x0)
#define SIP_FID_KERNEL_VIA_GZ	(0x1)
#define SIP_FID_GZ		(0x2)

#define GET_SMC_ORI(_fid)	(((_fid) & SIP_FID_ORI_MASK) >> SIP_FID_ORI_SHIFT)
#define GET_SMC_ORI_NUM(_fid)	((_fid) & ~(SIP_FID_ORI_MASK))

#define is_from_nsel2(_ori)	(_ori == SIP_FID_GZ)
#define is_from_bl33(_ori) \
	((_ori != SIP_FID_GZ) && (is_el1_2nd_bootloader() == 1))
#define is_from_nsel1(_ori) \
	(((_ori == SIP_FID_KERNEL) || \
	 (_ori == SIP_FID_KERNEL_VIA_GZ)) && \
	 (is_el1_2nd_bootloader() == 0))

#define is_smc_forbidden(_ori) (_ori == SIP_FID_KERNEL_VIA_GZ)

#define MASK_32_BIT (0xffffffffU)
#define SMC_ID_EXPAND_AS_SMC_OPERATION(_smc_id, _smc_num) \
	case _smc_id##_AARCH32: \
	{ \
		x1 = x1 & MASK_32_BIT; \
		x2 = x2 & MASK_32_BIT; \
		x3 = x3 & MASK_32_BIT; \
		x4 = x4 & MASK_32_BIT; \
	} \
	/* fallthrough */ \
	case _smc_id##_AARCH64: \
	{ \
		if (_smc_id##_descriptor_index < 0) { \
			SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_NOT_IMP_MSG, #_smc_id, smc_id); \
			break; \
		} \
		if (_smc_id##_descriptor_index >= smc_id_descriptor_max) { \
			SMC_HANDLER_DEBUG("smc descriptor index[%d] exceed max[%d]\n", \
					  _smc_id##_descriptor_index, smc_id_descriptor_max); \
			break; \
		} \
		SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_START_MSG, #_smc_id, smc_id, \
				  _smc_id##_descriptor_index); \
		ret  = smc_handler_pool[_smc_id##_descriptor_index].smc_handler(x1,\
				x2, x3, x4, handle, &smc_ret); \
		SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_END_MSG, #_smc_id, smc_id); \
		break; \
	}

#define SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX(_smc_id, _smc_num) \
	short _smc_id##_descriptor_index __section("mtk_plat_ro") = -1;

MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX);
MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX);
MTK_SIP_SMC_FROM_S_EL1_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX);

IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_START__, MTK_SMC_POOL_START);
IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_END_UNALIGNED__, MTK_SMC_POOL_END_UNALIGNED);

static const struct smc_descriptor *smc_handler_pool;
static short smc_id_descriptor_max;

#if !MTK_SIP_KERNEL_BOOT_ENABLE
/*
 * If there is no SMC request needs to be served in 2nd bootloader,
 * disable the service path inherently.
 */
bool is_el1_2nd_bootloader(void)
{
	return false;
}
#endif

static void print_smc_descriptor(const struct smc_descriptor pool[])
{
	const struct smc_descriptor *p_smc_desc;

	INFO("print smc descriptor pool\n");
	for (p_smc_desc = &pool[0];
	     (char *)p_smc_desc < (char *)MTK_SMC_POOL_END_UNALIGNED;
	     p_smc_desc++) {
		INFO("descriptor name:%s\n", p_smc_desc->smc_name);
		INFO("descriptor index:%d\n", *p_smc_desc->smc_descriptor_index);
		INFO("smc id 32:0x%x, smc id 64:0x%x\n",
		     p_smc_desc->smc_id_aarch32, p_smc_desc->smc_id_aarch64);
	}
}

static int mtk_smc_handler_init(void)
{
	const struct smc_descriptor *iter;
	short index_cnt;
	int ret = 0;

	smc_handler_pool = (const struct smc_descriptor *)MTK_SMC_POOL_START;
	/* Designate descriptor index point to smc_handler_pool */
	for (index_cnt = 0, iter = &smc_handler_pool[0];
	     (char *)iter < (char *)MTK_SMC_POOL_END_UNALIGNED;
	     iter++, index_cnt++) {
		if (index_cnt < 0) {
			SMC_HANDLER_DEBUG("smc handler pool index overflow!\n");
			ret = -EPERM;
			assert(0);
			break;
		}
		*(iter->smc_descriptor_index) = index_cnt;
	}
	smc_id_descriptor_max = index_cnt;
	print_smc_descriptor(smc_handler_pool);
	return ret;
}
MTK_EARLY_PLAT_INIT(mtk_smc_handler_init);

/* This function handles Mediatek defined SiP Calls from Secure world */
static u_register_t mtk_smc_handler_sel1(uint32_t smc_id,
					 u_register_t x1,
					 u_register_t x2,
					 u_register_t x3,
					 u_register_t x4,
					 void *cookie,
					 void *handle,
					 u_register_t flags)
{
	u_register_t ret = MTK_SIP_E_SUCCESS;
	struct smccc_res smc_ret = {0};

	switch (smc_id) {
		MTK_SIP_SMC_FROM_S_EL1_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION);
	default:
		INFO("SEL1 SMC ID:0x%x not support\n", smc_id);
		ret = SMC_UNK;
	}
	SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3);
}

/* This function handles Mediatek defined SiP Calls from Bootloader */
static uintptr_t mtk_smc_handler_bl33(uint32_t smc_id,
				      u_register_t x1,
				      u_register_t x2,
				      u_register_t x3,
				      u_register_t x4,
				      void *cookie,
				      void *handle,
				      u_register_t flags)
{
	uintptr_t ret = MTK_SIP_E_SUCCESS;
	struct smccc_res smc_ret = {0};

	switch (smc_id) {
		MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION);
	default:
		INFO("BL33 SMC ID:0x%x not supported\n", smc_id);
		ret = SMC_UNK;
		break;
	}
	SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3);
}

/* This function handles Mediatek defined SiP Calls from Kernel */
static uintptr_t mtk_smc_handler_nsel1(uint32_t smc_id,
				       u_register_t x1,
				       u_register_t x2,
				       u_register_t x3,
				       u_register_t x4,
				       void *cookie,
				       void *handle,
				       u_register_t flags)
{
	uintptr_t ret = MTK_SIP_E_SUCCESS;
	struct smccc_res smc_ret = {0};

	switch (smc_id) {
		MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION);
	default:
		INFO("NSEL1 SMC ID:0x%x not supported\n", smc_id);
		ret = SMC_UNK;
		break;
	}
	SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3);
}

static uintptr_t mtk_smc_handler(uint32_t smc_id,
				 u_register_t x1,
				 u_register_t x2,
				 u_register_t x3,
				 u_register_t x4,
				 void *cookie,
				 void *handle,
				 u_register_t flags)
{
	uintptr_t ret = SMC_UNK;
	uint32_t ns;
	uint32_t smc_ori;
	uint32_t smc_num;

	/* Get SMC Originator bit 14.15 */
	smc_ori = GET_SMC_ORI(smc_id);
	/* Get SMC Number. Clean bit 14.15 */
	smc_num = GET_SMC_ORI_NUM(smc_id);

	/* Determine which security state this SMC originated from */
	ns = is_caller_non_secure(flags);

	if (ns && is_smc_forbidden(smc_ori)) {
		ERROR("%s: Forbidden SMC call (0x%x)\n", __func__, smc_id);
		SMC_RET1(handle, ret);
	}

	if (!ns) {
		/* SiP SMC service secure world's call */
		return mtk_smc_handler_sel1(smc_num, x1, x2, x3, x4,
					    cookie, handle, flags);
	}
	if (is_from_bl33(smc_ori)) {
		/* SiP SMC service secure bootloader's call */
		return mtk_smc_handler_bl33(smc_num, x1, x2, x3, x4,
					    cookie, handle, flags);
	} else if (is_from_nsel1(smc_ori)) {
		/* SiP SMC service kernel's call */
		return mtk_smc_handler_nsel1(smc_num, x1, x2, x3, x4,
					     cookie, handle, flags);
	}
	INFO("SMC ID:0x%x not supported\n", smc_id);
	SMC_RET1(handle, ret);
}

/* Define a runtime service descriptor for fast SMC calls */
DECLARE_RT_SVC(
	mtk_smc_handler,
	OEN_SIP_START,
	OEN_SIP_END,
	SMC_TYPE_FAST,
	NULL,
	mtk_smc_handler
);
