1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <string.h> 9*91f16700Schasinglulu #include <libfdt.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #if CRYPTO_SUPPORT 12*91f16700Schasinglulu #include <mbedtls/version.h> 13*91f16700Schasinglulu #endif /* CRYPTO_SUPPORT */ 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include <common/debug.h> 16*91f16700Schasinglulu #include <common/desc_image_load.h> 17*91f16700Schasinglulu #include <common/tbbr/tbbr_img_def.h> 18*91f16700Schasinglulu #include <lib/fconf/fconf.h> 19*91f16700Schasinglulu #include <lib/fconf/fconf_dyn_cfg_getter.h> 20*91f16700Schasinglulu #include <lib/fconf/fconf_tbbr_getter.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu #include <plat/arm/common/arm_dyn_cfg_helpers.h> 23*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 24*91f16700Schasinglulu #include <platform_def.h> 25*91f16700Schasinglulu 26*91f16700Schasinglulu #if CRYPTO_SUPPORT 27*91f16700Schasinglulu 28*91f16700Schasinglulu static void *mbedtls_heap_addr; 29*91f16700Schasinglulu static size_t mbedtls_heap_size; 30*91f16700Schasinglulu 31*91f16700Schasinglulu /* 32*91f16700Schasinglulu * This function is the implementation of the shared Mbed TLS heap between 33*91f16700Schasinglulu * BL1 and BL2 for Arm platforms. The shared heap address is passed from BL1 34*91f16700Schasinglulu * to BL2 with a pointer. This pointer resides inside the TB_FW_CONFIG file 35*91f16700Schasinglulu * which is a DTB. 36*91f16700Schasinglulu * 37*91f16700Schasinglulu * This function is placed inside an #if directive for the below reasons: 38*91f16700Schasinglulu * - To allocate space for the Mbed TLS heap --only if-- Trusted Board Boot 39*91f16700Schasinglulu * is enabled. 40*91f16700Schasinglulu * - This implementation requires the DTB to be present so that BL1 has a 41*91f16700Schasinglulu * mechanism to pass the pointer to BL2. 42*91f16700Schasinglulu */ 43*91f16700Schasinglulu int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size) 44*91f16700Schasinglulu { 45*91f16700Schasinglulu assert(heap_addr != NULL); 46*91f16700Schasinglulu assert(heap_size != NULL); 47*91f16700Schasinglulu 48*91f16700Schasinglulu #if defined(IMAGE_BL1) || RESET_TO_BL2 || defined(IMAGE_BL31) 49*91f16700Schasinglulu 50*91f16700Schasinglulu /* If in BL1 or RESET_TO_BL2 define a heap */ 51*91f16700Schasinglulu static unsigned char heap[TF_MBEDTLS_HEAP_SIZE]; 52*91f16700Schasinglulu 53*91f16700Schasinglulu *heap_addr = heap; 54*91f16700Schasinglulu *heap_size = sizeof(heap); 55*91f16700Schasinglulu mbedtls_heap_addr = heap; 56*91f16700Schasinglulu mbedtls_heap_size = sizeof(heap); 57*91f16700Schasinglulu 58*91f16700Schasinglulu #elif defined(IMAGE_BL2) 59*91f16700Schasinglulu 60*91f16700Schasinglulu /* If in BL2, retrieve the already allocated heap's info from DTB */ 61*91f16700Schasinglulu *heap_addr = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_addr); 62*91f16700Schasinglulu *heap_size = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_size); 63*91f16700Schasinglulu 64*91f16700Schasinglulu #endif 65*91f16700Schasinglulu 66*91f16700Schasinglulu return 0; 67*91f16700Schasinglulu } 68*91f16700Schasinglulu 69*91f16700Schasinglulu /* 70*91f16700Schasinglulu * Puts the shared Mbed TLS heap information to the DTB. 71*91f16700Schasinglulu * Executed only from BL1. 72*91f16700Schasinglulu */ 73*91f16700Schasinglulu void arm_bl1_set_mbedtls_heap(void) 74*91f16700Schasinglulu { 75*91f16700Schasinglulu int err; 76*91f16700Schasinglulu uintptr_t tb_fw_cfg_dtb; 77*91f16700Schasinglulu const struct dyn_cfg_dtb_info_t *tb_fw_config_info; 78*91f16700Schasinglulu 79*91f16700Schasinglulu /* 80*91f16700Schasinglulu * If tb_fw_cfg_dtb==NULL then DTB is not present for the current 81*91f16700Schasinglulu * platform. As such, we don't attempt to write to the DTB at all. 82*91f16700Schasinglulu * 83*91f16700Schasinglulu * If mbedtls_heap_addr==NULL, then it means we are using the default 84*91f16700Schasinglulu * heap implementation. As such, BL2 will have its own heap for sure 85*91f16700Schasinglulu * and hence there is no need to pass any information to the DTB. 86*91f16700Schasinglulu * 87*91f16700Schasinglulu * In the latter case, if we still wanted to write in the DTB the heap 88*91f16700Schasinglulu * information, we would need to call plat_get_mbedtls_heap to retrieve 89*91f16700Schasinglulu * the default heap's address and size. 90*91f16700Schasinglulu */ 91*91f16700Schasinglulu 92*91f16700Schasinglulu tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID); 93*91f16700Schasinglulu assert(tb_fw_config_info != NULL); 94*91f16700Schasinglulu 95*91f16700Schasinglulu tb_fw_cfg_dtb = tb_fw_config_info->config_addr; 96*91f16700Schasinglulu 97*91f16700Schasinglulu if ((tb_fw_cfg_dtb != 0UL) && (mbedtls_heap_addr != NULL)) { 98*91f16700Schasinglulu /* As libfdt uses void *, we can't avoid this cast */ 99*91f16700Schasinglulu void *dtb = (void *)tb_fw_cfg_dtb; 100*91f16700Schasinglulu 101*91f16700Schasinglulu err = arm_set_dtb_mbedtls_heap_info(dtb, 102*91f16700Schasinglulu mbedtls_heap_addr, mbedtls_heap_size); 103*91f16700Schasinglulu if (err < 0) { 104*91f16700Schasinglulu ERROR("%swrite shared Mbed TLS heap information%s", 105*91f16700Schasinglulu "BL1: unable to ", " to DTB\n"); 106*91f16700Schasinglulu panic(); 107*91f16700Schasinglulu } 108*91f16700Schasinglulu #if !MEASURED_BOOT 109*91f16700Schasinglulu /* 110*91f16700Schasinglulu * Ensure that the info written to the DTB is visible to other 111*91f16700Schasinglulu * images. It's critical because BL2 won't be able to proceed 112*91f16700Schasinglulu * without the heap info. 113*91f16700Schasinglulu * 114*91f16700Schasinglulu * In MEASURED_BOOT case flushing is done in a function which 115*91f16700Schasinglulu * is called after heap information is written in the DTB. 116*91f16700Schasinglulu */ 117*91f16700Schasinglulu flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize(dtb)); 118*91f16700Schasinglulu #endif /* !MEASURED_BOOT */ 119*91f16700Schasinglulu } 120*91f16700Schasinglulu } 121*91f16700Schasinglulu #endif /* CRYPTO_SUPPORT */ 122*91f16700Schasinglulu 123*91f16700Schasinglulu /* 124*91f16700Schasinglulu * BL2 utility function to initialize dynamic configuration specified by 125*91f16700Schasinglulu * FW_CONFIG. Populate the bl_mem_params_node_t of other FW_CONFIGs if 126*91f16700Schasinglulu * specified in FW_CONFIG. 127*91f16700Schasinglulu */ 128*91f16700Schasinglulu void arm_bl2_dyn_cfg_init(void) 129*91f16700Schasinglulu { 130*91f16700Schasinglulu unsigned int i; 131*91f16700Schasinglulu bl_mem_params_node_t *cfg_mem_params = NULL; 132*91f16700Schasinglulu uintptr_t image_base; 133*91f16700Schasinglulu uint32_t image_size; 134*91f16700Schasinglulu unsigned int error_config_id = MAX_IMAGE_IDS; 135*91f16700Schasinglulu const unsigned int config_ids[] = { 136*91f16700Schasinglulu HW_CONFIG_ID, 137*91f16700Schasinglulu SOC_FW_CONFIG_ID, 138*91f16700Schasinglulu NT_FW_CONFIG_ID, 139*91f16700Schasinglulu TOS_FW_CONFIG_ID 140*91f16700Schasinglulu }; 141*91f16700Schasinglulu 142*91f16700Schasinglulu const struct dyn_cfg_dtb_info_t *dtb_info; 143*91f16700Schasinglulu 144*91f16700Schasinglulu /* Iterate through all the fw config IDs */ 145*91f16700Schasinglulu for (i = 0; i < ARRAY_SIZE(config_ids); i++) { 146*91f16700Schasinglulu /* Get the config load address and size */ 147*91f16700Schasinglulu cfg_mem_params = get_bl_mem_params_node(config_ids[i]); 148*91f16700Schasinglulu if (cfg_mem_params == NULL) { 149*91f16700Schasinglulu VERBOSE("%sconfig_id = %d in bl_mem_params_node\n", 150*91f16700Schasinglulu "Couldn't find ", config_ids[i]); 151*91f16700Schasinglulu continue; 152*91f16700Schasinglulu } 153*91f16700Schasinglulu 154*91f16700Schasinglulu dtb_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, config_ids[i]); 155*91f16700Schasinglulu if (dtb_info == NULL) { 156*91f16700Schasinglulu VERBOSE("%sconfig_id %d load info in FW_CONFIG\n", 157*91f16700Schasinglulu "Couldn't find ", config_ids[i]); 158*91f16700Schasinglulu continue; 159*91f16700Schasinglulu } 160*91f16700Schasinglulu 161*91f16700Schasinglulu image_base = dtb_info->config_addr; 162*91f16700Schasinglulu image_size = dtb_info->config_max_size; 163*91f16700Schasinglulu 164*91f16700Schasinglulu /* 165*91f16700Schasinglulu * Do some runtime checks on the load addresses of soc_fw_config, 166*91f16700Schasinglulu * tos_fw_config, nt_fw_config. This is not a comprehensive check 167*91f16700Schasinglulu * of all invalid addresses but to prevent trivial porting errors. 168*91f16700Schasinglulu */ 169*91f16700Schasinglulu if (config_ids[i] != HW_CONFIG_ID) { 170*91f16700Schasinglulu 171*91f16700Schasinglulu if (check_uptr_overflow(image_base, image_size)) { 172*91f16700Schasinglulu VERBOSE("%s=%d as its %s is overflowing uptr\n", 173*91f16700Schasinglulu "skip loading of firmware config", 174*91f16700Schasinglulu config_ids[i], 175*91f16700Schasinglulu "load-address"); 176*91f16700Schasinglulu error_config_id = config_ids[i]; 177*91f16700Schasinglulu continue; 178*91f16700Schasinglulu } 179*91f16700Schasinglulu #ifdef BL31_BASE 180*91f16700Schasinglulu /* Ensure the configs don't overlap with BL31 */ 181*91f16700Schasinglulu if ((image_base >= BL31_BASE) && 182*91f16700Schasinglulu (image_base <= BL31_LIMIT)) { 183*91f16700Schasinglulu VERBOSE("%s=%d as its %s is overlapping BL31\n", 184*91f16700Schasinglulu "skip loading of firmware config", 185*91f16700Schasinglulu config_ids[i], 186*91f16700Schasinglulu "load-address"); 187*91f16700Schasinglulu error_config_id = config_ids[i]; 188*91f16700Schasinglulu continue; 189*91f16700Schasinglulu } 190*91f16700Schasinglulu #endif 191*91f16700Schasinglulu /* Ensure the configs are loaded in a valid address */ 192*91f16700Schasinglulu if (image_base < ARM_BL_RAM_BASE) { 193*91f16700Schasinglulu VERBOSE("%s=%d as its %s is invalid\n", 194*91f16700Schasinglulu "skip loading of firmware config", 195*91f16700Schasinglulu config_ids[i], 196*91f16700Schasinglulu "load-address"); 197*91f16700Schasinglulu error_config_id = config_ids[i]; 198*91f16700Schasinglulu continue; 199*91f16700Schasinglulu } 200*91f16700Schasinglulu #ifdef BL32_BASE 201*91f16700Schasinglulu /* 202*91f16700Schasinglulu * If BL32 is present, ensure that the configs don't 203*91f16700Schasinglulu * overlap with it. 204*91f16700Schasinglulu */ 205*91f16700Schasinglulu if ((image_base >= BL32_BASE) && 206*91f16700Schasinglulu (image_base <= BL32_LIMIT)) { 207*91f16700Schasinglulu VERBOSE("%s=%d as its %s is overlapping BL32\n", 208*91f16700Schasinglulu "skip loading of firmware config", 209*91f16700Schasinglulu config_ids[i], 210*91f16700Schasinglulu "load-address"); 211*91f16700Schasinglulu error_config_id = config_ids[i]; 212*91f16700Schasinglulu continue; 213*91f16700Schasinglulu } 214*91f16700Schasinglulu #endif 215*91f16700Schasinglulu } 216*91f16700Schasinglulu 217*91f16700Schasinglulu cfg_mem_params->image_info.image_base = image_base; 218*91f16700Schasinglulu cfg_mem_params->image_info.image_max_size = (uint32_t)image_size; 219*91f16700Schasinglulu 220*91f16700Schasinglulu /* 221*91f16700Schasinglulu * Remove the IMAGE_ATTRIB_SKIP_LOADING attribute from 222*91f16700Schasinglulu * HW_CONFIG or FW_CONFIG nodes 223*91f16700Schasinglulu */ 224*91f16700Schasinglulu cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; 225*91f16700Schasinglulu } 226*91f16700Schasinglulu 227*91f16700Schasinglulu if (error_config_id != MAX_IMAGE_IDS) { 228*91f16700Schasinglulu ERROR("Invalid config file %u\n", error_config_id); 229*91f16700Schasinglulu panic(); 230*91f16700Schasinglulu } 231*91f16700Schasinglulu } 232