1bcc1726aSKever Yang /* 2bcc1726aSKever Yang * Reference to the ARM TF Project, 3bcc1726aSKever Yang * plat/arm/common/arm_bl2_setup.c 4bcc1726aSKever Yang * Portions copyright (c) 2013-2016, ARM Limited and Contributors. All rights 5bcc1726aSKever Yang * reserved. 6bcc1726aSKever Yang * Copyright (C) 2016 Rockchip Electronic Co.,Ltd 7bcc1726aSKever Yang * Written by Kever Yang <kever.yang@rock-chips.com> 82e15a11cSPhilipp Tomsich * Copyright (C) 2017 Theobroma Systems Design und Consulting GmbH 9bcc1726aSKever Yang * 10bcc1726aSKever Yang * SPDX-License-Identifier: BSD-3-Clause 11bcc1726aSKever Yang */ 12bcc1726aSKever Yang 13bcc1726aSKever Yang #include <common.h> 14bcc1726aSKever Yang #include <atf_common.h> 15bcc1726aSKever Yang #include <errno.h> 16bcc1726aSKever Yang #include <spl.h> 17bcc1726aSKever Yang 18bcc1726aSKever Yang static struct bl2_to_bl31_params_mem bl31_params_mem; 19bcc1726aSKever Yang static struct bl31_params *bl2_to_bl31_params; 20bcc1726aSKever Yang 21bcc1726aSKever Yang /** 22bcc1726aSKever Yang * bl2_plat_get_bl31_params() - prepare params for bl31. 23bcc1726aSKever Yang * 24bcc1726aSKever Yang * This function assigns a pointer to the memory that the platform has kept 25bcc1726aSKever Yang * aside to pass platform specific and trusted firmware related information 26bcc1726aSKever Yang * to BL31. This memory is allocated by allocating memory to 27bcc1726aSKever Yang * bl2_to_bl31_params_mem structure which is a superset of all the 28bcc1726aSKever Yang * structure whose information is passed to BL31 29bcc1726aSKever Yang * NOTE: This function should be called only once and should be done 30bcc1726aSKever Yang * before generating params to BL31 31bcc1726aSKever Yang * 32bcc1726aSKever Yang * @return bl31 params structure pointer 33bcc1726aSKever Yang */ 34*3bf65388SJason Zhu static struct bl31_params *bl2_plat_get_bl31_params(struct spl_image_info *spl_image, 35*3bf65388SJason Zhu uintptr_t bl32_entry, 36b04f87d7SJoseph Chen uintptr_t bl33_entry) 37bcc1726aSKever Yang { 38b04f87d7SJoseph Chen struct entry_point_info *bl32_ep_info; 39bcc1726aSKever Yang struct entry_point_info *bl33_ep_info; 40bcc1726aSKever Yang 41bcc1726aSKever Yang /* 42bcc1726aSKever Yang * Initialise the memory for all the arguments that needs to 43bcc1726aSKever Yang * be passed to BL31 44bcc1726aSKever Yang */ 45bcc1726aSKever Yang memset(&bl31_params_mem, 0, sizeof(struct bl2_to_bl31_params_mem)); 46bcc1726aSKever Yang 47bcc1726aSKever Yang /* Assign memory for TF related information */ 48bcc1726aSKever Yang bl2_to_bl31_params = &bl31_params_mem.bl31_params; 49bcc1726aSKever Yang SET_PARAM_HEAD(bl2_to_bl31_params, ATF_PARAM_BL31, ATF_VERSION_1, 0); 50bcc1726aSKever Yang 51bcc1726aSKever Yang /* Fill BL31 related information */ 52bcc1726aSKever Yang SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, 53bcc1726aSKever Yang ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); 54bcc1726aSKever Yang 55b04f87d7SJoseph Chen if (bl32_entry == -1) 56b04f87d7SJoseph Chen goto bl33_setup; 57b04f87d7SJoseph Chen 58b04f87d7SJoseph Chen /* Fill BL32 related information */ 59bcc1726aSKever Yang bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; 60b04f87d7SJoseph Chen bl32_ep_info = &bl31_params_mem.bl32_ep_info; 61b04f87d7SJoseph Chen SET_PARAM_HEAD(bl32_ep_info, ATF_PARAM_EP, ATF_VERSION_1, 62b04f87d7SJoseph Chen ATF_EP_SECURE); 63b04f87d7SJoseph Chen 64b04f87d7SJoseph Chen bl32_ep_info->pc = bl32_entry; 65b04f87d7SJoseph Chen bl32_ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 66b04f87d7SJoseph Chen DISABLE_ALL_EXECPTIONS); 67b04f87d7SJoseph Chen 68bcc1726aSKever Yang bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; 69bcc1726aSKever Yang SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, 70bcc1726aSKever Yang ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); 71bcc1726aSKever Yang 72b04f87d7SJoseph Chen bl33_setup: 73bcc1726aSKever Yang /* Fill BL33 related information */ 74bcc1726aSKever Yang bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; 75bcc1726aSKever Yang bl33_ep_info = &bl31_params_mem.bl33_ep_info; 76bcc1726aSKever Yang SET_PARAM_HEAD(bl33_ep_info, ATF_PARAM_EP, ATF_VERSION_1, 77bcc1726aSKever Yang ATF_EP_NON_SECURE); 78bcc1726aSKever Yang 79bcc1726aSKever Yang /* BL33 expects to receive the primary CPU MPID (through x0) */ 80bcc1726aSKever Yang bl33_ep_info->args.arg0 = 0xffff & read_mpidr(); 812e15a11cSPhilipp Tomsich bl33_ep_info->pc = bl33_entry; 82bcc1726aSKever Yang bl33_ep_info->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, 83bcc1726aSKever Yang DISABLE_ALL_EXECPTIONS); 84*3bf65388SJason Zhu 85189f3a8cSJason Zhu /* 86189f3a8cSJason Zhu * Reference: arch/arm/lib/bootm.c 87189f3a8cSJason Zhu * boot_jump_linux(bootm_headers_t *images, int flag) 88189f3a8cSJason Zhu * { 89189f3a8cSJason Zhu * ...... 90189f3a8cSJason Zhu * armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0, 91189f3a8cSJason Zhu * images->ep, ES_TO_AARCH64); 92189f3a8cSJason Zhu * } 93189f3a8cSJason Zhu */ 94*3bf65388SJason Zhu if (spl_image->next_stage == SPL_NEXT_STAGE_KERNEL) 95*3bf65388SJason Zhu bl33_ep_info->args.arg0 = (unsigned long)spl_image->fdt_addr; 96*3bf65388SJason Zhu 97bcc1726aSKever Yang bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; 98bcc1726aSKever Yang SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, 99bcc1726aSKever Yang ATF_PARAM_IMAGE_BINARY, ATF_VERSION_1, 0); 100bcc1726aSKever Yang 101bcc1726aSKever Yang return bl2_to_bl31_params; 102bcc1726aSKever Yang } 103bcc1726aSKever Yang 1042e15a11cSPhilipp Tomsich static inline void raw_write_daif(unsigned int daif) 105bcc1726aSKever Yang { 106bcc1726aSKever Yang __asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory"); 107bcc1726aSKever Yang } 108bcc1726aSKever Yang 1092e15a11cSPhilipp Tomsich typedef void (*atf_entry_t)(struct bl31_params *params, void *plat_params); 1102e15a11cSPhilipp Tomsich 111*3bf65388SJason Zhu void bl31_entry(struct spl_image_info *spl_image, 112*3bf65388SJason Zhu uintptr_t bl31_entry, uintptr_t bl32_entry, 113b04f87d7SJoseph Chen uintptr_t bl33_entry, uintptr_t fdt_addr) 114bcc1726aSKever Yang { 115bcc1726aSKever Yang struct bl31_params *bl31_params; 1162e15a11cSPhilipp Tomsich atf_entry_t atf_entry = (atf_entry_t)bl31_entry; 117bcc1726aSKever Yang 118*3bf65388SJason Zhu bl31_params = bl2_plat_get_bl31_params(spl_image, bl32_entry, bl33_entry); 119bcc1726aSKever Yang 1202e15a11cSPhilipp Tomsich atf_entry((void *)bl31_params, (void *)fdt_addr); 1212e15a11cSPhilipp Tomsich } 1222e15a11cSPhilipp Tomsich 123b04f87d7SJoseph Chen static int spl_fit_images_find(void *blob, int os) 1242e15a11cSPhilipp Tomsich { 12569a04b4fSJoseph Chen int parent, node; 1262e15a11cSPhilipp Tomsich const void *data; 1272e15a11cSPhilipp Tomsich 1282e15a11cSPhilipp Tomsich if (!blob) 1292e15a11cSPhilipp Tomsich return -FDT_ERR_BADMAGIC; 1302e15a11cSPhilipp Tomsich 1312e15a11cSPhilipp Tomsich parent = fdt_path_offset(blob, "/fit-images"); 1322e15a11cSPhilipp Tomsich if (parent < 0) 1332e15a11cSPhilipp Tomsich return -FDT_ERR_NOTFOUND; 1342e15a11cSPhilipp Tomsich 13569a04b4fSJoseph Chen fdt_for_each_subnode(node, blob, parent) { 1362e15a11cSPhilipp Tomsich data = fdt_getprop(blob, node, FIT_OS_PROP, NULL); 1372e15a11cSPhilipp Tomsich if (!data) 1382e15a11cSPhilipp Tomsich continue; 1392e15a11cSPhilipp Tomsich 140b04f87d7SJoseph Chen if (genimg_get_os_id(data) == os) 1412e15a11cSPhilipp Tomsich return node; 14269a04b4fSJoseph Chen } 1432e15a11cSPhilipp Tomsich 1442e15a11cSPhilipp Tomsich return -FDT_ERR_NOTFOUND; 1452e15a11cSPhilipp Tomsich } 1462e15a11cSPhilipp Tomsich 1472e15a11cSPhilipp Tomsich uintptr_t spl_fit_images_get_entry(void *blob, int node) 1482e15a11cSPhilipp Tomsich { 1492e15a11cSPhilipp Tomsich ulong val; 1502e15a11cSPhilipp Tomsich 1512e15a11cSPhilipp Tomsich val = fdt_getprop_u32(blob, node, "entry-point"); 1522e15a11cSPhilipp Tomsich if (val == FDT_ERROR) 1532e15a11cSPhilipp Tomsich val = fdt_getprop_u32(blob, node, "load-addr"); 1542e15a11cSPhilipp Tomsich 1552e15a11cSPhilipp Tomsich debug("%s: entry point 0x%lx\n", __func__, val); 1562e15a11cSPhilipp Tomsich return val; 1572e15a11cSPhilipp Tomsich } 1582e15a11cSPhilipp Tomsich 1592e15a11cSPhilipp Tomsich void spl_invoke_atf(struct spl_image_info *spl_image) 1602e15a11cSPhilipp Tomsich { 1611620aad4SJoseph Chen uintptr_t bl32_entry, bl33_entry; 1622e15a11cSPhilipp Tomsich void *blob = spl_image->fdt_addr; 1634bba5ee7SPhilipp Tomsich uintptr_t platform_param = (uintptr_t)blob; 1642e15a11cSPhilipp Tomsich int node; 1652e15a11cSPhilipp Tomsich 1661620aad4SJoseph Chen /* 1671620aad4SJoseph Chen * Find the OP-TEE binary (in /fit-images) load address or 1681620aad4SJoseph Chen * entry point (if different) and pass it as the BL3-2 entry 1691620aad4SJoseph Chen * point, this is optional. 1701620aad4SJoseph Chen * This will need to be extended to support Falcon mode. 1711620aad4SJoseph Chen */ 172b04f87d7SJoseph Chen node = spl_fit_images_find(blob, IH_OS_OP_TEE); 173b04f87d7SJoseph Chen if (node >= 0) 174b04f87d7SJoseph Chen bl32_entry = spl_fit_images_get_entry(blob, node); 1751620aad4SJoseph Chen else 1761620aad4SJoseph Chen bl32_entry = spl_image->entry_point_bl32; /* optional */ 177b04f87d7SJoseph Chen 1782e15a11cSPhilipp Tomsich /* 1792e15a11cSPhilipp Tomsich * Find the U-Boot binary (in /fit-images) load addreess or 1802e15a11cSPhilipp Tomsich * entry point (if different) and pass it as the BL3-3 entry 1812e15a11cSPhilipp Tomsich * point. 1822e15a11cSPhilipp Tomsich * This will need to be extended to support Falcon mode. 1832e15a11cSPhilipp Tomsich */ 184b04f87d7SJoseph Chen node = spl_fit_images_find(blob, IH_OS_U_BOOT); 1852e15a11cSPhilipp Tomsich if (node >= 0) 1862e15a11cSPhilipp Tomsich bl33_entry = spl_fit_images_get_entry(blob, node); 1871620aad4SJoseph Chen else 1881620aad4SJoseph Chen bl33_entry = spl_image->entry_point_bl33; 1892e15a11cSPhilipp Tomsich 1902e15a11cSPhilipp Tomsich /* 1914bba5ee7SPhilipp Tomsich * If ATF_NO_PLATFORM_PARAM is set, we override the platform 1924bba5ee7SPhilipp Tomsich * parameter and always pass 0. This is a workaround for 1934bba5ee7SPhilipp Tomsich * older ATF versions that have insufficiently robust (or 1944bba5ee7SPhilipp Tomsich * overzealous) argument validation. 1954bba5ee7SPhilipp Tomsich */ 1964bba5ee7SPhilipp Tomsich if (CONFIG_IS_ENABLED(ATF_NO_PLATFORM_PARAM)) 1974bba5ee7SPhilipp Tomsich platform_param = 0; 1984bba5ee7SPhilipp Tomsich 199f8ca9d16SJoseph Chen /* do cleanup */ 200f8ca9d16SJoseph Chen spl_cleanup_before_jump(spl_image); 201f8ca9d16SJoseph Chen 2024bba5ee7SPhilipp Tomsich /* 2032e15a11cSPhilipp Tomsich * We don't provide a BL3-2 entry yet, but this will be possible 2042e15a11cSPhilipp Tomsich * using similar logic. 2052e15a11cSPhilipp Tomsich */ 206*3bf65388SJason Zhu bl31_entry(spl_image, spl_image->entry_point, bl32_entry, 207b04f87d7SJoseph Chen bl33_entry, platform_param); 208bcc1726aSKever Yang } 209