summaryrefslogtreecommitdiff
path: root/common/bl_common.c
diff options
context:
space:
mode:
authorYatharth Kochar <yatharth.kochar@arm.com>2016-09-12 16:08:41 +0100
committerYatharth Kochar <yatharth.kochar@arm.com>2016-09-20 16:16:42 +0100
commit7260022636e3b0d3ef641cbda135d98f9a7df177 (patch)
tree6b6e59c23ca8242a4798230a34e8b7286ff91054 /common/bl_common.c
parent131f7cd4016732a572c4341fc4e13dbf3ceae82a (diff)
downloadarm-trusted-firmware-7260022636e3b0d3ef641cbda135d98f9a7df177.tar.gz
Add new version of image loading.
This patch adds capability to load BL images based on image descriptors instead of hard coded way of loading BL images. This framework is designed such that it can be readily adapted by any BL stage that needs to load images. In order to provide the above capability the following new platform functions are introduced: bl_load_info_t *plat_get_bl_image_load_info(void); This function returns pointer to the list of images that the platform has populated to load. bl_params_t *plat_get_next_bl_params(void); This function returns a pointer to the shared memory that the platform has kept aside to pass trusted firmware related information that next BL image needs. void plat_flush_next_bl_params(void); This function flushes to main memory all the params that are passed to next image. int bl2_plat_handle_post_image_load(unsigned int image_id) This function can be used by the platforms to update/use image information for given `image_id`. `desc_image_load.c` contains utility functions which can be used by the platforms to generate, load and executable, image list based on the registered image descriptors. This patch also adds new version of `load_image/load_auth_image` functions in-order to achieve the above capability. Following are the changes for the new version as compared to old: - Refactor the signature and only keep image_id and image_info_t arguments. Removed image_base argument as it is already passed through image_info_t. Given that the BL image base addresses and limit/size are already provided by the platforms, the meminfo_t and entry_point_info arguments are not needed to provide/reserve the extent of free memory for the given BL image. - Added check for the image size against the defined max size. This is needed because the image size could come from an unauthenticated source (e.g. the FIP header). To make this check, new member is added to the image_info_t struct for identifying the image maximum size. New flag `LOAD_IMAGE_V2` is added in the Makefile. Default value is 0. NOTE: `TRUSTED_BOARD_BOOT` is currently not supported when `LOAD_IMAGE_V2` is enabled. Change-Id: Ia7b643f4817a170d5a2fbf479b9bc12e63112e79
Diffstat (limited to 'common/bl_common.c')
-rw-r--r--common/bl_common.c166
1 files changed, 159 insertions, 7 deletions
diff --git a/common/bl_common.c b/common/bl_common.c
index bae02d4bf..193e972c3 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -53,10 +53,7 @@ uintptr_t page_align(uintptr_t value, unsigned dir)
return value;
}
-static inline unsigned int is_page_aligned (uintptr_t addr) {
- return (addr & (PAGE_SIZE - 1)) == 0;
-}
-
+#if !LOAD_IMAGE_V2
/******************************************************************************
* Determine whether the memory region delimited by 'addr' and 'size' is free,
* given the extents of free memory.
@@ -179,6 +176,7 @@ static void dump_load_info(uintptr_t image_load_addr,
INFO(" free region = [base = %p, size = 0x%zx]\n",
(void *) mem_layout->free_base, mem_layout->free_size);
}
+#endif /* LOAD_IMAGE_V2 */
/* Generic function to return the size of an image */
size_t image_size(unsigned int image_id)
@@ -223,6 +221,156 @@ size_t image_size(unsigned int image_id)
return image_size;
}
+#if LOAD_IMAGE_V2
+
+/*******************************************************************************
+ * Generic function to load an image at a specific address given
+ * an image ID and extents of free memory.
+ *
+ * If the load is successful then the image information is updated.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ ******************************************************************************/
+int load_image(unsigned int image_id, image_info_t *image_data)
+{
+ uintptr_t dev_handle;
+ uintptr_t image_handle;
+ uintptr_t image_spec;
+ uintptr_t image_base;
+ size_t image_size;
+ size_t bytes_read;
+ int io_result;
+
+ assert(image_data != NULL);
+ assert(image_data->h.version >= VERSION_2);
+
+ image_base = image_data->image_base;
+
+ /* Obtain a reference to the image by querying the platform layer */
+ io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
+ if (io_result != 0) {
+ WARN("Failed to obtain reference to image id=%u (%i)\n",
+ image_id, io_result);
+ return io_result;
+ }
+
+ /* Attempt to access the image */
+ io_result = io_open(dev_handle, image_spec, &image_handle);
+ if (io_result != 0) {
+ WARN("Failed to access image id=%u (%i)\n",
+ image_id, io_result);
+ return io_result;
+ }
+
+ INFO("Loading image id=%u at address %p\n", image_id,
+ (void *) image_base);
+
+ /* Find the size of the image */
+ io_result = io_size(image_handle, &image_size);
+ if ((io_result != 0) || (image_size == 0)) {
+ WARN("Failed to determine the size of the image id=%u (%i)\n",
+ image_id, io_result);
+ goto exit;
+ }
+
+ /* Check that the image size to load is within limit */
+ if (image_size > image_data->image_max_size) {
+ WARN("Image id=%u size out of bounds\n", image_id);
+ io_result = -EFBIG;
+ goto exit;
+ }
+
+ image_data->image_size = image_size;
+
+ /* We have enough space so load the image now */
+ /* TODO: Consider whether to try to recover/retry a partially successful read */
+ io_result = io_read(image_handle, image_base, image_size, &bytes_read);
+ if ((io_result != 0) || (bytes_read < image_size)) {
+ WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
+ goto exit;
+ }
+
+#if !TRUSTED_BOARD_BOOT
+ /*
+ * File has been successfully loaded.
+ * Flush the image to main memory so that it can be executed later by
+ * any CPU, regardless of cache and MMU state.
+ * When TBB is enabled the image is flushed later, after image
+ * authentication.
+ */
+ flush_dcache_range(image_base, image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
+ INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base,
+ (void *) (image_base + image_size));
+
+exit:
+ io_close(image_handle);
+ /* Ignore improbable/unrecoverable error in 'close' */
+
+ /* TODO: Consider maintaining open device connection from this bootloader stage */
+ io_dev_close(dev_handle);
+ /* Ignore improbable/unrecoverable error in 'dev_close' */
+
+ return io_result;
+}
+
+/*******************************************************************************
+ * Generic function to load and authenticate an image. The image is actually
+ * loaded by calling the 'load_image()' function. Therefore, it returns the
+ * same error codes if the loading operation failed, or -EAUTH if the
+ * authentication failed. In addition, this function uses recursion to
+ * authenticate the parent images up to the root of trust.
+ ******************************************************************************/
+int load_auth_image(unsigned int image_id, image_info_t *image_data)
+{
+ int rc;
+
+#if TRUSTED_BOARD_BOOT
+ unsigned int parent_id;
+
+ /* Use recursion to authenticate parent images */
+ rc = auth_mod_get_parent_id(image_id, &parent_id);
+ if (rc == 0) {
+ rc = load_auth_image(parent_id, image_data);
+ if (rc != 0) {
+ return rc;
+ }
+ }
+#endif /* TRUSTED_BOARD_BOOT */
+
+ /* Load the image */
+ rc = load_image(image_id, image_data);
+ if (rc != 0) {
+ return rc;
+ }
+
+#if TRUSTED_BOARD_BOOT
+ /* Authenticate it */
+ rc = auth_mod_verify_img(image_id,
+ (void *)image_data->image_base,
+ image_data->image_size);
+ if (rc != 0) {
+ memset((void *)image_data->image_base, 0x00,
+ image_data->image_size);
+ flush_dcache_range(image_data->image_base,
+ image_data->image_size);
+ return -EAUTH;
+ }
+
+ /*
+ * File has been successfully loaded and authenticated.
+ * Flush the image to main memory so that it can be executed later by
+ * any CPU, regardless of cache and MMU state.
+ */
+ flush_dcache_range(image_data->image_base, image_data->image_size);
+#endif /* TRUSTED_BOARD_BOOT */
+
+ return 0;
+}
+
+#else /* LOAD_IMAGE_V2 */
+
/*******************************************************************************
* Generic function to load an image at a specific address given an image ID and
* extents of free memory.
@@ -255,7 +403,7 @@ int load_image(meminfo_t *mem_layout,
assert(mem_layout != NULL);
assert(image_data != NULL);
- assert(image_data->h.version >= VERSION_1);
+ assert(image_data->h.version == VERSION_1);
/* Obtain a reference to the image by querying the platform layer */
io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
@@ -348,8 +496,10 @@ exit:
/*******************************************************************************
* Generic function to load and authenticate an image. The image is actually
- * loaded by calling the 'load_image()' function. In addition, this function
- * uses recursion to authenticate the parent images up to the root of trust.
+ * loaded by calling the 'load_image()' function. Therefore, it returns the
+ * same error codes if the loading operation failed, or -EAUTH if the
+ * authentication failed. In addition, this function uses recursion to
+ * authenticate the parent images up to the root of trust.
******************************************************************************/
int load_auth_image(meminfo_t *mem_layout,
unsigned int image_id,
@@ -403,6 +553,8 @@ int load_auth_image(meminfo_t *mem_layout,
return 0;
}
+#endif /* LOAD_IMAGE_V2 */
+
/*******************************************************************************
* Print the content of an entry_point_info_t structure.
******************************************************************************/