rpi4: Determine BL33 entry point at runtime

Now that we have the armstub magic value in place, the GPU firmware will
write the kernel load address (and DTB address) into our special page,
so we can always easily access the actual location without hardcoding
any addresses into the BL31 image.

Make the compile-time defined PRELOADED_BL33_BASE macro optional, and
read the BL33 entry point from the magic location, if the macro was not
defined. We do the same for the DTB address.

This also splits the currently "common" definition of
plat_get_ns_image_entrypoint() to be separate between RPi3 and RPi4.

Change-Id: I6f26c0adc6fce2df47786b271c490928b4529abb
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
diff --git a/plat/rpi/common/rpi3_common.c b/plat/rpi/common/rpi3_common.c
index 4317b3a..ff33694 100644
--- a/plat/rpi/common/rpi3_common.c
+++ b/plat/rpi/common/rpi3_common.c
@@ -176,18 +176,6 @@
 }
 
 /*******************************************************************************
- * Return entrypoint of BL33.
- ******************************************************************************/
-uintptr_t plat_get_ns_image_entrypoint(void)
-{
-#ifdef PRELOADED_BL33_BASE
-	return PRELOADED_BL33_BASE;
-#else
-	return PLAT_RPI3_NS_IMAGE_OFFSET;
-#endif
-}
-
-/*******************************************************************************
  * Gets SPSR for BL32 entry
  ******************************************************************************/
 uint32_t rpi3_get_spsr_for_bl32_entry(void)
diff --git a/plat/rpi/rpi3/rpi3_bl31_setup.c b/plat/rpi/rpi3/rpi3_bl31_setup.c
index c16dbff..24a5613 100644
--- a/plat/rpi/rpi3/rpi3_bl31_setup.c
+++ b/plat/rpi/rpi3/rpi3_bl31_setup.c
@@ -48,6 +48,18 @@
 }
 
 /*******************************************************************************
+ * Return entrypoint of BL33.
+ ******************************************************************************/
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+	return PRELOADED_BL33_BASE;
+#else
+	return PLAT_RPI3_NS_IMAGE_OFFSET;
+#endif
+}
+
+/*******************************************************************************
  * 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
diff --git a/plat/rpi/rpi4/platform.mk b/plat/rpi/rpi4/platform.mk
index b20251c..6ac2169 100644
--- a/plat/rpi/rpi4/platform.mk
+++ b/plat/rpi/rpi4/platform.mk
@@ -68,8 +68,8 @@
 # Platform build flags
 # --------------------
 
-# Assume that BL33 isn't the Linux kernel by default
-RPI3_DIRECT_LINUX_BOOT		:= 0
+# There is not much else than a Linux kernel to load at the moment.
+RPI3_DIRECT_LINUX_BOOT		:= 1
 
 # BL33 images are in AArch64 by default
 RPI3_BL33_IN_AARCH32		:= 0
@@ -92,15 +92,6 @@
 $(eval $(call add_define,RPI3_RUNTIME_UART))
 $(eval $(call add_define,RPI3_USE_UEFI_MAP))
 
-# Verify build config
-# -------------------
-#
-ifneq (${RPI3_DIRECT_LINUX_BOOT}, 0)
-  ifndef RPI3_PRELOADED_DTB_BASE
-      $(error Error: RPI3_PRELOADED_DTB_BASE needed if RPI3_DIRECT_LINUX_BOOT=1)
-  endif
-endif
-
 ifeq (${ARCH},aarch32)
   $(error Error: AArch32 not supported on rpi4)
 endif
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c
index 58025b2..f5f74bd 100644
--- a/plat/rpi/rpi4/rpi4_bl31_setup.c
+++ b/plat/rpi/rpi4/rpi4_bl31_setup.c
@@ -27,6 +27,8 @@
  * confirmation and puts the kernel and DT address in the following words.
  */
 extern uint32_t stub_magic;
+extern uint32_t dtb_ptr32;
+extern uint32_t kernel_entry32;
 
 static const gicv2_driver_data_t rpi4_gic_data = {
 	.gicd_base = RPI4_GIC_GICD_BASE,
@@ -63,6 +65,34 @@
 	}
 }
 
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+	return PRELOADED_BL33_BASE;
+#else
+	/* Cleared by the GPU if kernel address is valid. */
+	if (stub_magic == 0)
+		return kernel_entry32;
+
+	WARN("Stub magic failure, using default kernel address 0x80000\n");
+	return 0x80000;
+#endif
+}
+
+static uintptr_t rpi4_get_dtb_address(void)
+{
+#ifdef RPI3_PRELOADED_DTB_BASE
+	return RPI3_PRELOADED_DTB_BASE;
+#else
+	/* Cleared by the GPU if DTB address is valid. */
+	if (stub_magic == 0)
+		return dtb_ptr32;
+
+	WARN("Stub magic failure, DTB address unknown\n");
+	return 0;
+#endif
+}
+
 static void ldelay(register_t delay)
 {
 	__asm__ volatile (
@@ -114,12 +144,11 @@
 		div_reg = 1;
 	rpi3_console_init(PLAT_RPI4_VPU_CLK_RATE / div_reg);
 
-#if RPI3_DIRECT_LINUX_BOOT
 	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
-	bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
-					  DISABLE_ALL_EXCEPTIONS);
+	bl33_image_ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 
+#if RPI3_DIRECT_LINUX_BOOT
 # if RPI3_BL33_IN_AARCH32
 	/*
 	 * According to the file ``Documentation/arm/Booting`` of the Linux
@@ -131,7 +160,7 @@
 	VERBOSE("rpi4: 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;
+	bl33_image_ep_info.args.arg2 = rpi4_get_dtb_address();
 # else
 	/*
 	 * According to the file ``Documentation/arm64/booting.txt`` of the
@@ -140,7 +169,7 @@
 	 * must be 0.
 	 */
 	VERBOSE("rpi4: 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.arg0 = rpi4_get_dtb_address();
 	bl33_image_ep_info.args.arg1 = 0ULL;
 	bl33_image_ep_info.args.arg2 = 0ULL;
 	bl33_image_ep_info.args.arg3 = 0ULL;