uboot/common/spl/spl_atf.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause
   2/*
   3 * Reference to the ARM TF Project,
   4 * plat/arm/common/arm_bl2_setup.c
   5 * Portions copyright (c) 2013-2016, ARM Limited and Contributors. All rights
   6 * reserved.
   7 * Copyright (C) 2016 Rockchip Electronic Co.,Ltd
   8 * Written by Kever Yang <kever.yang@rock-chips.com>
   9 * Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH
  10 */
  11
  12#include <common.h>
  13#include <atf_common.h>
  14#include <cpu_func.h>
  15#include <errno.h>
  16#include <image.h>
  17#include <log.h>
  18#include <spl.h>
  19#include <asm/cache.h>
  20
  21static struct bl2_to_bl31_params_mem bl31_params_mem;
  22static struct bl31_params *bl2_to_bl31_params;
  23
  24__weak struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
  25                                                    uintptr_t bl33_entry,
  26                                                    uintptr_t fdt_addr)
  27{
  28        struct entry_point_info *bl32_ep_info;
  29        struct entry_point_info *bl33_ep_info;
  30
  31        /*
  32         * Initialise the memory for all the arguments that needs to
  33         * be passed to BL31
  34         */
  35        memset(&bl31_params_mem, 0, sizeof(struct bl2_to_bl31_params_mem));
  36
  37        /* Assign memory for TF related information */
  38        bl2_to_bl31_params = &bl31_params_mem.bl31_params;
  39        SET_PARAM_HEAD(bl2_to_bl31_params, ATF_PARAM_BL31, ATF_VERSION_1, 0);
  40
  41        /* Fill BL31 related information */
  42        bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info;
  43        SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info,
  44                       ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0);
  45
  46        /* Fill BL32 related information */
  47        bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
  48        bl32_ep_info = &bl31_params_mem.bl32_ep_info;
  49        SET_PARAM_HEAD(bl32_ep_info, ATF_PARAM_EP, ATF_VERSION_1,
  50                       ATF_EP_SECURE);
  51
  52        /* secure payload is optional, so set pc to 0 if absent */
  53        bl32_ep_info->args.arg3 = fdt_addr;
  54        bl32_ep_info->pc = bl32_entry ? bl32_entry : 0;
  55        bl32_ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
  56                                     DISABLE_ALL_EXECPTIONS);
  57
  58        bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
  59        SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info,
  60                       ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0);
  61
  62        /* Fill BL33 related information */
  63        bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
  64        bl33_ep_info = &bl31_params_mem.bl33_ep_info;
  65        SET_PARAM_HEAD(bl33_ep_info, ATF_PARAM_EP, ATF_VERSION_1,
  66                       ATF_EP_NON_SECURE);
  67
  68        /* BL33 expects to receive the primary CPU MPID (through x0) */
  69        bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
  70        bl33_ep_info->pc = bl33_entry;
  71        bl33_ep_info->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
  72                                     DISABLE_ALL_EXECPTIONS);
  73
  74        bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info;
  75        SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info,
  76                       ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0);
  77
  78        return bl2_to_bl31_params;
  79}
  80
  81static inline void raw_write_daif(unsigned int daif)
  82{
  83        __asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory");
  84}
  85
  86typedef void (*atf_entry_t)(struct bl31_params *params, void *plat_params);
  87
  88static void bl31_entry(uintptr_t bl31_entry, uintptr_t bl32_entry,
  89                       uintptr_t bl33_entry, uintptr_t fdt_addr)
  90{
  91        struct bl31_params *bl31_params;
  92        atf_entry_t  atf_entry = (atf_entry_t)bl31_entry;
  93
  94        bl31_params = bl2_plat_get_bl31_params(bl32_entry, bl33_entry,
  95                                               fdt_addr);
  96
  97        raw_write_daif(SPSR_EXCEPTION_MASK);
  98        dcache_disable();
  99
 100        atf_entry((void *)bl31_params, (void *)fdt_addr);
 101}
 102
 103static int spl_fit_images_find(void *blob, int os)
 104{
 105        int parent, node, ndepth = 0;
 106        const void *data;
 107
 108        if (!blob)
 109                return -FDT_ERR_BADMAGIC;
 110
 111        parent = fdt_path_offset(blob, "/fit-images");
 112        if (parent < 0)
 113                return -FDT_ERR_NOTFOUND;
 114
 115        for (node = fdt_next_node(blob, parent, &ndepth);
 116             (node >= 0) && (ndepth > 0);
 117             node = fdt_next_node(blob, node, &ndepth)) {
 118                if (ndepth != 1)
 119                        continue;
 120
 121                data = fdt_getprop(blob, node, FIT_OS_PROP, NULL);
 122                if (!data)
 123                        continue;
 124
 125                if (genimg_get_os_id(data) == os)
 126                        return node;
 127        };
 128
 129        return -FDT_ERR_NOTFOUND;
 130}
 131
 132uintptr_t spl_fit_images_get_entry(void *blob, int node)
 133{
 134        ulong  val;
 135
 136        val = fdt_getprop_u32(blob, node, "entry-point");
 137        if (val == FDT_ERROR)
 138                val = fdt_getprop_u32(blob, node, "load-addr");
 139
 140        debug("%s: entry point 0x%lx\n", __func__, val);
 141        return val;
 142}
 143
 144void spl_invoke_atf(struct spl_image_info *spl_image)
 145{
 146        uintptr_t  bl32_entry = 0;
 147        uintptr_t  bl33_entry = CONFIG_SYS_TEXT_BASE;
 148        void *blob = spl_image->fdt_addr;
 149        uintptr_t platform_param = (uintptr_t)blob;
 150        int node;
 151
 152        /*
 153         * Find the OP-TEE binary (in /fit-images) load address or
 154         * entry point (if different) and pass it as the BL3-2 entry
 155         * point, this is optional.
 156         */
 157        node = spl_fit_images_find(blob, IH_OS_TEE);
 158        if (node >= 0)
 159                bl32_entry = spl_fit_images_get_entry(blob, node);
 160
 161        /*
 162         * Find the U-Boot binary (in /fit-images) load addreess or
 163         * entry point (if different) and pass it as the BL3-3 entry
 164         * point.
 165         * This will need to be extended to support Falcon mode.
 166         */
 167
 168        node = spl_fit_images_find(blob, IH_OS_U_BOOT);
 169        if (node >= 0)
 170                bl33_entry = spl_fit_images_get_entry(blob, node);
 171
 172        /*
 173         * If ATF_NO_PLATFORM_PARAM is set, we override the platform
 174         * parameter and always pass 0.  This is a workaround for
 175         * older ATF versions that have insufficiently robust (or
 176         * overzealous) argument validation.
 177         */
 178        if (CONFIG_IS_ENABLED(ATF_NO_PLATFORM_PARAM))
 179                platform_param = 0;
 180
 181        /*
 182         * We don't provide a BL3-2 entry yet, but this will be possible
 183         * using similar logic.
 184         */
 185        bl31_entry(spl_image->entry_point, bl32_entry,
 186                   bl33_entry, platform_param);
 187}
 188