172600226SYatharth Kochar /* 272600226SYatharth Kochar * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 372600226SYatharth Kochar * 472600226SYatharth Kochar * Redistribution and use in source and binary forms, with or without 572600226SYatharth Kochar * modification, are permitted provided that the following conditions are met: 672600226SYatharth Kochar * 772600226SYatharth Kochar * Redistributions of source code must retain the above copyright notice, this 872600226SYatharth Kochar * list of conditions and the following disclaimer. 972600226SYatharth Kochar * 1072600226SYatharth Kochar * Redistributions in binary form must reproduce the above copyright notice, 1172600226SYatharth Kochar * this list of conditions and the following disclaimer in the documentation 1272600226SYatharth Kochar * and/or other materials provided with the distribution. 1372600226SYatharth Kochar * 1472600226SYatharth Kochar * Neither the name of ARM nor the names of its contributors may be used 1572600226SYatharth Kochar * to endorse or promote products derived from this software without specific 1672600226SYatharth Kochar * prior written permission. 1772600226SYatharth Kochar * 1872600226SYatharth Kochar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1972600226SYatharth Kochar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2072600226SYatharth Kochar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2172600226SYatharth Kochar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2272600226SYatharth Kochar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2372600226SYatharth Kochar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2472600226SYatharth Kochar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2572600226SYatharth Kochar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2672600226SYatharth Kochar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2772600226SYatharth Kochar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2872600226SYatharth Kochar * POSSIBILITY OF SUCH DAMAGE. 2972600226SYatharth Kochar */ 3072600226SYatharth Kochar 3172600226SYatharth Kochar #include <arch_helpers.h> 3272600226SYatharth Kochar #include <assert.h> 3372600226SYatharth Kochar #include <bl_common.h> 3472600226SYatharth Kochar #include <desc_image_load.h> 3572600226SYatharth Kochar 3672600226SYatharth Kochar 3772600226SYatharth Kochar extern bl_mem_params_node_t *bl_mem_params_desc_ptr; 3872600226SYatharth Kochar extern unsigned int bl_mem_params_desc_num; 3972600226SYatharth Kochar 4072600226SYatharth Kochar static bl_load_info_t bl_load_info; 4172600226SYatharth Kochar static bl_params_t next_bl_params; 4272600226SYatharth Kochar 4372600226SYatharth Kochar 4472600226SYatharth Kochar /******************************************************************************* 4572600226SYatharth Kochar * This function flushes the data structures so that they are visible 4672600226SYatharth Kochar * in memory for the next BL image. 4772600226SYatharth Kochar ******************************************************************************/ 4872600226SYatharth Kochar void flush_bl_params_desc(void) 4972600226SYatharth Kochar { 50*c2a9ee63SDan Handley flush_dcache_range((uintptr_t)bl_mem_params_desc_ptr, 5172600226SYatharth Kochar sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num); 52*c2a9ee63SDan Handley 53*c2a9ee63SDan Handley flush_dcache_range((uintptr_t)&next_bl_params, 54*c2a9ee63SDan Handley sizeof(next_bl_params)); 5572600226SYatharth Kochar } 5672600226SYatharth Kochar 5772600226SYatharth Kochar /******************************************************************************* 5872600226SYatharth Kochar * This function returns the index for given image_id, within the 5972600226SYatharth Kochar * image descriptor array provided by bl_image_info_descs_ptr, if the 6072600226SYatharth Kochar * image is found else it returns -1. 6172600226SYatharth Kochar ******************************************************************************/ 6272600226SYatharth Kochar int get_bl_params_node_index(unsigned int image_id) 6372600226SYatharth Kochar { 6472600226SYatharth Kochar int index; 6572600226SYatharth Kochar assert(image_id != INVALID_IMAGE_ID); 6672600226SYatharth Kochar 6772600226SYatharth Kochar for (index = 0; index < bl_mem_params_desc_num; index++) { 6872600226SYatharth Kochar if (bl_mem_params_desc_ptr[index].image_id == image_id) 6972600226SYatharth Kochar return index; 7072600226SYatharth Kochar } 7172600226SYatharth Kochar 7272600226SYatharth Kochar return -1; 7372600226SYatharth Kochar } 7472600226SYatharth Kochar 7572600226SYatharth Kochar /******************************************************************************* 7672600226SYatharth Kochar * This function returns the pointer to `bl_mem_params_node_t` object for 7772600226SYatharth Kochar * given image_id, within the image descriptor array provided by 7872600226SYatharth Kochar * bl_mem_params_desc_ptr, if the image is found else it returns NULL. 7972600226SYatharth Kochar ******************************************************************************/ 8072600226SYatharth Kochar bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) 8172600226SYatharth Kochar { 8272600226SYatharth Kochar int index; 8372600226SYatharth Kochar assert(image_id != INVALID_IMAGE_ID); 8472600226SYatharth Kochar 8572600226SYatharth Kochar index = get_bl_params_node_index(image_id); 8672600226SYatharth Kochar if (index >= 0) 8772600226SYatharth Kochar return &bl_mem_params_desc_ptr[index]; 8872600226SYatharth Kochar else 8972600226SYatharth Kochar return NULL; 9072600226SYatharth Kochar } 9172600226SYatharth Kochar 9272600226SYatharth Kochar /******************************************************************************* 9372600226SYatharth Kochar * This function creates the list of loadable images, by populating and 9472600226SYatharth Kochar * linking each `bl_load_info_node_t` type node, using the internal array 9572600226SYatharth Kochar * of image descriptor provided by bl_mem_params_desc_ptr. It also populates 9672600226SYatharth Kochar * and returns `bl_load_info_t` type structure that contains head of the list 9772600226SYatharth Kochar * of loadable images. 9872600226SYatharth Kochar ******************************************************************************/ 9972600226SYatharth Kochar bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) 10072600226SYatharth Kochar { 10172600226SYatharth Kochar int index = 0; 10272600226SYatharth Kochar 10372600226SYatharth Kochar /* If there is no image to start with, return NULL */ 10472600226SYatharth Kochar if (!bl_mem_params_desc_num) 10572600226SYatharth Kochar return NULL; 10672600226SYatharth Kochar 10772600226SYatharth Kochar /* Assign initial data structures */ 10872600226SYatharth Kochar bl_load_info_node_t *bl_node_info = 10972600226SYatharth Kochar &bl_mem_params_desc_ptr[index].load_node_mem; 11072600226SYatharth Kochar bl_load_info.head = bl_node_info; 11172600226SYatharth Kochar SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0); 11272600226SYatharth Kochar 11372600226SYatharth Kochar /* Go through the image descriptor array and create the list */ 11472600226SYatharth Kochar for (; index < bl_mem_params_desc_num; index++) { 11572600226SYatharth Kochar 11672600226SYatharth Kochar /* Populate the image information */ 11772600226SYatharth Kochar bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; 11872600226SYatharth Kochar bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; 11972600226SYatharth Kochar 12072600226SYatharth Kochar /* Link next image if present */ 12172600226SYatharth Kochar if ((index + 1) < bl_mem_params_desc_num) { 12272600226SYatharth Kochar /* Get the memory and link the next node */ 12372600226SYatharth Kochar bl_node_info->next_load_info = 12472600226SYatharth Kochar &bl_mem_params_desc_ptr[index + 1].load_node_mem; 12572600226SYatharth Kochar bl_node_info = bl_node_info->next_load_info; 12672600226SYatharth Kochar } 12772600226SYatharth Kochar } 12872600226SYatharth Kochar 12972600226SYatharth Kochar return &bl_load_info; 13072600226SYatharth Kochar } 13172600226SYatharth Kochar 13272600226SYatharth Kochar /******************************************************************************* 13372600226SYatharth Kochar * This function creates the list of executable images, by populating and 13472600226SYatharth Kochar * linking each `bl_params_node_t` type node, using the internal array of 13572600226SYatharth Kochar * image descriptor provided by bl_mem_params_desc_ptr. It also populates 13672600226SYatharth Kochar * and returns `bl_params_t` type structure that contains head of the list 13772600226SYatharth Kochar * of executable images. 13872600226SYatharth Kochar ******************************************************************************/ 13972600226SYatharth Kochar bl_params_t *get_next_bl_params_from_mem_params_desc(void) 14072600226SYatharth Kochar { 14172600226SYatharth Kochar int count; 14272600226SYatharth Kochar unsigned int img_id = 0; 14372600226SYatharth Kochar int link_index = 0; 14472600226SYatharth Kochar bl_params_node_t *bl_current_exec_node = NULL; 14572600226SYatharth Kochar bl_params_node_t *bl_last_exec_node = NULL; 14672600226SYatharth Kochar bl_mem_params_node_t *desc_ptr; 14772600226SYatharth Kochar 14872600226SYatharth Kochar /* If there is no image to start with, return NULL */ 14972600226SYatharth Kochar if (!bl_mem_params_desc_num) 15072600226SYatharth Kochar return NULL; 15172600226SYatharth Kochar 15272600226SYatharth Kochar /* Get the list HEAD */ 15372600226SYatharth Kochar for (count = 0; count < bl_mem_params_desc_num; count++) { 15472600226SYatharth Kochar 15572600226SYatharth Kochar desc_ptr = &bl_mem_params_desc_ptr[count]; 15672600226SYatharth Kochar 15772600226SYatharth Kochar if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && 15872600226SYatharth Kochar (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { 15972600226SYatharth Kochar next_bl_params.head = &desc_ptr->params_node_mem; 16072600226SYatharth Kochar link_index = count; 16172600226SYatharth Kochar break; 16272600226SYatharth Kochar } 16372600226SYatharth Kochar } 16472600226SYatharth Kochar 16572600226SYatharth Kochar /* Make sure we have a HEAD node */ 16672600226SYatharth Kochar assert(next_bl_params.head != NULL); 16772600226SYatharth Kochar 16872600226SYatharth Kochar /* Populate the HEAD information */ 16972600226SYatharth Kochar SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0); 17072600226SYatharth Kochar 17172600226SYatharth Kochar /* 17272600226SYatharth Kochar * Go through the image descriptor array and create the list. 17372600226SYatharth Kochar * This bounded loop is to make sure that we are not looping forever. 17472600226SYatharth Kochar */ 17572600226SYatharth Kochar for (count = 0 ; count < bl_mem_params_desc_num; count++) { 17672600226SYatharth Kochar 17772600226SYatharth Kochar desc_ptr = &bl_mem_params_desc_ptr[link_index]; 17872600226SYatharth Kochar 17972600226SYatharth Kochar /* Make sure the image is executable */ 18072600226SYatharth Kochar assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); 18172600226SYatharth Kochar 18272600226SYatharth Kochar /* Get the memory for current node */ 18372600226SYatharth Kochar bl_current_exec_node = &desc_ptr->params_node_mem; 18472600226SYatharth Kochar 18572600226SYatharth Kochar /* Populate the image information */ 18672600226SYatharth Kochar bl_current_exec_node->image_id = desc_ptr->image_id; 18772600226SYatharth Kochar bl_current_exec_node->image_info = &desc_ptr->image_info; 18872600226SYatharth Kochar bl_current_exec_node->ep_info = &desc_ptr->ep_info; 18972600226SYatharth Kochar 19072600226SYatharth Kochar if (bl_last_exec_node) { 19172600226SYatharth Kochar /* Assert if loop detected */ 19272600226SYatharth Kochar assert(bl_last_exec_node->next_params_info == NULL); 19372600226SYatharth Kochar 19472600226SYatharth Kochar /* Link the previous node to the current one */ 19572600226SYatharth Kochar bl_last_exec_node->next_params_info = bl_current_exec_node; 19672600226SYatharth Kochar } 19772600226SYatharth Kochar 19872600226SYatharth Kochar /* Update the last node */ 19972600226SYatharth Kochar bl_last_exec_node = bl_current_exec_node; 20072600226SYatharth Kochar 20172600226SYatharth Kochar /* If no next hand-off image then break out */ 20272600226SYatharth Kochar img_id = desc_ptr->next_handoff_image_id; 20372600226SYatharth Kochar if (img_id == INVALID_IMAGE_ID) 20472600226SYatharth Kochar break; 20572600226SYatharth Kochar 20672600226SYatharth Kochar /* Get the index for the next hand-off image */ 20772600226SYatharth Kochar link_index = get_bl_params_node_index(img_id); 20872600226SYatharth Kochar assert((link_index > 0) && 20972600226SYatharth Kochar (link_index < bl_mem_params_desc_num)); 21072600226SYatharth Kochar } 21172600226SYatharth Kochar 21272600226SYatharth Kochar /* Invalid image is expected to terminate the loop */ 21372600226SYatharth Kochar assert(img_id == INVALID_IMAGE_ID); 21472600226SYatharth Kochar 21572600226SYatharth Kochar return &next_bl_params; 21672600226SYatharth Kochar } 217