#include "Enclave_u.h"
#include <errno.h>

typedef struct ms_ecall_sahe_add_t {
	void* ms_a;
	void* ms_b;
	void* ms_c;
	size_t ms_outlen;
	int ms_isLeftFloat;
	int ms_isRightFloat;
} ms_ecall_sahe_add_t;

typedef struct ms_ecall_sahe_mul_t {
	void* ms_a;
	long int ms_b;
	void* ms_c;
	size_t ms_outlen;
} ms_ecall_sahe_mul_t;

typedef struct ms_ecall_sahe_sub_t {
	void* ms_a;
	void* ms_b;
	void* ms_c;
	size_t ms_outlen;
	int ms_isLeftFloat;
	int ms_isRightFloat;
} ms_ecall_sahe_sub_t;

typedef struct ms_ecall_sahe_neg_t {
	void* ms_a;
	void* ms_c;
	size_t ms_outlen;
} ms_ecall_sahe_neg_t;

typedef struct ms_ecall_smhe_mul_t {
	void* ms_a;
	void* ms_b;
	void* ms_c;
	size_t ms_outlen;
	int ms_isLeftFloat;
	int ms_isRightFloat;
} ms_ecall_smhe_mul_t;

typedef struct ms_ecall_smhe_mulp_t {
	void* ms_a;
	long int ms_b;
	void* ms_c;
	size_t ms_outlen;
} ms_ecall_smhe_mulp_t;

typedef struct ms_ecall_smhe_div_t {
	void* ms_a;
	void* ms_b;
	void* ms_c;
	size_t ms_outlen;
	int ms_isLeftFloat;
	int ms_isRightFloat;
} ms_ecall_smhe_div_t;

typedef struct ms_ecall_smhe_pow_t {
	void* ms_a;
	long int ms_b;
	void* ms_c;
	size_t ms_outlen;
} ms_ecall_smhe_pow_t;

typedef struct ms_ecall_smhe_inv_t {
	void* ms_a;
	void* ms_c;
	size_t ms_outlen;
} ms_ecall_smhe_inv_t;

typedef struct ms_ecall_ore_compare_t {
	void* ms_a;
	void* ms_b;
	int* ms_c;
} ms_ecall_ore_compare_t;

typedef struct ms_ecall_genMasterKey_t {
	const char* ms_path;
} ms_ecall_genMasterKey_t;

typedef struct ms_ecall_openMasterKey_t {
	const char* ms_path;
	void* ms_out;
	size_t ms_outlen;
} ms_ecall_openMasterKey_t;

typedef struct ms_ecall_encryptKeyWithEnclave_t {
	const char* ms_key;
	size_t ms_keySize;
	const char* ms_path;
} ms_ecall_encryptKeyWithEnclave_t;

typedef struct ms_ecall_init_t {
	void* ms_pTaskQueue;
} ms_ecall_init_t;

typedef struct ms_sl_init_switchless_t {
	sgx_status_t ms_retval;
	void* ms_sl_data;
} ms_sl_init_switchless_t;

typedef struct ms_sl_run_switchless_tworker_t {
	sgx_status_t ms_retval;
} ms_sl_run_switchless_tworker_t;

typedef struct ms_ocall_ereport_t {
	const char* ms_str;
} ms_ocall_ereport_t;

typedef struct ms_ocall_usleep_t {
	size_t ms_us;
} ms_ocall_usleep_t;

typedef struct ms_ocall_read_dek_t {
	const char* ms_filename;
	char* ms_buffer;
	size_t ms_max_size;
	size_t* ms_actual_size;
} ms_ocall_read_dek_t;

typedef struct ms_u_sgxprotectedfs_exclusive_file_open_t {
	void* ms_retval;
	const char* ms_filename;
	uint8_t ms_read_only;
	int64_t* ms_file_size;
	int32_t* ms_error_code;
} ms_u_sgxprotectedfs_exclusive_file_open_t;

typedef struct ms_u_sgxprotectedfs_check_if_file_exists_t {
	uint8_t ms_retval;
	const char* ms_filename;
} ms_u_sgxprotectedfs_check_if_file_exists_t;

typedef struct ms_u_sgxprotectedfs_fread_node_t {
	int32_t ms_retval;
	void* ms_f;
	uint64_t ms_node_number;
	uint8_t* ms_buffer;
	uint32_t ms_node_size;
} ms_u_sgxprotectedfs_fread_node_t;

typedef struct ms_u_sgxprotectedfs_fwrite_node_t {
	int32_t ms_retval;
	void* ms_f;
	uint64_t ms_node_number;
	uint8_t* ms_buffer;
	uint32_t ms_node_size;
} ms_u_sgxprotectedfs_fwrite_node_t;

typedef struct ms_u_sgxprotectedfs_fclose_t {
	int32_t ms_retval;
	void* ms_f;
} ms_u_sgxprotectedfs_fclose_t;

typedef struct ms_u_sgxprotectedfs_fflush_t {
	uint8_t ms_retval;
	void* ms_f;
} ms_u_sgxprotectedfs_fflush_t;

typedef struct ms_u_sgxprotectedfs_remove_t {
	int32_t ms_retval;
	const char* ms_filename;
} ms_u_sgxprotectedfs_remove_t;

typedef struct ms_u_sgxprotectedfs_recovery_file_open_t {
	void* ms_retval;
	const char* ms_filename;
} ms_u_sgxprotectedfs_recovery_file_open_t;

typedef struct ms_u_sgxprotectedfs_fwrite_recovery_node_t {
	uint8_t ms_retval;
	void* ms_f;
	uint8_t* ms_data;
	uint32_t ms_data_length;
} ms_u_sgxprotectedfs_fwrite_recovery_node_t;

typedef struct ms_u_sgxprotectedfs_do_file_recovery_t {
	int32_t ms_retval;
	const char* ms_filename;
	const char* ms_recovery_filename;
	uint32_t ms_node_size;
} ms_u_sgxprotectedfs_do_file_recovery_t;

typedef struct ms_sgx_oc_cpuidex_t {
	int* ms_cpuinfo;
	int ms_leaf;
	int ms_subleaf;
} ms_sgx_oc_cpuidex_t;

typedef struct ms_sgx_thread_wait_untrusted_event_ocall_t {
	int ms_retval;
	const void* ms_self;
} ms_sgx_thread_wait_untrusted_event_ocall_t;

typedef struct ms_sgx_thread_set_untrusted_event_ocall_t {
	int ms_retval;
	const void* ms_waiter;
} ms_sgx_thread_set_untrusted_event_ocall_t;

typedef struct ms_sgx_thread_setwait_untrusted_events_ocall_t {
	int ms_retval;
	const void* ms_waiter;
	const void* ms_self;
} ms_sgx_thread_setwait_untrusted_events_ocall_t;

typedef struct ms_sgx_thread_set_multiple_untrusted_events_ocall_t {
	int ms_retval;
	const void** ms_waiters;
	size_t ms_total;
} ms_sgx_thread_set_multiple_untrusted_events_ocall_t;

typedef struct ms_pthread_wait_timeout_ocall_t {
	int ms_retval;
	unsigned long long ms_waiter;
	unsigned long long ms_timeout;
} ms_pthread_wait_timeout_ocall_t;

typedef struct ms_pthread_create_ocall_t {
	int ms_retval;
	unsigned long long ms_self;
} ms_pthread_create_ocall_t;

typedef struct ms_pthread_wakeup_ocall_t {
	int ms_retval;
	unsigned long long ms_waiter;
} ms_pthread_wakeup_ocall_t;

static sgx_status_t SGX_CDECL Enclave_ocall_ereport(void* pms)
{
	ms_ocall_ereport_t* ms = SGX_CAST(ms_ocall_ereport_t*, pms);
	ocall_ereport(ms->ms_str);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_ocall_usleep(void* pms)
{
	ms_ocall_usleep_t* ms = SGX_CAST(ms_ocall_usleep_t*, pms);
	ocall_usleep(ms->ms_us);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_ocall_read_dek(void* pms)
{
	ms_ocall_read_dek_t* ms = SGX_CAST(ms_ocall_read_dek_t*, pms);
	ocall_read_dek(ms->ms_filename, ms->ms_buffer, ms->ms_max_size, ms->ms_actual_size);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_u_sgxprotectedfs_exclusive_file_open(void* pms)
{
	ms_u_sgxprotectedfs_exclusive_file_open_t* ms = SGX_CAST(ms_u_sgxprotectedfs_exclusive_file_open_t*, pms);
	ms->ms_retval = u_sgxprotectedfs_exclusive_file_open(ms->ms_filename, ms->ms_read_only, ms->ms_file_size, ms->ms_error_code);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_u_sgxprotectedfs_check_if_file_exists(void* pms)
{
	ms_u_sgxprotectedfs_check_if_file_exists_t* ms = SGX_CAST(ms_u_sgxprotectedfs_check_if_file_exists_t*, pms);
	ms->ms_retval = u_sgxprotectedfs_check_if_file_exists(ms->ms_filename);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_u_sgxprotectedfs_fread_node(void* pms)
{
	ms_u_sgxprotectedfs_fread_node_t* ms = SGX_CAST(ms_u_sgxprotectedfs_fread_node_t*, pms);
	ms->ms_retval = u_sgxprotectedfs_fread_node(ms->ms_f, ms->ms_node_number, ms->ms_buffer, ms->ms_node_size);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_u_sgxprotectedfs_fwrite_node(void* pms)
{
	ms_u_sgxprotectedfs_fwrite_node_t* ms = SGX_CAST(ms_u_sgxprotectedfs_fwrite_node_t*, pms);
	ms->ms_retval = u_sgxprotectedfs_fwrite_node(ms->ms_f, ms->ms_node_number, ms->ms_buffer, ms->ms_node_size);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_u_sgxprotectedfs_fclose(void* pms)
{
	ms_u_sgxprotectedfs_fclose_t* ms = SGX_CAST(ms_u_sgxprotectedfs_fclose_t*, pms);
	ms->ms_retval = u_sgxprotectedfs_fclose(ms->ms_f);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_u_sgxprotectedfs_fflush(void* pms)
{
	ms_u_sgxprotectedfs_fflush_t* ms = SGX_CAST(ms_u_sgxprotectedfs_fflush_t*, pms);
	ms->ms_retval = u_sgxprotectedfs_fflush(ms->ms_f);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_u_sgxprotectedfs_remove(void* pms)
{
	ms_u_sgxprotectedfs_remove_t* ms = SGX_CAST(ms_u_sgxprotectedfs_remove_t*, pms);
	ms->ms_retval = u_sgxprotectedfs_remove(ms->ms_filename);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_u_sgxprotectedfs_recovery_file_open(void* pms)
{
	ms_u_sgxprotectedfs_recovery_file_open_t* ms = SGX_CAST(ms_u_sgxprotectedfs_recovery_file_open_t*, pms);
	ms->ms_retval = u_sgxprotectedfs_recovery_file_open(ms->ms_filename);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_u_sgxprotectedfs_fwrite_recovery_node(void* pms)
{
	ms_u_sgxprotectedfs_fwrite_recovery_node_t* ms = SGX_CAST(ms_u_sgxprotectedfs_fwrite_recovery_node_t*, pms);
	ms->ms_retval = u_sgxprotectedfs_fwrite_recovery_node(ms->ms_f, ms->ms_data, ms->ms_data_length);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_u_sgxprotectedfs_do_file_recovery(void* pms)
{
	ms_u_sgxprotectedfs_do_file_recovery_t* ms = SGX_CAST(ms_u_sgxprotectedfs_do_file_recovery_t*, pms);
	ms->ms_retval = u_sgxprotectedfs_do_file_recovery(ms->ms_filename, ms->ms_recovery_filename, ms->ms_node_size);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_sgx_oc_cpuidex(void* pms)
{
	ms_sgx_oc_cpuidex_t* ms = SGX_CAST(ms_sgx_oc_cpuidex_t*, pms);
	sgx_oc_cpuidex(ms->ms_cpuinfo, ms->ms_leaf, ms->ms_subleaf);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_sgx_thread_wait_untrusted_event_ocall(void* pms)
{
	ms_sgx_thread_wait_untrusted_event_ocall_t* ms = SGX_CAST(ms_sgx_thread_wait_untrusted_event_ocall_t*, pms);
	ms->ms_retval = sgx_thread_wait_untrusted_event_ocall(ms->ms_self);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_sgx_thread_set_untrusted_event_ocall(void* pms)
{
	ms_sgx_thread_set_untrusted_event_ocall_t* ms = SGX_CAST(ms_sgx_thread_set_untrusted_event_ocall_t*, pms);
	ms->ms_retval = sgx_thread_set_untrusted_event_ocall(ms->ms_waiter);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_sgx_thread_setwait_untrusted_events_ocall(void* pms)
{
	ms_sgx_thread_setwait_untrusted_events_ocall_t* ms = SGX_CAST(ms_sgx_thread_setwait_untrusted_events_ocall_t*, pms);
	ms->ms_retval = sgx_thread_setwait_untrusted_events_ocall(ms->ms_waiter, ms->ms_self);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_sgx_thread_set_multiple_untrusted_events_ocall(void* pms)
{
	ms_sgx_thread_set_multiple_untrusted_events_ocall_t* ms = SGX_CAST(ms_sgx_thread_set_multiple_untrusted_events_ocall_t*, pms);
	ms->ms_retval = sgx_thread_set_multiple_untrusted_events_ocall(ms->ms_waiters, ms->ms_total);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_pthread_wait_timeout_ocall(void* pms)
{
	ms_pthread_wait_timeout_ocall_t* ms = SGX_CAST(ms_pthread_wait_timeout_ocall_t*, pms);
	ms->ms_retval = pthread_wait_timeout_ocall(ms->ms_waiter, ms->ms_timeout);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_pthread_create_ocall(void* pms)
{
	ms_pthread_create_ocall_t* ms = SGX_CAST(ms_pthread_create_ocall_t*, pms);
	ms->ms_retval = pthread_create_ocall(ms->ms_self);

	return SGX_SUCCESS;
}

static sgx_status_t SGX_CDECL Enclave_pthread_wakeup_ocall(void* pms)
{
	ms_pthread_wakeup_ocall_t* ms = SGX_CAST(ms_pthread_wakeup_ocall_t*, pms);
	ms->ms_retval = pthread_wakeup_ocall(ms->ms_waiter);

	return SGX_SUCCESS;
}

static const struct {
	size_t nr_ocall;
	void * table[21];
} ocall_table_Enclave = {
	21,
	{
		(void*)Enclave_ocall_ereport,
		(void*)Enclave_ocall_usleep,
		(void*)Enclave_ocall_read_dek,
		(void*)Enclave_u_sgxprotectedfs_exclusive_file_open,
		(void*)Enclave_u_sgxprotectedfs_check_if_file_exists,
		(void*)Enclave_u_sgxprotectedfs_fread_node,
		(void*)Enclave_u_sgxprotectedfs_fwrite_node,
		(void*)Enclave_u_sgxprotectedfs_fclose,
		(void*)Enclave_u_sgxprotectedfs_fflush,
		(void*)Enclave_u_sgxprotectedfs_remove,
		(void*)Enclave_u_sgxprotectedfs_recovery_file_open,
		(void*)Enclave_u_sgxprotectedfs_fwrite_recovery_node,
		(void*)Enclave_u_sgxprotectedfs_do_file_recovery,
		(void*)Enclave_sgx_oc_cpuidex,
		(void*)Enclave_sgx_thread_wait_untrusted_event_ocall,
		(void*)Enclave_sgx_thread_set_untrusted_event_ocall,
		(void*)Enclave_sgx_thread_setwait_untrusted_events_ocall,
		(void*)Enclave_sgx_thread_set_multiple_untrusted_events_ocall,
		(void*)Enclave_pthread_wait_timeout_ocall,
		(void*)Enclave_pthread_create_ocall,
		(void*)Enclave_pthread_wakeup_ocall,
	}
};
sgx_status_t ecall_sahe_add(sgx_enclave_id_t eid, void* a, void* b, void* c, size_t outlen, int isLeftFloat, int isRightFloat)
{
	sgx_status_t status;
	ms_ecall_sahe_add_t ms;
	ms.ms_a = a;
	ms.ms_b = b;
	ms.ms_c = c;
	ms.ms_outlen = outlen;
	ms.ms_isLeftFloat = isLeftFloat;
	ms.ms_isRightFloat = isRightFloat;
	status = sgx_ecall_switchless(eid, 0, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_sahe_mul(sgx_enclave_id_t eid, void* a, long int b, void* c, size_t outlen)
{
	sgx_status_t status;
	ms_ecall_sahe_mul_t ms;
	ms.ms_a = a;
	ms.ms_b = b;
	ms.ms_c = c;
	ms.ms_outlen = outlen;
	status = sgx_ecall_switchless(eid, 1, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_sahe_sub(sgx_enclave_id_t eid, void* a, void* b, void* c, size_t outlen, int isLeftFloat, int isRightFloat)
{
	sgx_status_t status;
	ms_ecall_sahe_sub_t ms;
	ms.ms_a = a;
	ms.ms_b = b;
	ms.ms_c = c;
	ms.ms_outlen = outlen;
	ms.ms_isLeftFloat = isLeftFloat;
	ms.ms_isRightFloat = isRightFloat;
	status = sgx_ecall_switchless(eid, 2, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_sahe_neg(sgx_enclave_id_t eid, void* a, void* c, size_t outlen)
{
	sgx_status_t status;
	ms_ecall_sahe_neg_t ms;
	ms.ms_a = a;
	ms.ms_c = c;
	ms.ms_outlen = outlen;
	status = sgx_ecall_switchless(eid, 3, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_smhe_mul(sgx_enclave_id_t eid, void* a, void* b, void* c, size_t outlen, int isLeftFloat, int isRightFloat)
{
	sgx_status_t status;
	ms_ecall_smhe_mul_t ms;
	ms.ms_a = a;
	ms.ms_b = b;
	ms.ms_c = c;
	ms.ms_outlen = outlen;
	ms.ms_isLeftFloat = isLeftFloat;
	ms.ms_isRightFloat = isRightFloat;
	status = sgx_ecall_switchless(eid, 4, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_smhe_mulp(sgx_enclave_id_t eid, void* a, long int b, void* c, size_t outlen)
{
	sgx_status_t status;
	ms_ecall_smhe_mulp_t ms;
	ms.ms_a = a;
	ms.ms_b = b;
	ms.ms_c = c;
	ms.ms_outlen = outlen;
	status = sgx_ecall_switchless(eid, 5, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_smhe_div(sgx_enclave_id_t eid, void* a, void* b, void* c, size_t outlen, int isLeftFloat, int isRightFloat)
{
	sgx_status_t status;
	ms_ecall_smhe_div_t ms;
	ms.ms_a = a;
	ms.ms_b = b;
	ms.ms_c = c;
	ms.ms_outlen = outlen;
	ms.ms_isLeftFloat = isLeftFloat;
	ms.ms_isRightFloat = isRightFloat;
	status = sgx_ecall_switchless(eid, 6, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_smhe_pow(sgx_enclave_id_t eid, void* a, long int b, void* c, size_t outlen)
{
	sgx_status_t status;
	ms_ecall_smhe_pow_t ms;
	ms.ms_a = a;
	ms.ms_b = b;
	ms.ms_c = c;
	ms.ms_outlen = outlen;
	status = sgx_ecall_switchless(eid, 7, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_smhe_inv(sgx_enclave_id_t eid, void* a, void* c, size_t outlen)
{
	sgx_status_t status;
	ms_ecall_smhe_inv_t ms;
	ms.ms_a = a;
	ms.ms_c = c;
	ms.ms_outlen = outlen;
	status = sgx_ecall_switchless(eid, 8, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_ore_compare(sgx_enclave_id_t eid, void* a, void* b, int* c)
{
	sgx_status_t status;
	ms_ecall_ore_compare_t ms;
	ms.ms_a = a;
	ms.ms_b = b;
	ms.ms_c = c;
	status = sgx_ecall_switchless(eid, 9, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_genMasterKey(sgx_enclave_id_t eid, const char* path)
{
	sgx_status_t status;
	ms_ecall_genMasterKey_t ms;
	ms.ms_path = path;
	status = sgx_ecall_switchless(eid, 10, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_openMasterKey(sgx_enclave_id_t eid, const char* path, void* out, size_t outlen)
{
	sgx_status_t status;
	ms_ecall_openMasterKey_t ms;
	ms.ms_path = path;
	ms.ms_out = out;
	ms.ms_outlen = outlen;
	status = sgx_ecall_switchless(eid, 11, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_encryptKeyWithEnclave(sgx_enclave_id_t eid, const char* key, size_t keySize, const char* path)
{
	sgx_status_t status;
	ms_ecall_encryptKeyWithEnclave_t ms;
	ms.ms_key = key;
	ms.ms_keySize = keySize;
	ms.ms_path = path;
	status = sgx_ecall_switchless(eid, 12, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t ecall_init(sgx_enclave_id_t eid, void* pTaskQueue)
{
	sgx_status_t status;
	ms_ecall_init_t ms;
	ms.ms_pTaskQueue = pTaskQueue;
	status = sgx_ecall(eid, 13, &ocall_table_Enclave, &ms);
	return status;
}

sgx_status_t sl_init_switchless(sgx_enclave_id_t eid, sgx_status_t* retval, void* sl_data)
{
	sgx_status_t status;
	ms_sl_init_switchless_t ms;
	ms.ms_sl_data = sl_data;
	status = sgx_ecall(eid, 14, &ocall_table_Enclave, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

sgx_status_t sl_run_switchless_tworker(sgx_enclave_id_t eid, sgx_status_t* retval)
{
	sgx_status_t status;
	ms_sl_run_switchless_tworker_t ms;
	status = sgx_ecall(eid, 15, &ocall_table_Enclave, &ms);
	if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval;
	return status;
}

