/*
 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <bl_common.h>
#include <libfdt.h>
#include <platform.h>
#include <platform_def.h>
#include <xlat_mmu_helpers.h>
#include <xlat_tables_defs.h>

#include "rpi3_private.h"

#define BL31_END	(uintptr_t)(&__BL31_END__)

/*
 * Placeholder variables for copying the arguments that have been passed to
 * BL31 from BL2.
 */
static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;

/*******************************************************************************
 * Return a pointer to the 'entry_point_info' structure of the next image for
 * the security state specified. BL33 corresponds to the non-secure image type
 * while BL32 corresponds to the secure image type. A NULL pointer is returned
 * if the image does not exist.
 ******************************************************************************/
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
{
	entry_point_info_t *next_image_info;

	assert(sec_state_is_valid(type) != 0);

	next_image_info = (type == NON_SECURE)
			? &bl33_image_ep_info : &bl32_image_ep_info;

	/* None of the images can have 0x0 as the entrypoint. */
	if (next_image_info->pc) {
		return next_image_info;
	} else {
		return NULL;
	}
}

/*******************************************************************************
 * Perform any BL31 early platform setup. Here is an opportunity to copy
 * parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before
 * they are lost (potentially). This needs to be done before the MMU is
 * initialized so that the memory layout can be used while creating page
 * tables. BL2 has flushed this information to memory, so we are guaranteed
 * to pick up good data.
 ******************************************************************************/
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
				u_register_t arg2, u_register_t arg3)

{
	/* Initialize the console to provide early debug support */
	rpi3_console_init();

	/*
	 * In debug builds, a special value is passed in 'arg1' to verify
	 * platform parameters from BL2 to BL31. Not used in release builds.
	 */
	assert(arg1 == RPI3_BL31_PLAT_PARAM_VAL);

	/* Check that params passed from BL2 are not NULL. */
	bl_params_t *params_from_bl2 = (bl_params_t *) arg0;

	assert(params_from_bl2 != NULL);
	assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
	assert(params_from_bl2->h.version >= VERSION_2);

	bl_params_node_t *bl_params = params_from_bl2->head;

	/*
	 * Copy BL33 and BL32 (if present), entry point information.
	 * They are stored in Secure RAM, in BL2's address space.
	 */
	while (bl_params) {
		if (bl_params->image_id == BL32_IMAGE_ID) {
			bl32_image_ep_info = *bl_params->ep_info;
		}

		if (bl_params->image_id == BL33_IMAGE_ID) {
			bl33_image_ep_info = *bl_params->ep_info;
		}

		bl_params = bl_params->next_params_info;
	}

	if (bl33_image_ep_info.pc == 0) {
		panic();
	}

#if RPI3_DIRECT_LINUX_BOOT
# if RPI3_BL33_IN_AARCH32
	/*
	 * According to the file ``Documentation/arm/Booting`` of the Linux
	 * kernel tree, Linux expects:
	 * r0 = 0
	 * r1 = machine type number, optional in DT-only platforms (~0 if so)
	 * r2 = Physical address of the device tree blob
	 */
	VERBOSE("rpi3: Preparing to boot 32-bit Linux kernel\n");
	bl33_image_ep_info.args.arg0 = 0U;
	bl33_image_ep_info.args.arg1 = ~0U;
	bl33_image_ep_info.args.arg2 = (u_register_t) RPI3_PRELOADED_DTB_BASE;
# else
	/*
	 * According to the file ``Documentation/arm64/booting.txt`` of the
	 * Linux kernel tree, Linux expects the physical address of the device
	 * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
	 * must be 0.
	 */
	VERBOSE("rpi3: Preparing to boot 64-bit Linux kernel\n");
	bl33_image_ep_info.args.arg0 = (u_register_t) RPI3_PRELOADED_DTB_BASE;
	bl33_image_ep_info.args.arg1 = 0ULL;
	bl33_image_ep_info.args.arg2 = 0ULL;
	bl33_image_ep_info.args.arg3 = 0ULL;
# endif /* RPI3_BL33_IN_AARCH32 */
#endif /* RPI3_DIRECT_LINUX_BOOT */
}

void bl31_plat_arch_setup(void)
{
	rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE,
			       BL_CODE_BASE, BL_CODE_END,
			       BL_RO_DATA_BASE, BL_RO_DATA_END
#if USE_COHERENT_MEM
			       , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
#endif
			      );

	enable_mmu_el3(0);
}

/*
 * Add information to the device tree (if any) about the reserved DRAM used by
 * the Trusted Firmware.
 */
static void rpi3_dtb_add_mem_rsv(void)
{
	int i, regions, rc;
	uint64_t addr, size;
	void *dtb = (void *)RPI3_PRELOADED_DTB_BASE;

	INFO("rpi3: Checking DTB...\n");

	/* Return if no device tree is detected */
	if (fdt_check_header(dtb) != 0)
		return;

	regions = fdt_num_mem_rsv(dtb);

	VERBOSE("rpi3: Found %d mem reserve region(s)\n", regions);

	/* We expect to find one reserved region that we can modify */
	if (regions < 1)
		return;

	/*
	 * Look for the region that corresponds to the default boot firmware. It
	 * starts at address 0, and it is not needed when the default firmware
	 * is replaced by this port of the Trusted Firmware.
	 */
	for (i = 0; i < regions; i++) {
		if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0)
			continue;

		if (addr != 0x0)
			continue;

		VERBOSE("rpi3: Firmware mem reserve region found\n");

		rc = fdt_del_mem_rsv(dtb, i);
		if (rc != 0) {
			INFO("rpi3: Can't remove mem reserve region (%d)\n", rc);
		}

		break;
	}

	if (i == regions) {
		VERBOSE("rpi3: Firmware mem reserve region not found\n");
	}

	/*
	 * Reserve all SRAM. As said in the documentation, this isn't actually
	 * secure memory, so it is needed to tell BL33 that this is a reserved
	 * memory region. It doesn't guarantee it won't use it, though.
	 */
	rc = fdt_add_mem_rsv(dtb, SEC_SRAM_BASE, SEC_SRAM_SIZE);
	if (rc != 0) {
		WARN("rpi3: Can't add mem reserve region (%d)\n", rc);
	}

	INFO("rpi3: Reserved 0x%llx - 0x%llx in DTB\n", SEC_SRAM_BASE,
	     SEC_SRAM_BASE + SEC_SRAM_SIZE);
}

void bl31_platform_setup(void)
{
#ifdef RPI3_PRELOADED_DTB_BASE
	/* Only modify a DTB if we know where to look for it */
	rpi3_dtb_add_mem_rsv();
#endif
}
