Modern SoCs such as Rockchip RK3576 need TFA to be running to provide
firmware services to the OS.

Enable the TFA boot flow to allow using Linux as BL33 (including its
calling convention) to facilitate Falcon mode boot on such SoCs.

Signed-off-by: Alexey Charkov <[email protected]>
---
 common/spl/Kconfig   | 22 ++++++++++++++++++++--
 common/spl/spl_atf.c | 49 +++++++++++++++++++++++++++++++++----------------
 2 files changed, 53 insertions(+), 18 deletions(-)

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 0618f42c9410..7c639ed8f763 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1230,22 +1230,40 @@ config SPL_BOOTZ
        help
          Boot a linux zimage from memory in falcon boot.
 
+         This provides an entry path which is unused when the OS is entered
+         through TF-A, since SPL then only places the kernel in memory and
+         BL31 is what enters it. It remains selectable: SPL can still enter
+         a kernel itself on such a platform, dropping to EL2 without TF-A
+         resident, just without any firmware services being available to the
+         OS afterwards.
+
 config SPL_BOOTI
        bool "Allow booting an Image style Linux kernel from SPL"
        depends on SPL_OS_BOOT && !SPL_OS_BOOT_SECURE
-       default y if ARM64 || RISCV
+       default y if (ARM64 || RISCV) && !SPL_ATF
        select SPL_LIB_BOOTI
        help
          Boot an uncompressed linux kernel image from memory in falcon boot.
 
+         This provides an entry path which is unused when the OS is entered
+         through TF-A, since SPL then only places the kernel in memory and
+         BL31 is what enters it, so it does not default to y in that case. It
+         remains selectable: SPL can still enter a kernel itself on such a
+         platform, dropping to EL2 without TF-A resident, just without any
+         firmware services being available to the OS afterwards.
+
 config SPL_OS_BOOT_ARGS
        bool "Allow SPL to load args for kernel in falcon mode"
        depends on (SPL_OS_BOOT || SPL_LOAD_FIT_OPENSBI_OS_BOOT) && 
!SPL_OS_BOOT_SECURE
-       default y if !SPL_OS_BOOT_SECURE
+       default y if !SPL_OS_BOOT_SECURE && !SPL_ATF
        help
          This option enables the SPL to load an args file (usually the FDT)
          alongside the kernel image in falcon boot mode.
 
+         This is not needed when the OS is entered through TF-A, since the
+         device tree is then taken from the same FIT as the kernel, which is
+         why it does not default to y in that case.
+
 config SPL_PAYLOAD_ARGS_ADDR
        hex "Address in memory to load 'args' file for Falcon Mode to"
        depends on SPL_OS_BOOT_ARGS
diff --git a/common/spl/spl_atf.c b/common/spl/spl_atf.c
index 17acd3665dfa..0cec5d8d46fe 100644
--- a/common/spl/spl_atf.c
+++ b/common/spl/spl_atf.c
@@ -15,6 +15,7 @@
 #include <image.h>
 #include <log.h>
 #include <spl.h>
+#include <vsprintf.h>
 #include <asm/cache.h>
 
 /* Holds all the structures we need for bl31 parameter passing */
@@ -87,8 +88,8 @@ struct bl31_params *bl2_plat_get_bl31_params_default(ulong 
bl32_entry,
        SET_PARAM_HEAD(bl33_ep_info, ATF_PARAM_EP, ATF_VERSION_1,
                       ATF_EP_NON_SECURE);
 
-       /* BL33 expects to receive the primary CPU MPID (through x0) */
-       bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
+       /* Pass the FDT address in x0, per the TF-A BL33 / Linux boot protocol. 
*/
+       bl33_ep_info->args.arg0 = fdt_addr;
        bl33_ep_info->pc = bl33_entry;
        bl33_ep_info->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
                                     DISABLE_ALL_EXECPTIONS);
@@ -162,8 +163,8 @@ struct bl_params *bl2_plat_get_bl31_params_v2_default(ulong 
bl32_entry,
        SET_PARAM_HEAD(bl_params_node->ep_info, ATF_PARAM_EP,
                       ATF_VERSION_2, ATF_EP_NON_SECURE);
 
-       /* BL33 expects to receive the primary CPU MPID (through x0) */
-       bl_params_node->ep_info->args.arg0 = 0xffff & read_mpidr();
+       /* Pass the FDT address in x0, per the TF-A BL33 / Linux boot protocol. 
*/
+       bl_params_node->ep_info->args.arg0 = fdt_addr;
        bl_params_node->ep_info->pc = bl33_entry;
        bl_params_node->ep_info->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
                                                DISABLE_ALL_EXECPTIONS);
@@ -189,7 +190,8 @@ static inline void raw_write_daif(unsigned int daif)
 typedef void __noreturn (*atf_entry_t)(struct bl31_params *params, void 
*plat_params);
 
 static void __noreturn bl31_entry(ulong bl31_entry, ulong bl32_entry,
-                                 ulong bl33_entry, ulong fdt_addr)
+                                 ulong bl33_entry, ulong fdt_addr,
+                                 ulong plat_param)
 {
        atf_entry_t  atf_entry = (atf_entry_t)bl31_entry;
        void *bl31_params;
@@ -206,7 +208,7 @@ static void __noreturn bl31_entry(ulong bl31_entry, ulong 
bl32_entry,
        if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
                dcache_disable();
 
-       atf_entry(bl31_params, (void *)fdt_addr);
+       atf_entry(bl31_params, (void *)plat_param);
 }
 
 static int spl_fit_images_find(void *blob, int os)
@@ -267,10 +269,11 @@ ulong spl_fit_images_get_entry(void *blob, int node)
 
 void __noreturn spl_invoke_atf(struct spl_image_info *spl_image)
 {
-       ulong  bl32_entry = 0;
-       ulong  bl33_entry = CONFIG_TEXT_BASE;
-       void *blob = spl_image->fdt_addr;
+       bool falcon = CONFIG_IS_ENABLED(OS_BOOT) && spl_falcon_boot();
+       void *blob = spl_image_fdt_addr(spl_image);
+       ulong bl33_entry = CONFIG_TEXT_BASE;
        ulong platform_param = (ulong)blob;
+       ulong bl32_entry = 0;
        int node;
 
        /*
@@ -283,15 +286,29 @@ void __noreturn spl_invoke_atf(struct spl_image_info 
*spl_image)
                bl32_entry = spl_fit_images_get_entry(blob, node);
 
        /*
-        * Find the U-Boot binary (in /fit-images) load addreess or
-        * entry point (if different) and pass it as the BL3-3 entry
-        * point.
-        * This will need to be extended to support Falcon mode.
+        * Find BL33 entry point. In Falcon mode, prefer Linux when requested.
+        * Fall back to U-Boot if Linux cannot be resolved, unless secure Falcon
+        * mode is in effect, in which case an unsigned fallback is not allowed.
         */
+       node = -FDT_ERR_NOTFOUND;
+       if (falcon)
+               node = spl_fit_images_find(blob, IH_OS_LINUX);
 
-       node = spl_fit_images_find(blob, IH_OS_U_BOOT);
-       if (node >= 0)
+       if (node < 0) {
+               if (falcon && CONFIG_IS_ENABLED(OS_BOOT_SECURE))
+                       panic("SPL: TF-A: no Linux BL33 image for secure Falcon 
boot");
+               node = spl_fit_images_find(blob, IH_OS_U_BOOT);
+       }
+
+       if (node >= 0) {
                bl33_entry = spl_fit_images_get_entry(blob, node);
+       } else if (falcon) {
+               /*
+                * Falcon mode was requested, so U-Boot proper was never loaded
+                * and CONFIG_TEXT_BASE holds nothing we could enter.
+                */
+               panic("SPL: TF-A: no BL33 image to boot");
+       }
 
        /*
         * If ATF_NO_PLATFORM_PARAM is set, we override the platform
@@ -307,5 +324,5 @@ void __noreturn spl_invoke_atf(struct spl_image_info 
*spl_image)
         * using similar logic.
         */
        bl31_entry(spl_image->entry_point, bl32_entry,
-                  bl33_entry, platform_param);
+                  bl33_entry, (ulong)blob, platform_param);
 }

-- 
2.54.0

Reply via email to