blob: a9762b71704edc72882a14dae2abbfb86b9e82d6 [file] [log] [blame]
Yatharth Kochar3345a8d2016-09-12 16:08:41 +01001/*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch_helpers.h>
32#include <assert.h>
33#include <bl_common.h>
34#include <desc_image_load.h>
35
36
37extern bl_mem_params_node_t *bl_mem_params_desc_ptr;
38extern unsigned int bl_mem_params_desc_num;
39
40static bl_load_info_t bl_load_info;
41static bl_params_t next_bl_params;
42
43
44/*******************************************************************************
45 * This function flushes the data structures so that they are visible
46 * in memory for the next BL image.
47 ******************************************************************************/
48void flush_bl_params_desc(void)
49{
50 flush_dcache_range((unsigned long)bl_mem_params_desc_ptr,
51 sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num);
52}
53
54/*******************************************************************************
55 * This function returns the index for given image_id, within the
56 * image descriptor array provided by bl_image_info_descs_ptr, if the
57 * image is found else it returns -1.
58 ******************************************************************************/
59int get_bl_params_node_index(unsigned int image_id)
60{
61 int index;
62 assert(image_id != INVALID_IMAGE_ID);
63
64 for (index = 0; index < bl_mem_params_desc_num; index++) {
65 if (bl_mem_params_desc_ptr[index].image_id == image_id)
66 return index;
67 }
68
69 return -1;
70}
71
72/*******************************************************************************
73 * This function returns the pointer to `bl_mem_params_node_t` object for
74 * given image_id, within the image descriptor array provided by
75 * bl_mem_params_desc_ptr, if the image is found else it returns NULL.
76 ******************************************************************************/
77bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id)
78{
79 int index;
80 assert(image_id != INVALID_IMAGE_ID);
81
82 index = get_bl_params_node_index(image_id);
83 if (index >= 0)
84 return &bl_mem_params_desc_ptr[index];
85 else
86 return NULL;
87}
88
89/*******************************************************************************
90 * This function creates the list of loadable images, by populating and
91 * linking each `bl_load_info_node_t` type node, using the internal array
92 * of image descriptor provided by bl_mem_params_desc_ptr. It also populates
93 * and returns `bl_load_info_t` type structure that contains head of the list
94 * of loadable images.
95 ******************************************************************************/
96bl_load_info_t *get_bl_load_info_from_mem_params_desc(void)
97{
98 int index = 0;
99
100 /* If there is no image to start with, return NULL */
101 if (!bl_mem_params_desc_num)
102 return NULL;
103
104 /* Assign initial data structures */
105 bl_load_info_node_t *bl_node_info =
106 &bl_mem_params_desc_ptr[index].load_node_mem;
107 bl_load_info.head = bl_node_info;
108 SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0);
109
110 /* Go through the image descriptor array and create the list */
111 for (; index < bl_mem_params_desc_num; index++) {
112
113 /* Populate the image information */
114 bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id;
115 bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info;
116
117 /* Link next image if present */
118 if ((index + 1) < bl_mem_params_desc_num) {
119 /* Get the memory and link the next node */
120 bl_node_info->next_load_info =
121 &bl_mem_params_desc_ptr[index + 1].load_node_mem;
122 bl_node_info = bl_node_info->next_load_info;
123 }
124 }
125
126 return &bl_load_info;
127}
128
129/*******************************************************************************
130 * This function creates the list of executable images, by populating and
131 * linking each `bl_params_node_t` type node, using the internal array of
132 * image descriptor provided by bl_mem_params_desc_ptr. It also populates
133 * and returns `bl_params_t` type structure that contains head of the list
134 * of executable images.
135 ******************************************************************************/
136bl_params_t *get_next_bl_params_from_mem_params_desc(void)
137{
138 int count;
139 unsigned int img_id = 0;
140 int link_index = 0;
141 bl_params_node_t *bl_current_exec_node = NULL;
142 bl_params_node_t *bl_last_exec_node = NULL;
143 bl_mem_params_node_t *desc_ptr;
144
145 /* If there is no image to start with, return NULL */
146 if (!bl_mem_params_desc_num)
147 return NULL;
148
149 /* Get the list HEAD */
150 for (count = 0; count < bl_mem_params_desc_num; count++) {
151
152 desc_ptr = &bl_mem_params_desc_ptr[count];
153
154 if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) &&
155 (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) {
156 next_bl_params.head = &desc_ptr->params_node_mem;
157 link_index = count;
158 break;
159 }
160 }
161
162 /* Make sure we have a HEAD node */
163 assert(next_bl_params.head != NULL);
164
165 /* Populate the HEAD information */
166 SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0);
167
168 /*
169 * Go through the image descriptor array and create the list.
170 * This bounded loop is to make sure that we are not looping forever.
171 */
172 for (count = 0 ; count < bl_mem_params_desc_num; count++) {
173
174 desc_ptr = &bl_mem_params_desc_ptr[link_index];
175
176 /* Make sure the image is executable */
177 assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE);
178
179 /* Get the memory for current node */
180 bl_current_exec_node = &desc_ptr->params_node_mem;
181
182 /* Populate the image information */
183 bl_current_exec_node->image_id = desc_ptr->image_id;
184 bl_current_exec_node->image_info = &desc_ptr->image_info;
185 bl_current_exec_node->ep_info = &desc_ptr->ep_info;
186
187 if (bl_last_exec_node) {
188 /* Assert if loop detected */
189 assert(bl_last_exec_node->next_params_info == NULL);
190
191 /* Link the previous node to the current one */
192 bl_last_exec_node->next_params_info = bl_current_exec_node;
193 }
194
195 /* Update the last node */
196 bl_last_exec_node = bl_current_exec_node;
197
198 /* If no next hand-off image then break out */
199 img_id = desc_ptr->next_handoff_image_id;
200 if (img_id == INVALID_IMAGE_ID)
201 break;
202
203 /* Get the index for the next hand-off image */
204 link_index = get_bl_params_node_index(img_id);
205 assert((link_index > 0) &&
206 (link_index < bl_mem_params_desc_num));
207 }
208
209 /* Invalid image is expected to terminate the loop */
210 assert(img_id == INVALID_IMAGE_ID);
211
212 /* Populate arg0 for the next BL image */
213 next_bl_params.head->ep_info->args.arg0 = (unsigned long)&next_bl_params;
214
215 /* Flush the parameters to be passed to the next BL image */
216 flush_dcache_range((unsigned long)&next_bl_params,
217 sizeof(next_bl_params));
218
219 return &next_bl_params;
220}