xref: /rk3399_ARM-atf/common/desc_image_load.c (revision 51faada71a219a8b94cd8d8e423f0f22e9da4d8f)
1 /*
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 
37 extern bl_mem_params_node_t *bl_mem_params_desc_ptr;
38 extern unsigned int bl_mem_params_desc_num;
39 
40 static bl_load_info_t bl_load_info;
41 static 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  ******************************************************************************/
48 void 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  ******************************************************************************/
59 int 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  ******************************************************************************/
77 bl_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  ******************************************************************************/
96 bl_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  ******************************************************************************/
136 bl_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 }
221