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