1 /* 2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <arch_helpers.h> 32 #include <assert.h> 33 #include <bl_common.h> 34 #include <desc_image_load.h> 35 36 37 extern bl_mem_params_node_t *bl_mem_params_desc_ptr; 38 extern unsigned int bl_mem_params_desc_num; 39 40 static bl_load_info_t bl_load_info; 41 static bl_params_t next_bl_params; 42 43 44 /******************************************************************************* 45 * This function flushes the data structures so that they are visible 46 * in memory for the next BL image. 47 ******************************************************************************/ 48 void flush_bl_params_desc(void) 49 { 50 flush_dcache_range((uintptr_t)bl_mem_params_desc_ptr, 51 sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num); 52 53 flush_dcache_range((uintptr_t)&next_bl_params, 54 sizeof(next_bl_params)); 55 } 56 57 /******************************************************************************* 58 * This function returns the index for given image_id, within the 59 * image descriptor array provided by bl_image_info_descs_ptr, if the 60 * image is found else it returns -1. 61 ******************************************************************************/ 62 int get_bl_params_node_index(unsigned int image_id) 63 { 64 int index; 65 assert(image_id != INVALID_IMAGE_ID); 66 67 for (index = 0; index < bl_mem_params_desc_num; index++) { 68 if (bl_mem_params_desc_ptr[index].image_id == image_id) 69 return index; 70 } 71 72 return -1; 73 } 74 75 /******************************************************************************* 76 * This function returns the pointer to `bl_mem_params_node_t` object for 77 * given image_id, within the image descriptor array provided by 78 * bl_mem_params_desc_ptr, if the image is found else it returns NULL. 79 ******************************************************************************/ 80 bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) 81 { 82 int index; 83 assert(image_id != INVALID_IMAGE_ID); 84 85 index = get_bl_params_node_index(image_id); 86 if (index >= 0) 87 return &bl_mem_params_desc_ptr[index]; 88 else 89 return NULL; 90 } 91 92 /******************************************************************************* 93 * This function creates the list of loadable images, by populating and 94 * linking each `bl_load_info_node_t` type node, using the internal array 95 * of image descriptor provided by bl_mem_params_desc_ptr. It also populates 96 * and returns `bl_load_info_t` type structure that contains head of the list 97 * of loadable images. 98 ******************************************************************************/ 99 bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) 100 { 101 int index = 0; 102 103 /* If there is no image to start with, return NULL */ 104 if (!bl_mem_params_desc_num) 105 return NULL; 106 107 /* Assign initial data structures */ 108 bl_load_info_node_t *bl_node_info = 109 &bl_mem_params_desc_ptr[index].load_node_mem; 110 bl_load_info.head = bl_node_info; 111 SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0); 112 113 /* Go through the image descriptor array and create the list */ 114 for (; index < bl_mem_params_desc_num; index++) { 115 116 /* Populate the image information */ 117 bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; 118 bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; 119 120 /* Link next image if present */ 121 if ((index + 1) < bl_mem_params_desc_num) { 122 /* Get the memory and link the next node */ 123 bl_node_info->next_load_info = 124 &bl_mem_params_desc_ptr[index + 1].load_node_mem; 125 bl_node_info = bl_node_info->next_load_info; 126 } 127 } 128 129 return &bl_load_info; 130 } 131 132 /******************************************************************************* 133 * This function creates the list of executable images, by populating and 134 * linking each `bl_params_node_t` type node, using the internal array of 135 * image descriptor provided by bl_mem_params_desc_ptr. It also populates 136 * and returns `bl_params_t` type structure that contains head of the list 137 * of executable images. 138 ******************************************************************************/ 139 bl_params_t *get_next_bl_params_from_mem_params_desc(void) 140 { 141 int count; 142 unsigned int img_id = 0; 143 int link_index = 0; 144 bl_params_node_t *bl_current_exec_node = NULL; 145 bl_params_node_t *bl_last_exec_node = NULL; 146 bl_mem_params_node_t *desc_ptr; 147 148 /* If there is no image to start with, return NULL */ 149 if (!bl_mem_params_desc_num) 150 return NULL; 151 152 /* Get the list HEAD */ 153 for (count = 0; count < bl_mem_params_desc_num; count++) { 154 155 desc_ptr = &bl_mem_params_desc_ptr[count]; 156 157 if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && 158 (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { 159 next_bl_params.head = &desc_ptr->params_node_mem; 160 link_index = count; 161 break; 162 } 163 } 164 165 /* Make sure we have a HEAD node */ 166 assert(next_bl_params.head != NULL); 167 168 /* Populate the HEAD information */ 169 SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0); 170 171 /* 172 * Go through the image descriptor array and create the list. 173 * This bounded loop is to make sure that we are not looping forever. 174 */ 175 for (count = 0 ; count < bl_mem_params_desc_num; count++) { 176 177 desc_ptr = &bl_mem_params_desc_ptr[link_index]; 178 179 /* Make sure the image is executable */ 180 assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); 181 182 /* Get the memory for current node */ 183 bl_current_exec_node = &desc_ptr->params_node_mem; 184 185 /* Populate the image information */ 186 bl_current_exec_node->image_id = desc_ptr->image_id; 187 bl_current_exec_node->image_info = &desc_ptr->image_info; 188 bl_current_exec_node->ep_info = &desc_ptr->ep_info; 189 190 if (bl_last_exec_node) { 191 /* Assert if loop detected */ 192 assert(bl_last_exec_node->next_params_info == NULL); 193 194 /* Link the previous node to the current one */ 195 bl_last_exec_node->next_params_info = bl_current_exec_node; 196 } 197 198 /* Update the last node */ 199 bl_last_exec_node = bl_current_exec_node; 200 201 /* If no next hand-off image then break out */ 202 img_id = desc_ptr->next_handoff_image_id; 203 if (img_id == INVALID_IMAGE_ID) 204 break; 205 206 /* Get the index for the next hand-off image */ 207 link_index = get_bl_params_node_index(img_id); 208 assert((link_index > 0) && 209 (link_index < bl_mem_params_desc_num)); 210 } 211 212 /* Invalid image is expected to terminate the loop */ 213 assert(img_id == INVALID_IMAGE_ID); 214 215 return &next_bl_params; 216 } 217