/*
 * Copyright (c) 2022 Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier:    BSD-3-Clause
 *
 * DRTM service
 *
 * Authors:
 *	Lucian Paul-Trifu <lucian.paultrifu@gmail.com>
 *	Brian Nezvadovitz <brinez@microsoft.com> 2021-02-01
 *
 */

#ifndef ARM_DRTM_SVC_H
#define ARM_DRTM_SVC_H

/*
 * SMC function IDs for DRTM Service
 * Upper word bits set: Fast call, SMC64, Standard Secure Svc. Call (OEN = 4)
 */
#define DRTM_FID(func_num)				\
	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) |		\
	(SMC_64 << FUNCID_CC_SHIFT) |			\
	(OEN_STD_START << FUNCID_OEN_SHIFT) |		\
	((func_num) << FUNCID_NUM_SHIFT))

#define DRTM_FNUM_SVC_VERSION		U(0x110)
#define DRTM_FNUM_SVC_FEATURES		U(0x111)
#define DRTM_FNUM_SVC_UNPROTECT_MEM	U(0x113)
#define DRTM_FNUM_SVC_DYNAMIC_LAUNCH	U(0x114)
#define DRTM_FNUM_SVC_CLOSE_LOCALITY	U(0x115)
#define DRTM_FNUM_SVC_GET_ERROR		U(0x116)
#define DRTM_FNUM_SVC_SET_ERROR		U(0x117)
#define DRTM_FNUM_SVC_SET_TCB_HASH	U(0x118)
#define DRTM_FNUM_SVC_LOCK_TCB_HASH	U(0x119)

#define ARM_DRTM_SVC_VERSION		DRTM_FID(DRTM_FNUM_SVC_VERSION)
#define ARM_DRTM_SVC_FEATURES		DRTM_FID(DRTM_FNUM_SVC_FEATURES)
#define ARM_DRTM_SVC_UNPROTECT_MEM	DRTM_FID(DRTM_FNUM_SVC_UNPROTECT_MEM)
#define ARM_DRTM_SVC_DYNAMIC_LAUNCH	DRTM_FID(DRTM_FNUM_SVC_DYNAMIC_LAUNCH)
#define ARM_DRTM_SVC_CLOSE_LOCALITY	DRTM_FID(DRTM_FNUM_SVC_CLOSE_LOCALITY)
#define ARM_DRTM_SVC_GET_ERROR		DRTM_FID(DRTM_FNUM_SVC_GET_ERROR)
#define ARM_DRTM_SVC_SET_ERROR		DRTM_FID(DRTM_FNUM_SVC_SET_ERROR)
#define ARM_DRTM_SVC_SET_TCB_HASH	DRTM_FID(DRTM_FNUM_SVC_SET_TCB_HASH)
#define ARM_DRTM_SVC_LOCK_TCB_HASH	DRTM_FID(DRTM_FNUM_SVC_LOCK_TCB_HASH)

#define ARM_DRTM_FEATURES_TPM		U(0x1)
#define ARM_DRTM_FEATURES_MEM_REQ	U(0x2)
#define ARM_DRTM_FEATURES_DMA_PROT	U(0x3)
#define ARM_DRTM_FEATURES_BOOT_PE_ID	U(0x4)
#define ARM_DRTM_FEATURES_TCB_HASHES	U(0x5)

#define is_drtm_fid(_fid) \
	(((_fid) >= ARM_DRTM_SVC_VERSION) && ((_fid) <= ARM_DRTM_SVC_LOCK_TCB_HASH))

/* ARM DRTM Service Calls version numbers */
#define ARM_DRTM_VERSION_MAJOR		U(0)
#define ARM_DRTM_VERSION_MAJOR_SHIFT	16
#define ARM_DRTM_VERSION_MAJOR_MASK	U(0x7FFF)
#define ARM_DRTM_VERSION_MINOR		U(1)
#define ARM_DRTM_VERSION_MINOR_SHIFT	0
#define ARM_DRTM_VERSION_MINOR_MASK	U(0xFFFF)

#define ARM_DRTM_VERSION						\
	((((ARM_DRTM_VERSION_MAJOR) & ARM_DRTM_VERSION_MAJOR_MASK) <<	\
	ARM_DRTM_VERSION_MAJOR_SHIFT)					\
	| (((ARM_DRTM_VERSION_MINOR) & ARM_DRTM_VERSION_MINOR_MASK) <<	\
	ARM_DRTM_VERSION_MINOR_SHIFT))

#define ARM_DRTM_FUNC_SHIFT	U(63)
#define ARM_DRTM_FUNC_MASK	ULL(0x1)
#define ARM_DRTM_FUNC_ID	U(0x0)
#define ARM_DRTM_FEAT_ID	U(0x1)
#define ARM_DRTM_FEAT_ID_MASK	ULL(0xff)

/*
 * Definitions for DRTM features as per DRTM beta0 section 3.3,
 * Table 6 DRTM_FEATURES
 */
#define ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_SHIFT		U(33)
#define ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_MASK		ULL(0xF)
#define ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_DEFAULT	ULL(0x1)

#define ARM_DRTM_TPM_FEATURES_TPM_HASH_SHIFT		U(32)
#define ARM_DRTM_TPM_FEATURES_TPM_HASH_MASK		ULL(0x1)
#define ARM_DRTM_TPM_FEATURES_TPM_HASH_NOT_SUPPORTED	ULL(0x0)
#define ARM_DRTM_TPM_FEATURES_TPM_HASH_SUPPORTED	ULL(0x1)

#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHIFT		U(0)
#define ARM_DRTM_TPM_FEATURES_FW_HASH_MASK		ULL(0xFFFFFFFF)
#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHA256		ULL(0xB)
#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHA384		ULL(0xC)
#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHA512		ULL(0xD)

#define ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_SHIFT		U(32)
#define ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_MASK		ULL(0xFFFFFFFF)

#define ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_SHIFT	U(0)
#define ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_MASK	ULL(0xFFFFFFFF)

#define ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_SHIFT	U(8)
#define ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_MASK	ULL(0xF)

#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_SHIFT	U(0)
#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_MASK	ULL(0xFF)
#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_COMPLETE	ULL(0x1)
#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_REGION	ULL(0x2)

#define ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT	U(0)
#define ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_MASK	ULL(0xFF)

#define ARM_DRTM_TPM_FEATURES_SET_PCR_SCHEMA(reg, val)			\
	do {								\
		reg = (((reg) & ~(ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_MASK \
		<< ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_SHIFT)) | (((val) & \
		ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_MASK) <<		\
		ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_SHIFT));		\
	} while (false)

#define ARM_DRTM_TPM_FEATURES_SET_TPM_HASH(reg, val)			\
	do {								\
		reg = (((reg) & ~(ARM_DRTM_TPM_FEATURES_TPM_HASH_MASK	\
		<< ARM_DRTM_TPM_FEATURES_TPM_HASH_SHIFT)) | (((val) &	\
		ARM_DRTM_TPM_FEATURES_TPM_HASH_MASK) <<			\
		ARM_DRTM_TPM_FEATURES_TPM_HASH_SHIFT));			\
	} while (false)

#define ARM_DRTM_TPM_FEATURES_SET_FW_HASH(reg, val)			\
	do {								\
		reg = (((reg) & ~(ARM_DRTM_TPM_FEATURES_FW_HASH_MASK	\
		<< ARM_DRTM_TPM_FEATURES_FW_HASH_SHIFT)) | (((val) &	\
		ARM_DRTM_TPM_FEATURES_FW_HASH_MASK) <<			\
		ARM_DRTM_TPM_FEATURES_FW_HASH_SHIFT));			\
	} while (false)

#define ARM_DRTM_MIN_MEM_REQ_SET_DCE_SIZE(reg, val)			\
	do {								\
		reg = (((reg) & ~(ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_MASK	\
		<< ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_SHIFT)) | (((val) &	\
		ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_MASK) <<			\
		ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_SHIFT));			\
	} while (false)

#define ARM_DRTM_MIN_MEM_REQ_SET_MIN_DLME_DATA_SIZE(reg, val)		\
	do {								\
		reg = (((reg) &						\
		~(ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_MASK <<	\
		ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_SHIFT)) |	\
		(((val) & ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_MASK) \
		<< ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_SHIFT));	\
	} while (false)

#define ARM_DRTM_DMA_PROT_FEATURES_SET_MAX_REGIONS(reg, val)		\
	do {								\
		reg = (((reg) &						\
		~(ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_MASK <<	\
		ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_SHIFT)) |	\
		(((val) & ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_MASK)	\
		<< ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_SHIFT));	\
	} while (false)

#define ARM_DRTM_DMA_PROT_FEATURES_SET_DMA_SUPPORT(reg, val) \
	do {								\
		reg = (((reg) &						\
		~(ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_MASK <<	\
		ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_SHIFT)) |	\
		(((val) & ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_MASK)	\
		<< ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_SHIFT));	\
	} while (false)

#define ARM_DRTM_TCB_HASH_FEATURES_SET_MAX_NUM_HASHES(reg, val)		\
	do {								\
		reg = (((reg) &						\
		~(ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_MASK <<	\
		ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT)) |	\
		(((val) &						\
		ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_MASK) <<	\
		ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT));	\
	} while (false)

/* Definitions for DRTM address map */
#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_SHIFT	U(55)
#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_MASK	ULL(0x3)
#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_NC	ULL(0)
#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_WC	ULL(1)
#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_WT	ULL(2)
#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_WB	ULL(3)

#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_SHIFT	U(52)
#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_MASK	ULL(0x7)
#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NORMAL	ULL(0)
#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NCAR	ULL(1)
#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_DEVICE	ULL(2)
#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NV	ULL(3)
#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_RSVD	ULL(4)

#define ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_SHIFT	U(0)
#define ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_MASK	ULL(0xFFFFFFFFFFFFF)

#define ARM_DRTM_REGION_SIZE_TYPE_SET_CACHEABILITY(reg, val)		\
	do {								\
		reg = (((reg) &						\
		~(ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_MASK << 	\
		ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_SHIFT)) |	\
		(((val) &						\
		ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_MASK) <<		\
		ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_SHIFT));		\
	} while (false)

#define ARM_DRTM_REGION_SIZE_TYPE_SET_REGION_TYPE(reg, val)		\
	do {								\
		reg = (((reg) &						\
		~(ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_MASK <<		\
		ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_SHIFT)) |		\
		(((val) & ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_MASK)	\
		<< ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_SHIFT));	\
	} while (false)

#define ARM_DRTM_REGION_SIZE_TYPE_SET_4K_PAGE_NUM(reg, val)		\
	do {								\
		reg = (((reg) &						\
		~(ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_MASK <<		\
		ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_SHIFT)) |		\
		(((val) & ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_MASK)	\
		<< ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_SHIFT));	\
	} while (false)

/* Initialization routine for the DRTM service */
int drtm_setup(void);

/* Handler to be called to handle DRTM SMC calls */
uint64_t drtm_smc_handler(uint32_t smc_fid,
			  uint64_t x1,
			  uint64_t x2,
			  uint64_t x3,
			  uint64_t x4,
			  void *cookie,
			  void *handle,
			  uint64_t flags);

#endif /* ARM_DRTM_SVC_H */
