1 /* 2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch_helpers.h> 8 #include <assert.h> 9 #include <bl_common.h> 10 #include <desc_image_load.h> 11 12 13 extern bl_mem_params_node_t *bl_mem_params_desc_ptr; 14 extern unsigned int bl_mem_params_desc_num; 15 16 static bl_load_info_t bl_load_info; 17 static bl_params_t next_bl_params; 18 19 20 /******************************************************************************* 21 * This function flushes the data structures so that they are visible 22 * in memory for the next BL image. 23 ******************************************************************************/ 24 void flush_bl_params_desc(void) 25 { 26 flush_dcache_range((uintptr_t)bl_mem_params_desc_ptr, 27 sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num); 28 29 flush_dcache_range((uintptr_t)&next_bl_params, 30 sizeof(next_bl_params)); 31 } 32 33 /******************************************************************************* 34 * This function returns the index for given image_id, within the 35 * image descriptor array provided by bl_image_info_descs_ptr, if the 36 * image is found else it returns -1. 37 ******************************************************************************/ 38 int get_bl_params_node_index(unsigned int image_id) 39 { 40 int index; 41 assert(image_id != INVALID_IMAGE_ID); 42 43 for (index = 0; index < bl_mem_params_desc_num; index++) { 44 if (bl_mem_params_desc_ptr[index].image_id == image_id) 45 return index; 46 } 47 48 return -1; 49 } 50 51 /******************************************************************************* 52 * This function returns the pointer to `bl_mem_params_node_t` object for 53 * given image_id, within the image descriptor array provided by 54 * bl_mem_params_desc_ptr, if the image is found else it returns NULL. 55 ******************************************************************************/ 56 bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) 57 { 58 int index; 59 assert(image_id != INVALID_IMAGE_ID); 60 61 index = get_bl_params_node_index(image_id); 62 if (index >= 0) 63 return &bl_mem_params_desc_ptr[index]; 64 else 65 return NULL; 66 } 67 68 /******************************************************************************* 69 * This function creates the list of loadable images, by populating and 70 * linking each `bl_load_info_node_t` type node, using the internal array 71 * of image descriptor provided by bl_mem_params_desc_ptr. It also populates 72 * and returns `bl_load_info_t` type structure that contains head of the list 73 * of loadable images. 74 ******************************************************************************/ 75 bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) 76 { 77 int index = 0; 78 79 /* If there is no image to start with, return NULL */ 80 if (!bl_mem_params_desc_num) 81 return NULL; 82 83 /* Assign initial data structures */ 84 bl_load_info_node_t *bl_node_info = 85 &bl_mem_params_desc_ptr[index].load_node_mem; 86 bl_load_info.head = bl_node_info; 87 SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0); 88 89 /* Go through the image descriptor array and create the list */ 90 for (; index < bl_mem_params_desc_num; index++) { 91 92 /* Populate the image information */ 93 bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; 94 bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; 95 96 /* Link next image if present */ 97 if ((index + 1) < bl_mem_params_desc_num) { 98 /* Get the memory and link the next node */ 99 bl_node_info->next_load_info = 100 &bl_mem_params_desc_ptr[index + 1].load_node_mem; 101 bl_node_info = bl_node_info->next_load_info; 102 } 103 } 104 105 return &bl_load_info; 106 } 107 108 /******************************************************************************* 109 * This function creates the list of executable images, by populating and 110 * linking each `bl_params_node_t` type node, using the internal array of 111 * image descriptor provided by bl_mem_params_desc_ptr. It also populates 112 * and returns `bl_params_t` type structure that contains head of the list 113 * of executable images. 114 ******************************************************************************/ 115 bl_params_t *get_next_bl_params_from_mem_params_desc(void) 116 { 117 int count; 118 unsigned int img_id = 0; 119 int link_index = 0; 120 bl_params_node_t *bl_current_exec_node = NULL; 121 bl_params_node_t *bl_last_exec_node = NULL; 122 bl_mem_params_node_t *desc_ptr; 123 124 /* If there is no image to start with, return NULL */ 125 if (!bl_mem_params_desc_num) 126 return NULL; 127 128 /* Get the list HEAD */ 129 for (count = 0; count < bl_mem_params_desc_num; count++) { 130 131 desc_ptr = &bl_mem_params_desc_ptr[count]; 132 133 if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && 134 (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { 135 next_bl_params.head = &desc_ptr->params_node_mem; 136 link_index = count; 137 break; 138 } 139 } 140 141 /* Make sure we have a HEAD node */ 142 assert(next_bl_params.head != NULL); 143 144 /* Populate the HEAD information */ 145 SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0); 146 147 /* 148 * Go through the image descriptor array and create the list. 149 * This bounded loop is to make sure that we are not looping forever. 150 */ 151 for (count = 0 ; count < bl_mem_params_desc_num; count++) { 152 153 desc_ptr = &bl_mem_params_desc_ptr[link_index]; 154 155 /* Make sure the image is executable */ 156 assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); 157 158 /* Get the memory for current node */ 159 bl_current_exec_node = &desc_ptr->params_node_mem; 160 161 /* Populate the image information */ 162 bl_current_exec_node->image_id = desc_ptr->image_id; 163 bl_current_exec_node->image_info = &desc_ptr->image_info; 164 bl_current_exec_node->ep_info = &desc_ptr->ep_info; 165 166 if (bl_last_exec_node) { 167 /* Assert if loop detected */ 168 assert(bl_last_exec_node->next_params_info == NULL); 169 170 /* Link the previous node to the current one */ 171 bl_last_exec_node->next_params_info = bl_current_exec_node; 172 } 173 174 /* Update the last node */ 175 bl_last_exec_node = bl_current_exec_node; 176 177 /* If no next hand-off image then break out */ 178 img_id = desc_ptr->next_handoff_image_id; 179 if (img_id == INVALID_IMAGE_ID) 180 break; 181 182 /* Get the index for the next hand-off image */ 183 link_index = get_bl_params_node_index(img_id); 184 assert((link_index > 0) && 185 (link_index < bl_mem_params_desc_num)); 186 } 187 188 /* Invalid image is expected to terminate the loop */ 189 assert(img_id == INVALID_IMAGE_ID); 190 191 return &next_bl_params; 192 } 193