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((unsigned long)bl_mem_params_desc_ptr, 51 sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num); 52 } 53 54 /******************************************************************************* 55 * This function returns the index for given image_id, within the 56 * image descriptor array provided by bl_image_info_descs_ptr, if the 57 * image is found else it returns -1. 58 ******************************************************************************/ 59 int get_bl_params_node_index(unsigned int image_id) 60 { 61 int index; 62 assert(image_id != INVALID_IMAGE_ID); 63 64 for (index = 0; index < bl_mem_params_desc_num; index++) { 65 if (bl_mem_params_desc_ptr[index].image_id == image_id) 66 return index; 67 } 68 69 return -1; 70 } 71 72 /******************************************************************************* 73 * This function returns the pointer to `bl_mem_params_node_t` object for 74 * given image_id, within the image descriptor array provided by 75 * bl_mem_params_desc_ptr, if the image is found else it returns NULL. 76 ******************************************************************************/ 77 bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) 78 { 79 int index; 80 assert(image_id != INVALID_IMAGE_ID); 81 82 index = get_bl_params_node_index(image_id); 83 if (index >= 0) 84 return &bl_mem_params_desc_ptr[index]; 85 else 86 return NULL; 87 } 88 89 /******************************************************************************* 90 * This function creates the list of loadable images, by populating and 91 * linking each `bl_load_info_node_t` type node, using the internal array 92 * of image descriptor provided by bl_mem_params_desc_ptr. It also populates 93 * and returns `bl_load_info_t` type structure that contains head of the list 94 * of loadable images. 95 ******************************************************************************/ 96 bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) 97 { 98 int index = 0; 99 100 /* If there is no image to start with, return NULL */ 101 if (!bl_mem_params_desc_num) 102 return NULL; 103 104 /* Assign initial data structures */ 105 bl_load_info_node_t *bl_node_info = 106 &bl_mem_params_desc_ptr[index].load_node_mem; 107 bl_load_info.head = bl_node_info; 108 SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0); 109 110 /* Go through the image descriptor array and create the list */ 111 for (; index < bl_mem_params_desc_num; index++) { 112 113 /* Populate the image information */ 114 bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; 115 bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; 116 117 /* Link next image if present */ 118 if ((index + 1) < bl_mem_params_desc_num) { 119 /* Get the memory and link the next node */ 120 bl_node_info->next_load_info = 121 &bl_mem_params_desc_ptr[index + 1].load_node_mem; 122 bl_node_info = bl_node_info->next_load_info; 123 } 124 } 125 126 return &bl_load_info; 127 } 128 129 /******************************************************************************* 130 * This function creates the list of executable images, by populating and 131 * linking each `bl_params_node_t` type node, using the internal array of 132 * image descriptor provided by bl_mem_params_desc_ptr. It also populates 133 * and returns `bl_params_t` type structure that contains head of the list 134 * of executable images. 135 ******************************************************************************/ 136 bl_params_t *get_next_bl_params_from_mem_params_desc(void) 137 { 138 int count; 139 unsigned int img_id = 0; 140 int link_index = 0; 141 bl_params_node_t *bl_current_exec_node = NULL; 142 bl_params_node_t *bl_last_exec_node = NULL; 143 bl_mem_params_node_t *desc_ptr; 144 145 /* If there is no image to start with, return NULL */ 146 if (!bl_mem_params_desc_num) 147 return NULL; 148 149 /* Get the list HEAD */ 150 for (count = 0; count < bl_mem_params_desc_num; count++) { 151 152 desc_ptr = &bl_mem_params_desc_ptr[count]; 153 154 if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && 155 (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { 156 next_bl_params.head = &desc_ptr->params_node_mem; 157 link_index = count; 158 break; 159 } 160 } 161 162 /* Make sure we have a HEAD node */ 163 assert(next_bl_params.head != NULL); 164 165 /* Populate the HEAD information */ 166 SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0); 167 168 /* 169 * Go through the image descriptor array and create the list. 170 * This bounded loop is to make sure that we are not looping forever. 171 */ 172 for (count = 0 ; count < bl_mem_params_desc_num; count++) { 173 174 desc_ptr = &bl_mem_params_desc_ptr[link_index]; 175 176 /* Make sure the image is executable */ 177 assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); 178 179 /* Get the memory for current node */ 180 bl_current_exec_node = &desc_ptr->params_node_mem; 181 182 /* Populate the image information */ 183 bl_current_exec_node->image_id = desc_ptr->image_id; 184 bl_current_exec_node->image_info = &desc_ptr->image_info; 185 bl_current_exec_node->ep_info = &desc_ptr->ep_info; 186 187 if (bl_last_exec_node) { 188 /* Assert if loop detected */ 189 assert(bl_last_exec_node->next_params_info == NULL); 190 191 /* Link the previous node to the current one */ 192 bl_last_exec_node->next_params_info = bl_current_exec_node; 193 } 194 195 /* Update the last node */ 196 bl_last_exec_node = bl_current_exec_node; 197 198 /* If no next hand-off image then break out */ 199 img_id = desc_ptr->next_handoff_image_id; 200 if (img_id == INVALID_IMAGE_ID) 201 break; 202 203 /* Get the index for the next hand-off image */ 204 link_index = get_bl_params_node_index(img_id); 205 assert((link_index > 0) && 206 (link_index < bl_mem_params_desc_num)); 207 } 208 209 /* Invalid image is expected to terminate the loop */ 210 assert(img_id == INVALID_IMAGE_ID); 211 212 /* Populate arg0 for the next BL image */ 213 next_bl_params.head->ep_info->args.arg0 = (unsigned long)&next_bl_params; 214 215 /* Flush the parameters to be passed to the next BL image */ 216 flush_dcache_range((unsigned long)&next_bl_params, 217 sizeof(next_bl_params)); 218 219 return &next_bl_params; 220 } 221