/*
 * Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved.
 * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <inttypes.h>
#include <stdint.h>

#include <arch_helpers.h>
#include <common/debug.h>
#include <plat_startup.h>


/*
 * TFAHandoffParams
 * Parameter		bitfield	encoding
 * -----------------------------------------------------------------------------
 * Exec State		0		0 -> Aarch64, 1-> Aarch32
 * endianness		1		0 -> LE, 1 -> BE
 * secure (TZ)		2		0 -> Non secure, 1 -> secure
 * EL			3:4		00 -> EL0, 01 -> EL1, 10 -> EL2, 11 -> EL3
 * CPU#			5:6		00 -> A53_0, 01 -> A53_1, 10 -> A53_2, 11 -> A53_3
 */

#define FSBL_FLAGS_ESTATE_SHIFT		0U
#define FSBL_FLAGS_ESTATE_MASK		(1U << FSBL_FLAGS_ESTATE_SHIFT)
#define FSBL_FLAGS_ESTATE_A64		0U
#define FSBL_FLAGS_ESTATE_A32		1U

#define FSBL_FLAGS_ENDIAN_SHIFT		1U
#define FSBL_FLAGS_ENDIAN_MASK		(1U << FSBL_FLAGS_ENDIAN_SHIFT)
#define FSBL_FLAGS_ENDIAN_LE		0U
#define FSBL_FLAGS_ENDIAN_BE		1U

#define FSBL_FLAGS_TZ_SHIFT		2U
#define FSBL_FLAGS_TZ_MASK		(1U << FSBL_FLAGS_TZ_SHIFT)
#define FSBL_FLAGS_NON_SECURE		0U
#define FSBL_FLAGS_SECURE		1U

#define FSBL_FLAGS_EL_SHIFT		3U
#define FSBL_FLAGS_EL_MASK		(3U << FSBL_FLAGS_EL_SHIFT)
#define FSBL_FLAGS_EL0			0U
#define FSBL_FLAGS_EL1			1U
#define FSBL_FLAGS_EL2			2U
#define FSBL_FLAGS_EL3			3U

#define FSBL_FLAGS_CPU_SHIFT		5U
#define FSBL_FLAGS_CPU_MASK		(3U << FSBL_FLAGS_CPU_SHIFT)
#define FSBL_FLAGS_A53_0		0U
#define FSBL_FLAGS_A53_1		1U
#define FSBL_FLAGS_A53_2		2U
#define FSBL_FLAGS_A53_3		3U

/**
 * @partition: Pointer to partition struct
 *
 * Get the target CPU for @partition.
 *
 * Return: FSBL_FLAGS_A53_0, FSBL_FLAGS_A53_1, FSBL_FLAGS_A53_2 or FSBL_FLAGS_A53_3
 */
static int32_t get_fsbl_cpu(const struct xfsbl_partition *partition)
{
	uint64_t flags = partition->flags & FSBL_FLAGS_CPU_MASK;

	return flags >> FSBL_FLAGS_CPU_SHIFT;
}

/**
 * @partition: Pointer to partition struct
 *
 * Get the target exception level for @partition.
 *
 * Return: FSBL_FLAGS_EL0, FSBL_FLAGS_EL1, FSBL_FLAGS_EL2 or FSBL_FLAGS_EL3
 */
static int32_t get_fsbl_el(const struct xfsbl_partition *partition)
{
	uint64_t flags = partition->flags & FSBL_FLAGS_EL_MASK;

	return flags >> FSBL_FLAGS_EL_SHIFT;
}

/**
 * @partition: Pointer to partition struct
 *
 * Get the target security state for @partition.
 *
 * Return: FSBL_FLAGS_NON_SECURE or FSBL_FLAGS_SECURE
 */
static int32_t get_fsbl_ss(const struct xfsbl_partition *partition)
{
	uint64_t flags = partition->flags & FSBL_FLAGS_TZ_MASK;

	return flags >> FSBL_FLAGS_TZ_SHIFT;
}

/**
 * @partition: Pointer to partition struct
 *
 * Get the target endianness for @partition.
 *
 * Return: SPSR_E_LITTLE or SPSR_E_BIG
 */
static int32_t get_fsbl_endian(const struct xfsbl_partition *partition)
{
	uint64_t flags = partition->flags & FSBL_FLAGS_ENDIAN_MASK;

	flags >>= FSBL_FLAGS_ENDIAN_SHIFT;

	if (flags == FSBL_FLAGS_ENDIAN_BE) {
		return SPSR_E_BIG;
	} else {
		return SPSR_E_LITTLE;
	}
}

/**
 * @partition: Pointer to partition struct
 *
 * Get the target execution state for @partition.
 *
 * Return: FSBL_FLAGS_ESTATE_A32 or FSBL_FLAGS_ESTATE_A64
 */
static int32_t get_fsbl_estate(const struct xfsbl_partition *partition)
{
	uint64_t flags = partition->flags & FSBL_FLAGS_ESTATE_MASK;

	return flags >> FSBL_FLAGS_ESTATE_SHIFT;
}

/**
 * Populates the bl32 and bl33 image info structures
 * @bl32:	BL32 image info structure
 * @bl33:	BL33 image info structure
 * tfa_handoff_addr:  TF-A handoff address
 *
 * Process the handoff parameters from the FSBL and populate the BL32 and BL33
 * image info structures accordingly.
 *
 * Return: Return the status of the handoff. The value will be from the
 *         fsbl_handoff enum.
 */
enum fsbl_handoff fsbl_tfa_handover(entry_point_info_t *bl32,
					entry_point_info_t *bl33,
					uint64_t tfa_handoff_addr)
{
	const struct xfsbl_tfa_handoff_params *TFAHandoffParams;
	if (!tfa_handoff_addr) {
		WARN("BL31: No TFA handoff structure passed\n");
		return FSBL_HANDOFF_NO_STRUCT;
	}

	TFAHandoffParams = (struct xfsbl_tfa_handoff_params *)tfa_handoff_addr;
	if ((TFAHandoffParams->magic[0] != 'X') ||
	    (TFAHandoffParams->magic[1] != 'L') ||
	    (TFAHandoffParams->magic[2] != 'N') ||
	    (TFAHandoffParams->magic[3] != 'X')) {
		ERROR("BL31: invalid TF-A handoff structure at %" PRIx64 "\n",
		      tfa_handoff_addr);
		return FSBL_HANDOFF_INVAL_STRUCT;
	}

	VERBOSE("BL31: TF-A handoff params at:0x%" PRIx64 ", entries:%u\n",
		tfa_handoff_addr, TFAHandoffParams->num_entries);
	if (TFAHandoffParams->num_entries > FSBL_MAX_PARTITIONS) {
		ERROR("BL31: TF-A handoff params: too many partitions (%u/%u)\n",
		      TFAHandoffParams->num_entries, FSBL_MAX_PARTITIONS);
		return FSBL_HANDOFF_TOO_MANY_PARTS;
	}

	/*
	 * we loop over all passed entries but only populate two image structs
	 * (bl32, bl33). I.e. the last applicable images in the handoff
	 * structure will be used for the hand off
	 */
	for (size_t i = 0; i < TFAHandoffParams->num_entries; i++) {
		entry_point_info_t *image;
		int32_t target_estate, target_secure, target_cpu;
		uint32_t target_endianness, target_el;

		VERBOSE("BL31: %zd: entry:0x%" PRIx64 ", flags:0x%" PRIx64 "\n", i,
			TFAHandoffParams->partition[i].entry_point,
			TFAHandoffParams->partition[i].flags);

		target_cpu = get_fsbl_cpu(&TFAHandoffParams->partition[i]);
		if (target_cpu != FSBL_FLAGS_A53_0) {
			WARN("BL31: invalid target CPU (%i)\n", target_cpu);
			continue;
		}

		target_el = get_fsbl_el(&TFAHandoffParams->partition[i]);
		if ((target_el == FSBL_FLAGS_EL3) ||
		    (target_el == FSBL_FLAGS_EL0)) {
			WARN("BL31: invalid exception level (%i)\n", target_el);
			continue;
		}

		target_secure = get_fsbl_ss(&TFAHandoffParams->partition[i]);
		if (target_secure == FSBL_FLAGS_SECURE &&
		    target_el == FSBL_FLAGS_EL2) {
			WARN("BL31: invalid security state (%i) for exception level (%i)\n",
			     target_secure, target_el);
			continue;
		}

		target_estate = get_fsbl_estate(&TFAHandoffParams->partition[i]);
		target_endianness = get_fsbl_endian(&TFAHandoffParams->partition[i]);

		if (target_secure == FSBL_FLAGS_SECURE) {
			image = bl32;

			if (target_estate == FSBL_FLAGS_ESTATE_A32) {
				bl32->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
							 target_endianness,
							 DISABLE_ALL_EXCEPTIONS);
			} else {
				bl32->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
						     DISABLE_ALL_EXCEPTIONS);
			}
		} else {
			image = bl33;

			if (target_estate == FSBL_FLAGS_ESTATE_A32) {
				if (target_el == FSBL_FLAGS_EL2) {
					target_el = MODE32_hyp;
				} else {
					target_el = MODE32_sys;
				}

				bl33->spsr = SPSR_MODE32(target_el, SPSR_T_ARM,
							 target_endianness,
							 DISABLE_ALL_EXCEPTIONS);
			} else {
				if (target_el == FSBL_FLAGS_EL2) {
					target_el = MODE_EL2;
				} else {
					target_el = MODE_EL1;
				}

				bl33->spsr = SPSR_64(target_el, MODE_SP_ELX,
						     DISABLE_ALL_EXCEPTIONS);
			}
		}

		VERBOSE("Setting up %s entry point to:%" PRIx64 ", el:%x\n",
			target_secure == FSBL_FLAGS_SECURE ? "BL32" : "BL33",
			TFAHandoffParams->partition[i].entry_point,
			target_el);
		image->pc = TFAHandoffParams->partition[i].entry_point;

		if (target_endianness == SPSR_E_BIG) {
			EP_SET_EE(image->h.attr, EP_EE_BIG);
		} else {
			EP_SET_EE(image->h.attr, EP_EE_LITTLE);
		}
	}

	return FSBL_HANDOFF_SUCCESS;
}
