bl_common.c 7.7 KB

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