172600226SYatharth Kochar /* 2*0cb64d01SAchin Gupta * Copyright (c) 2016-2020, 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> 12d9af1f7bSJulius Werner #include <common/tbbr/tbbr_img_def.h> 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 { 245b8d50e4SSathees Balya flush_bl_params_desc_args(bl_mem_params_desc_ptr, 255b8d50e4SSathees Balya bl_mem_params_desc_num, 265b8d50e4SSathees Balya &next_bl_params); 275b8d50e4SSathees Balya } 28c2a9ee63SDan Handley 295b8d50e4SSathees Balya /******************************************************************************* 305b8d50e4SSathees Balya * This function flushes the data structures specified as arguments so that they 315b8d50e4SSathees Balya * are visible in memory for the next BL image. 325b8d50e4SSathees Balya ******************************************************************************/ 335b8d50e4SSathees Balya void flush_bl_params_desc_args(bl_mem_params_node_t *mem_params_desc_ptr, 345b8d50e4SSathees Balya unsigned int mem_params_desc_num, 355b8d50e4SSathees Balya bl_params_t *next_bl_params_ptr) 365b8d50e4SSathees Balya { 375b8d50e4SSathees Balya assert(mem_params_desc_ptr != NULL); 385b8d50e4SSathees Balya assert(mem_params_desc_num != 0U); 395b8d50e4SSathees Balya assert(next_bl_params_ptr != NULL); 405b8d50e4SSathees Balya 415b8d50e4SSathees Balya flush_dcache_range((uintptr_t)mem_params_desc_ptr, 425b8d50e4SSathees Balya sizeof(*mem_params_desc_ptr) * mem_params_desc_num); 435b8d50e4SSathees Balya 445b8d50e4SSathees Balya flush_dcache_range((uintptr_t)next_bl_params_ptr, 455b8d50e4SSathees Balya sizeof(*next_bl_params_ptr)); 4672600226SYatharth Kochar } 4772600226SYatharth Kochar 4872600226SYatharth Kochar /******************************************************************************* 4972600226SYatharth Kochar * This function returns the index for given image_id, within the 5072600226SYatharth Kochar * image descriptor array provided by bl_image_info_descs_ptr, if the 5172600226SYatharth Kochar * image is found else it returns -1. 5272600226SYatharth Kochar ******************************************************************************/ 5372600226SYatharth Kochar int get_bl_params_node_index(unsigned int image_id) 5472600226SYatharth Kochar { 5581542c00SAntonio Nino Diaz unsigned int index; 5672600226SYatharth Kochar assert(image_id != INVALID_IMAGE_ID); 5772600226SYatharth Kochar 5881542c00SAntonio Nino Diaz for (index = 0U; index < bl_mem_params_desc_num; index++) { 5972600226SYatharth Kochar if (bl_mem_params_desc_ptr[index].image_id == image_id) 6081542c00SAntonio Nino Diaz return (int)index; 6172600226SYatharth Kochar } 6272600226SYatharth Kochar 6372600226SYatharth Kochar return -1; 6472600226SYatharth Kochar } 6572600226SYatharth Kochar 6672600226SYatharth Kochar /******************************************************************************* 6772600226SYatharth Kochar * This function returns the pointer to `bl_mem_params_node_t` object for 6872600226SYatharth Kochar * given image_id, within the image descriptor array provided by 6972600226SYatharth Kochar * bl_mem_params_desc_ptr, if the image is found else it returns NULL. 7072600226SYatharth Kochar ******************************************************************************/ 7172600226SYatharth Kochar bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) 7272600226SYatharth Kochar { 7372600226SYatharth Kochar int index; 7472600226SYatharth Kochar assert(image_id != INVALID_IMAGE_ID); 7572600226SYatharth Kochar 7672600226SYatharth Kochar index = get_bl_params_node_index(image_id); 7772600226SYatharth Kochar if (index >= 0) 7872600226SYatharth Kochar return &bl_mem_params_desc_ptr[index]; 7972600226SYatharth Kochar else 8072600226SYatharth Kochar return NULL; 8172600226SYatharth Kochar } 8272600226SYatharth Kochar 8372600226SYatharth Kochar /******************************************************************************* 8472600226SYatharth Kochar * This function creates the list of loadable images, by populating and 8572600226SYatharth Kochar * linking each `bl_load_info_node_t` type node, using the internal array 8672600226SYatharth Kochar * of image descriptor provided by bl_mem_params_desc_ptr. It also populates 8772600226SYatharth Kochar * and returns `bl_load_info_t` type structure that contains head of the list 8872600226SYatharth Kochar * of loadable images. 8972600226SYatharth Kochar ******************************************************************************/ 9072600226SYatharth Kochar bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) 9172600226SYatharth Kochar { 9281542c00SAntonio Nino Diaz unsigned int index = 0; 9372600226SYatharth Kochar 9472600226SYatharth Kochar /* If there is no image to start with, return NULL */ 9581542c00SAntonio Nino Diaz if (bl_mem_params_desc_num == 0U) 9672600226SYatharth Kochar return NULL; 9772600226SYatharth Kochar 9872600226SYatharth Kochar /* Assign initial data structures */ 9972600226SYatharth Kochar bl_load_info_node_t *bl_node_info = 10072600226SYatharth Kochar &bl_mem_params_desc_ptr[index].load_node_mem; 10172600226SYatharth Kochar bl_load_info.head = bl_node_info; 10281542c00SAntonio Nino Diaz SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0U); 10372600226SYatharth Kochar 10472600226SYatharth Kochar /* Go through the image descriptor array and create the list */ 10572600226SYatharth Kochar for (; index < bl_mem_params_desc_num; index++) { 10672600226SYatharth Kochar 10772600226SYatharth Kochar /* Populate the image information */ 10872600226SYatharth Kochar bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; 10972600226SYatharth Kochar bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; 11072600226SYatharth Kochar 11172600226SYatharth Kochar /* Link next image if present */ 11281542c00SAntonio Nino Diaz if ((index + 1U) < bl_mem_params_desc_num) { 11372600226SYatharth Kochar /* Get the memory and link the next node */ 11472600226SYatharth Kochar bl_node_info->next_load_info = 11581542c00SAntonio Nino Diaz &bl_mem_params_desc_ptr[index + 1U].load_node_mem; 11672600226SYatharth Kochar bl_node_info = bl_node_info->next_load_info; 11772600226SYatharth Kochar } 11872600226SYatharth Kochar } 11972600226SYatharth Kochar 12072600226SYatharth Kochar return &bl_load_info; 12172600226SYatharth Kochar } 12272600226SYatharth Kochar 12372600226SYatharth Kochar /******************************************************************************* 12472600226SYatharth Kochar * This function creates the list of executable images, by populating and 12572600226SYatharth Kochar * linking each `bl_params_node_t` type node, using the internal array of 12672600226SYatharth Kochar * image descriptor provided by bl_mem_params_desc_ptr. It also populates 12772600226SYatharth Kochar * and returns `bl_params_t` type structure that contains head of the list 12872600226SYatharth Kochar * of executable images. 12972600226SYatharth Kochar ******************************************************************************/ 13072600226SYatharth Kochar bl_params_t *get_next_bl_params_from_mem_params_desc(void) 13172600226SYatharth Kochar { 13281542c00SAntonio Nino Diaz unsigned int count; 13381542c00SAntonio Nino Diaz unsigned int img_id = 0U; 13481542c00SAntonio Nino Diaz unsigned int link_index = 0U; 13572600226SYatharth Kochar bl_params_node_t *bl_current_exec_node = NULL; 13672600226SYatharth Kochar bl_params_node_t *bl_last_exec_node = NULL; 13772600226SYatharth Kochar bl_mem_params_node_t *desc_ptr; 13872600226SYatharth Kochar 13972600226SYatharth Kochar /* If there is no image to start with, return NULL */ 14081542c00SAntonio Nino Diaz if (bl_mem_params_desc_num == 0U) 14172600226SYatharth Kochar return NULL; 14272600226SYatharth Kochar 14372600226SYatharth Kochar /* Get the list HEAD */ 14481542c00SAntonio Nino Diaz for (count = 0U; count < bl_mem_params_desc_num; count++) { 14572600226SYatharth Kochar 14672600226SYatharth Kochar desc_ptr = &bl_mem_params_desc_ptr[count]; 14772600226SYatharth Kochar 14872600226SYatharth Kochar if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && 14972600226SYatharth Kochar (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { 15072600226SYatharth Kochar next_bl_params.head = &desc_ptr->params_node_mem; 15172600226SYatharth Kochar link_index = count; 15272600226SYatharth Kochar break; 15372600226SYatharth Kochar } 15472600226SYatharth Kochar } 15572600226SYatharth Kochar 15672600226SYatharth Kochar /* Make sure we have a HEAD node */ 15772600226SYatharth Kochar assert(next_bl_params.head != NULL); 15872600226SYatharth Kochar 15972600226SYatharth Kochar /* Populate the HEAD information */ 16081542c00SAntonio Nino Diaz SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0U); 16172600226SYatharth Kochar 16272600226SYatharth Kochar /* 16372600226SYatharth Kochar * Go through the image descriptor array and create the list. 16472600226SYatharth Kochar * This bounded loop is to make sure that we are not looping forever. 16572600226SYatharth Kochar */ 16681542c00SAntonio Nino Diaz for (count = 0U; count < bl_mem_params_desc_num; count++) { 16772600226SYatharth Kochar 16872600226SYatharth Kochar desc_ptr = &bl_mem_params_desc_ptr[link_index]; 16972600226SYatharth Kochar 17072600226SYatharth Kochar /* Make sure the image is executable */ 17172600226SYatharth Kochar assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); 17272600226SYatharth Kochar 17372600226SYatharth Kochar /* Get the memory for current node */ 17472600226SYatharth Kochar bl_current_exec_node = &desc_ptr->params_node_mem; 17572600226SYatharth Kochar 17672600226SYatharth Kochar /* Populate the image information */ 17772600226SYatharth Kochar bl_current_exec_node->image_id = desc_ptr->image_id; 17872600226SYatharth Kochar bl_current_exec_node->image_info = &desc_ptr->image_info; 17972600226SYatharth Kochar bl_current_exec_node->ep_info = &desc_ptr->ep_info; 18072600226SYatharth Kochar 18181542c00SAntonio Nino Diaz if (bl_last_exec_node != NULL) { 18272600226SYatharth Kochar /* Assert if loop detected */ 18372600226SYatharth Kochar assert(bl_last_exec_node->next_params_info == NULL); 18472600226SYatharth Kochar 18572600226SYatharth Kochar /* Link the previous node to the current one */ 18672600226SYatharth Kochar bl_last_exec_node->next_params_info = bl_current_exec_node; 18772600226SYatharth Kochar } 18872600226SYatharth Kochar 18972600226SYatharth Kochar /* Update the last node */ 19072600226SYatharth Kochar bl_last_exec_node = bl_current_exec_node; 19172600226SYatharth Kochar 19272600226SYatharth Kochar /* If no next hand-off image then break out */ 19372600226SYatharth Kochar img_id = desc_ptr->next_handoff_image_id; 19472600226SYatharth Kochar if (img_id == INVALID_IMAGE_ID) 19572600226SYatharth Kochar break; 19672600226SYatharth Kochar 19772600226SYatharth Kochar /* Get the index for the next hand-off image */ 19872600226SYatharth Kochar link_index = get_bl_params_node_index(img_id); 19981542c00SAntonio Nino Diaz assert((link_index > 0U) && 20072600226SYatharth Kochar (link_index < bl_mem_params_desc_num)); 20172600226SYatharth Kochar } 20272600226SYatharth Kochar 20372600226SYatharth Kochar /* Invalid image is expected to terminate the loop */ 20472600226SYatharth Kochar assert(img_id == INVALID_IMAGE_ID); 20572600226SYatharth Kochar 20672600226SYatharth Kochar return &next_bl_params; 20772600226SYatharth Kochar } 208cab0b5b0SSoby Mathew 209cab0b5b0SSoby Mathew /******************************************************************************* 210cab0b5b0SSoby Mathew * This function populates the entry point information with the corresponding 211cab0b5b0SSoby Mathew * config file for all executable BL images described in bl_params. 212cab0b5b0SSoby Mathew ******************************************************************************/ 213cab0b5b0SSoby Mathew void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params) 214cab0b5b0SSoby Mathew { 215cab0b5b0SSoby Mathew bl_params_node_t *params_node; 216cab0b5b0SSoby Mathew unsigned int fw_config_id; 217cab0b5b0SSoby Mathew uintptr_t hw_config_base = 0, fw_config_base; 218*0cb64d01SAchin Gupta #if defined(SPD_spmd) 219*0cb64d01SAchin Gupta uint32_t fw_config_size = 0; 220*0cb64d01SAchin Gupta #endif 221cab0b5b0SSoby Mathew bl_mem_params_node_t *mem_params; 222cab0b5b0SSoby Mathew 223da5f2745SSoby Mathew assert(bl2_to_next_bl_params != NULL); 224cab0b5b0SSoby Mathew 225cab0b5b0SSoby Mathew /* 226cab0b5b0SSoby Mathew * Get the `bl_mem_params_node_t` corresponding to HW_CONFIG 227cab0b5b0SSoby Mathew * if available. 228cab0b5b0SSoby Mathew */ 229cab0b5b0SSoby Mathew mem_params = get_bl_mem_params_node(HW_CONFIG_ID); 230cab0b5b0SSoby Mathew if (mem_params != NULL) 231cab0b5b0SSoby Mathew hw_config_base = mem_params->image_info.image_base; 232cab0b5b0SSoby Mathew 233cab0b5b0SSoby Mathew for (params_node = bl2_to_next_bl_params->head; params_node != NULL; 234cab0b5b0SSoby Mathew params_node = params_node->next_params_info) { 235cab0b5b0SSoby Mathew 236cab0b5b0SSoby Mathew fw_config_base = 0; 237cab0b5b0SSoby Mathew 238cab0b5b0SSoby Mathew switch (params_node->image_id) { 239cab0b5b0SSoby Mathew case BL31_IMAGE_ID: 240cab0b5b0SSoby Mathew fw_config_id = SOC_FW_CONFIG_ID; 241cab0b5b0SSoby Mathew break; 242cab0b5b0SSoby Mathew case BL32_IMAGE_ID: 243cab0b5b0SSoby Mathew fw_config_id = TOS_FW_CONFIG_ID; 244cab0b5b0SSoby Mathew break; 245cab0b5b0SSoby Mathew case BL33_IMAGE_ID: 246cab0b5b0SSoby Mathew fw_config_id = NT_FW_CONFIG_ID; 247cab0b5b0SSoby Mathew break; 248cab0b5b0SSoby Mathew default: 249cab0b5b0SSoby Mathew fw_config_id = INVALID_IMAGE_ID; 250cab0b5b0SSoby Mathew break; 251cab0b5b0SSoby Mathew } 252cab0b5b0SSoby Mathew 253cab0b5b0SSoby Mathew if (fw_config_id != INVALID_IMAGE_ID) { 254cab0b5b0SSoby Mathew mem_params = get_bl_mem_params_node(fw_config_id); 255*0cb64d01SAchin Gupta if (mem_params != NULL) { 256cab0b5b0SSoby Mathew fw_config_base = mem_params->image_info.image_base; 257*0cb64d01SAchin Gupta #if defined(SPD_spmd) 258*0cb64d01SAchin Gupta fw_config_size = 259*0cb64d01SAchin Gupta mem_params->image_info.image_size; 260*0cb64d01SAchin Gupta #endif 261cab0b5b0SSoby Mathew } 262*0cb64d01SAchin Gupta } 263cab0b5b0SSoby Mathew /* 264cab0b5b0SSoby Mathew * Pass hw and tb_fw config addresses to next images. NOTE - for 265cab0b5b0SSoby Mathew * EL3 runtime images (BL31 for AArch64 and BL32 for AArch32), 2661cc99de8SAmit Daniel Kachhap * arg0 is already used by generic code. Take care of not 2671cc99de8SAmit Daniel Kachhap * overwriting the previous initialisations. 268cab0b5b0SSoby Mathew */ 269cab0b5b0SSoby Mathew if (params_node == bl2_to_next_bl_params->head) { 27081542c00SAntonio Nino Diaz if (params_node->ep_info->args.arg1 == 0U) 2711cc99de8SAmit Daniel Kachhap params_node->ep_info->args.arg1 = 2721cc99de8SAmit Daniel Kachhap fw_config_base; 27381542c00SAntonio Nino Diaz if (params_node->ep_info->args.arg2 == 0U) 2741cc99de8SAmit Daniel Kachhap params_node->ep_info->args.arg2 = 2751cc99de8SAmit Daniel Kachhap hw_config_base; 276cab0b5b0SSoby Mathew } else { 27781542c00SAntonio Nino Diaz if (params_node->ep_info->args.arg0 == 0U) 2781cc99de8SAmit Daniel Kachhap params_node->ep_info->args.arg0 = 2791cc99de8SAmit Daniel Kachhap fw_config_base; 28081542c00SAntonio Nino Diaz if (params_node->ep_info->args.arg1 == 0U) 2811cc99de8SAmit Daniel Kachhap params_node->ep_info->args.arg1 = 2821cc99de8SAmit Daniel Kachhap hw_config_base; 283*0cb64d01SAchin Gupta #if defined(SPD_spmd) 284*0cb64d01SAchin Gupta if (params_node->ep_info->args.arg2 == 0U) 285*0cb64d01SAchin Gupta params_node->ep_info->args.arg2 = 286*0cb64d01SAchin Gupta fw_config_size; 287*0cb64d01SAchin Gupta #endif 288cab0b5b0SSoby Mathew } 289cab0b5b0SSoby Mathew } 290cab0b5b0SSoby Mathew } 291d9af1f7bSJulius Werner 292d9af1f7bSJulius Werner /******************************************************************************* 293d9af1f7bSJulius Werner * Helper to extract BL32/BL33 entry point info from arg0 passed to BL31, for 294d9af1f7bSJulius Werner * platforms that are only interested in those. Platforms that need to extract 295d9af1f7bSJulius Werner * more information can parse the structures themselves. 296d9af1f7bSJulius Werner ******************************************************************************/ 297d9af1f7bSJulius Werner 298d9af1f7bSJulius Werner void bl31_params_parse_helper(u_register_t param, 299d9af1f7bSJulius Werner entry_point_info_t *bl32_ep_info_out, 300d9af1f7bSJulius Werner entry_point_info_t *bl33_ep_info_out) 301d9af1f7bSJulius Werner { 302d9af1f7bSJulius Werner bl_params_node_t *node; 303d9af1f7bSJulius Werner bl_params_t *v2 = (void *)(uintptr_t)param; 304d9af1f7bSJulius Werner 305d9af1f7bSJulius Werner #if !ERROR_DEPRECATED 306d9af1f7bSJulius Werner if (v2->h.version == PARAM_VERSION_1) { 307d9af1f7bSJulius Werner struct { /* Deprecated version 1 parameter structure. */ 308d9af1f7bSJulius Werner param_header_t h; 309d9af1f7bSJulius Werner image_info_t *bl31_image_info; 310d9af1f7bSJulius Werner entry_point_info_t *bl32_ep_info; 311d9af1f7bSJulius Werner image_info_t *bl32_image_info; 312d9af1f7bSJulius Werner entry_point_info_t *bl33_ep_info; 313d9af1f7bSJulius Werner image_info_t *bl33_image_info; 314d9af1f7bSJulius Werner } *v1 = (void *)(uintptr_t)param; 315d9af1f7bSJulius Werner assert(v1->h.type == PARAM_BL31); 316d9af1f7bSJulius Werner if (bl32_ep_info_out) 317d9af1f7bSJulius Werner *bl32_ep_info_out = *v1->bl32_ep_info; 318d9af1f7bSJulius Werner if (bl33_ep_info_out) 319d9af1f7bSJulius Werner *bl33_ep_info_out = *v1->bl33_ep_info; 320d9af1f7bSJulius Werner return; 321d9af1f7bSJulius Werner } 322d9af1f7bSJulius Werner #endif /* !ERROR_DEPRECATED */ 323d9af1f7bSJulius Werner 324d9af1f7bSJulius Werner assert(v2->h.version == PARAM_VERSION_2); 325d9af1f7bSJulius Werner assert(v2->h.type == PARAM_BL_PARAMS); 326d9af1f7bSJulius Werner for (node = v2->head; node; node = node->next_params_info) { 327d9af1f7bSJulius Werner if (node->image_id == BL32_IMAGE_ID) 328d9af1f7bSJulius Werner if (bl32_ep_info_out) 329d9af1f7bSJulius Werner *bl32_ep_info_out = *node->ep_info; 330d9af1f7bSJulius Werner if (node->image_id == BL33_IMAGE_ID) 331d9af1f7bSJulius Werner if (bl33_ep_info_out) 332d9af1f7bSJulius Werner *bl33_ep_info_out = *node->ep_info; 333d9af1f7bSJulius Werner } 334d9af1f7bSJulius Werner } 335