plat/arm/board/arm_fpga: Use preloaded BL33 alternative boot flow

This makes use of the PRELOADED_BL33_BASE flag to indicate to BL31 that
the BL33 payload (kernel) has already been loaded and resides in memory;
BL31 will then jump to the non-secure address.

For this port the BL33 payload is the Linux kernel, and in accordance
with the pre-kernel setup requirements (as specified in the `Booting
AArch64 Linux' documentation:
https://www.kernel.org/doc/Documentation/arm64/booting.txt),
this change also sets up the primary CPU's registers x0-x3 so they are
the expected values, which includes the address of the DTB at x0.

An external linker script is currently required to combine BL31, the
BL33 payload, and any other software images to create an ELF file that
can be uploaded to the FPGA board along with the bit file. It therefore
has dependencies on the value of PRELOADED_BL33_BASE (kernel base) and
the DTB base (plus any other relevant base addresses used to
distinguish the different ELF sections), both of which are set in this
patch.

Signed-off-by: Oliver Swede <oli.swede@arm.com>
Change-Id: If7ae8ee82d1e09fb05f553f6077ae13680dbf66b
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
index aaa25bc..b641ad1 100644
--- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -4,19 +4,43 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
+
 #include <plat/common/platform.h>
 #include <platform_def.h>
 
 #include "fpga_private.h"
 
+static entry_point_info_t bl33_image_ep_info;
+
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+	return PRELOADED_BL33_BASE;
+#else
+	return 0;
+#endif
+}
+
+uint32_t fpga_get_spsr_for_bl33_entry(void)
+{
+	return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+}
+
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
 	fpga_console_init();
-	/*
-	 * TODO: implement any extra early platform setup before jumping to BL33
-	 * payload
-	 */
+
+	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+	bl33_image_ep_info.spsr = fpga_get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+	/* Set x0-x3 for the primary CPU as expected by the kernel */
+	bl33_image_ep_info.args.arg0 = (u_register_t)FPGA_PRELOADED_DTB_BASE;
+	bl33_image_ep_info.args.arg1 = 0U;
+	bl33_image_ep_info.args.arg2 = 0U;
+	bl33_image_ep_info.args.arg3 = 0U;
 }
 
 void bl31_plat_arch_setup(void)
@@ -30,11 +54,18 @@
 
 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
 {
-	/*
-	 * TODO: return entry_point_info_t struct containing information about the
-	 *       BL33 payload, which will run in EL2NS mode.
-	 */
-	return NULL;
+	entry_point_info_t *next_image_info;
+	next_image_info = &bl33_image_ep_info;
+
+	/* Only expecting BL33: the kernel will run in EL2NS */
+	assert(type == NON_SECURE);
+
+	/* None of the images can have 0x0 as the entrypoint */
+	if (next_image_info->pc) {
+		return next_image_info;
+	} else {
+		return NULL;
+	}
 }
 
 unsigned int plat_get_syscnt_freq2(void)