172600226SYatharth Kochar /* 2*637955caSRoberto 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 <arch_helpers.h> 872600226SYatharth Kochar #include <assert.h> 972600226SYatharth Kochar #include <bl_common.h> 1072600226SYatharth Kochar #include <desc_image_load.h> 1172600226SYatharth Kochar 1272600226SYatharth Kochar 1372600226SYatharth Kochar 1472600226SYatharth Kochar static bl_load_info_t bl_load_info; 1572600226SYatharth Kochar static bl_params_t next_bl_params; 1672600226SYatharth Kochar 1772600226SYatharth Kochar 1872600226SYatharth Kochar /******************************************************************************* 1972600226SYatharth Kochar * This function flushes the data structures so that they are visible 2072600226SYatharth Kochar * in memory for the next BL image. 2172600226SYatharth Kochar ******************************************************************************/ 2272600226SYatharth Kochar void flush_bl_params_desc(void) 2372600226SYatharth Kochar { 24c2a9ee63SDan Handley flush_dcache_range((uintptr_t)bl_mem_params_desc_ptr, 2572600226SYatharth Kochar sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num); 26c2a9ee63SDan Handley 27c2a9ee63SDan Handley flush_dcache_range((uintptr_t)&next_bl_params, 28c2a9ee63SDan Handley sizeof(next_bl_params)); 2972600226SYatharth Kochar } 3072600226SYatharth Kochar 3172600226SYatharth Kochar /******************************************************************************* 3272600226SYatharth Kochar * This function returns the index for given image_id, within the 3372600226SYatharth Kochar * image descriptor array provided by bl_image_info_descs_ptr, if the 3472600226SYatharth Kochar * image is found else it returns -1. 3572600226SYatharth Kochar ******************************************************************************/ 3672600226SYatharth Kochar int get_bl_params_node_index(unsigned int image_id) 3772600226SYatharth Kochar { 3872600226SYatharth Kochar int index; 3972600226SYatharth Kochar assert(image_id != INVALID_IMAGE_ID); 4072600226SYatharth Kochar 4172600226SYatharth Kochar for (index = 0; index < bl_mem_params_desc_num; index++) { 4272600226SYatharth Kochar if (bl_mem_params_desc_ptr[index].image_id == image_id) 4372600226SYatharth Kochar return index; 4472600226SYatharth Kochar } 4572600226SYatharth Kochar 4672600226SYatharth Kochar return -1; 4772600226SYatharth Kochar } 4872600226SYatharth Kochar 4972600226SYatharth Kochar /******************************************************************************* 5072600226SYatharth Kochar * This function returns the pointer to `bl_mem_params_node_t` object for 5172600226SYatharth Kochar * given image_id, within the image descriptor array provided by 5272600226SYatharth Kochar * bl_mem_params_desc_ptr, if the image is found else it returns NULL. 5372600226SYatharth Kochar ******************************************************************************/ 5472600226SYatharth Kochar bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) 5572600226SYatharth Kochar { 5672600226SYatharth Kochar int index; 5772600226SYatharth Kochar assert(image_id != INVALID_IMAGE_ID); 5872600226SYatharth Kochar 5972600226SYatharth Kochar index = get_bl_params_node_index(image_id); 6072600226SYatharth Kochar if (index >= 0) 6172600226SYatharth Kochar return &bl_mem_params_desc_ptr[index]; 6272600226SYatharth Kochar else 6372600226SYatharth Kochar return NULL; 6472600226SYatharth Kochar } 6572600226SYatharth Kochar 6672600226SYatharth Kochar /******************************************************************************* 6772600226SYatharth Kochar * This function creates the list of loadable images, by populating and 6872600226SYatharth Kochar * linking each `bl_load_info_node_t` type node, using the internal array 6972600226SYatharth Kochar * of image descriptor provided by bl_mem_params_desc_ptr. It also populates 7072600226SYatharth Kochar * and returns `bl_load_info_t` type structure that contains head of the list 7172600226SYatharth Kochar * of loadable images. 7272600226SYatharth Kochar ******************************************************************************/ 7372600226SYatharth Kochar bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) 7472600226SYatharth Kochar { 7572600226SYatharth Kochar int index = 0; 7672600226SYatharth Kochar 7772600226SYatharth Kochar /* If there is no image to start with, return NULL */ 7872600226SYatharth Kochar if (!bl_mem_params_desc_num) 7972600226SYatharth Kochar return NULL; 8072600226SYatharth Kochar 8172600226SYatharth Kochar /* Assign initial data structures */ 8272600226SYatharth Kochar bl_load_info_node_t *bl_node_info = 8372600226SYatharth Kochar &bl_mem_params_desc_ptr[index].load_node_mem; 8472600226SYatharth Kochar bl_load_info.head = bl_node_info; 8572600226SYatharth Kochar SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0); 8672600226SYatharth Kochar 8772600226SYatharth Kochar /* Go through the image descriptor array and create the list */ 8872600226SYatharth Kochar for (; index < bl_mem_params_desc_num; index++) { 8972600226SYatharth Kochar 9072600226SYatharth Kochar /* Populate the image information */ 9172600226SYatharth Kochar bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; 9272600226SYatharth Kochar bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; 9372600226SYatharth Kochar 9472600226SYatharth Kochar /* Link next image if present */ 9572600226SYatharth Kochar if ((index + 1) < bl_mem_params_desc_num) { 9672600226SYatharth Kochar /* Get the memory and link the next node */ 9772600226SYatharth Kochar bl_node_info->next_load_info = 9872600226SYatharth Kochar &bl_mem_params_desc_ptr[index + 1].load_node_mem; 9972600226SYatharth Kochar bl_node_info = bl_node_info->next_load_info; 10072600226SYatharth Kochar } 10172600226SYatharth Kochar } 10272600226SYatharth Kochar 10372600226SYatharth Kochar return &bl_load_info; 10472600226SYatharth Kochar } 10572600226SYatharth Kochar 10672600226SYatharth Kochar /******************************************************************************* 10772600226SYatharth Kochar * This function creates the list of executable images, by populating and 10872600226SYatharth Kochar * linking each `bl_params_node_t` type node, using the internal array of 10972600226SYatharth Kochar * image descriptor provided by bl_mem_params_desc_ptr. It also populates 11072600226SYatharth Kochar * and returns `bl_params_t` type structure that contains head of the list 11172600226SYatharth Kochar * of executable images. 11272600226SYatharth Kochar ******************************************************************************/ 11372600226SYatharth Kochar bl_params_t *get_next_bl_params_from_mem_params_desc(void) 11472600226SYatharth Kochar { 11572600226SYatharth Kochar int count; 11672600226SYatharth Kochar unsigned int img_id = 0; 11772600226SYatharth Kochar int link_index = 0; 11872600226SYatharth Kochar bl_params_node_t *bl_current_exec_node = NULL; 11972600226SYatharth Kochar bl_params_node_t *bl_last_exec_node = NULL; 12072600226SYatharth Kochar bl_mem_params_node_t *desc_ptr; 12172600226SYatharth Kochar 12272600226SYatharth Kochar /* If there is no image to start with, return NULL */ 12372600226SYatharth Kochar if (!bl_mem_params_desc_num) 12472600226SYatharth Kochar return NULL; 12572600226SYatharth Kochar 12672600226SYatharth Kochar /* Get the list HEAD */ 12772600226SYatharth Kochar for (count = 0; count < bl_mem_params_desc_num; count++) { 12872600226SYatharth Kochar 12972600226SYatharth Kochar desc_ptr = &bl_mem_params_desc_ptr[count]; 13072600226SYatharth Kochar 13172600226SYatharth Kochar if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && 13272600226SYatharth Kochar (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { 13372600226SYatharth Kochar next_bl_params.head = &desc_ptr->params_node_mem; 13472600226SYatharth Kochar link_index = count; 13572600226SYatharth Kochar break; 13672600226SYatharth Kochar } 13772600226SYatharth Kochar } 13872600226SYatharth Kochar 13972600226SYatharth Kochar /* Make sure we have a HEAD node */ 14072600226SYatharth Kochar assert(next_bl_params.head != NULL); 14172600226SYatharth Kochar 14272600226SYatharth Kochar /* Populate the HEAD information */ 14372600226SYatharth Kochar SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0); 14472600226SYatharth Kochar 14572600226SYatharth Kochar /* 14672600226SYatharth Kochar * Go through the image descriptor array and create the list. 14772600226SYatharth Kochar * This bounded loop is to make sure that we are not looping forever. 14872600226SYatharth Kochar */ 14972600226SYatharth Kochar for (count = 0 ; count < bl_mem_params_desc_num; count++) { 15072600226SYatharth Kochar 15172600226SYatharth Kochar desc_ptr = &bl_mem_params_desc_ptr[link_index]; 15272600226SYatharth Kochar 15372600226SYatharth Kochar /* Make sure the image is executable */ 15472600226SYatharth Kochar assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); 15572600226SYatharth Kochar 15672600226SYatharth Kochar /* Get the memory for current node */ 15772600226SYatharth Kochar bl_current_exec_node = &desc_ptr->params_node_mem; 15872600226SYatharth Kochar 15972600226SYatharth Kochar /* Populate the image information */ 16072600226SYatharth Kochar bl_current_exec_node->image_id = desc_ptr->image_id; 16172600226SYatharth Kochar bl_current_exec_node->image_info = &desc_ptr->image_info; 16272600226SYatharth Kochar bl_current_exec_node->ep_info = &desc_ptr->ep_info; 16372600226SYatharth Kochar 16472600226SYatharth Kochar if (bl_last_exec_node) { 16572600226SYatharth Kochar /* Assert if loop detected */ 16672600226SYatharth Kochar assert(bl_last_exec_node->next_params_info == NULL); 16772600226SYatharth Kochar 16872600226SYatharth Kochar /* Link the previous node to the current one */ 16972600226SYatharth Kochar bl_last_exec_node->next_params_info = bl_current_exec_node; 17072600226SYatharth Kochar } 17172600226SYatharth Kochar 17272600226SYatharth Kochar /* Update the last node */ 17372600226SYatharth Kochar bl_last_exec_node = bl_current_exec_node; 17472600226SYatharth Kochar 17572600226SYatharth Kochar /* If no next hand-off image then break out */ 17672600226SYatharth Kochar img_id = desc_ptr->next_handoff_image_id; 17772600226SYatharth Kochar if (img_id == INVALID_IMAGE_ID) 17872600226SYatharth Kochar break; 17972600226SYatharth Kochar 18072600226SYatharth Kochar /* Get the index for the next hand-off image */ 18172600226SYatharth Kochar link_index = get_bl_params_node_index(img_id); 18272600226SYatharth Kochar assert((link_index > 0) && 18372600226SYatharth Kochar (link_index < bl_mem_params_desc_num)); 18472600226SYatharth Kochar } 18572600226SYatharth Kochar 18672600226SYatharth Kochar /* Invalid image is expected to terminate the loop */ 18772600226SYatharth Kochar assert(img_id == INVALID_IMAGE_ID); 18872600226SYatharth Kochar 18972600226SYatharth Kochar return &next_bl_params; 19072600226SYatharth Kochar } 191cab0b5b0SSoby Mathew 192cab0b5b0SSoby Mathew /******************************************************************************* 193cab0b5b0SSoby Mathew * This function populates the entry point information with the corresponding 194cab0b5b0SSoby Mathew * config file for all executable BL images described in bl_params. 195cab0b5b0SSoby Mathew ******************************************************************************/ 196cab0b5b0SSoby Mathew void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params) 197cab0b5b0SSoby Mathew { 198cab0b5b0SSoby Mathew bl_params_node_t *params_node; 199cab0b5b0SSoby Mathew unsigned int fw_config_id; 200cab0b5b0SSoby Mathew uintptr_t hw_config_base = 0, fw_config_base; 201cab0b5b0SSoby Mathew bl_mem_params_node_t *mem_params; 202cab0b5b0SSoby Mathew 203da5f2745SSoby Mathew assert(bl2_to_next_bl_params != NULL); 204cab0b5b0SSoby Mathew 205cab0b5b0SSoby Mathew /* 206cab0b5b0SSoby Mathew * Get the `bl_mem_params_node_t` corresponding to HW_CONFIG 207cab0b5b0SSoby Mathew * if available. 208cab0b5b0SSoby Mathew */ 209cab0b5b0SSoby Mathew mem_params = get_bl_mem_params_node(HW_CONFIG_ID); 210cab0b5b0SSoby Mathew if (mem_params != NULL) 211cab0b5b0SSoby Mathew hw_config_base = mem_params->image_info.image_base; 212cab0b5b0SSoby Mathew 213cab0b5b0SSoby Mathew for (params_node = bl2_to_next_bl_params->head; params_node != NULL; 214cab0b5b0SSoby Mathew params_node = params_node->next_params_info) { 215cab0b5b0SSoby Mathew 216cab0b5b0SSoby Mathew fw_config_base = 0; 217cab0b5b0SSoby Mathew 218cab0b5b0SSoby Mathew switch (params_node->image_id) { 219cab0b5b0SSoby Mathew case BL31_IMAGE_ID: 220cab0b5b0SSoby Mathew fw_config_id = SOC_FW_CONFIG_ID; 221cab0b5b0SSoby Mathew break; 222cab0b5b0SSoby Mathew case BL32_IMAGE_ID: 223cab0b5b0SSoby Mathew fw_config_id = TOS_FW_CONFIG_ID; 224cab0b5b0SSoby Mathew break; 225cab0b5b0SSoby Mathew case BL33_IMAGE_ID: 226cab0b5b0SSoby Mathew fw_config_id = NT_FW_CONFIG_ID; 227cab0b5b0SSoby Mathew break; 228cab0b5b0SSoby Mathew default: 229cab0b5b0SSoby Mathew fw_config_id = INVALID_IMAGE_ID; 230cab0b5b0SSoby Mathew break; 231cab0b5b0SSoby Mathew } 232cab0b5b0SSoby Mathew 233cab0b5b0SSoby Mathew if (fw_config_id != INVALID_IMAGE_ID) { 234cab0b5b0SSoby Mathew mem_params = get_bl_mem_params_node(fw_config_id); 235cab0b5b0SSoby Mathew if (mem_params != NULL) 236cab0b5b0SSoby Mathew fw_config_base = mem_params->image_info.image_base; 237cab0b5b0SSoby Mathew } 238cab0b5b0SSoby Mathew 239cab0b5b0SSoby Mathew /* 240cab0b5b0SSoby Mathew * Pass hw and tb_fw config addresses to next images. NOTE - for 241cab0b5b0SSoby Mathew * EL3 runtime images (BL31 for AArch64 and BL32 for AArch32), 242cab0b5b0SSoby Mathew * arg0 is already used by generic code. 243cab0b5b0SSoby Mathew */ 244cab0b5b0SSoby Mathew if (params_node == bl2_to_next_bl_params->head) { 245cab0b5b0SSoby Mathew params_node->ep_info->args.arg1 = fw_config_base; 246cab0b5b0SSoby Mathew params_node->ep_info->args.arg2 = hw_config_base; 247cab0b5b0SSoby Mathew } else { 248cab0b5b0SSoby Mathew params_node->ep_info->args.arg0 = fw_config_base; 249cab0b5b0SSoby Mathew params_node->ep_info->args.arg1 = hw_config_base; 250cab0b5b0SSoby Mathew } 251cab0b5b0SSoby Mathew } 252cab0b5b0SSoby Mathew } 253