bl_common.c 7.0 KB

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