172600226SYatharth Kochar /* 2637955caSRoberto Vargas * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. 372600226SYatharth Kochar * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 572600226SYatharth Kochar */ 672600226SYatharth Kochar 772600226SYatharth Kochar #include <assert.h> 872600226SYatharth Kochar 909d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 1009d40e0eSAntonio Nino Diaz #include <common/bl_common.h> 1109d40e0eSAntonio Nino Diaz #include <common/desc_image_load.h> 1272600226SYatharth Kochar 1372600226SYatharth Kochar static bl_load_info_t bl_load_info; 1472600226SYatharth Kochar static bl_params_t next_bl_params; 1572600226SYatharth Kochar 1672600226SYatharth Kochar 1772600226SYatharth Kochar /******************************************************************************* 1872600226SYatharth Kochar * This function flushes the data structures so that they are visible 1972600226SYatharth Kochar * in memory for the next BL image. 2072600226SYatharth Kochar ******************************************************************************/ 2172600226SYatharth Kochar void flush_bl_params_desc(void) 2272600226SYatharth Kochar { 23*5b8d50e4SSathees Balya flush_bl_params_desc_args(bl_mem_params_desc_ptr, 24*5b8d50e4SSathees Balya bl_mem_params_desc_num, 25*5b8d50e4SSathees Balya &next_bl_params); 26*5b8d50e4SSathees Balya } 27c2a9ee63SDan Handley 28*5b8d50e4SSathees Balya /******************************************************************************* 29*5b8d50e4SSathees Balya * This function flushes the data structures specified as arguments so that they 30*5b8d50e4SSathees Balya * are visible in memory for the next BL image. 31*5b8d50e4SSathees Balya ******************************************************************************/ 32*5b8d50e4SSathees Balya void flush_bl_params_desc_args(bl_mem_params_node_t *mem_params_desc_ptr, 33*5b8d50e4SSathees Balya unsigned int mem_params_desc_num, 34*5b8d50e4SSathees Balya bl_params_t *next_bl_params_ptr) 35*5b8d50e4SSathees Balya { 36*5b8d50e4SSathees Balya assert(mem_params_desc_ptr != NULL); 37*5b8d50e4SSathees Balya assert(mem_params_desc_num != 0U); 38*5b8d50e4SSathees Balya assert(next_bl_params_ptr != NULL); 39*5b8d50e4SSathees Balya 40*5b8d50e4SSathees Balya flush_dcache_range((uintptr_t)mem_params_desc_ptr, 41*5b8d50e4SSathees Balya sizeof(*mem_params_desc_ptr) * mem_params_desc_num); 42*5b8d50e4SSathees Balya 43*5b8d50e4SSathees Balya flush_dcache_range((uintptr_t)next_bl_params_ptr, 44*5b8d50e4SSathees Balya sizeof(*next_bl_params_ptr)); 4572600226SYatharth Kochar } 4672600226SYatharth Kochar 4772600226SYatharth Kochar /******************************************************************************* 4872600226SYatharth Kochar * This function returns the index for given image_id, within the 4972600226SYatharth Kochar * image descriptor array provided by bl_image_info_descs_ptr, if the 5072600226SYatharth Kochar * image is found else it returns -1. 5172600226SYatharth Kochar ******************************************************************************/ 5272600226SYatharth Kochar int get_bl_params_node_index(unsigned int image_id) 5372600226SYatharth Kochar { 5481542c00SAntonio Nino Diaz unsigned int index; 5572600226SYatharth Kochar assert(image_id != INVALID_IMAGE_ID); 5672600226SYatharth Kochar 5781542c00SAntonio Nino Diaz for (index = 0U; index < bl_mem_params_desc_num; index++) { 5872600226SYatharth Kochar if (bl_mem_params_desc_ptr[index].image_id == image_id) 5981542c00SAntonio Nino Diaz return (int)index; 6072600226SYatharth Kochar } 6172600226SYatharth Kochar 6272600226SYatharth Kochar return -1; 6372600226SYatharth Kochar } 6472600226SYatharth Kochar 6572600226SYatharth Kochar /******************************************************************************* 6672600226SYatharth Kochar * This function returns the pointer to `bl_mem_params_node_t` object for 6772600226SYatharth Kochar * given image_id, within the image descriptor array provided by 6872600226SYatharth Kochar * bl_mem_params_desc_ptr, if the image is found else it returns NULL. 6972600226SYatharth Kochar ******************************************************************************/ 7072600226SYatharth Kochar bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) 7172600226SYatharth Kochar { 7272600226SYatharth Kochar int index; 7372600226SYatharth Kochar assert(image_id != INVALID_IMAGE_ID); 7472600226SYatharth Kochar 7572600226SYatharth Kochar index = get_bl_params_node_index(image_id); 7672600226SYatharth Kochar if (index >= 0) 7772600226SYatharth Kochar return &bl_mem_params_desc_ptr[index]; 7872600226SYatharth Kochar else 7972600226SYatharth Kochar return NULL; 8072600226SYatharth Kochar } 8172600226SYatharth Kochar 8272600226SYatharth Kochar /******************************************************************************* 8372600226SYatharth Kochar * This function creates the list of loadable images, by populating and 8472600226SYatharth Kochar * linking each `bl_load_info_node_t` type node, using the internal array 8572600226SYatharth Kochar * of image descriptor provided by bl_mem_params_desc_ptr. It also populates 8672600226SYatharth Kochar * and returns `bl_load_info_t` type structure that contains head of the list 8772600226SYatharth Kochar * of loadable images. 8872600226SYatharth Kochar ******************************************************************************/ 8972600226SYatharth Kochar bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) 9072600226SYatharth Kochar { 9181542c00SAntonio Nino Diaz unsigned int index = 0; 9272600226SYatharth Kochar 9372600226SYatharth Kochar /* If there is no image to start with, return NULL */ 9481542c00SAntonio Nino Diaz if (bl_mem_params_desc_num == 0U) 9572600226SYatharth Kochar return NULL; 9672600226SYatharth Kochar 9772600226SYatharth Kochar /* Assign initial data structures */ 9872600226SYatharth Kochar bl_load_info_node_t *bl_node_info = 9972600226SYatharth Kochar &bl_mem_params_desc_ptr[index].load_node_mem; 10072600226SYatharth Kochar bl_load_info.head = bl_node_info; 10181542c00SAntonio Nino Diaz SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0U); 10272600226SYatharth Kochar 10372600226SYatharth Kochar /* Go through the image descriptor array and create the list */ 10472600226SYatharth Kochar for (; index < bl_mem_params_desc_num; index++) { 10572600226SYatharth Kochar 10672600226SYatharth Kochar /* Populate the image information */ 10772600226SYatharth Kochar bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; 10872600226SYatharth Kochar bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; 10972600226SYatharth Kochar 11072600226SYatharth Kochar /* Link next image if present */ 11181542c00SAntonio Nino Diaz if ((index + 1U) < bl_mem_params_desc_num) { 11272600226SYatharth Kochar /* Get the memory and link the next node */ 11372600226SYatharth Kochar bl_node_info->next_load_info = 11481542c00SAntonio Nino Diaz &bl_mem_params_desc_ptr[index + 1U].load_node_mem; 11572600226SYatharth Kochar bl_node_info = bl_node_info->next_load_info; 11672600226SYatharth Kochar } 11772600226SYatharth Kochar } 11872600226SYatharth Kochar 11972600226SYatharth Kochar return &bl_load_info; 12072600226SYatharth Kochar } 12172600226SYatharth Kochar 12272600226SYatharth Kochar /******************************************************************************* 12372600226SYatharth Kochar * This function creates the list of executable images, by populating and 12472600226SYatharth Kochar * linking each `bl_params_node_t` type node, using the internal array of 12572600226SYatharth Kochar * image descriptor provided by bl_mem_params_desc_ptr. It also populates 12672600226SYatharth Kochar * and returns `bl_params_t` type structure that contains head of the list 12772600226SYatharth Kochar * of executable images. 12872600226SYatharth Kochar ******************************************************************************/ 12972600226SYatharth Kochar bl_params_t *get_next_bl_params_from_mem_params_desc(void) 13072600226SYatharth Kochar { 13181542c00SAntonio Nino Diaz unsigned int count; 13281542c00SAntonio Nino Diaz unsigned int img_id = 0U; 13381542c00SAntonio Nino Diaz unsigned int link_index = 0U; 13472600226SYatharth Kochar bl_params_node_t *bl_current_exec_node = NULL; 13572600226SYatharth Kochar bl_params_node_t *bl_last_exec_node = NULL; 13672600226SYatharth Kochar bl_mem_params_node_t *desc_ptr; 13772600226SYatharth Kochar 13872600226SYatharth Kochar /* If there is no image to start with, return NULL */ 13981542c00SAntonio Nino Diaz if (bl_mem_params_desc_num == 0U) 14072600226SYatharth Kochar return NULL; 14172600226SYatharth Kochar 14272600226SYatharth Kochar /* Get the list HEAD */ 14381542c00SAntonio Nino Diaz for (count = 0U; count < bl_mem_params_desc_num; count++) { 14472600226SYatharth Kochar 14572600226SYatharth Kochar desc_ptr = &bl_mem_params_desc_ptr[count]; 14672600226SYatharth Kochar 14772600226SYatharth Kochar if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && 14872600226SYatharth Kochar (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { 14972600226SYatharth Kochar next_bl_params.head = &desc_ptr->params_node_mem; 15072600226SYatharth Kochar link_index = count; 15172600226SYatharth Kochar break; 15272600226SYatharth Kochar } 15372600226SYatharth Kochar } 15472600226SYatharth Kochar 15572600226SYatharth Kochar /* Make sure we have a HEAD node */ 15672600226SYatharth Kochar assert(next_bl_params.head != NULL); 15772600226SYatharth Kochar 15872600226SYatharth Kochar /* Populate the HEAD information */ 15981542c00SAntonio Nino Diaz SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0U); 16072600226SYatharth Kochar 16172600226SYatharth Kochar /* 16272600226SYatharth Kochar * Go through the image descriptor array and create the list. 16372600226SYatharth Kochar * This bounded loop is to make sure that we are not looping forever. 16472600226SYatharth Kochar */ 16581542c00SAntonio Nino Diaz for (count = 0U; count < bl_mem_params_desc_num; count++) { 16672600226SYatharth Kochar 16772600226SYatharth Kochar desc_ptr = &bl_mem_params_desc_ptr[link_index]; 16872600226SYatharth Kochar 16972600226SYatharth Kochar /* Make sure the image is executable */ 17072600226SYatharth Kochar assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); 17172600226SYatharth Kochar 17272600226SYatharth Kochar /* Get the memory for current node */ 17372600226SYatharth Kochar bl_current_exec_node = &desc_ptr->params_node_mem; 17472600226SYatharth Kochar 17572600226SYatharth Kochar /* Populate the image information */ 17672600226SYatharth Kochar bl_current_exec_node->image_id = desc_ptr->image_id; 17772600226SYatharth Kochar bl_current_exec_node->image_info = &desc_ptr->image_info; 17872600226SYatharth Kochar bl_current_exec_node->ep_info = &desc_ptr->ep_info; 17972600226SYatharth Kochar 18081542c00SAntonio Nino Diaz if (bl_last_exec_node != NULL) { 18172600226SYatharth Kochar /* Assert if loop detected */ 18272600226SYatharth Kochar assert(bl_last_exec_node->next_params_info == NULL); 18372600226SYatharth Kochar 18472600226SYatharth Kochar /* Link the previous node to the current one */ 18572600226SYatharth Kochar bl_last_exec_node->next_params_info = bl_current_exec_node; 18672600226SYatharth Kochar } 18772600226SYatharth Kochar 18872600226SYatharth Kochar /* Update the last node */ 18972600226SYatharth Kochar bl_last_exec_node = bl_current_exec_node; 19072600226SYatharth Kochar 19172600226SYatharth Kochar /* If no next hand-off image then break out */ 19272600226SYatharth Kochar img_id = desc_ptr->next_handoff_image_id; 19372600226SYatharth Kochar if (img_id == INVALID_IMAGE_ID) 19472600226SYatharth Kochar break; 19572600226SYatharth Kochar 19672600226SYatharth Kochar /* Get the index for the next hand-off image */ 19772600226SYatharth Kochar link_index = get_bl_params_node_index(img_id); 19881542c00SAntonio Nino Diaz assert((link_index > 0U) && 19972600226SYatharth Kochar (link_index < bl_mem_params_desc_num)); 20072600226SYatharth Kochar } 20172600226SYatharth Kochar 20272600226SYatharth Kochar /* Invalid image is expected to terminate the loop */ 20372600226SYatharth Kochar assert(img_id == INVALID_IMAGE_ID); 20472600226SYatharth Kochar 20572600226SYatharth Kochar return &next_bl_params; 20672600226SYatharth Kochar } 207cab0b5b0SSoby Mathew 208cab0b5b0SSoby Mathew /******************************************************************************* 209cab0b5b0SSoby Mathew * This function populates the entry point information with the corresponding 210cab0b5b0SSoby Mathew * config file for all executable BL images described in bl_params. 211cab0b5b0SSoby Mathew ******************************************************************************/ 212cab0b5b0SSoby Mathew void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params) 213cab0b5b0SSoby Mathew { 214cab0b5b0SSoby Mathew bl_params_node_t *params_node; 215cab0b5b0SSoby Mathew unsigned int fw_config_id; 216cab0b5b0SSoby Mathew uintptr_t hw_config_base = 0, fw_config_base; 217cab0b5b0SSoby Mathew bl_mem_params_node_t *mem_params; 218cab0b5b0SSoby Mathew 219da5f2745SSoby Mathew assert(bl2_to_next_bl_params != NULL); 220cab0b5b0SSoby Mathew 221cab0b5b0SSoby Mathew /* 222cab0b5b0SSoby Mathew * Get the `bl_mem_params_node_t` corresponding to HW_CONFIG 223cab0b5b0SSoby Mathew * if available. 224cab0b5b0SSoby Mathew */ 225cab0b5b0SSoby Mathew mem_params = get_bl_mem_params_node(HW_CONFIG_ID); 226cab0b5b0SSoby Mathew if (mem_params != NULL) 227cab0b5b0SSoby Mathew hw_config_base = mem_params->image_info.image_base; 228cab0b5b0SSoby Mathew 229cab0b5b0SSoby Mathew for (params_node = bl2_to_next_bl_params->head; params_node != NULL; 230cab0b5b0SSoby Mathew params_node = params_node->next_params_info) { 231cab0b5b0SSoby Mathew 232cab0b5b0SSoby Mathew fw_config_base = 0; 233cab0b5b0SSoby Mathew 234cab0b5b0SSoby Mathew switch (params_node->image_id) { 235cab0b5b0SSoby Mathew case BL31_IMAGE_ID: 236cab0b5b0SSoby Mathew fw_config_id = SOC_FW_CONFIG_ID; 237cab0b5b0SSoby Mathew break; 238cab0b5b0SSoby Mathew case BL32_IMAGE_ID: 239cab0b5b0SSoby Mathew fw_config_id = TOS_FW_CONFIG_ID; 240cab0b5b0SSoby Mathew break; 241cab0b5b0SSoby Mathew case BL33_IMAGE_ID: 242cab0b5b0SSoby Mathew fw_config_id = NT_FW_CONFIG_ID; 243cab0b5b0SSoby Mathew break; 244cab0b5b0SSoby Mathew default: 245cab0b5b0SSoby Mathew fw_config_id = INVALID_IMAGE_ID; 246cab0b5b0SSoby Mathew break; 247cab0b5b0SSoby Mathew } 248cab0b5b0SSoby Mathew 249cab0b5b0SSoby Mathew if (fw_config_id != INVALID_IMAGE_ID) { 250cab0b5b0SSoby Mathew mem_params = get_bl_mem_params_node(fw_config_id); 251cab0b5b0SSoby Mathew if (mem_params != NULL) 252cab0b5b0SSoby Mathew fw_config_base = mem_params->image_info.image_base; 253cab0b5b0SSoby Mathew } 254cab0b5b0SSoby Mathew 255cab0b5b0SSoby Mathew /* 256cab0b5b0SSoby Mathew * Pass hw and tb_fw config addresses to next images. NOTE - for 257cab0b5b0SSoby Mathew * EL3 runtime images (BL31 for AArch64 and BL32 for AArch32), 2581cc99de8SAmit Daniel Kachhap * arg0 is already used by generic code. Take care of not 2591cc99de8SAmit Daniel Kachhap * overwriting the previous initialisations. 260cab0b5b0SSoby Mathew */ 261cab0b5b0SSoby Mathew if (params_node == bl2_to_next_bl_params->head) { 26281542c00SAntonio Nino Diaz if (params_node->ep_info->args.arg1 == 0U) 2631cc99de8SAmit Daniel Kachhap params_node->ep_info->args.arg1 = 2641cc99de8SAmit Daniel Kachhap fw_config_base; 26581542c00SAntonio Nino Diaz if (params_node->ep_info->args.arg2 == 0U) 2661cc99de8SAmit Daniel Kachhap params_node->ep_info->args.arg2 = 2671cc99de8SAmit Daniel Kachhap hw_config_base; 268cab0b5b0SSoby Mathew } else { 26981542c00SAntonio Nino Diaz if (params_node->ep_info->args.arg0 == 0U) 2701cc99de8SAmit Daniel Kachhap params_node->ep_info->args.arg0 = 2711cc99de8SAmit Daniel Kachhap fw_config_base; 27281542c00SAntonio Nino Diaz if (params_node->ep_info->args.arg1 == 0U) 2731cc99de8SAmit Daniel Kachhap params_node->ep_info->args.arg1 = 2741cc99de8SAmit Daniel Kachhap hw_config_base; 275cab0b5b0SSoby Mathew } 276cab0b5b0SSoby Mathew } 277cab0b5b0SSoby Mathew } 278