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