xref: /rk3399_ARM-atf/common/desc_image_load.c (revision c948f77136c42a92d0bb660543a3600c36dcf7f1)
1 /*
2  * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 
9 #include <arch_helpers.h>
10 #include <common/bl_common.h>
11 #include <common/desc_image_load.h>
12 
13 static bl_load_info_t bl_load_info;
14 static bl_params_t next_bl_params;
15 
16 
17 /*******************************************************************************
18  * This function flushes the data structures so that they are visible
19  * in memory for the next BL image.
20  ******************************************************************************/
21 void flush_bl_params_desc(void)
22 {
23 	flush_dcache_range((uintptr_t)bl_mem_params_desc_ptr,
24 			sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num);
25 
26 	flush_dcache_range((uintptr_t)&next_bl_params,
27 			sizeof(next_bl_params));
28 }
29 
30 /*******************************************************************************
31  * This function returns the index for given image_id, within the
32  * image descriptor array provided by bl_image_info_descs_ptr, if the
33  * image is found else it returns -1.
34  ******************************************************************************/
35 int get_bl_params_node_index(unsigned int image_id)
36 {
37 	unsigned int index;
38 	assert(image_id != INVALID_IMAGE_ID);
39 
40 	for (index = 0U; index < bl_mem_params_desc_num; index++) {
41 		if (bl_mem_params_desc_ptr[index].image_id == image_id)
42 			return (int)index;
43 	}
44 
45 	return -1;
46 }
47 
48 /*******************************************************************************
49  * This function returns the pointer to `bl_mem_params_node_t` object for
50  * given image_id, within the image descriptor array provided by
51  * bl_mem_params_desc_ptr, if the image is found else it returns NULL.
52  ******************************************************************************/
53 bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id)
54 {
55 	int index;
56 	assert(image_id != INVALID_IMAGE_ID);
57 
58 	index = get_bl_params_node_index(image_id);
59 	if (index >= 0)
60 		return &bl_mem_params_desc_ptr[index];
61 	else
62 		return NULL;
63 }
64 
65 /*******************************************************************************
66  * This function creates the list of loadable images, by populating and
67  * linking each `bl_load_info_node_t` type node, using the internal array
68  * of image descriptor provided by bl_mem_params_desc_ptr. It also populates
69  * and returns `bl_load_info_t` type structure that contains head of the list
70  * of loadable images.
71  ******************************************************************************/
72 bl_load_info_t *get_bl_load_info_from_mem_params_desc(void)
73 {
74 	unsigned int index = 0;
75 
76 	/* If there is no image to start with, return NULL */
77 	if (bl_mem_params_desc_num == 0U)
78 		return NULL;
79 
80 	/* Assign initial data structures */
81 	bl_load_info_node_t *bl_node_info =
82 		&bl_mem_params_desc_ptr[index].load_node_mem;
83 	bl_load_info.head = bl_node_info;
84 	SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0U);
85 
86 	/* Go through the image descriptor array and create the list */
87 	for (; index < bl_mem_params_desc_num; index++) {
88 
89 		/* Populate the image information */
90 		bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id;
91 		bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info;
92 
93 		/* Link next image if present */
94 		if ((index + 1U) < bl_mem_params_desc_num) {
95 			/* Get the memory and link the next node */
96 			bl_node_info->next_load_info =
97 				&bl_mem_params_desc_ptr[index + 1U].load_node_mem;
98 			bl_node_info = bl_node_info->next_load_info;
99 		}
100 	}
101 
102 	return &bl_load_info;
103 }
104 
105 /*******************************************************************************
106  * This function creates the list of executable images, by populating and
107  * linking each `bl_params_node_t` type node, using the internal array of
108  * image descriptor provided by bl_mem_params_desc_ptr. It also populates
109  * and returns `bl_params_t` type structure that contains head of the list
110  * of executable images.
111  ******************************************************************************/
112 bl_params_t *get_next_bl_params_from_mem_params_desc(void)
113 {
114 	unsigned int count;
115 	unsigned int img_id = 0U;
116 	unsigned int link_index = 0U;
117 	bl_params_node_t *bl_current_exec_node = NULL;
118 	bl_params_node_t *bl_last_exec_node = NULL;
119 	bl_mem_params_node_t *desc_ptr;
120 
121 	/* If there is no image to start with, return NULL */
122 	if (bl_mem_params_desc_num == 0U)
123 		return NULL;
124 
125 	/* Get the list HEAD */
126 	for (count = 0U; count < bl_mem_params_desc_num; count++) {
127 
128 		desc_ptr = &bl_mem_params_desc_ptr[count];
129 
130 		if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) &&
131 			(EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) {
132 			next_bl_params.head = &desc_ptr->params_node_mem;
133 			link_index = count;
134 			break;
135 		}
136 	}
137 
138 	/* Make sure we have a HEAD node */
139 	assert(next_bl_params.head != NULL);
140 
141 	/* Populate the HEAD information */
142 	SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0U);
143 
144 	/*
145 	 * Go through the image descriptor array and create the list.
146 	 * This bounded loop is to make sure that we are not looping forever.
147 	 */
148 	for (count = 0U; count < bl_mem_params_desc_num; count++) {
149 
150 		desc_ptr = &bl_mem_params_desc_ptr[link_index];
151 
152 		/* Make sure the image is executable */
153 		assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE);
154 
155 		/* Get the memory for current node */
156 		bl_current_exec_node = &desc_ptr->params_node_mem;
157 
158 		/* Populate the image information */
159 		bl_current_exec_node->image_id = desc_ptr->image_id;
160 		bl_current_exec_node->image_info = &desc_ptr->image_info;
161 		bl_current_exec_node->ep_info = &desc_ptr->ep_info;
162 
163 		if (bl_last_exec_node != NULL) {
164 			/* Assert if loop detected */
165 			assert(bl_last_exec_node->next_params_info == NULL);
166 
167 			/* Link the previous node to the current one */
168 			bl_last_exec_node->next_params_info = bl_current_exec_node;
169 		}
170 
171 		/* Update the last node */
172 		bl_last_exec_node = bl_current_exec_node;
173 
174 		/* If no next hand-off image then break out */
175 		img_id = desc_ptr->next_handoff_image_id;
176 		if (img_id == INVALID_IMAGE_ID)
177 			break;
178 
179 		/* Get the index for the next hand-off image */
180 		link_index = get_bl_params_node_index(img_id);
181 		assert((link_index > 0U) &&
182 			(link_index < bl_mem_params_desc_num));
183 	}
184 
185 	/* Invalid image is expected to terminate the loop */
186 	assert(img_id == INVALID_IMAGE_ID);
187 
188 	return &next_bl_params;
189 }
190 
191 /*******************************************************************************
192  * This function populates the entry point information with the corresponding
193  * config file for all executable BL images described in bl_params.
194  ******************************************************************************/
195 void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params)
196 {
197 	bl_params_node_t *params_node;
198 	unsigned int fw_config_id;
199 	uintptr_t hw_config_base = 0, fw_config_base;
200 	bl_mem_params_node_t *mem_params;
201 
202 	assert(bl2_to_next_bl_params != NULL);
203 
204 	/*
205 	 * Get the `bl_mem_params_node_t` corresponding to HW_CONFIG
206 	 * if available.
207 	 */
208 	mem_params = get_bl_mem_params_node(HW_CONFIG_ID);
209 	if (mem_params != NULL)
210 		hw_config_base = mem_params->image_info.image_base;
211 
212 	for (params_node = bl2_to_next_bl_params->head; params_node != NULL;
213 			params_node = params_node->next_params_info) {
214 
215 		fw_config_base = 0;
216 
217 		switch (params_node->image_id) {
218 		case BL31_IMAGE_ID:
219 			fw_config_id = SOC_FW_CONFIG_ID;
220 			break;
221 		case BL32_IMAGE_ID:
222 			fw_config_id = TOS_FW_CONFIG_ID;
223 			break;
224 		case BL33_IMAGE_ID:
225 			fw_config_id = NT_FW_CONFIG_ID;
226 			break;
227 		default:
228 			fw_config_id = INVALID_IMAGE_ID;
229 			break;
230 		}
231 
232 		if (fw_config_id != INVALID_IMAGE_ID) {
233 			mem_params = get_bl_mem_params_node(fw_config_id);
234 			if (mem_params != NULL)
235 				fw_config_base = mem_params->image_info.image_base;
236 		}
237 
238 		/*
239 		 * Pass hw and tb_fw config addresses to next images. NOTE - for
240 		 * EL3 runtime images (BL31 for AArch64 and BL32 for AArch32),
241 		 * arg0 is already used by generic code. Take care of not
242 		 * overwriting the previous initialisations.
243 		 */
244 		if (params_node == bl2_to_next_bl_params->head) {
245 			if (params_node->ep_info->args.arg1 == 0U)
246 				params_node->ep_info->args.arg1 =
247 								fw_config_base;
248 			if (params_node->ep_info->args.arg2 == 0U)
249 				params_node->ep_info->args.arg2 =
250 								hw_config_base;
251 		} else {
252 			if (params_node->ep_info->args.arg0 == 0U)
253 				params_node->ep_info->args.arg0 =
254 								fw_config_base;
255 			if (params_node->ep_info->args.arg1 == 0U)
256 				params_node->ep_info->args.arg1 =
257 								hw_config_base;
258 		}
259 	}
260 }
261