blob: d01ef9244c410b6024fcb7323a6e04f9d356b0d1 [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Chris Kay758ccb82024-03-08 16:08:31 +00002 * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
dp-arm82cb2c12017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Achin Gupta4f6ad662013-10-25 09:08:21 +01005 */
6
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +00007#include <assert.h>
8#include <errno.h>
9#include <string.h>
10
Dan Handley97043ac2014-04-09 13:14:54 +010011#include <arch.h>
Antonio Nino Diazb86048c2019-02-19 11:53:51 +000012#include <arch_features.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010013#include <arch_helpers.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000014#include <common/bl_common.h>
Chris Kay758ccb82024-03-08 16:08:31 +000015#include <common/build_message.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000016#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>
Achin Gupta4f6ad662013-10-25 09:08:21 +010022
Soby Mathew209a60c2018-03-26 12:43:37 +010023#if TRUSTED_BOARD_BOOT
24# ifdef DYN_DISABLE_AUTH
25static int disable_auth;
26
27/******************************************************************************
28 * API to dynamically disable authentication. Only meant for development
Roberto Vargased51b512018-09-24 17:20:48 +010029 * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
Soby Mathew209a60c2018-03-26 12:43:37 +010030 *****************************************************************************/
31void 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 *****************************************************************************/
41static 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
Soby Mathew4c0d0392016-06-16 14:52:04 +010051uintptr_t page_align(uintptr_t value, unsigned dir)
Achin Gupta4f6ad662013-10-25 09:08:21 +010052{
Achin Gupta4f6ad662013-10-25 09:08:21 +010053 /* Round up the limit to the next page boundary */
Jimmy Brissond7b5f402020-08-04 16:18:52 -050054 if ((value & PAGE_SIZE_MASK) != 0U) {
55 value &= ~PAGE_SIZE_MASK;
Achin Gupta4f6ad662013-10-25 09:08:21 +010056 if (dir == UP)
Soby Mathew4c0d0392016-06-16 14:52:04 +010057 value += PAGE_SIZE;
Achin Gupta4f6ad662013-10-25 09:08:21 +010058 }
59
60 return value;
61}
62
Yatharth Kochar72600222016-09-12 16:08:41 +010063/*******************************************************************************
Soby Mathew76163b32017-11-10 13:14:40 +000064 * Internal function to load an image at a specific address given
Yatharth Kochar72600222016-09-12 16:08:41 +010065 * an image ID and extents of free memory.
66 *
67 * If the load is successful then the image information is updated.
68 *
69 * Returns 0 on success, a negative error code otherwise.
70 ******************************************************************************/
Soby Mathew76163b32017-11-10 13:14:40 +000071static int load_image(unsigned int image_id, image_info_t *image_data)
Yatharth Kochar72600222016-09-12 16:08:41 +010072{
73 uintptr_t dev_handle;
74 uintptr_t image_handle;
75 uintptr_t image_spec;
76 uintptr_t image_base;
77 size_t image_size;
78 size_t bytes_read;
79 int io_result;
80
81 assert(image_data != NULL);
82 assert(image_data->h.version >= VERSION_2);
83
84 image_base = image_data->image_base;
85
86 /* Obtain a reference to the image by querying the platform layer */
87 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
88 if (io_result != 0) {
89 WARN("Failed to obtain reference to image id=%u (%i)\n",
90 image_id, io_result);
91 return io_result;
92 }
93
94 /* Attempt to access the image */
95 io_result = io_open(dev_handle, image_spec, &image_handle);
96 if (io_result != 0) {
97 WARN("Failed to access image id=%u (%i)\n",
98 image_id, io_result);
99 return io_result;
100 }
101
Antonio Nino Diaz81542c02018-10-04 09:55:23 +0100102 INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base);
Yatharth Kochar72600222016-09-12 16:08:41 +0100103
104 /* Find the size of the image */
105 io_result = io_size(image_handle, &image_size);
Antonio Nino Diaz81542c02018-10-04 09:55:23 +0100106 if ((io_result != 0) || (image_size == 0U)) {
Yatharth Kochar72600222016-09-12 16:08:41 +0100107 WARN("Failed to determine the size of the image id=%u (%i)\n",
108 image_id, io_result);
109 goto exit;
110 }
111
112 /* Check that the image size to load is within limit */
113 if (image_size > image_data->image_max_size) {
114 WARN("Image id=%u size out of bounds\n", image_id);
115 io_result = -EFBIG;
116 goto exit;
117 }
118
Antonio Nino Diaz81542c02018-10-04 09:55:23 +0100119 /*
120 * image_data->image_max_size is a uint32_t so image_size will always
121 * fit in image_data->image_size.
122 */
123 image_data->image_size = (uint32_t)image_size;
Yatharth Kochar72600222016-09-12 16:08:41 +0100124
125 /* We have enough space so load the image now */
126 /* TODO: Consider whether to try to recover/retry a partially successful read */
127 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
128 if ((io_result != 0) || (bytes_read < image_size)) {
129 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
130 goto exit;
131 }
132
Antonio Nino Diaz81542c02018-10-04 09:55:23 +0100133 INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base,
134 (uintptr_t)(image_base + image_size));
Yatharth Kochar72600222016-09-12 16:08:41 +0100135
136exit:
Antonio Nino Diaz81542c02018-10-04 09:55:23 +0100137 (void)io_close(image_handle);
Yatharth Kochar72600222016-09-12 16:08:41 +0100138 /* Ignore improbable/unrecoverable error in 'close' */
139
140 /* TODO: Consider maintaining open device connection from this bootloader stage */
Antonio Nino Diaz81542c02018-10-04 09:55:23 +0100141 (void)io_dev_close(dev_handle);
Yatharth Kochar72600222016-09-12 16:08:41 +0100142 /* Ignore improbable/unrecoverable error in 'dev_close' */
143
144 return io_result;
145}
146
Sandrine Bailleux9e7d6632019-10-14 13:47:21 +0200147#if TRUSTED_BOARD_BOOT
148/*
149 * This function uses recursion to authenticate the parent images up to the root
150 * of trust.
151 */
152static int load_auth_image_recursive(unsigned int image_id,
Antonio Nino Diaz0f325c62016-11-22 10:58:30 +0000153 image_info_t *image_data,
154 int is_parent_image)
Yatharth Kochar72600222016-09-12 16:08:41 +0100155{
156 int rc;
Sandrine Bailleux9e7d6632019-10-14 13:47:21 +0200157 unsigned int parent_id;
Yatharth Kochar72600222016-09-12 16:08:41 +0100158
Sandrine Bailleux9e7d6632019-10-14 13:47:21 +0200159 /* 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, 1);
163 if (rc != 0) {
164 return rc;
Yatharth Kochar72600222016-09-12 16:08:41 +0100165 }
166 }
Yatharth Kochar72600222016-09-12 16:08:41 +0100167
168 /* Load the image */
169 rc = load_image(image_id, image_data);
170 if (rc != 0) {
171 return rc;
172 }
173
Sandrine Bailleux9e7d6632019-10-14 13:47:21 +0200174 /* 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,
Soby Mathew209a60c2018-03-26 12:43:37 +0100181 image_data->image_size);
Sandrine Bailleux9e7d6632019-10-14 13:47:21 +0200182 flush_dcache_range(image_data->image_base,
183 image_data->image_size);
184 return -EAUTH;
Yatharth Kochar72600222016-09-12 16:08:41 +0100185 }
186
Yatharth Kochar72600222016-09-12 16:08:41 +0100187 return 0;
188}
Sandrine Bailleux9e7d6632019-10-14 13:47:21 +0200189#endif /* TRUSTED_BOARD_BOOT */
190
191static 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, 0);
197 }
198#endif
199
Manish V Badarkhe0aa0b3a2021-12-16 10:41:47 +0000200 return load_image(image_id, image_data);
Sandrine Bailleux9e7d6632019-10-14 13:47:21 +0200201}
Yatharth Kochar72600222016-09-12 16:08:41 +0100202
Antonio Nino Diaz0f325c62016-11-22 10:58:30 +0000203/*******************************************************************************
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
Sandrine Bailleux9e7d6632019-10-14 13:47:21 +0200208 * authenticate the parent images up to the root of trust (if TBB is enabled).
Antonio Nino Diaz0f325c62016-11-22 10:58:30 +0000209 ******************************************************************************/
210int load_auth_image(unsigned int image_id, image_info_t *image_data)
211{
Roberto Vargas01f62b62017-09-26 12:53:01 +0100212 int err;
213
Manish V Badarkhe4b48f7b2021-07-01 21:32:31 +0100214 err = load_auth_image_internal(image_id, image_data);
Roberto Vargas01f62b62017-09-26 12:53:01 +0100215
Manish V Badarkhe0aa0b3a2021-12-16 10:41:47 +0000216 if (err == 0) {
217 /*
218 * If loading of the image gets passed (along with its
219 * authentication in case of Trusted-Boot flow) then measure
220 * it (if MEASURED_BOOT flag is enabled).
221 */
222 err = plat_mboot_measure_image(image_id, image_data);
223 if (err != 0) {
224 return err;
225 }
226
227 /*
228 * Flush the image to main memory so that it can be executed
229 * later by any CPU, regardless of cache and MMU state.
230 */
231 flush_dcache_range(image_data->image_base,
232 image_data->image_size);
233 }
234
Roberto Vargas01f62b62017-09-26 12:53:01 +0100235 return err;
Antonio Nino Diaz0f325c62016-11-22 10:58:30 +0000236}
237
Sandrine Bailleux68a68c92015-09-28 17:03:06 +0100238/*******************************************************************************
239 * Print the content of an entry_point_info_t structure.
240 ******************************************************************************/
241void print_entry_point_info(const entry_point_info_t *ep_info)
242{
Antonio Nino Diaz81542c02018-10-04 09:55:23 +0100243 INFO("Entry point address = 0x%lx\n", ep_info->pc);
Soby Mathew4c0d0392016-06-16 14:52:04 +0100244 INFO("SPSR = 0x%x\n", ep_info->spsr);
Sandrine Bailleux68a68c92015-09-28 17:03:06 +0100245
246#define PRINT_IMAGE_ARG(n) \
247 VERBOSE("Argument #" #n " = 0x%llx\n", \
248 (unsigned long long) ep_info->args.arg##n)
249
250 PRINT_IMAGE_ARG(0);
251 PRINT_IMAGE_ARG(1);
252 PRINT_IMAGE_ARG(2);
253 PRINT_IMAGE_ARG(3);
Julius Werner402b3cf2019-07-09 14:02:43 -0700254#ifdef __aarch64__
Sandrine Bailleux68a68c92015-09-28 17:03:06 +0100255 PRINT_IMAGE_ARG(4);
256 PRINT_IMAGE_ARG(5);
257 PRINT_IMAGE_ARG(6);
258 PRINT_IMAGE_ARG(7);
Soby Mathew51c79b72016-08-30 13:07:31 +0100259#endif
Sandrine Bailleux68a68c92015-09-28 17:03:06 +0100260#undef PRINT_IMAGE_ARG
261}
laurenw-armdddf4282022-07-12 10:12:05 -0500262
263/*
264 * This function is for returning the TF-A version
265 */
266const char *get_version(void)
267{
Chris Kay758ccb82024-03-08 16:08:31 +0000268 return build_version;
laurenw-armdddf4282022-07-12 10:12:05 -0500269}