1 /* 2 * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <arch_helpers.h> 10 #include <common/bl_common.h> 11 #include <common/desc_image_load.h> 12 13 static bl_load_info_t bl_load_info; 14 static bl_params_t next_bl_params; 15 16 17 /******************************************************************************* 18 * This function flushes the data structures so that they are visible 19 * in memory for the next BL image. 20 ******************************************************************************/ 21 void flush_bl_params_desc(void) 22 { 23 flush_bl_params_desc_args(bl_mem_params_desc_ptr, 24 bl_mem_params_desc_num, 25 &next_bl_params); 26 } 27 28 /******************************************************************************* 29 * This function flushes the data structures specified as arguments so that they 30 * are visible in memory for the next BL image. 31 ******************************************************************************/ 32 void flush_bl_params_desc_args(bl_mem_params_node_t *mem_params_desc_ptr, 33 unsigned int mem_params_desc_num, 34 bl_params_t *next_bl_params_ptr) 35 { 36 assert(mem_params_desc_ptr != NULL); 37 assert(mem_params_desc_num != 0U); 38 assert(next_bl_params_ptr != NULL); 39 40 flush_dcache_range((uintptr_t)mem_params_desc_ptr, 41 sizeof(*mem_params_desc_ptr) * mem_params_desc_num); 42 43 flush_dcache_range((uintptr_t)next_bl_params_ptr, 44 sizeof(*next_bl_params_ptr)); 45 } 46 47 /******************************************************************************* 48 * This function returns the index for given image_id, within the 49 * image descriptor array provided by bl_image_info_descs_ptr, if the 50 * image is found else it returns -1. 51 ******************************************************************************/ 52 int get_bl_params_node_index(unsigned int image_id) 53 { 54 unsigned int index; 55 assert(image_id != INVALID_IMAGE_ID); 56 57 for (index = 0U; index < bl_mem_params_desc_num; index++) { 58 if (bl_mem_params_desc_ptr[index].image_id == image_id) 59 return (int)index; 60 } 61 62 return -1; 63 } 64 65 /******************************************************************************* 66 * This function returns the pointer to `bl_mem_params_node_t` object for 67 * given image_id, within the image descriptor array provided by 68 * bl_mem_params_desc_ptr, if the image is found else it returns NULL. 69 ******************************************************************************/ 70 bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) 71 { 72 int index; 73 assert(image_id != INVALID_IMAGE_ID); 74 75 index = get_bl_params_node_index(image_id); 76 if (index >= 0) 77 return &bl_mem_params_desc_ptr[index]; 78 else 79 return NULL; 80 } 81 82 /******************************************************************************* 83 * This function creates the list of loadable images, by populating and 84 * linking each `bl_load_info_node_t` type node, using the internal array 85 * of image descriptor provided by bl_mem_params_desc_ptr. It also populates 86 * and returns `bl_load_info_t` type structure that contains head of the list 87 * of loadable images. 88 ******************************************************************************/ 89 bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) 90 { 91 unsigned int index = 0; 92 93 /* If there is no image to start with, return NULL */ 94 if (bl_mem_params_desc_num == 0U) 95 return NULL; 96 97 /* Assign initial data structures */ 98 bl_load_info_node_t *bl_node_info = 99 &bl_mem_params_desc_ptr[index].load_node_mem; 100 bl_load_info.head = bl_node_info; 101 SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0U); 102 103 /* Go through the image descriptor array and create the list */ 104 for (; index < bl_mem_params_desc_num; index++) { 105 106 /* Populate the image information */ 107 bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; 108 bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; 109 110 /* Link next image if present */ 111 if ((index + 1U) < bl_mem_params_desc_num) { 112 /* Get the memory and link the next node */ 113 bl_node_info->next_load_info = 114 &bl_mem_params_desc_ptr[index + 1U].load_node_mem; 115 bl_node_info = bl_node_info->next_load_info; 116 } 117 } 118 119 return &bl_load_info; 120 } 121 122 /******************************************************************************* 123 * This function creates the list of executable images, by populating and 124 * linking each `bl_params_node_t` type node, using the internal array of 125 * image descriptor provided by bl_mem_params_desc_ptr. It also populates 126 * and returns `bl_params_t` type structure that contains head of the list 127 * of executable images. 128 ******************************************************************************/ 129 bl_params_t *get_next_bl_params_from_mem_params_desc(void) 130 { 131 unsigned int count; 132 unsigned int img_id = 0U; 133 unsigned int link_index = 0U; 134 bl_params_node_t *bl_current_exec_node = NULL; 135 bl_params_node_t *bl_last_exec_node = NULL; 136 bl_mem_params_node_t *desc_ptr; 137 138 /* If there is no image to start with, return NULL */ 139 if (bl_mem_params_desc_num == 0U) 140 return NULL; 141 142 /* Get the list HEAD */ 143 for (count = 0U; count < bl_mem_params_desc_num; count++) { 144 145 desc_ptr = &bl_mem_params_desc_ptr[count]; 146 147 if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && 148 (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { 149 next_bl_params.head = &desc_ptr->params_node_mem; 150 link_index = count; 151 break; 152 } 153 } 154 155 /* Make sure we have a HEAD node */ 156 assert(next_bl_params.head != NULL); 157 158 /* Populate the HEAD information */ 159 SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0U); 160 161 /* 162 * Go through the image descriptor array and create the list. 163 * This bounded loop is to make sure that we are not looping forever. 164 */ 165 for (count = 0U; count < bl_mem_params_desc_num; count++) { 166 167 desc_ptr = &bl_mem_params_desc_ptr[link_index]; 168 169 /* Make sure the image is executable */ 170 assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); 171 172 /* Get the memory for current node */ 173 bl_current_exec_node = &desc_ptr->params_node_mem; 174 175 /* Populate the image information */ 176 bl_current_exec_node->image_id = desc_ptr->image_id; 177 bl_current_exec_node->image_info = &desc_ptr->image_info; 178 bl_current_exec_node->ep_info = &desc_ptr->ep_info; 179 180 if (bl_last_exec_node != NULL) { 181 /* Assert if loop detected */ 182 assert(bl_last_exec_node->next_params_info == NULL); 183 184 /* Link the previous node to the current one */ 185 bl_last_exec_node->next_params_info = bl_current_exec_node; 186 } 187 188 /* Update the last node */ 189 bl_last_exec_node = bl_current_exec_node; 190 191 /* If no next hand-off image then break out */ 192 img_id = desc_ptr->next_handoff_image_id; 193 if (img_id == INVALID_IMAGE_ID) 194 break; 195 196 /* Get the index for the next hand-off image */ 197 link_index = get_bl_params_node_index(img_id); 198 assert((link_index > 0U) && 199 (link_index < bl_mem_params_desc_num)); 200 } 201 202 /* Invalid image is expected to terminate the loop */ 203 assert(img_id == INVALID_IMAGE_ID); 204 205 return &next_bl_params; 206 } 207 208 /******************************************************************************* 209 * This function populates the entry point information with the corresponding 210 * config file for all executable BL images described in bl_params. 211 ******************************************************************************/ 212 void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params) 213 { 214 bl_params_node_t *params_node; 215 unsigned int fw_config_id; 216 uintptr_t hw_config_base = 0, fw_config_base; 217 bl_mem_params_node_t *mem_params; 218 219 assert(bl2_to_next_bl_params != NULL); 220 221 /* 222 * Get the `bl_mem_params_node_t` corresponding to HW_CONFIG 223 * if available. 224 */ 225 mem_params = get_bl_mem_params_node(HW_CONFIG_ID); 226 if (mem_params != NULL) 227 hw_config_base = mem_params->image_info.image_base; 228 229 for (params_node = bl2_to_next_bl_params->head; params_node != NULL; 230 params_node = params_node->next_params_info) { 231 232 fw_config_base = 0; 233 234 switch (params_node->image_id) { 235 case BL31_IMAGE_ID: 236 fw_config_id = SOC_FW_CONFIG_ID; 237 break; 238 case BL32_IMAGE_ID: 239 fw_config_id = TOS_FW_CONFIG_ID; 240 break; 241 case BL33_IMAGE_ID: 242 fw_config_id = NT_FW_CONFIG_ID; 243 break; 244 default: 245 fw_config_id = INVALID_IMAGE_ID; 246 break; 247 } 248 249 if (fw_config_id != INVALID_IMAGE_ID) { 250 mem_params = get_bl_mem_params_node(fw_config_id); 251 if (mem_params != NULL) 252 fw_config_base = mem_params->image_info.image_base; 253 } 254 255 /* 256 * Pass hw and tb_fw config addresses to next images. NOTE - for 257 * EL3 runtime images (BL31 for AArch64 and BL32 for AArch32), 258 * arg0 is already used by generic code. Take care of not 259 * overwriting the previous initialisations. 260 */ 261 if (params_node == bl2_to_next_bl_params->head) { 262 if (params_node->ep_info->args.arg1 == 0U) 263 params_node->ep_info->args.arg1 = 264 fw_config_base; 265 if (params_node->ep_info->args.arg2 == 0U) 266 params_node->ep_info->args.arg2 = 267 hw_config_base; 268 } else { 269 if (params_node->ep_info->args.arg0 == 0U) 270 params_node->ep_info->args.arg0 = 271 fw_config_base; 272 if (params_node->ep_info->args.arg1 == 0U) 273 params_node->ep_info->args.arg1 = 274 hw_config_base; 275 } 276 } 277 } 278