xref: /rk3399_ARM-atf/common/bl_common.c (revision 929a290e26c3c0600eef80dad43ead370a5bd9d7)
1 /*
2  * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <errno.h>
9 #include <string.h>
10 
11 #include <arch.h>
12 #include <arch_features.h>
13 #include <arch_helpers.h>
14 #include <common/bl_common.h>
15 #include <common/build_message.h>
16 #include <common/debug.h>
17 #include <drivers/auth/auth_mod.h>
18 #include <drivers/io/io_storage.h>
19 #include <lib/utils.h>
20 #include <lib/xlat_tables/xlat_tables_defs.h>
21 #include <plat/common/platform.h>
22 
23 #if TRUSTED_BOARD_BOOT
24 # ifdef DYN_DISABLE_AUTH
25 static int disable_auth;
26 
27 /******************************************************************************
28  * API to dynamically disable authentication. Only meant for development
29  * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
30  *****************************************************************************/
31 void dyn_disable_auth(void)
32 {
33 	INFO("Disabling authentication of images dynamically\n");
34 	disable_auth = 1;
35 }
36 # endif /* DYN_DISABLE_AUTH */
37 
38 /******************************************************************************
39  * Function to determine whether the authentication is disabled dynamically.
40  *****************************************************************************/
41 static int dyn_is_auth_disabled(void)
42 {
43 # ifdef DYN_DISABLE_AUTH
44 	return disable_auth;
45 # else
46 	return 0;
47 # endif
48 }
49 #endif /* TRUSTED_BOARD_BOOT */
50 
51 uintptr_t page_align(uintptr_t value, unsigned dir)
52 {
53 	/* Round up the limit to the next page boundary */
54 	if ((value & PAGE_SIZE_MASK) != 0U) {
55 		value &= ~PAGE_SIZE_MASK;
56 		if (dir == UP) {
57 			value += PAGE_SIZE;
58 		}
59 	}
60 
61 	return value;
62 }
63 
64 /*******************************************************************************
65  * Internal function to load an image at a specific address given
66  * an image ID and extents of free memory.
67  *
68  * If the load is successful then the image information is updated.
69  *
70  * Returns 0 on success, a negative error code otherwise.
71  ******************************************************************************/
72 static int load_image(unsigned int image_id, image_info_t *image_data)
73 {
74 	uintptr_t dev_handle = 0ULL;
75 	uintptr_t image_handle = 0ULL;
76 	uintptr_t image_spec = 0ULL;
77 	uintptr_t image_base;
78 	size_t image_size = 0ULL;
79 	size_t bytes_read = 0ULL;
80 	int io_result;
81 
82 	assert(image_data != NULL);
83 	assert(image_data->h.version >= VERSION_2);
84 
85 	image_base = image_data->image_base;
86 
87 	/* Obtain a reference to the image by querying the platform layer */
88 	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
89 	if (io_result != 0) {
90 		WARN("Failed to obtain reference to image id=%u (%i)\n",
91 			image_id, io_result);
92 		return io_result;
93 	}
94 
95 	/* Attempt to access the image */
96 	io_result = io_open(dev_handle, image_spec, &image_handle);
97 	if (io_result != 0) {
98 		WARN("Failed to access image id=%u (%i)\n",
99 			image_id, io_result);
100 		return io_result;
101 	}
102 
103 	INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base);
104 
105 	/* Find the size of the image */
106 	io_result = io_size(image_handle, &image_size);
107 	if ((io_result != 0) || (image_size == 0U)) {
108 		WARN("Failed to determine the size of the image id=%u (%i)\n",
109 			image_id, io_result);
110 		goto exit_load_image;
111 	}
112 
113 	/* Check that the image size to load is within limit */
114 	if (image_size > image_data->image_max_size) {
115 		WARN("Image id=%u size out of bounds\n", image_id);
116 		io_result = -EFBIG;
117 		goto exit_load_image;
118 	}
119 
120 	/*
121 	 * image_data->image_max_size is a uint32_t so image_size will always
122 	 * fit in image_data->image_size.
123 	 */
124 	image_data->image_size = (uint32_t)image_size;
125 
126 	/* We have enough space so load the image now */
127 	/* TODO: Consider whether to try to recover/retry a partially successful read */
128 	io_result = io_read(image_handle, image_base, image_size, &bytes_read);
129 	if ((io_result != 0) || (bytes_read < image_size)) {
130 		WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
131 		goto exit_load_image;
132 	}
133 
134 	INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base,
135 	     (uintptr_t)(image_base + image_size));
136 
137 exit_load_image:
138 	(void)io_close(image_handle);
139 	/* Ignore improbable/unrecoverable error in 'close' */
140 
141 	/* TODO: Consider maintaining open device connection from this bootloader stage */
142 	(void)io_dev_close(dev_handle);
143 	/* Ignore improbable/unrecoverable error in 'dev_close' */
144 
145 	return io_result;
146 }
147 
148 #if TRUSTED_BOARD_BOOT
149 /*
150  * This function uses recursion to authenticate the parent images up to the root
151  * of trust.
152  */
153 static int load_auth_image_recursive(unsigned int image_id,
154 				    image_info_t *image_data)
155 {
156 	int rc;
157 	unsigned int parent_id;
158 
159 	/* Use recursion to authenticate parent images */
160 	rc = auth_mod_get_parent_id(image_id, &parent_id);
161 	if (rc == 0) {
162 		rc = load_auth_image_recursive(parent_id, image_data);
163 		if (rc != 0) {
164 			return rc;
165 		}
166 	}
167 
168 	/* Load the image */
169 	rc = load_image(image_id, image_data);
170 	if (rc != 0) {
171 		return rc;
172 	}
173 
174 	/* Authenticate it */
175 	rc = auth_mod_verify_img(image_id,
176 				 (void *)image_data->image_base,
177 				 image_data->image_size);
178 	if (rc != 0) {
179 		/* Authentication error, zero memory and flush it right away. */
180 		zero_normalmem((void *)image_data->image_base,
181 			       image_data->image_size);
182 		flush_dcache_range(image_data->image_base,
183 				   image_data->image_size);
184 		return -EAUTH;
185 	}
186 
187 	return 0;
188 }
189 #endif /* TRUSTED_BOARD_BOOT */
190 
191 static int load_auth_image_internal(unsigned int image_id,
192 				    image_info_t *image_data)
193 {
194 #if TRUSTED_BOARD_BOOT
195 	if (dyn_is_auth_disabled() == 0) {
196 		return load_auth_image_recursive(image_id, image_data);
197 	}
198 #endif
199 
200 	return load_image(image_id, image_data);
201 }
202 
203 /*******************************************************************************
204  * Generic function to load and authenticate an image. The image is actually
205  * loaded by calling the 'load_image()' function. Therefore, it returns the
206  * same error codes if the loading operation failed, or -EAUTH if the
207  * authentication failed. In addition, this function uses recursion to
208  * authenticate the parent images up to the root of trust (if TBB is enabled).
209  ******************************************************************************/
210 int load_auth_image(unsigned int image_id, image_info_t *image_data)
211 {
212 	int err;
213 
214 	if ((plat_try_img_ops == NULL) || (plat_try_img_ops->next_instance == NULL)) {
215 		err = load_auth_image_internal(image_id, image_data);
216 	} else {
217 		do {
218 			err = load_auth_image_internal(image_id, image_data);
219 			if (err != 0) {
220 				if (plat_try_img_ops->next_instance(image_id) != 0) {
221 					return err;
222 				}
223 			}
224 		} while (err != 0);
225 	}
226 
227 	if (err == 0) {
228 		/*
229 		 * If loading of the image gets passed (along with its
230 		 * authentication in case of Trusted-Boot flow) then measure
231 		 * it (if MEASURED_BOOT flag is enabled).
232 		 */
233 		err = plat_mboot_measure_image(image_id, image_data);
234 		if (err != 0) {
235 			return err;
236 		}
237 
238 		/*
239 		 * Flush the image to main memory so that it can be executed
240 		 * later by any CPU, regardless of cache and MMU state.
241 		 */
242 		flush_dcache_range(image_data->image_base,
243 				   image_data->image_size);
244 	}
245 
246 	return err;
247 }
248 
249 /*******************************************************************************
250  * Print the content of an entry_point_info_t structure.
251  ******************************************************************************/
252 void print_entry_point_info(const entry_point_info_t *ep_info)
253 {
254 	INFO("Entry point address = 0x%lx\n", ep_info->pc);
255 	INFO("SPSR = 0x%x\n", ep_info->spsr);
256 
257 #define PRINT_IMAGE_ARG(n)					\
258 	VERBOSE("Argument #" #n " = 0x%llx\n",			\
259 		(unsigned long long) ep_info->args.arg##n)
260 
261 	PRINT_IMAGE_ARG(0);
262 	PRINT_IMAGE_ARG(1);
263 	PRINT_IMAGE_ARG(2);
264 	PRINT_IMAGE_ARG(3);
265 #ifdef __aarch64__
266 	PRINT_IMAGE_ARG(4);
267 	PRINT_IMAGE_ARG(5);
268 	PRINT_IMAGE_ARG(6);
269 	PRINT_IMAGE_ARG(7);
270 #endif
271 #undef PRINT_IMAGE_ARG
272 }
273 
274 /*
275  * This function is for returning the TF-A version
276  */
277 const char *get_version(void)
278 {
279 	return build_version;
280 }
281