1*83d290c5STom Rini // SPDX-License-Identifier: BSD-3-Clause
2bcc1726aSKever Yang /*
3bcc1726aSKever Yang * Reference to the ARM TF Project,
4bcc1726aSKever Yang * plat/arm/common/arm_bl2_setup.c
5bcc1726aSKever Yang * Portions copyright (c) 2013-2016, ARM Limited and Contributors. All rights
6bcc1726aSKever Yang * reserved.
7bcc1726aSKever Yang * Copyright (C) 2016 Rockchip Electronic Co.,Ltd
8bcc1726aSKever Yang * Written by Kever Yang <kever.yang@rock-chips.com>
91d379090SPhilipp Tomsich * Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH
10bcc1726aSKever Yang */
11bcc1726aSKever Yang
12bcc1726aSKever Yang #include <common.h>
13bcc1726aSKever Yang #include <atf_common.h>
14bcc1726aSKever Yang #include <errno.h>
15bcc1726aSKever Yang #include <spl.h>
16bcc1726aSKever Yang
17bcc1726aSKever Yang static struct bl2_to_bl31_params_mem bl31_params_mem;
18bcc1726aSKever Yang static struct bl31_params *bl2_to_bl31_params;
19bcc1726aSKever Yang
20bcc1726aSKever Yang /**
21bcc1726aSKever Yang * bl2_plat_get_bl31_params() - prepare params for bl31.
22bcc1726aSKever Yang *
23bcc1726aSKever Yang * This function assigns a pointer to the memory that the platform has kept
24bcc1726aSKever Yang * aside to pass platform specific and trusted firmware related information
25bcc1726aSKever Yang * to BL31. This memory is allocated by allocating memory to
26bcc1726aSKever Yang * bl2_to_bl31_params_mem structure which is a superset of all the
27bcc1726aSKever Yang * structure whose information is passed to BL31
28bcc1726aSKever Yang * NOTE: This function should be called only once and should be done
29bcc1726aSKever Yang * before generating params to BL31
30bcc1726aSKever Yang *
31bcc1726aSKever Yang * @return bl31 params structure pointer
32bcc1726aSKever Yang */
bl2_plat_get_bl31_params(uintptr_t bl33_entry)331d379090SPhilipp Tomsich static struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl33_entry)
34bcc1726aSKever Yang {
35bcc1726aSKever Yang struct entry_point_info *bl33_ep_info;
36bcc1726aSKever Yang
37bcc1726aSKever Yang /*
38bcc1726aSKever Yang * Initialise the memory for all the arguments that needs to
39bcc1726aSKever Yang * be passed to BL31
40bcc1726aSKever Yang */
41bcc1726aSKever Yang memset(&bl31_params_mem, 0, sizeof(struct bl2_to_bl31_params_mem));
42bcc1726aSKever Yang
43bcc1726aSKever Yang /* Assign memory for TF related information */
44bcc1726aSKever Yang bl2_to_bl31_params = &bl31_params_mem.bl31_params;
45bcc1726aSKever Yang SET_PARAM_HEAD(bl2_to_bl31_params, ATF_PARAM_BL31, ATF_VERSION_1, 0);
46bcc1726aSKever Yang
47bcc1726aSKever Yang /* Fill BL31 related information */
48bcc1726aSKever Yang SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info,
49bcc1726aSKever Yang ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0);
50bcc1726aSKever Yang
51bcc1726aSKever Yang /* Fill BL32 related information if it exists */
52bcc1726aSKever Yang bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info;
53bcc1726aSKever Yang SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, ATF_PARAM_EP,
54bcc1726aSKever Yang ATF_VERSION_1, 0);
55bcc1726aSKever Yang bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info;
56bcc1726aSKever Yang SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info,
57bcc1726aSKever Yang ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0);
580289e291SKever Yang #ifndef BL32_BASE
590289e291SKever Yang bl2_to_bl31_params->bl32_ep_info->pc = 0;
60bcc1726aSKever Yang #endif /* BL32_BASE */
61bcc1726aSKever Yang
62bcc1726aSKever Yang /* Fill BL33 related information */
63bcc1726aSKever Yang bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info;
64bcc1726aSKever Yang bl33_ep_info = &bl31_params_mem.bl33_ep_info;
65bcc1726aSKever Yang SET_PARAM_HEAD(bl33_ep_info, ATF_PARAM_EP, ATF_VERSION_1,
66bcc1726aSKever Yang ATF_EP_NON_SECURE);
67bcc1726aSKever Yang
68bcc1726aSKever Yang /* BL33 expects to receive the primary CPU MPID (through x0) */
69bcc1726aSKever Yang bl33_ep_info->args.arg0 = 0xffff & read_mpidr();
701d379090SPhilipp Tomsich bl33_ep_info->pc = bl33_entry;
71bcc1726aSKever Yang bl33_ep_info->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
72bcc1726aSKever Yang DISABLE_ALL_EXECPTIONS);
73bcc1726aSKever Yang
74bcc1726aSKever Yang bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info;
75bcc1726aSKever Yang SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info,
76bcc1726aSKever Yang ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0);
77bcc1726aSKever Yang
78bcc1726aSKever Yang return bl2_to_bl31_params;
79bcc1726aSKever Yang }
80bcc1726aSKever Yang
raw_write_daif(unsigned int daif)811d379090SPhilipp Tomsich static inline void raw_write_daif(unsigned int daif)
82bcc1726aSKever Yang {
83bcc1726aSKever Yang __asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory");
84bcc1726aSKever Yang }
85bcc1726aSKever Yang
861d379090SPhilipp Tomsich typedef void (*atf_entry_t)(struct bl31_params *params, void *plat_params);
871d379090SPhilipp Tomsich
bl31_entry(uintptr_t bl31_entry,uintptr_t bl33_entry,uintptr_t fdt_addr)881d379090SPhilipp Tomsich static void bl31_entry(uintptr_t bl31_entry, uintptr_t bl33_entry,
891d379090SPhilipp Tomsich uintptr_t fdt_addr)
90bcc1726aSKever Yang {
91bcc1726aSKever Yang struct bl31_params *bl31_params;
921d379090SPhilipp Tomsich atf_entry_t atf_entry = (atf_entry_t)bl31_entry;
93bcc1726aSKever Yang
941d379090SPhilipp Tomsich bl31_params = bl2_plat_get_bl31_params(bl33_entry);
95bcc1726aSKever Yang
96bcc1726aSKever Yang raw_write_daif(SPSR_EXCEPTION_MASK);
97bcc1726aSKever Yang dcache_disable();
98bcc1726aSKever Yang
991d379090SPhilipp Tomsich atf_entry((void *)bl31_params, (void *)fdt_addr);
1001d379090SPhilipp Tomsich }
1011d379090SPhilipp Tomsich
spl_fit_images_find_uboot(void * blob)1021d379090SPhilipp Tomsich static int spl_fit_images_find_uboot(void *blob)
1031d379090SPhilipp Tomsich {
1041d379090SPhilipp Tomsich int parent, node, ndepth;
1051d379090SPhilipp Tomsich const void *data;
1061d379090SPhilipp Tomsich
1071d379090SPhilipp Tomsich if (!blob)
1081d379090SPhilipp Tomsich return -FDT_ERR_BADMAGIC;
1091d379090SPhilipp Tomsich
1101d379090SPhilipp Tomsich parent = fdt_path_offset(blob, "/fit-images");
1111d379090SPhilipp Tomsich if (parent < 0)
1121d379090SPhilipp Tomsich return -FDT_ERR_NOTFOUND;
1131d379090SPhilipp Tomsich
1141d379090SPhilipp Tomsich for (node = fdt_next_node(blob, parent, &ndepth);
1151d379090SPhilipp Tomsich (node >= 0) && (ndepth > 0);
1161d379090SPhilipp Tomsich node = fdt_next_node(blob, node, &ndepth)) {
1171d379090SPhilipp Tomsich if (ndepth != 1)
1181d379090SPhilipp Tomsich continue;
1191d379090SPhilipp Tomsich
1201d379090SPhilipp Tomsich data = fdt_getprop(blob, node, FIT_OS_PROP, NULL);
1211d379090SPhilipp Tomsich if (!data)
1221d379090SPhilipp Tomsich continue;
1231d379090SPhilipp Tomsich
1241d379090SPhilipp Tomsich if (genimg_get_os_id(data) == IH_OS_U_BOOT)
1251d379090SPhilipp Tomsich return node;
1261d379090SPhilipp Tomsich };
1271d379090SPhilipp Tomsich
1281d379090SPhilipp Tomsich return -FDT_ERR_NOTFOUND;
1291d379090SPhilipp Tomsich }
1301d379090SPhilipp Tomsich
spl_fit_images_get_entry(void * blob,int node)1311d379090SPhilipp Tomsich uintptr_t spl_fit_images_get_entry(void *blob, int node)
1321d379090SPhilipp Tomsich {
1331d379090SPhilipp Tomsich ulong val;
1341d379090SPhilipp Tomsich
1351d379090SPhilipp Tomsich val = fdt_getprop_u32(blob, node, "entry-point");
1361d379090SPhilipp Tomsich if (val == FDT_ERROR)
1371d379090SPhilipp Tomsich val = fdt_getprop_u32(blob, node, "load-addr");
1381d379090SPhilipp Tomsich
1391d379090SPhilipp Tomsich debug("%s: entry point 0x%lx\n", __func__, val);
1401d379090SPhilipp Tomsich return val;
1411d379090SPhilipp Tomsich }
1421d379090SPhilipp Tomsich
spl_invoke_atf(struct spl_image_info * spl_image)1431d379090SPhilipp Tomsich void spl_invoke_atf(struct spl_image_info *spl_image)
1441d379090SPhilipp Tomsich {
1451d379090SPhilipp Tomsich uintptr_t bl33_entry = CONFIG_SYS_TEXT_BASE;
1461d379090SPhilipp Tomsich void *blob = spl_image->fdt_addr;
147d21fb63dSPhilipp Tomsich uintptr_t platform_param = (uintptr_t)blob;
1481d379090SPhilipp Tomsich int node;
1491d379090SPhilipp Tomsich
1501d379090SPhilipp Tomsich /*
1511d379090SPhilipp Tomsich * Find the U-Boot binary (in /fit-images) load addreess or
1521d379090SPhilipp Tomsich * entry point (if different) and pass it as the BL3-3 entry
1531d379090SPhilipp Tomsich * point.
1541d379090SPhilipp Tomsich * This will need to be extended to support Falcon mode.
1551d379090SPhilipp Tomsich */
1561d379090SPhilipp Tomsich
1571d379090SPhilipp Tomsich node = spl_fit_images_find_uboot(blob);
1581d379090SPhilipp Tomsich if (node >= 0)
1591d379090SPhilipp Tomsich bl33_entry = spl_fit_images_get_entry(blob, node);
1601d379090SPhilipp Tomsich
1611d379090SPhilipp Tomsich /*
162d21fb63dSPhilipp Tomsich * If ATF_NO_PLATFORM_PARAM is set, we override the platform
163d21fb63dSPhilipp Tomsich * parameter and always pass 0. This is a workaround for
164d21fb63dSPhilipp Tomsich * older ATF versions that have insufficiently robust (or
165d21fb63dSPhilipp Tomsich * overzealous) argument validation.
166d21fb63dSPhilipp Tomsich */
167d21fb63dSPhilipp Tomsich if (CONFIG_IS_ENABLED(ATF_NO_PLATFORM_PARAM))
168d21fb63dSPhilipp Tomsich platform_param = 0;
169d21fb63dSPhilipp Tomsich
170d21fb63dSPhilipp Tomsich /*
1711d379090SPhilipp Tomsich * We don't provide a BL3-2 entry yet, but this will be possible
1721d379090SPhilipp Tomsich * using similar logic.
1731d379090SPhilipp Tomsich */
174d21fb63dSPhilipp Tomsich bl31_entry(spl_image->entry_point, bl33_entry, platform_param);
175bcc1726aSKever Yang }
176