/*
 * Copyright (C) 2014, Samsung Electronics Co., Ltd.
 *
 * Custom SMC Handler main program for Exynos 5433
 * Header file
 */

#ifndef __HANDLER_H__
#define __HANDLER_H__

#include <stdint.h>
#include <fcTimaHashCopy.h>

struct custom_handler_params
{
    unsigned long p0;
    unsigned long p1;
    unsigned long p2;
#if defined(CONFIG_SDK30) || defined(CONFIG_SDK40)
    unsigned long p3;
    unsigned long p4;
    unsigned long p5;
#endif
    unsigned long ret_r0;
    unsigned long ret_r1;
    unsigned long ret_r2;
    unsigned long ret_r3;
};

uint32_t test_logic(uint32_t p1, uint32_t p2);

/*
 * Sample Handler Sub-function List
 */
#define SUBFUN_TEST_LOGIC	0	/* Test math, stack and global variables */
#define SUBFUN_CHECK_HASH 	100
#define SUBFUN_TRUSTBOOT_SUPPORT  110
#define SUBFUN_SECURE_PIN    120
#define SUBFUN_FP_PM_SUSPEND		121 /* handler for FingerPrint PM SUSPEND */
#define SUBFUN_FP_PM_RESUME			122 /* handler for FingerPrint PM RESUME */
#define SUBFUN_FP_BTP_OCP_HIGH		123 /* handler for FingerPrint regulator ON */
#define SUBFUN_FP_BTP_OCP_LOW		124 /* handler for FingerPrint regulator OFF */
#define SUBFUN_DMVERITY_RECOVERY   130
#define SUBFUN_KAP_VAL             140
#define SUBFUN_KAP_STATUS          150
#define SUBFUN_ICCC				180
#define SUBFUN_ICCC_SAVE        190
#define SUBFUN_ICCC_READ        200
#define SUBFUN_ICCC_SVB_RESULT  230
#define SUBFUN_ICCC_DATA_LOCK   240
#define SUBFUN_DMV_WRITE        210
#define SUBFUN_ICCC_HDM_POLICY  250

/* Jenkins Build Info */
#define SUBFUN_JENKINS_INFO		220

#define SUBFUN_TEST_CUSTOM	 44	/* Test custom call */
#define MAKE_TIMA_HASH_TABLE 	 55 /* copy hash table */
/*
 * SMC FID to finish the handler
 */
/*
#define CUSTOM_SMC_EXEC_DONE       0x83000110


#define RET_SMC_ARG4(cmd, arg0, arg1, arg2, arg3)	\
    __asm__ __volatile__ (	\
    ".arch_extension sec\n\t"	\
    "mov r0, %0\n\t"		\
    "mov r1, %1\n\t"		\
    "mov r2, %2\n\t"		\
    "mov r3, %3\n\t"		\
    "mov r4, %4\n\t"		\
    "smc #0"			\
    :				\
    : "r" (cmd), "r" (arg0), "r" (arg1),	\
    "r" (arg2), "r" (arg3)	\
    : "r0", "r1", "r2", "r3", "r4");
*/
#if defined(__aarch64__)
#define SMC_ARG1(cmd, arg0)	\
    ({int res; __asm__ __volatile__ (	\
    "mov x0, %1\n\t"		\
    "mov x1, %2\n\t"		\
    "smc #0\n\t"		\
    "mov %0, x0":		\
    "=r" (res):			\
    "r" (cmd), "r" (arg0):	\
    "x0", "x1"); res;})
#else
#define SMC_ARG1(cmd, arg0)	\
    ({int res; __asm__ __volatile__ (	\
    ".arch_extension sec\n\t"	\
    "mov r0, %1\n\t"		\
    "mov r1, %2\n\t"		\
    "smc #0\n\t"		\
    "mov %0, r0":		\
    "=r" (res):			\
    "r" (cmd), "r" (arg0):	\
    "r0", "r1"); res;})
#endif

#if defined(EXYNOS7570)
#define CONFIG_EXYNOS
#define SRAM_HASH_TABLE_PA		((uint32_t) 0x02023800) /* HASH table in iRAM */
#elif defined(EXYNOS7885) || defined(EXYNOS7870) || defined(EXYNOS7904) ||\
	defined(EXYNOS9610) || defined(EXYNOS9110) || defined(EXYNOS9810)
#define CONFIG_EXYNOS
#define SRAM_HASH_TABLE_PA		((uint32_t) 0x02023800) /* HASH table in iRAM */
#elif defined(EXYNOS9820) || defined(EXYNOS9830) || defined(EXYNOS3830) 
#define CONFIG_EXYNOS
#define SRAM_HASH_TABLE_PA		((uint32_t) 0x02025000) /* HASH table in iRAM */
#define CONFIG_SUPPORT_SHA512
#elif defined(EXYNOS9630) || defined(EXYNOS2100)
#define CONFIG_EXYNOS
#define SRAM_HASH_TABLE_PA		((uint32_t) 0x02026000) /* HASH table in iRAM */
#elif defined(S5E9925) || defined(S5E8825)
#define CONFIG_EXYNOS
#elif defined(MT6757)
#define CONFIG_MEDIATEK
#elif defined(MT6737T)
#define CONFIG_MEDIATEK
#endif

/* Common features */
#if defined(CONFIG_EXYNOS)
#define TIMA_FEATURE_FOR_64BIT
#define ICCC_SECURE_PARAMETERS_AREA
#define ICCC_ADD_CPUID
#define CONFIG_ROT_IN_ICCC
#define CONFIG_PARAMEXPANSION_ICCC
#elif defined(CONFIG_MEDIATEK)
#define ICCC_SECURE_PARAMETERS_AREA
#define ICCC_ADD_CPUID
#define CONFIG_ROT_IN_ICCC
#define CONFIG_PARAMEXPANSION_ICCC
#define TIMA_HAVE_GOOD_MEASUREMENT
#endif

#if defined(TIMA_HAVE_GOOD_MEASUREMENT)
#define GOOD_MEASUREMENT_OFFSET	((uint32_t)0xFFC00)		/* The offset of HASH values at build time */
#endif

/* SHA digest length */
#define SHA256_DIGEST_LEN 32
#define SHA512_DIGEST_LEN 64

#if defined(CONFIG_SUPPORT_SHA512)
#define SHA_DIGEST_LEN SHA512_DIGEST_LEN
#else
#define SHA_DIGEST_LEN SHA256_DIGEST_LEN
#endif

uint32_t get_efuse(int offset);
uint32_t get_seckey(int offset);
uint32_t get_chipid(void);
uint32_t get_ttbr1(void);
uint32_t get_el3_reg(int index);

#if defined(ICCC_SECURE_PARAMETERS_AREA)
#define MAX_IMAGES 12			// BOOT, RECOVERY, SYSTEM, CACHE, HIDDEN, USERDATA, OMR, VENDOR, ODM, reserved(3)
#define RESERVED_BYTES 96
#define ROT_KEY_SIZE	32
#define BL_MAGIC_STR 0xFFFA
#define TA_MAGIC_STR 0xFFFB
#define KERN_MAGIC_STR 0xFFFC
#define SYS_MAGIC_STR 0xFFFD
#define ROT_MAGIC_STR 0xFFFE

//Structure which will be passed by bootloader
typedef struct {
	uint32_t rp_ver;					/* possible values : 0,1,2.. */
	uint32_t kernel_rp;					/* possible values : 0,1,2..0xFFFFFFFF (0,1,2 ... : kernel RP version , 0XFFFFFFFF :feature not present) */
	uint32_t system_rp;					/* possible values : 0,1,2..0xFFFFFFFF (0,1,2 ... : system RP version , 0XFFFFFFFF :feature not present) */
	uint32_t test_bit;					/* possible values : 0,1 (0: not blown , 1:blown) */
	uint32_t sec_boot;					/* possible values : 0,1 (0:disable , 1:enable) */
	uint32_t react_lock;				/* possible values : 0,1,0xFFFFFFFF(0:off , 1:on , 0xFFFFFFFF:feature not present) */
	uint32_t kiwi_lock;					/* possible values : 0,1,0xFFFFFFFF(0:off , 1:on , 0xFFFFFFFF:feature not present) */
	uint32_t frp_lock;					/* possible values : 0,1,0xFFFFFFFF(0:off , 1:on , 0xFFFFFFFF:feature not present) */
	uint32_t cc_mode;					/* possible values : 0,1,0xFFFFFFFF(0:off , 1:on , 0xFFFFFFFF:feature not present) */
	uint32_t mdm_mode;					/* possible values : 0,1,0xFFFFFFFF(0:off , 1:on , 0xFFFFFFFF:feature not present) */
	uint32_t curr_bin_status;			/* possible values : 0,1 (0:official , 1:custom) */
	uint32_t afw_value;					/* possible values : 0,1,0xFFFFFFFF (0:off , 1:on, 0xFFFFFFFF: Unknown/Uninitialized) */
	uint32_t warranty_bit;				/* possible values : 0,1 (0: not blown , 1:blown) */
	uint32_t kap_status;				/* possible values : 0,1,3,0xFFFFFFFF(0:KAP OFF , 1:KAP ON - No tamper , 3:Violation(RKP and/or DMVerity says device is tampered) , 0xFFFFFFFF:feature not present) */
	uint32_t sysscope_flag;				/* possible values : 0,1,2,0xFFFFFFFF (0:official , 1:custom , 2:Scanning , 0xFFFFFFFF : rooted/value is not present/uninitialized) */
	uint32_t dmv_status;				/* possible values : 0,1,0xFFFFFFFF(0:Success , 1:Failed , 0xFFFFFFFF:Uninitialized) */
	uint8_t image_status[MAX_IMAGES];	/* possible values : 0,1,0xFF (0:official , 1:custom , 0xFF : FRP not present so cannot get image status) */
	uint32_t image_status_bl;
	uint32_t WbHistory;
	uint32_t ap_serial_0;
	uint32_t ap_serial_1;
	uint32_t verified_boot_state;
	uint32_t device_locked;
	uint32_t os_version;
	uint32_t patch_month_year;
	uint8_t verified_boot_key[SHA256_DIGEST_LEN];
	uint32_t em_status;					/* possible values : 0(market), 1(dev) */
	uint32_t em_token;
	uint32_t boot_patch_level;
	uint32_t vendor_patch_level;
	uint32_t verified_boot_hash[8];
} smc_secure_info_t;

//Start of ICCC data structures
typedef struct {
	uint16_t magic_str;
	uint16_t used_size;  //check what to do with it
}secure_param_header_t;

typedef struct {
	secure_param_header_t header;
	uint32_t rp_ver;
	uint32_t kernel_rp;
	uint32_t system_rp;
	uint32_t test_bit;
	uint32_t sec_boot;
	uint32_t react_lock;
	uint32_t kiwi_lock;
	uint32_t frp_lock;
	uint32_t cc_mode;
	uint32_t mdm_mode;
	uint32_t curr_bin_status;
	uint32_t afw_value;
	uint32_t warranty_bit;
	uint32_t kap_status;
	uint32_t image_status[MAX_IMAGES];
	uint32_t image_status_bl;
	uint32_t WbHistory;
	/* PHASE 3 */
	uint32_t ap_serial_0;
	uint32_t ap_serial_1;
	uint32_t em_status;
	uint32_t em_token;
	uint8_t reserved[RESERVED_BYTES - 32 - 8 - 8];
}bl_secure_info_t;

typedef struct {
	secure_param_header_t header;
	uint32_t pkm_text;				// possible values : 0,1,0xFFFFFFFF(0:Success , 1:Failed , 0xFFFFFFFF:Uninitialized)
	uint32_t pkm_ro;				// possible values : 0,1,0xFFFFFFFF(0:Success , 1:Failed , 0xFFFFFFFF:Uninitialized)
	uint32_t selinux_status;		// possible values : 0,1,0xFFFFFFFF(0:Enforcing , 1:Perimissive , 0xFFFFFFFF:Uninitialized)
	uint32_t sectimer_base;
	uint32_t sectimer_flag;
	uint32_t sectimer_status;
	uint32_t hdm_status;
	uint32_t atn_blob_hash[8];
	uint8_t reserved[RESERVED_BYTES - 48];
}ta_secure_info_t;

typedef struct {
	secure_param_header_t header;
	uint32_t dmv_status;			// possible values : 0,1,0xFFFFFFFF(0:Success , 1:Failed , 0xFFFFFFFF:Uninitialized)
	uint32_t verified_boot_hash[8];
	uint8_t reserved[RESERVED_BYTES - 32];
} kern_secure_info_t;

typedef struct {
	secure_param_header_t header;
	uint32_t sysscope_flag;			// possible values : 0,1,2,0xFFFFFFFF (0:official , 1:custom , 2:Scanning , 0xFFFFFFFF : rooted/value is not present/uninitialized)
	uint32_t trustboot_flag;		// possible values : 0,1,0xFFFFFFFF(0:Success , 1:Failed , 0xFFFFFFFF:Uninitialized)
	uint32_t tima_version_flag;		// possible values : 3,0xFFFFFFFF(3:TIMA version is 3.0 , 0xFFFFFFFF:Uninitialized)
	uint8_t reserved[RESERVED_BYTES - 4 ];
} sys_secure_info_t;

typedef struct {
	secure_param_header_t header;
	uint32_t verified_boot_state;
	uint32_t device_locked;
	uint32_t os_version;
	uint32_t patch_month_year;
	uint32_t verified_boot_key[8];
	uint32_t boot_patch_level;
	uint32_t vendor_patch_level;
	uint32_t reserved;
} rot_secure_info_t;

typedef struct {
	bl_secure_info_t  bl_secure_info;
	ta_secure_info_t  ta_secure_info;
	kern_secure_info_t kern_secure_info;
	sys_secure_info_t sys_secure_info;
	rot_secure_info_t rot_secure_info;
} iccc_secure_pamameters_info_t;

#define ICCC_SECURE_PARAMETERS_OFFSET 			((uint32_t)0x400)
#define ICCC_SECURE_PARAMETERS_LENGTH 			((uint32_t)sizeof(iccc_secure_pamameters_info_t))
#define ICCC_LOCK_FLAG_OFFSET 			 		((uint32_t)(ICCC_SECURE_PARAMETERS_OFFSET + ICCC_SECURE_PARAMETERS_LENGTH))
#define ICCC_LOCK_FLAG_LENGTH 			 		((uint32_t)sizeof(uint32_t))
#define ICCC_TRUSTBOOT_LOCK     0x00000001
#endif

#if (TB_TIMA_BOOT_HASH_NUM == 8)
#define TIMA_8TH_HASH_IN_SRAM
#define TIMA_7TH_HASH_IN_SRAM
#define TIMA_6TH_HASH_IN_SRAM
#elif (TB_TIMA_BOOT_HASH_NUM == 7)
#define TIMA_7TH_HASH_IN_SRAM
#define TIMA_6TH_HASH_IN_SRAM
#elif (TB_TIMA_BOOT_HASH_NUM == 6)
#define TIMA_6TH_HASH_IN_SRAM
#endif

typedef struct {
	char magic[TB_TIMA_MAGIC_LEN];
	unsigned int hash_num;
	unsigned int reserved[5];
	unsigned char hash[TB_TIMA_BOOT_HASH_NUM][SHA_DIGEST_LEN];
} TB_HASH_T;

typedef struct {
	uint8_t magic_string[16];
	uint8_t svb_magic[16];
	uint32_t vpcr1[SHA_DIGEST_LEN / sizeof(uint32_t)];
	uint32_t vpcr2[SHA_DIGEST_LEN / sizeof(uint32_t)];
	uint32_t vpcr3[SHA_DIGEST_LEN / sizeof(uint32_t)];
	uint32_t vpcr4[SHA_DIGEST_LEN / sizeof(uint32_t)];
	uint32_t vpcr5[SHA_DIGEST_LEN / sizeof(uint32_t)];
#if defined(TIMA_6TH_HASH_IN_SRAM)
	uint32_t vpcr6[SHA_DIGEST_LEN / sizeof(uint32_t)];
#endif
#if defined(TIMA_7TH_HASH_IN_SRAM)
	uint32_t vpcr7[SHA_DIGEST_LEN / sizeof(uint32_t)];
#endif
#if defined(TIMA_8TH_HASH_IN_SRAM)
	uint32_t vpcr8[SHA_DIGEST_LEN / sizeof(uint32_t)];
#endif
	uint8_t warranty_string[32];
} tima_ctx_t;

#if defined(TIMA_SHARED_INFO)
typedef struct {
	uint32_t screen_res;
}tima_info;
#endif

#endif  /* __HANDLER_H__ */
