/*
 * Copyright (c) 2019-2020 The Fuchsia Authors
 *
 * SPDX-License-Identifier:	BSD-3-Clause
 */

#include <common.h>
#include <tee.h>
#include <tee/ta_helper.h>
#include <tee/ta_vx.h>
#include <tee/ta_vx_helper.h>

#ifdef CONFIG_TA_VX
#define VX_PERM_ATTR_HASH_SIZE 32

static struct tee_optee_ta_uuid vx_uuid = TA_VX_UUID;

static int ta_vx_setup(void)
{
	uint32_t options = 0;
	static bool setup_done = false;
	static int setup_result = 0;

	if (setup_done) {
		return setup_result;
	}

#ifdef CONFIG_TA_VX_AUTO_PROVISION_RPMB
	options |= VX_OPTION_AUTO_PROVISION_RPMB;
#endif

	if (options) {
		struct tee_param params[1] = { 0 };
		params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
		params[0].u.value.a = options;
		setup_result = ta_call(&vx_uuid, TA_VX_CMD_SET_OPTIONS,
				       ARRAY_SIZE(params), params);
	}

	setup_done = true;
	return setup_result;
}

#define SETUP_OR_FAIL()                                                        \
	do {                                                                   \
		int rc = ta_vx_setup();                                        \
		if (rc) {                                                      \
			printf("ta_vx_setup() failed, rc = %d.", rc);          \
			return rc;                                             \
		}                                                              \
	} while (0)

static int ta_vx_read_lock_state(enum vx_lock_state *lock_state)
{
	int rc;

	struct tee_param param = { 0 };
	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;

	SETUP_OR_FAIL();

	rc = ta_call(&vx_uuid, TA_VX_CMD_READ_LOCK_STATE, 1, &param);
	if (!rc) {
		*lock_state = param.u.value.a;
	}

	return rc;
}

static int ta_vx_write_lock_state(enum vx_lock_state lock_state)
{
	struct tee_param param = { 0 };
	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
	param.u.value.a = lock_state;

	SETUP_OR_FAIL();

	return ta_call(&vx_uuid, TA_VX_CMD_WRITE_LOCK_STATE, 1, &param);
}

int ta_vx_lock(void)
{
	return ta_vx_write_lock_state(VX_LOCKED);
}

int ta_vx_unlock(void)
{
	return ta_vx_write_lock_state(VX_UNLOCKED);
}

int ta_vx_is_unlocked(bool *unlocked)
{
	enum vx_lock_state lock_state;
	if (ta_vx_read_lock_state(&lock_state)) {
		return -EIO;
	}
	*unlocked = (lock_state == VX_UNLOCKED);
	return 0;
}

int ta_vx_read_rollback_index(uint32_t slot, uint64_t *rollback_index)
{
	int rc;
	struct tee_param params[2] = { 0 };

	SETUP_OR_FAIL();

	params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = slot;

	params[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;

	rc = ta_call(&vx_uuid, TA_VX_CMD_READ_ROLLBACK_INDEX,
		     ARRAY_SIZE(params), params);
	if (!rc) {
		*rollback_index = ((uint64_t)params[1].u.value.a) << 32 |
				  params[1].u.value.b;
	}

	return rc;
}

int ta_vx_write_rollback_index(uint32_t slot, uint64_t rollback_index)
{
	struct tee_param params[2] = { 0 };

	SETUP_OR_FAIL();

	params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = slot;

	params[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[1].u.value.a = rollback_index >> 32;
	params[1].u.value.b = rollback_index;

	return ta_call(&vx_uuid, TA_VX_CMD_WRITE_ROLLBACK_INDEX,
		       ARRAY_SIZE(params), params);
}

int ta_vx_read_persistent_value(const char *name, void *buf, size_t buf_len,
				size_t *bytes_read)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[2] = { 0 };

	struct tee_shm *shm_key = NULL;
	struct tee_shm *shm_buf = NULL;

	size_t key_len = strlen(name) + 1;

	SETUP_OR_FAIL();

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc)
		return rc;

	/* Pass in @key via shared memory. */
	rc = tee_shm_alloc(context.tee, key_len, TEE_SHM_ALLOC, &shm_key);
	if (rc)
		goto out;

	memcpy(shm_key->addr, name, key_len);
	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = shm_key;
	params[0].u.memref.size = key_len;

	/* Pass in buf via shared memory. */
	rc = tee_shm_alloc(context.tee, buf_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc)
		goto out;

	params[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
	params[1].u.memref.shm = shm_buf;
	params[1].u.memref.size = buf_len;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_READ_PERSIST_VALUE,
		       ARRAY_SIZE(params), params);
	if (!rc) {
		memcpy(buf, (void *)(params[1].u.memref.shm->addr),
		       params[1].u.memref.size);
		if (bytes_read) {
			*bytes_read = params[1].u.memref.size;
		}
	}

out:
	tee_shm_free(shm_key);
	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

int ta_vx_write_persistent_value(const char *name, const void *buf,
				 size_t buf_len)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[2] = { 0 };

	struct tee_shm *shm_key = NULL;
	struct tee_shm *shm_buf = NULL;

	size_t key_len = strlen(name) + 1;

	SETUP_OR_FAIL();

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc)
		return rc;

	/* Pass in @key via shared memory. */
	rc = tee_shm_alloc(context.tee, key_len, TEE_SHM_ALLOC, &shm_key);
	if (rc)
		goto out;

	memcpy(shm_key->addr, name, key_len);
	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = shm_key;
	params[0].u.memref.size = key_len;

	/* Pass in buf via shared memory. */
	rc = tee_shm_alloc(context.tee, buf_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc)
		goto out;

	memcpy(shm_buf->addr, buf, buf_len);
	params[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[1].u.memref.shm = shm_buf;
	params[1].u.memref.size = buf_len;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_WRITE_PERSIST_VALUE,
		       ARRAY_SIZE(params), params);

out:
	tee_shm_free(shm_key);
	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

int ta_vx_delete_persistent_value(const char *name)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };

	struct tee_shm *shm_key = NULL;
	size_t key_len = strlen(name) + 1;

	SETUP_OR_FAIL();

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc)
		return rc;

	/* Pass in @key via shared memory. */
	rc = tee_shm_alloc(context.tee, key_len, TEE_SHM_ALLOC, &shm_key);
	if (rc)
		goto out;
	memcpy(shm_key->addr, name, key_len);
	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = shm_key;
	params[0].u.memref.size = key_len;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_DELETE_PERSIST_VALUE,
		       ARRAY_SIZE(params), params);

out:
	tee_shm_free(shm_key);
	ta_close(&context);
	return rc;
}

int ta_vx_cprng_draw(void *buf, size_t buf_len)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };
	struct tee_shm *shm_buf = NULL;

	SETUP_OR_FAIL();

	if (!(buf && buf_len))
		return -EINVAL;

	rc = ta_open(&vx_uuid, &context);
	if (rc)
		return rc;

	rc = tee_shm_alloc(context.tee, buf_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc)
		goto out;

	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
	params[0].u.memref.shm = shm_buf;
	params[0].u.memref.size = buf_len;

	rc = ta_invoke(&context, TA_VX_CMD_CPRNG_DRAW, ARRAY_SIZE(params),
		       params);
	if (!rc) {
		memcpy(buf, (void *)(params[0].u.memref.shm->addr),
		       params[0].u.memref.size);
	}

out:
	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

void ta_vx_exit_bootloader(void)
{
	/* Exiting bootloader should panic on failure so call ta_vx_setup()
	   directly rather than using SETUP_OR_FAIL. */
	int rc = ta_vx_setup();
	if (rc) {
		printf("ta_vx_setup() failed, rc = %d.", rc);
		panic("VX setup failed!");
	}

	if (ta_call(&vx_uuid, TA_VX_CMD_EXIT_BOOTLOADER, 0, NULL)) {
		panic("VX finalization failed!");
	}

	/* Make sure we are indeed beyond the bootloader security domain. */
	struct tee_param params[1] = { 0 };
	params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = VX_OPTION_FOR_TESTING;
	if (!ta_call(&vx_uuid, TA_VX_CMD_SET_OPTIONS, ARRAY_SIZE(params),
		     params)) {
		panic("VX finalization verification failed.");
	}

	return;
}

int ta_vx_read_perm_attr(void *buf, size_t buf_len, size_t *bytes_read)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };

	struct tee_shm *shm_buf = NULL;

	SETUP_OR_FAIL();

	if (!(buf && buf_len)) {
		return -EINVAL;
	}

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc) {
		return rc;
	}

	/* Pass in buf via shared memory. */
	rc = tee_shm_alloc(context.tee, buf_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc) {
		ta_close(&context);
		return rc;
	}

	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
	params[0].u.memref.shm = shm_buf;
	params[0].u.memref.size = buf_len;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_READ_PERM_ATTR, ARRAY_SIZE(params),
		       params);
	if (!rc) {
		memcpy(buf, (void *)(params[0].u.memref.shm->addr),
		       params[0].u.memref.size);
		if (bytes_read) {
			*bytes_read = params[0].u.memref.size;
		}
	}

	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

int ta_vx_write_perm_attr(const void *buf, size_t buf_len)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };

	struct tee_shm *shm_buf = NULL;

	SETUP_OR_FAIL();

	if (!(buf && buf_len))
		return -EINVAL;

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc) {
		return rc;
	}

	/* Pass in buf via shared memory. */
	rc = tee_shm_alloc(context.tee, buf_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc) {
		ta_close(&context);
		return rc;
	}

	memcpy(shm_buf->addr, buf, buf_len);
	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = shm_buf;
	params[0].u.memref.size = buf_len;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_WRITE_PERM_ATTR, ARRAY_SIZE(params),
		       params);

	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

int ta_vx_get_rpmb_status(uint32_t *out_status, uint32_t *out_write_count)
{
	int rc;
	struct tee_param params[1] = { 0 };

	SETUP_OR_FAIL();

	params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
	rc = ta_call(&vx_uuid, TA_VX_CMD_GET_RPMB_STATUS, ARRAY_SIZE(params),
		     params);
	if (rc) {
		return rc;
	}

	if (out_status) {
		*out_status = params[0].u.value.a;
	}
	if (out_write_count) {
		*out_write_count = params[0].u.value.b;
	}

	return 0;
}

int ta_vx_provision_rpmb(void)
{
	SETUP_OR_FAIL();

	return ta_call(&vx_uuid, TA_VX_CMD_PROVISION_RPMB, 0, NULL);
}

int ta_vx_delete_perm_attr(void)
{
	SETUP_OR_FAIL();

	return ta_call(&vx_uuid, TA_VX_CMD_DELETE_PERM_ATTR, 0, NULL);
}

int ta_vx_read_perm_attr_hash(void *buf, size_t buf_len)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };

	struct tee_shm *shm_buf = NULL;

	SETUP_OR_FAIL();

	if (!buf || (buf_len < VX_PERM_ATTR_HASH_SIZE))
		return -EINVAL;

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc) {
		return rc;
	}

	/* Pass in buf via shared memory. */
	rc = tee_shm_alloc(context.tee, VX_PERM_ATTR_HASH_SIZE, TEE_SHM_ALLOC,
			   &shm_buf);
	if (rc) {
		ta_close(&context);
		return rc;
	}

	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
	params[0].u.memref.shm = shm_buf;
	params[0].u.memref.size = VX_PERM_ATTR_HASH_SIZE;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_READ_PERM_ATTR_HASH,
		       ARRAY_SIZE(params), params);
	if (!rc) {
		memcpy(buf, (void *)(params[0].u.memref.shm->addr),
		       params[0].u.memref.size);
	}

	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

int ta_vx_get_perm_attr_status(uint32_t *status)
{
	int rc;

	struct tee_param param = { 0 };
	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;

	SETUP_OR_FAIL();

	rc = ta_call(&vx_uuid, TA_VX_CMD_GET_PERM_ATTR_STATUS, 1, &param);
	if (!rc) {
		if (status) {
			*status = param.u.value.a;
		}
	}

	return rc;
}

int ta_vx_lock_perm_attr(void)
{
	SETUP_OR_FAIL();

	return ta_call(&vx_uuid, TA_VX_CMD_LOCK_PERM_ATTR, 0, NULL);
}

int ta_vx_provision_usb_hash(void)
{
	SETUP_OR_FAIL();

	return ta_call(&vx_uuid, TA_VX_CMD_PROVISION_USBBOOT_PWD_HASH, 0, NULL);
}

int ta_vx_get_usbboot_status(uint32_t *status)
{
	int rc;

	struct tee_param param = { 0 };
	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;

	SETUP_OR_FAIL();

	rc = ta_call(&vx_uuid, TA_VX_CMD_GET_USBBOOT_STATUS, 1, &param);
	if (!rc) {
		if (status) {
			*status = param.u.value.a;
		}
	}

	return rc;
}

#ifdef CONFIG_TA_VX_TESTS
int ta_vx_run_tests(const char *name)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };
	size_t name_len = strlen(name) + 1;
	struct tee_shm *shm_buf = NULL;

	SETUP_OR_FAIL();

	rc = ta_open(&vx_uuid, &context);
	if (rc)
		return rc;

	rc = tee_shm_alloc(context.tee, name_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc)
		goto out;

	memcpy(shm_buf->addr, name, name_len);
	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = shm_buf;
	params[0].u.memref.size = name_len;

	rc = ta_invoke(&context, TA_VX_CMD_RUN_TESTS, ARRAY_SIZE(params),
		       params);

out:
	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}
#endif // CONFIG_TA_VX_TESTS

#else // CONFIG_TA_VX

static int ta_vx_fail(const char *func)
{
	printf("%s: failure due to disabled VX TA\n", func);
	return -1;
}

int ta_vx_lock()
{
	return ta_vx_fail(__func__);
}

int ta_vx_unlock()
{
	return ta_vx_fail(__func__);
}

int ta_vx_is_unlocked(bool *unlocked)
{
	return ta_vx_fail(__func__);
}

int ta_vx_read_rollback_index(uint32_t slot, uint64_t *rollback_index)
{
	return ta_vx_fail(__func__);
}

int ta_vx_write_rollback_index(uint32_t slot, uint64_t rollback_index)
{
	return ta_vx_fail(__func__);
}

int ta_vx_read_persistent_value(const char *name, void *buf, size_t buf_len,
				size_t *bytes_read)
{
	return ta_vx_fail(__func__);
}

int ta_vx_write_persistent_value(const char *name, const void *val_buf,
				 size_t val_buf_len)
{
	return ta_vx_fail(__func__);
}

int ta_vx_delete_persistent_value(const char *name)
{
	return ta_vx_fail(__func__);
}

int ta_vx_cprng_draw(void *buf, size_t buf_len)
{
	return ta_vx_fail(__func__);
}

void ta_vx_exit_bootloader()
{
	/* Unlike other VX stubs, this one succeeds by default as a no-op if
	   the VX TA is disabled. */
}

int ta_vx_read_perm_attr(void *buf, size_t buf_len, size_t *bytes_read)
{
	return ta_vx_fail(__func__);
}

int ta_vx_write_perm_attr(const void *val_buf, size_t val_buf_len)
{
	return ta_vx_fail(__func__);
}

int ta_vx_read_perm_attr_hash(void *buf, size_t buf_len)
{
	return ta_vx_fail(__func__);
}

int ta_vx_delete_perm_attr(void)
{
	return ta_vx_fail(__func__);
}

int ta_vx_get_perm_attr_status(uint32_t *status)
{
	return ta_vx_fail(__func__);
}

int ta_vx_lock_perm_attr(void)
{
	return ta_vx_fail(__func__);
}

int ta_vx_get_rpmb_status(uint32_t *out_status, uint32_t *out_write_count)
{
	return ta_vx_fail(__func__);
}

int ta_vx_provision_rpmb(void)
{
	return ta_vx_fail(__func__);
}

int ta_vx_provision_usb_hash(void)
{
	return ta_vx_fail(__func__);
}

int ta_vx_get_usbboot_status(uint32_t *status)
{
	return ta_vx_fail(__func__);
}

#endif // CONFIG_TA_VX
