Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
      3  *
      4  * SPDX-License-Identifier: BSD-3-Clause
      5  */
      6 
      7 #include <arch_helpers.h>
      8 #include <assert.h>
      9 #include <bl_common.h>
     10 #include <desc_image_load.h>
     11 
     12 
     13 extern bl_mem_params_node_t *bl_mem_params_desc_ptr;
     14 extern unsigned int bl_mem_params_desc_num;
     15 
     16 static bl_load_info_t bl_load_info;
     17 static bl_params_t next_bl_params;
     18 
     19 
     20 /*******************************************************************************
     21  * This function flushes the data structures so that they are visible
     22  * in memory for the next BL image.
     23  ******************************************************************************/
     24 void flush_bl_params_desc(void)
     25 {
     26 	flush_dcache_range((uintptr_t)bl_mem_params_desc_ptr,
     27 			sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num);
     28 
     29 	flush_dcache_range((uintptr_t)&next_bl_params,
     30 			sizeof(next_bl_params));
     31 }
     32 
     33 /*******************************************************************************
     34  * This function returns the index for given image_id, within the
     35  * image descriptor array provided by bl_image_info_descs_ptr, if the
     36  * image is found else it returns -1.
     37  ******************************************************************************/
     38 int get_bl_params_node_index(unsigned int image_id)
     39 {
     40 	int index;
     41 	assert(image_id != INVALID_IMAGE_ID);
     42 
     43 	for (index = 0; index < bl_mem_params_desc_num; index++) {
     44 		if (bl_mem_params_desc_ptr[index].image_id == image_id)
     45 			return index;
     46 	}
     47 
     48 	return -1;
     49 }
     50 
     51 /*******************************************************************************
     52  * This function returns the pointer to `bl_mem_params_node_t` object for
     53  * given image_id, within the image descriptor array provided by
     54  * bl_mem_params_desc_ptr, if the image is found else it returns NULL.
     55  ******************************************************************************/
     56 bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id)
     57 {
     58 	int index;
     59 	assert(image_id != INVALID_IMAGE_ID);
     60 
     61 	index = get_bl_params_node_index(image_id);
     62 	if (index >= 0)
     63 		return &bl_mem_params_desc_ptr[index];
     64 	else
     65 		return NULL;
     66 }
     67 
     68 /*******************************************************************************
     69  * This function creates the list of loadable images, by populating and
     70  * linking each `bl_load_info_node_t` type node, using the internal array
     71  * of image descriptor provided by bl_mem_params_desc_ptr. It also populates
     72  * and returns `bl_load_info_t` type structure that contains head of the list
     73  * of loadable images.
     74  ******************************************************************************/
     75 bl_load_info_t *get_bl_load_info_from_mem_params_desc(void)
     76 {
     77 	int index = 0;
     78 
     79 	/* If there is no image to start with, return NULL */
     80 	if (!bl_mem_params_desc_num)
     81 		return NULL;
     82 
     83 	/* Assign initial data structures */
     84 	bl_load_info_node_t *bl_node_info =
     85 		&bl_mem_params_desc_ptr[index].load_node_mem;
     86 	bl_load_info.head = bl_node_info;
     87 	SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0);
     88 
     89 	/* Go through the image descriptor array and create the list */
     90 	for (; index < bl_mem_params_desc_num; index++) {
     91 
     92 		/* Populate the image information */
     93 		bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id;
     94 		bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info;
     95 
     96 		/* Link next image if present */
     97 		if ((index + 1) < bl_mem_params_desc_num) {
     98 			/* Get the memory and link the next node */
     99 			bl_node_info->next_load_info =
    100 				&bl_mem_params_desc_ptr[index + 1].load_node_mem;
    101 			bl_node_info = bl_node_info->next_load_info;
    102 		}
    103 	}
    104 
    105 	return &bl_load_info;
    106 }
    107 
    108 /*******************************************************************************
    109  * This function creates the list of executable images, by populating and
    110  * linking each `bl_params_node_t` type node, using the internal array of
    111  * image descriptor provided by bl_mem_params_desc_ptr. It also populates
    112  * and returns `bl_params_t` type structure that contains head of the list
    113  * of executable images.
    114  ******************************************************************************/
    115 bl_params_t *get_next_bl_params_from_mem_params_desc(void)
    116 {
    117 	int count;
    118 	unsigned int img_id = 0;
    119 	int link_index = 0;
    120 	bl_params_node_t *bl_current_exec_node = NULL;
    121 	bl_params_node_t *bl_last_exec_node = NULL;
    122 	bl_mem_params_node_t *desc_ptr;
    123 
    124 	/* If there is no image to start with, return NULL */
    125 	if (!bl_mem_params_desc_num)
    126 		return NULL;
    127 
    128 	/* Get the list HEAD */
    129 	for (count = 0; count < bl_mem_params_desc_num; count++) {
    130 
    131 		desc_ptr = &bl_mem_params_desc_ptr[count];
    132 
    133 		if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) &&
    134 			(EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) {
    135 			next_bl_params.head = &desc_ptr->params_node_mem;
    136 			link_index = count;
    137 			break;
    138 		}
    139 	}
    140 
    141 	/* Make sure we have a HEAD node */
    142 	assert(next_bl_params.head != NULL);
    143 
    144 	/* Populate the HEAD information */
    145 	SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0);
    146 
    147 	/*
    148 	 * Go through the image descriptor array and create the list.
    149 	 * This bounded loop is to make sure that we are not looping forever.
    150 	 */
    151 	for (count = 0 ; count < bl_mem_params_desc_num; count++) {
    152 
    153 		desc_ptr = &bl_mem_params_desc_ptr[link_index];
    154 
    155 		/* Make sure the image is executable */
    156 		assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE);
    157 
    158 		/* Get the memory for current node */
    159 		bl_current_exec_node = &desc_ptr->params_node_mem;
    160 
    161 		/* Populate the image information */
    162 		bl_current_exec_node->image_id = desc_ptr->image_id;
    163 		bl_current_exec_node->image_info = &desc_ptr->image_info;
    164 		bl_current_exec_node->ep_info = &desc_ptr->ep_info;
    165 
    166 		if (bl_last_exec_node) {
    167 			/* Assert if loop detected */
    168 			assert(bl_last_exec_node->next_params_info == NULL);
    169 
    170 			/* Link the previous node to the current one */
    171 			bl_last_exec_node->next_params_info = bl_current_exec_node;
    172 		}
    173 
    174 		/* Update the last node */
    175 		bl_last_exec_node = bl_current_exec_node;
    176 
    177 		/* If no next hand-off image then break out */
    178 		img_id = desc_ptr->next_handoff_image_id;
    179 		if (img_id == INVALID_IMAGE_ID)
    180 			break;
    181 
    182 		/* Get the index for the next hand-off image */
    183 		link_index = get_bl_params_node_index(img_id);
    184 		assert((link_index > 0) &&
    185 			(link_index < bl_mem_params_desc_num));
    186 	}
    187 
    188 	/* Invalid image is expected to terminate the loop */
    189 	assert(img_id == INVALID_IMAGE_ID);
    190 
    191 	return &next_bl_params;
    192 }
    193