2 * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
7 #include <arch_helpers.h>
10 #include <desc_image_load.h>
14 static bl_load_info_t bl_load_info
;
15 static bl_params_t next_bl_params
;
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)
24 flush_dcache_range((uintptr_t)bl_mem_params_desc_ptr
,
25 sizeof(*bl_mem_params_desc_ptr
) * bl_mem_params_desc_num
);
27 flush_dcache_range((uintptr_t)&next_bl_params
,
28 sizeof(next_bl_params
));
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
)
39 assert(image_id
!= INVALID_IMAGE_ID
);
41 for (index
= 0U; index
< bl_mem_params_desc_num
; index
++) {
42 if (bl_mem_params_desc_ptr
[index
].image_id
== image_id
)
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
)
57 assert(image_id
!= INVALID_IMAGE_ID
);
59 index
= get_bl_params_node_index(image_id
);
61 return &bl_mem_params_desc_ptr
[index
];
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
72 ******************************************************************************/
73 bl_load_info_t
*get_bl_load_info_from_mem_params_desc(void)
75 unsigned int index
= 0;
77 /* If there is no image to start with, return NULL */
78 if (bl_mem_params_desc_num
== 0U)
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);
87 /* Go through the image descriptor array and create the list */
88 for (; index
< bl_mem_params_desc_num
; index
++) {
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
;
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
;
103 return &bl_load_info
;
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)
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
;
122 /* If there is no image to start with, return NULL */
123 if (bl_mem_params_desc_num
== 0U)
126 /* Get the list HEAD */
127 for (count
= 0U; count
< bl_mem_params_desc_num
; count
++) {
129 desc_ptr
= &bl_mem_params_desc_ptr
[count
];
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
;
139 /* Make sure we have a HEAD node */
140 assert(next_bl_params
.head
!= NULL
);
142 /* Populate the HEAD information */
143 SET_PARAM_HEAD(&next_bl_params
, PARAM_BL_PARAMS
, VERSION_2
, 0U);
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.
149 for (count
= 0U; count
< bl_mem_params_desc_num
; count
++) {
151 desc_ptr
= &bl_mem_params_desc_ptr
[link_index
];
153 /* Make sure the image is executable */
154 assert(EP_GET_EXE(desc_ptr
->ep_info
.h
.attr
) == EXECUTABLE
);
156 /* Get the memory for current node */
157 bl_current_exec_node
= &desc_ptr
->params_node_mem
;
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
;
164 if (bl_last_exec_node
!= NULL
) {
165 /* Assert if loop detected */
166 assert(bl_last_exec_node
->next_params_info
== NULL
);
168 /* Link the previous node to the current one */
169 bl_last_exec_node
->next_params_info
= bl_current_exec_node
;
172 /* Update the last node */
173 bl_last_exec_node
= bl_current_exec_node
;
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
)
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
));
186 /* Invalid image is expected to terminate the loop */
187 assert(img_id
== INVALID_IMAGE_ID
);
189 return &next_bl_params
;
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
)
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
;
203 assert(bl2_to_next_bl_params
!= NULL
);
206 * Get the `bl_mem_params_node_t` corresponding to HW_CONFIG
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
;
213 for (params_node
= bl2_to_next_bl_params
->head
; params_node
!= NULL
;
214 params_node
= params_node
->next_params_info
) {
218 switch (params_node
->image_id
) {
220 fw_config_id
= SOC_FW_CONFIG_ID
;
223 fw_config_id
= TOS_FW_CONFIG_ID
;
226 fw_config_id
= NT_FW_CONFIG_ID
;
229 fw_config_id
= INVALID_IMAGE_ID
;
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
;
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.
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
=
249 if (params_node
->ep_info
->args
.arg2
== 0U)
250 params_node
->ep_info
->args
.arg2
=
253 if (params_node
->ep_info
->args
.arg0
== 0U)
254 params_node
->ep_info
->args
.arg0
=
256 if (params_node
->ep_info
->args
.arg1
== 0U)
257 params_node
->ep_info
->args
.arg1
=