1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park */
6*54fd6939SJiyong Park
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park
9*54fd6939SJiyong Park #include <arch_helpers.h>
10*54fd6939SJiyong Park #include <common/bl_common.h>
11*54fd6939SJiyong Park #include <common/desc_image_load.h>
12*54fd6939SJiyong Park #include <common/tbbr/tbbr_img_def.h>
13*54fd6939SJiyong Park
14*54fd6939SJiyong Park static bl_load_info_t bl_load_info;
15*54fd6939SJiyong Park static bl_params_t next_bl_params;
16*54fd6939SJiyong Park
17*54fd6939SJiyong Park
18*54fd6939SJiyong Park /*******************************************************************************
19*54fd6939SJiyong Park * This function flushes the data structures so that they are visible
20*54fd6939SJiyong Park * in memory for the next BL image.
21*54fd6939SJiyong Park ******************************************************************************/
flush_bl_params_desc(void)22*54fd6939SJiyong Park void flush_bl_params_desc(void)
23*54fd6939SJiyong Park {
24*54fd6939SJiyong Park flush_bl_params_desc_args(bl_mem_params_desc_ptr,
25*54fd6939SJiyong Park bl_mem_params_desc_num,
26*54fd6939SJiyong Park &next_bl_params);
27*54fd6939SJiyong Park }
28*54fd6939SJiyong Park
29*54fd6939SJiyong Park /*******************************************************************************
30*54fd6939SJiyong Park * This function flushes the data structures specified as arguments so that they
31*54fd6939SJiyong Park * are visible in memory for the next BL image.
32*54fd6939SJiyong Park ******************************************************************************/
flush_bl_params_desc_args(bl_mem_params_node_t * mem_params_desc_ptr,unsigned int mem_params_desc_num,bl_params_t * next_bl_params_ptr)33*54fd6939SJiyong Park void flush_bl_params_desc_args(bl_mem_params_node_t *mem_params_desc_ptr,
34*54fd6939SJiyong Park unsigned int mem_params_desc_num,
35*54fd6939SJiyong Park bl_params_t *next_bl_params_ptr)
36*54fd6939SJiyong Park {
37*54fd6939SJiyong Park assert(mem_params_desc_ptr != NULL);
38*54fd6939SJiyong Park assert(mem_params_desc_num != 0U);
39*54fd6939SJiyong Park assert(next_bl_params_ptr != NULL);
40*54fd6939SJiyong Park
41*54fd6939SJiyong Park flush_dcache_range((uintptr_t)mem_params_desc_ptr,
42*54fd6939SJiyong Park sizeof(*mem_params_desc_ptr) * mem_params_desc_num);
43*54fd6939SJiyong Park
44*54fd6939SJiyong Park flush_dcache_range((uintptr_t)next_bl_params_ptr,
45*54fd6939SJiyong Park sizeof(*next_bl_params_ptr));
46*54fd6939SJiyong Park }
47*54fd6939SJiyong Park
48*54fd6939SJiyong Park /*******************************************************************************
49*54fd6939SJiyong Park * This function returns the index for given image_id, within the
50*54fd6939SJiyong Park * image descriptor array provided by bl_image_info_descs_ptr, if the
51*54fd6939SJiyong Park * image is found else it returns -1.
52*54fd6939SJiyong Park ******************************************************************************/
get_bl_params_node_index(unsigned int image_id)53*54fd6939SJiyong Park int get_bl_params_node_index(unsigned int image_id)
54*54fd6939SJiyong Park {
55*54fd6939SJiyong Park unsigned int index;
56*54fd6939SJiyong Park assert(image_id != INVALID_IMAGE_ID);
57*54fd6939SJiyong Park
58*54fd6939SJiyong Park for (index = 0U; index < bl_mem_params_desc_num; index++) {
59*54fd6939SJiyong Park if (bl_mem_params_desc_ptr[index].image_id == image_id)
60*54fd6939SJiyong Park return (int)index;
61*54fd6939SJiyong Park }
62*54fd6939SJiyong Park
63*54fd6939SJiyong Park return -1;
64*54fd6939SJiyong Park }
65*54fd6939SJiyong Park
66*54fd6939SJiyong Park /*******************************************************************************
67*54fd6939SJiyong Park * This function returns the pointer to `bl_mem_params_node_t` object for
68*54fd6939SJiyong Park * given image_id, within the image descriptor array provided by
69*54fd6939SJiyong Park * bl_mem_params_desc_ptr, if the image is found else it returns NULL.
70*54fd6939SJiyong Park ******************************************************************************/
get_bl_mem_params_node(unsigned int image_id)71*54fd6939SJiyong Park bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id)
72*54fd6939SJiyong Park {
73*54fd6939SJiyong Park int index;
74*54fd6939SJiyong Park assert(image_id != INVALID_IMAGE_ID);
75*54fd6939SJiyong Park
76*54fd6939SJiyong Park index = get_bl_params_node_index(image_id);
77*54fd6939SJiyong Park if (index >= 0)
78*54fd6939SJiyong Park return &bl_mem_params_desc_ptr[index];
79*54fd6939SJiyong Park else
80*54fd6939SJiyong Park return NULL;
81*54fd6939SJiyong Park }
82*54fd6939SJiyong Park
83*54fd6939SJiyong Park /*******************************************************************************
84*54fd6939SJiyong Park * This function creates the list of loadable images, by populating and
85*54fd6939SJiyong Park * linking each `bl_load_info_node_t` type node, using the internal array
86*54fd6939SJiyong Park * of image descriptor provided by bl_mem_params_desc_ptr. It also populates
87*54fd6939SJiyong Park * and returns `bl_load_info_t` type structure that contains head of the list
88*54fd6939SJiyong Park * of loadable images.
89*54fd6939SJiyong Park ******************************************************************************/
get_bl_load_info_from_mem_params_desc(void)90*54fd6939SJiyong Park bl_load_info_t *get_bl_load_info_from_mem_params_desc(void)
91*54fd6939SJiyong Park {
92*54fd6939SJiyong Park unsigned int index = 0;
93*54fd6939SJiyong Park
94*54fd6939SJiyong Park /* If there is no image to start with, return NULL */
95*54fd6939SJiyong Park if (bl_mem_params_desc_num == 0U)
96*54fd6939SJiyong Park return NULL;
97*54fd6939SJiyong Park
98*54fd6939SJiyong Park /* Assign initial data structures */
99*54fd6939SJiyong Park bl_load_info_node_t *bl_node_info =
100*54fd6939SJiyong Park &bl_mem_params_desc_ptr[index].load_node_mem;
101*54fd6939SJiyong Park bl_load_info.head = bl_node_info;
102*54fd6939SJiyong Park SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0U);
103*54fd6939SJiyong Park
104*54fd6939SJiyong Park /* Go through the image descriptor array and create the list */
105*54fd6939SJiyong Park for (; index < bl_mem_params_desc_num; index++) {
106*54fd6939SJiyong Park
107*54fd6939SJiyong Park /* Populate the image information */
108*54fd6939SJiyong Park bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id;
109*54fd6939SJiyong Park bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info;
110*54fd6939SJiyong Park
111*54fd6939SJiyong Park /* Link next image if present */
112*54fd6939SJiyong Park if ((index + 1U) < bl_mem_params_desc_num) {
113*54fd6939SJiyong Park /* Get the memory and link the next node */
114*54fd6939SJiyong Park bl_node_info->next_load_info =
115*54fd6939SJiyong Park &bl_mem_params_desc_ptr[index + 1U].load_node_mem;
116*54fd6939SJiyong Park bl_node_info = bl_node_info->next_load_info;
117*54fd6939SJiyong Park }
118*54fd6939SJiyong Park }
119*54fd6939SJiyong Park
120*54fd6939SJiyong Park return &bl_load_info;
121*54fd6939SJiyong Park }
122*54fd6939SJiyong Park
123*54fd6939SJiyong Park /*******************************************************************************
124*54fd6939SJiyong Park * This function creates the list of executable images, by populating and
125*54fd6939SJiyong Park * linking each `bl_params_node_t` type node, using the internal array of
126*54fd6939SJiyong Park * image descriptor provided by bl_mem_params_desc_ptr. It also populates
127*54fd6939SJiyong Park * and returns `bl_params_t` type structure that contains head of the list
128*54fd6939SJiyong Park * of executable images.
129*54fd6939SJiyong Park ******************************************************************************/
get_next_bl_params_from_mem_params_desc(void)130*54fd6939SJiyong Park bl_params_t *get_next_bl_params_from_mem_params_desc(void)
131*54fd6939SJiyong Park {
132*54fd6939SJiyong Park unsigned int count;
133*54fd6939SJiyong Park unsigned int img_id = 0U;
134*54fd6939SJiyong Park unsigned int link_index = 0U;
135*54fd6939SJiyong Park bl_params_node_t *bl_current_exec_node = NULL;
136*54fd6939SJiyong Park bl_params_node_t *bl_last_exec_node = NULL;
137*54fd6939SJiyong Park bl_mem_params_node_t *desc_ptr;
138*54fd6939SJiyong Park
139*54fd6939SJiyong Park /* If there is no image to start with, return NULL */
140*54fd6939SJiyong Park if (bl_mem_params_desc_num == 0U)
141*54fd6939SJiyong Park return NULL;
142*54fd6939SJiyong Park
143*54fd6939SJiyong Park /* Get the list HEAD */
144*54fd6939SJiyong Park for (count = 0U; count < bl_mem_params_desc_num; count++) {
145*54fd6939SJiyong Park
146*54fd6939SJiyong Park desc_ptr = &bl_mem_params_desc_ptr[count];
147*54fd6939SJiyong Park
148*54fd6939SJiyong Park if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) &&
149*54fd6939SJiyong Park (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) {
150*54fd6939SJiyong Park next_bl_params.head = &desc_ptr->params_node_mem;
151*54fd6939SJiyong Park link_index = count;
152*54fd6939SJiyong Park break;
153*54fd6939SJiyong Park }
154*54fd6939SJiyong Park }
155*54fd6939SJiyong Park
156*54fd6939SJiyong Park /* Make sure we have a HEAD node */
157*54fd6939SJiyong Park assert(next_bl_params.head != NULL);
158*54fd6939SJiyong Park
159*54fd6939SJiyong Park /* Populate the HEAD information */
160*54fd6939SJiyong Park SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0U);
161*54fd6939SJiyong Park
162*54fd6939SJiyong Park /*
163*54fd6939SJiyong Park * Go through the image descriptor array and create the list.
164*54fd6939SJiyong Park * This bounded loop is to make sure that we are not looping forever.
165*54fd6939SJiyong Park */
166*54fd6939SJiyong Park for (count = 0U; count < bl_mem_params_desc_num; count++) {
167*54fd6939SJiyong Park
168*54fd6939SJiyong Park desc_ptr = &bl_mem_params_desc_ptr[link_index];
169*54fd6939SJiyong Park
170*54fd6939SJiyong Park /* Make sure the image is executable */
171*54fd6939SJiyong Park assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE);
172*54fd6939SJiyong Park
173*54fd6939SJiyong Park /* Get the memory for current node */
174*54fd6939SJiyong Park bl_current_exec_node = &desc_ptr->params_node_mem;
175*54fd6939SJiyong Park
176*54fd6939SJiyong Park /* Populate the image information */
177*54fd6939SJiyong Park bl_current_exec_node->image_id = desc_ptr->image_id;
178*54fd6939SJiyong Park bl_current_exec_node->image_info = &desc_ptr->image_info;
179*54fd6939SJiyong Park bl_current_exec_node->ep_info = &desc_ptr->ep_info;
180*54fd6939SJiyong Park
181*54fd6939SJiyong Park if (bl_last_exec_node != NULL) {
182*54fd6939SJiyong Park /* Assert if loop detected */
183*54fd6939SJiyong Park assert(bl_last_exec_node->next_params_info == NULL);
184*54fd6939SJiyong Park
185*54fd6939SJiyong Park /* Link the previous node to the current one */
186*54fd6939SJiyong Park bl_last_exec_node->next_params_info = bl_current_exec_node;
187*54fd6939SJiyong Park }
188*54fd6939SJiyong Park
189*54fd6939SJiyong Park /* Update the last node */
190*54fd6939SJiyong Park bl_last_exec_node = bl_current_exec_node;
191*54fd6939SJiyong Park
192*54fd6939SJiyong Park /* If no next hand-off image then break out */
193*54fd6939SJiyong Park img_id = desc_ptr->next_handoff_image_id;
194*54fd6939SJiyong Park if (img_id == INVALID_IMAGE_ID)
195*54fd6939SJiyong Park break;
196*54fd6939SJiyong Park
197*54fd6939SJiyong Park /* Get the index for the next hand-off image */
198*54fd6939SJiyong Park link_index = get_bl_params_node_index(img_id);
199*54fd6939SJiyong Park assert((link_index > 0U) &&
200*54fd6939SJiyong Park (link_index < bl_mem_params_desc_num));
201*54fd6939SJiyong Park }
202*54fd6939SJiyong Park
203*54fd6939SJiyong Park /* Invalid image is expected to terminate the loop */
204*54fd6939SJiyong Park assert(img_id == INVALID_IMAGE_ID);
205*54fd6939SJiyong Park
206*54fd6939SJiyong Park return &next_bl_params;
207*54fd6939SJiyong Park }
208*54fd6939SJiyong Park
209*54fd6939SJiyong Park /*******************************************************************************
210*54fd6939SJiyong Park * This function populates the entry point information with the corresponding
211*54fd6939SJiyong Park * config file for all executable BL images described in bl_params.
212*54fd6939SJiyong Park ******************************************************************************/
populate_next_bl_params_config(bl_params_t * bl2_to_next_bl_params)213*54fd6939SJiyong Park void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params)
214*54fd6939SJiyong Park {
215*54fd6939SJiyong Park bl_params_node_t *params_node;
216*54fd6939SJiyong Park unsigned int fw_config_id;
217*54fd6939SJiyong Park uintptr_t fw_config_base;
218*54fd6939SJiyong Park bl_mem_params_node_t *mem_params;
219*54fd6939SJiyong Park uintptr_t hw_config_base = 0;
220*54fd6939SJiyong Park
221*54fd6939SJiyong Park assert(bl2_to_next_bl_params != NULL);
222*54fd6939SJiyong Park
223*54fd6939SJiyong Park /*
224*54fd6939SJiyong Park * Get the `bl_mem_params_node_t` corresponding to HW_CONFIG
225*54fd6939SJiyong Park * if available.
226*54fd6939SJiyong Park */
227*54fd6939SJiyong Park mem_params = get_bl_mem_params_node(HW_CONFIG_ID);
228*54fd6939SJiyong Park
229*54fd6939SJiyong Park if (mem_params != NULL)
230*54fd6939SJiyong Park hw_config_base = mem_params->image_info.image_base;
231*54fd6939SJiyong Park
232*54fd6939SJiyong Park for (params_node = bl2_to_next_bl_params->head; params_node != NULL;
233*54fd6939SJiyong Park params_node = params_node->next_params_info) {
234*54fd6939SJiyong Park
235*54fd6939SJiyong Park fw_config_base = 0;
236*54fd6939SJiyong Park
237*54fd6939SJiyong Park switch (params_node->image_id) {
238*54fd6939SJiyong Park case BL31_IMAGE_ID:
239*54fd6939SJiyong Park fw_config_id = SOC_FW_CONFIG_ID;
240*54fd6939SJiyong Park break;
241*54fd6939SJiyong Park case BL32_IMAGE_ID:
242*54fd6939SJiyong Park /*
243*54fd6939SJiyong Park * At the moment, OPTEE cannot accept a DTB in secure memory,
244*54fd6939SJiyong Park * so fall back and use NT_FW_CONFIG instead.
245*54fd6939SJiyong Park * This MUST be fixed as soon as OPTEE has support to
246*54fd6939SJiyong Park * receive DTBs in secure memory.
247*54fd6939SJiyong Park */
248*54fd6939SJiyong Park #ifndef SPD_opteed
249*54fd6939SJiyong Park fw_config_id = TOS_FW_CONFIG_ID;
250*54fd6939SJiyong Park break;
251*54fd6939SJiyong Park #endif
252*54fd6939SJiyong Park case BL33_IMAGE_ID:
253*54fd6939SJiyong Park fw_config_id = NT_FW_CONFIG_ID;
254*54fd6939SJiyong Park break;
255*54fd6939SJiyong Park default:
256*54fd6939SJiyong Park fw_config_id = INVALID_IMAGE_ID;
257*54fd6939SJiyong Park break;
258*54fd6939SJiyong Park }
259*54fd6939SJiyong Park
260*54fd6939SJiyong Park if (fw_config_id != INVALID_IMAGE_ID) {
261*54fd6939SJiyong Park mem_params = get_bl_mem_params_node(fw_config_id);
262*54fd6939SJiyong Park if (mem_params != NULL) {
263*54fd6939SJiyong Park fw_config_base = mem_params->image_info.image_base;
264*54fd6939SJiyong Park }
265*54fd6939SJiyong Park }
266*54fd6939SJiyong Park
267*54fd6939SJiyong Park #ifdef SPD_opteed
268*54fd6939SJiyong Park /*
269*54fd6939SJiyong Park * If SPD_opteed is enabled, arg[0,2] are populated by
270*54fd6939SJiyong Park * parse_optee_header(), which is called by
271*54fd6939SJiyong Park * arm_bl2_handle_post_image_load(). The meaning of the
272*54fd6939SJiyong Park * arguments are:
273*54fd6939SJiyong Park * arg0 <-- MODE_RW
274*54fd6939SJiyong Park * arg1 <-- Paged image base
275*54fd6939SJiyong Park * arg2 <-- Paged image size
276*54fd6939SJiyong Park */
277*54fd6939SJiyong Park if (params_node->image_id == BL32_IMAGE_ID) {
278*54fd6939SJiyong Park params_node->ep_info->args.arg3 = fw_config_base;
279*54fd6939SJiyong Park } else {
280*54fd6939SJiyong Park #endif
281*54fd6939SJiyong Park /*
282*54fd6939SJiyong Park * Pass hw and tb_fw config addresses to next images.
283*54fd6939SJiyong Park * NOTE - for EL3 runtime images (BL31 for AArch64
284*54fd6939SJiyong Park * and BL32 for AArch32), arg0 is already used by
285*54fd6939SJiyong Park * generic code. Take care of not overwriting the
286*54fd6939SJiyong Park * previous initialisations.
287*54fd6939SJiyong Park */
288*54fd6939SJiyong Park if (params_node == bl2_to_next_bl_params->head) {
289*54fd6939SJiyong Park if (params_node->ep_info->args.arg1 == 0U)
290*54fd6939SJiyong Park params_node->ep_info->args.arg1 =
291*54fd6939SJiyong Park fw_config_base;
292*54fd6939SJiyong Park if (params_node->ep_info->args.arg2 == 0U)
293*54fd6939SJiyong Park params_node->ep_info->args.arg2 =
294*54fd6939SJiyong Park hw_config_base;
295*54fd6939SJiyong Park } else {
296*54fd6939SJiyong Park if (params_node->ep_info->args.arg0 == 0U)
297*54fd6939SJiyong Park params_node->ep_info->args.arg0 =
298*54fd6939SJiyong Park fw_config_base;
299*54fd6939SJiyong Park if (params_node->ep_info->args.arg1 == 0U)
300*54fd6939SJiyong Park params_node->ep_info->args.arg1 =
301*54fd6939SJiyong Park hw_config_base;
302*54fd6939SJiyong Park }
303*54fd6939SJiyong Park #ifdef SPD_opteed
304*54fd6939SJiyong Park }
305*54fd6939SJiyong Park #endif
306*54fd6939SJiyong Park }
307*54fd6939SJiyong Park }
308*54fd6939SJiyong Park
309*54fd6939SJiyong Park /*******************************************************************************
310*54fd6939SJiyong Park * Helper to extract BL32/BL33 entry point info from arg0 passed to BL31, for
311*54fd6939SJiyong Park * platforms that are only interested in those. Platforms that need to extract
312*54fd6939SJiyong Park * more information can parse the structures themselves.
313*54fd6939SJiyong Park ******************************************************************************/
314*54fd6939SJiyong Park
bl31_params_parse_helper(u_register_t param,entry_point_info_t * bl32_ep_info_out,entry_point_info_t * bl33_ep_info_out)315*54fd6939SJiyong Park void bl31_params_parse_helper(u_register_t param,
316*54fd6939SJiyong Park entry_point_info_t *bl32_ep_info_out,
317*54fd6939SJiyong Park entry_point_info_t *bl33_ep_info_out)
318*54fd6939SJiyong Park {
319*54fd6939SJiyong Park bl_params_node_t *node;
320*54fd6939SJiyong Park bl_params_t *v2 = (void *)(uintptr_t)param;
321*54fd6939SJiyong Park
322*54fd6939SJiyong Park #if !ERROR_DEPRECATED
323*54fd6939SJiyong Park if (v2->h.version == PARAM_VERSION_1) {
324*54fd6939SJiyong Park struct { /* Deprecated version 1 parameter structure. */
325*54fd6939SJiyong Park param_header_t h;
326*54fd6939SJiyong Park image_info_t *bl31_image_info;
327*54fd6939SJiyong Park entry_point_info_t *bl32_ep_info;
328*54fd6939SJiyong Park image_info_t *bl32_image_info;
329*54fd6939SJiyong Park entry_point_info_t *bl33_ep_info;
330*54fd6939SJiyong Park image_info_t *bl33_image_info;
331*54fd6939SJiyong Park } *v1 = (void *)(uintptr_t)param;
332*54fd6939SJiyong Park assert(v1->h.type == PARAM_BL31);
333*54fd6939SJiyong Park if (bl32_ep_info_out != NULL)
334*54fd6939SJiyong Park *bl32_ep_info_out = *v1->bl32_ep_info;
335*54fd6939SJiyong Park if (bl33_ep_info_out != NULL)
336*54fd6939SJiyong Park *bl33_ep_info_out = *v1->bl33_ep_info;
337*54fd6939SJiyong Park return;
338*54fd6939SJiyong Park }
339*54fd6939SJiyong Park #endif /* !ERROR_DEPRECATED */
340*54fd6939SJiyong Park
341*54fd6939SJiyong Park assert(v2->h.version == PARAM_VERSION_2);
342*54fd6939SJiyong Park assert(v2->h.type == PARAM_BL_PARAMS);
343*54fd6939SJiyong Park for (node = v2->head; node != NULL; node = node->next_params_info) {
344*54fd6939SJiyong Park if (node->image_id == BL32_IMAGE_ID)
345*54fd6939SJiyong Park if (bl32_ep_info_out != NULL)
346*54fd6939SJiyong Park *bl32_ep_info_out = *node->ep_info;
347*54fd6939SJiyong Park if (node->image_id == BL33_IMAGE_ID)
348*54fd6939SJiyong Park if (bl33_ep_info_out != NULL)
349*54fd6939SJiyong Park *bl33_ep_info_out = *node->ep_info;
350*54fd6939SJiyong Park }
351*54fd6939SJiyong Park }
352