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