xref: /rk3399_ARM-atf/common/desc_image_load.c (revision b10d44995eb652675863c2cc6a7726683613da0d)
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((uintptr_t)bl_mem_params_desc_ptr,
51 			sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num);
52 
53 	flush_dcache_range((uintptr_t)&next_bl_params,
54 			sizeof(next_bl_params));
55 }
56 
57 /*******************************************************************************
58  * This function returns the index for given image_id, within the
59  * image descriptor array provided by bl_image_info_descs_ptr, if the
60  * image is found else it returns -1.
61  ******************************************************************************/
62 int get_bl_params_node_index(unsigned int image_id)
63 {
64 	int index;
65 	assert(image_id != INVALID_IMAGE_ID);
66 
67 	for (index = 0; index < bl_mem_params_desc_num; index++) {
68 		if (bl_mem_params_desc_ptr[index].image_id == image_id)
69 			return index;
70 	}
71 
72 	return -1;
73 }
74 
75 /*******************************************************************************
76  * This function returns the pointer to `bl_mem_params_node_t` object for
77  * given image_id, within the image descriptor array provided by
78  * bl_mem_params_desc_ptr, if the image is found else it returns NULL.
79  ******************************************************************************/
80 bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id)
81 {
82 	int index;
83 	assert(image_id != INVALID_IMAGE_ID);
84 
85 	index = get_bl_params_node_index(image_id);
86 	if (index >= 0)
87 		return &bl_mem_params_desc_ptr[index];
88 	else
89 		return NULL;
90 }
91 
92 /*******************************************************************************
93  * This function creates the list of loadable images, by populating and
94  * linking each `bl_load_info_node_t` type node, using the internal array
95  * of image descriptor provided by bl_mem_params_desc_ptr. It also populates
96  * and returns `bl_load_info_t` type structure that contains head of the list
97  * of loadable images.
98  ******************************************************************************/
99 bl_load_info_t *get_bl_load_info_from_mem_params_desc(void)
100 {
101 	int index = 0;
102 
103 	/* If there is no image to start with, return NULL */
104 	if (!bl_mem_params_desc_num)
105 		return NULL;
106 
107 	/* Assign initial data structures */
108 	bl_load_info_node_t *bl_node_info =
109 		&bl_mem_params_desc_ptr[index].load_node_mem;
110 	bl_load_info.head = bl_node_info;
111 	SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0);
112 
113 	/* Go through the image descriptor array and create the list */
114 	for (; index < bl_mem_params_desc_num; index++) {
115 
116 		/* Populate the image information */
117 		bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id;
118 		bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info;
119 
120 		/* Link next image if present */
121 		if ((index + 1) < bl_mem_params_desc_num) {
122 			/* Get the memory and link the next node */
123 			bl_node_info->next_load_info =
124 				&bl_mem_params_desc_ptr[index + 1].load_node_mem;
125 			bl_node_info = bl_node_info->next_load_info;
126 		}
127 	}
128 
129 	return &bl_load_info;
130 }
131 
132 /*******************************************************************************
133  * This function creates the list of executable images, by populating and
134  * linking each `bl_params_node_t` type node, using the internal array of
135  * image descriptor provided by bl_mem_params_desc_ptr. It also populates
136  * and returns `bl_params_t` type structure that contains head of the list
137  * of executable images.
138  ******************************************************************************/
139 bl_params_t *get_next_bl_params_from_mem_params_desc(void)
140 {
141 	int count;
142 	unsigned int img_id = 0;
143 	int link_index = 0;
144 	bl_params_node_t *bl_current_exec_node = NULL;
145 	bl_params_node_t *bl_last_exec_node = NULL;
146 	bl_mem_params_node_t *desc_ptr;
147 
148 	/* If there is no image to start with, return NULL */
149 	if (!bl_mem_params_desc_num)
150 		return NULL;
151 
152 	/* Get the list HEAD */
153 	for (count = 0; count < bl_mem_params_desc_num; count++) {
154 
155 		desc_ptr = &bl_mem_params_desc_ptr[count];
156 
157 		if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) &&
158 			(EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) {
159 			next_bl_params.head = &desc_ptr->params_node_mem;
160 			link_index = count;
161 			break;
162 		}
163 	}
164 
165 	/* Make sure we have a HEAD node */
166 	assert(next_bl_params.head != NULL);
167 
168 	/* Populate the HEAD information */
169 	SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0);
170 
171 	/*
172 	 * Go through the image descriptor array and create the list.
173 	 * This bounded loop is to make sure that we are not looping forever.
174 	 */
175 	for (count = 0 ; count < bl_mem_params_desc_num; count++) {
176 
177 		desc_ptr = &bl_mem_params_desc_ptr[link_index];
178 
179 		/* Make sure the image is executable */
180 		assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE);
181 
182 		/* Get the memory for current node */
183 		bl_current_exec_node = &desc_ptr->params_node_mem;
184 
185 		/* Populate the image information */
186 		bl_current_exec_node->image_id = desc_ptr->image_id;
187 		bl_current_exec_node->image_info = &desc_ptr->image_info;
188 		bl_current_exec_node->ep_info = &desc_ptr->ep_info;
189 
190 		if (bl_last_exec_node) {
191 			/* Assert if loop detected */
192 			assert(bl_last_exec_node->next_params_info == NULL);
193 
194 			/* Link the previous node to the current one */
195 			bl_last_exec_node->next_params_info = bl_current_exec_node;
196 		}
197 
198 		/* Update the last node */
199 		bl_last_exec_node = bl_current_exec_node;
200 
201 		/* If no next hand-off image then break out */
202 		img_id = desc_ptr->next_handoff_image_id;
203 		if (img_id == INVALID_IMAGE_ID)
204 			break;
205 
206 		/* Get the index for the next hand-off image */
207 		link_index = get_bl_params_node_index(img_id);
208 		assert((link_index > 0) &&
209 			(link_index < bl_mem_params_desc_num));
210 	}
211 
212 	/* Invalid image is expected to terminate the loop */
213 	assert(img_id == INVALID_IMAGE_ID);
214 
215 	return &next_bl_params;
216 }
217