// SPDX-License-Identifier: BSD-3-Clause
/*
 * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
 */

#include <assert.h>            // for assert
#include <stddef.h>            // for size_t
#include <stdint.h>            // for uint32_t, uint16_t, uintptr_t, U
#include "ffa_api.h"           // for FFA_OK, ffa_interrupt_handler, ffa_fea...
#include "ffa_api_defines.h"   // for FFA_PARAM_MBZ, FFA_OK, FFA_ERROR, FFA_...
#include "ffa_api_types.h"     // for ffa_result, ffa_direct_msg, ffa_uuid
#include "ffa_internal_api.h"  // for ffa_params, ffa_svc
#include "util.h"              // for GENMASK_32, SHIFT_U32, BIT

/*
 * Unpacks the error code from the FFA_ERROR message. It is a signed 32 bit
 * value in an unsigned 64 bit field so proper casting must be used to avoid
 * compiler dependent behavior.
 */
static inline ffa_result ffa_get_errorcode(struct ffa_params *result)
{
	uint32_t raw_value = result->a2;

	return *(ffa_result *)(&raw_value);
}

/*
 * Unpacks the content of the SVC result into an ffa_direct_msg structure.
 */
static inline void ffa_unpack_direct_msg(struct ffa_params *svc_result,
					 struct ffa_direct_msg *msg)
{
	msg->function_id = svc_result->a0;
	msg->source_id = (svc_result->a1 >> 16);
	msg->destination_id = svc_result->a1;
	msg->args[0] = svc_result->a3;
	msg->args[1] = svc_result->a4;
	msg->args[2] = svc_result->a5;
	msg->args[3] = svc_result->a6;
	msg->args[4] = svc_result->a7;
}

/*
 * The end of the interrupt handler is indicated by an FFA_MSG_WAIT call.
 */
static inline void ffa_return_from_interrupt(struct ffa_params *result)
{
	ffa_svc(FFA_MSG_WAIT, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		result);
}

static inline void ffa_uuid_to_abi_format(const struct ffa_uuid *uuid,
					  uint32_t *result)
{
	size_t i = 0;

	for (i = 0; i < 4; i++) {
		result[i] = uuid->uuid[4 * i];
		result[i] |= SHIFT_U32(uuid->uuid[4 * i + 1], 8);
		result[i] |= SHIFT_U32(uuid->uuid[4 * i + 2], 16);
		result[i] |= SHIFT_U32(uuid->uuid[4 * i + 3], 24);
	}
}

ffa_result ffa_version(uint32_t *version)
{
	struct ffa_params result = {0};
	uint32_t self_version = 0;

	self_version = (FFA_VERSION_MAJOR << FFA_VERSION_MAJOR_SHIFT) |
		       (FFA_VERSION_MINOR << FFA_VERSION_MINOR);

	ffa_svc(FFA_VERSION, self_version, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	if (result.a0 & BIT(31)) {
		uint32_t raw_error = result.a0;

		*version = 0;

		return *(ffa_result *)(&raw_error);
	}

	*version = result.a0;
	return FFA_OK;
}

ffa_result ffa_features(uint32_t ffa_function_id,
			struct ffa_interface_properties *interface_properties)
{
	struct ffa_params result = {0};

	ffa_svc(FFA_FEATURES, ffa_function_id, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	if (result.a0 == FFA_ERROR) {
		interface_properties->interface_properties[0] = 0;
		interface_properties->interface_properties[1] = 0;
		return ffa_get_errorcode(&result);
	}

	assert(result.a0 == FFA_SUCCESS_32);
	interface_properties->interface_properties[0] = result.a2;
	interface_properties->interface_properties[1] = result.a3;
	return FFA_OK;
}

ffa_result ffa_rx_release(void)
{
	struct ffa_params result = {0};

	ffa_svc(FFA_RX_RELEASE, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	if (result.a0 == FFA_ERROR)
		return ffa_get_errorcode(&result);

	assert(result.a0 == FFA_SUCCESS_32);
	return FFA_OK;
}

ffa_result ffa_rxtx_map(const void *tx_buffer, const void *rx_buffer,
			uint32_t page_count)
{
	struct ffa_params result = {0};

	assert(page_count <= FFA_RXTX_MAP_PAGE_COUNT_MAX);

	page_count = SHIFT_U32(page_count & FFA_RXTX_MAP_PAGE_COUNT_MASK,
			       FFA_RXTX_MAP_PAGE_COUNT_SHIFT);

	ffa_svc(FFA_RXTX_MAP_64, (uintptr_t)tx_buffer, (uintptr_t)rx_buffer,
		page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		FFA_PARAM_MBZ, &result);

	if (result.a0 == FFA_ERROR)
		return ffa_get_errorcode(&result);

	/*
	 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
	 * will use the default 32-bit version.
	 */
	assert(result.a0 == FFA_SUCCESS_32);
	return FFA_OK;
}

ffa_result ffa_rxtx_unmap(uint16_t id)
{
	struct ffa_params result = {0};

	ffa_svc(FFA_RXTX_UNMAP, SHIFT_U32(id, FFA_RXTX_UNMAP_ID_SHIFT),
		FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);

	if (result.a0 == FFA_ERROR)
		return ffa_get_errorcode(&result);

	assert(result.a0 == FFA_SUCCESS_32);
	return FFA_OK;
}

ffa_result ffa_partition_info_get(const struct ffa_uuid *uuid, uint32_t *count)
{
	struct ffa_params result = {0};
	uint32_t abi_uuid[4] = {0};

	ffa_uuid_to_abi_format(uuid, abi_uuid);

	ffa_svc(FFA_PARTITION_INFO_GET, abi_uuid[0], abi_uuid[1], abi_uuid[2],
		abi_uuid[3], FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	if (result.a0 == FFA_ERROR) {
		*count = UINT32_C(0);
		return ffa_get_errorcode(&result);
	}

	assert(result.a0 == FFA_SUCCESS_32);
	*count = result.a2;
	return FFA_OK;
}

ffa_result ffa_id_get(uint16_t *id)
{
	struct ffa_params result = {0};

	ffa_svc(FFA_ID_GET, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	if (result.a0 == FFA_ERROR) {
		*id = FFA_ID_GET_ID_MASK;
		return ffa_get_errorcode(&result);
	}

	assert(result.a0 == FFA_SUCCESS_32);
	*id = (result.a2 >> FFA_ID_GET_ID_SHIFT) & FFA_ID_GET_ID_MASK;
	return FFA_OK;
}

ffa_result ffa_msg_wait(struct ffa_direct_msg *msg)
{
	struct ffa_params result = {0};

	ffa_svc(FFA_MSG_WAIT, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	while (result.a0 == FFA_INTERRUPT) {
		ffa_interrupt_handler(result.a2);
		ffa_return_from_interrupt(&result);
	}

	if (result.a0 == FFA_ERROR) {
		return ffa_get_errorcode(&result);
	} else if (result.a0 == FFA_MSG_SEND_DIRECT_REQ_32) {
		ffa_unpack_direct_msg(&result, msg);
	} else {
		assert(result.a0 == FFA_SUCCESS_32);
		*msg = (struct ffa_direct_msg){.function_id = result.a0};
	}

	return FFA_OK;
}

ffa_result ffa_msg_send_direct_req(uint16_t source, uint16_t dest, uint32_t a0,
				   uint32_t a1, uint32_t a2, uint32_t a3,
				   uint32_t a4, struct ffa_direct_msg *msg)
{
	struct ffa_params result = {0};

	ffa_svc(FFA_MSG_SEND_DIRECT_REQ_32,
		SHIFT_U32(source, FFA_MSG_SEND_DIRECT_REQ_SOURCE_ID_SHIFT) |
		dest, FFA_PARAM_MBZ, a0, a1, a2, a3, a4, &result);

	while (result.a0 == FFA_INTERRUPT) {
		ffa_interrupt_handler(result.a2);
		ffa_return_from_interrupt(&result);
	}

	if (result.a0 == FFA_ERROR) {
		return ffa_get_errorcode(&result);
	} else if (result.a0 == FFA_MSG_SEND_DIRECT_RESP_32) {
		ffa_unpack_direct_msg(&result, msg);
	} else {
		assert(result.a0 == FFA_SUCCESS_32);
		*msg = (struct ffa_direct_msg){.function_id = result.a0};
	}

	return FFA_OK;
}

ffa_result ffa_msg_send_direct_resp(uint16_t source, uint16_t dest, uint32_t a0,
				    uint32_t a1, uint32_t a2, uint32_t a3,
				    uint32_t a4, struct ffa_direct_msg *msg)
{
	struct ffa_params result = {0};

	ffa_svc(FFA_MSG_SEND_DIRECT_RESP_32,
		SHIFT_U32(source, FFA_MSG_SEND_DIRECT_RESP_SOURCE_ID_SHIFT) |
		dest, FFA_PARAM_MBZ, a0, a1, a2, a3, a4, &result);

	while (result.a0 == FFA_INTERRUPT) {
		ffa_interrupt_handler(result.a2);
		ffa_return_from_interrupt(&result);
	}

	if (result.a0 == FFA_ERROR) {
		return ffa_get_errorcode(&result);
	} else if (result.a0 == FFA_MSG_SEND_DIRECT_REQ_32) {
		ffa_unpack_direct_msg(&result, msg);
	} else {
		assert(result.a0 == FFA_SUCCESS_32);
		*msg = (struct ffa_direct_msg){.function_id = result.a0};
	}

	return FFA_OK;
}

ffa_result ffa_mem_donate(uint32_t total_length, uint32_t fragment_length,
			  void *buffer_address, uint32_t page_count,
			  uint64_t *handle)
{
	struct ffa_params result = {0};

	ffa_svc((buffer_address) ? FFA_MEM_DONATE_64 : FFA_MEM_DONATE_32,
		total_length, fragment_length, (uintptr_t)buffer_address,
		page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	if (result.a0 == FFA_ERROR) {
		*handle = 0U;
		return ffa_get_errorcode(&result);
	}

	/*
	 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
	 * will use the default 32-bit version.
	 */
	assert(result.a0 == FFA_SUCCESS_32);
	*handle = reg_pair_to_64(result.a3, result.a2);
	return FFA_OK;
}

ffa_result ffa_mem_donate_rxtx(uint32_t total_length, uint32_t fragment_length,
			       uint64_t *handle)
{
	return ffa_mem_donate(total_length, fragment_length, NULL, 0, handle);
}

ffa_result ffa_mem_lend(uint32_t total_length, uint32_t fragment_length,
			void *buffer_address, uint32_t page_count,
			uint64_t *handle)
{
	struct ffa_params result = {0};

	ffa_svc((buffer_address) ? FFA_MEM_LEND_64 : FFA_MEM_LEND_32,
		total_length, fragment_length, (uintptr_t)buffer_address,
		page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	if (result.a0 == FFA_ERROR) {
		*handle = 0U;
		return ffa_get_errorcode(&result);
	}

	/*
	 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
	 * will use the default 32-bit version.
	 */
	assert(result.a0 == FFA_SUCCESS_32);
	*handle = reg_pair_to_64(result.a3, result.a2);
	return FFA_OK;
}

ffa_result ffa_mem_lend_rxtx(uint32_t total_length, uint32_t fragment_length,
			     uint64_t *handle)
{
	return ffa_mem_lend(total_length, fragment_length, NULL, 0, handle);
}

ffa_result ffa_mem_share(uint32_t total_length, uint32_t fragment_length,
			 void *buffer_address, uint32_t page_count,
			 uint64_t *handle)
{
	struct ffa_params result = {0};

	ffa_svc((buffer_address) ? FFA_MEM_SHARE_64 : FFA_MEM_SHARE_32,
		total_length, fragment_length, (uintptr_t)buffer_address,
		page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	if (result.a0 == FFA_ERROR) {
		*handle = 0U;
		return ffa_get_errorcode(&result);
	}

	/*
	 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
	 * will use the default 32-bit version.
	 */
	assert(result.a0 == FFA_SUCCESS_32);
	*handle = reg_pair_to_64(result.a3, result.a2);
	return FFA_OK;
}

ffa_result ffa_mem_share_rxtx(uint32_t total_length, uint32_t fragment_length,
			      uint64_t *handle)
{
	return ffa_mem_share(total_length, fragment_length, NULL, 0, handle);
}

ffa_result ffa_mem_retrieve_req(uint32_t total_length, uint32_t fragment_length,
				void *buffer_address, uint32_t page_count,
				uint32_t *resp_total_length,
				uint32_t *resp_fragment_length)
{
	struct ffa_params result = {0};

	ffa_svc((buffer_address) ? FFA_MEM_RETRIEVE_REQ_64 : FFA_MEM_RETRIEVE_REQ_32,
		total_length, fragment_length, (uintptr_t)buffer_address,
		page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	if (result.a0 == FFA_ERROR) {
		*resp_total_length = 0U;
		*resp_fragment_length = 0U;
		return ffa_get_errorcode(&result);
	}

	assert(result.a0 == FFA_MEM_RETRIEVE_RESP);
	*resp_total_length = result.a1;
	*resp_fragment_length = result.a2;
	return FFA_OK;
}

ffa_result ffa_mem_retrieve_req_rxtx(uint32_t total_length,
				     uint32_t fragment_length,
				     uint32_t *resp_total_length,
				     uint32_t *resp_fragment_length)
{
	return ffa_mem_retrieve_req(total_length, fragment_length, NULL, 0,
				    resp_total_length, resp_fragment_length);
}

ffa_result ffa_mem_relinquish(void)
{
	struct ffa_params result = {0};

	ffa_svc(FFA_MEM_RELINQUISH, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		&result);

	if (result.a0 == FFA_ERROR)
		return ffa_get_errorcode(&result);

	assert(result.a0 == FFA_SUCCESS_32);
	return FFA_OK;
}

ffa_result ffa_mem_reclaim(uint64_t handle, uint32_t flags)
{
	struct ffa_params result = {0};
	uint32_t handle_hi = 0;
	uint32_t handle_lo = 0;

	reg_pair_from_64(handle, &handle_hi, &handle_lo);

	ffa_svc(FFA_MEM_RECLAIM, handle_lo, handle_hi, flags, FFA_PARAM_MBZ,
		FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);

	if (result.a0 == FFA_ERROR)
		return ffa_get_errorcode(&result);

	assert(result.a0 == FFA_SUCCESS_32);
	return FFA_OK;
}
