From 7260022636e3b0d3ef641cbda135d98f9a7df177 Mon Sep 17 00:00:00 2001 From: Yatharth Kochar Date: Mon, 12 Sep 2016 16:08:41 +0100 Subject: [PATCH] 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 --- Makefile | 12 +- common/bl_common.c | 166 ++++++++++++++++++++++- common/desc_image_load.c | 220 +++++++++++++++++++++++++++++++ docs/porting-guide.md | 44 ++++++- docs/user-guide.md | 6 + include/common/bl_common.h | 70 +++++++++- include/common/desc_image_load.h | 63 +++++++++ include/plat/common/platform.h | 43 ++++++ 8 files changed, 609 insertions(+), 15 deletions(-) create mode 100644 common/desc_image_load.c create mode 100644 include/common/desc_image_load.h diff --git a/Makefile b/Makefile index 49d7cc4b3..376db8d2f 100644 --- a/Makefile +++ b/Makefile @@ -115,7 +115,8 @@ ENABLE_PSCI_STAT := 0 # Whether code and read-only data should be put on separate memory pages. # The platform Makefile is free to override this value. SEPARATE_CODE_AND_RODATA := 0 - +# Flag to enable new version of image loading +LOAD_IMAGE_V2 := 0 ################################################################################ # Checkpatch script options @@ -355,6 +356,13 @@ ifeq (${NEED_BL33},yes) endif endif +# TRUSTED_BOARD_BOOT is currently not supported when LOAD_IMAGE_V2 is enabled. +ifeq (${LOAD_IMAGE_V2},1) + ifeq (${TRUSTED_BOARD_BOOT},1) + $(error "TRUSTED_BOARD_BOOT is currently not supported \ + for LOAD_IMAGE_V2=1") + endif +endif ################################################################################ # Process platform overrideable behaviour @@ -445,6 +453,7 @@ $(eval $(call assert_boolean,PL011_GENERIC_UART)) $(eval $(call assert_boolean,ENABLE_PMF)) $(eval $(call assert_boolean,ENABLE_PSCI_STAT)) $(eval $(call assert_boolean,SEPARATE_CODE_AND_RODATA)) +$(eval $(call assert_boolean,LOAD_IMAGE_V2)) ################################################################################ @@ -475,6 +484,7 @@ $(eval $(call add_define,PL011_GENERIC_UART)) $(eval $(call add_define,ENABLE_PMF)) $(eval $(call add_define,ENABLE_PSCI_STAT)) $(eval $(call add_define,SEPARATE_CODE_AND_RODATA)) +$(eval $(call add_define,LOAD_IMAGE_V2)) # Define the EL3_PAYLOAD_BASE flag only if it is provided. ifdef EL3_PAYLOAD_BASE $(eval $(call add_define,EL3_PAYLOAD_BASE)) 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. ******************************************************************************/ diff --git a/common/desc_image_load.c b/common/desc_image_load.c new file mode 100644 index 000000000..a9762b717 --- /dev/null +++ b/common/desc_image_load.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + + +extern bl_mem_params_node_t *bl_mem_params_desc_ptr; +extern unsigned int bl_mem_params_desc_num; + +static bl_load_info_t bl_load_info; +static bl_params_t next_bl_params; + + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void flush_bl_params_desc(void) +{ + flush_dcache_range((unsigned long)bl_mem_params_desc_ptr, + sizeof(*bl_mem_params_desc_ptr) * bl_mem_params_desc_num); +} + +/******************************************************************************* + * This function returns the index for given image_id, within the + * image descriptor array provided by bl_image_info_descs_ptr, if the + * image is found else it returns -1. + ******************************************************************************/ +int get_bl_params_node_index(unsigned int image_id) +{ + int index; + assert(image_id != INVALID_IMAGE_ID); + + for (index = 0; index < bl_mem_params_desc_num; index++) { + if (bl_mem_params_desc_ptr[index].image_id == image_id) + return index; + } + + return -1; +} + +/******************************************************************************* + * This function returns the pointer to `bl_mem_params_node_t` object for + * given image_id, within the image descriptor array provided by + * bl_mem_params_desc_ptr, if the image is found else it returns NULL. + ******************************************************************************/ +bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) +{ + int index; + assert(image_id != INVALID_IMAGE_ID); + + index = get_bl_params_node_index(image_id); + if (index >= 0) + return &bl_mem_params_desc_ptr[index]; + else + return NULL; +} + +/******************************************************************************* + * This function creates the list of loadable images, by populating and + * linking each `bl_load_info_node_t` type node, using the internal array + * of image descriptor provided by bl_mem_params_desc_ptr. It also populates + * and returns `bl_load_info_t` type structure that contains head of the list + * of loadable images. + ******************************************************************************/ +bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) +{ + int index = 0; + + /* If there is no image to start with, return NULL */ + if (!bl_mem_params_desc_num) + return NULL; + + /* Assign initial data structures */ + bl_load_info_node_t *bl_node_info = + &bl_mem_params_desc_ptr[index].load_node_mem; + bl_load_info.head = bl_node_info; + SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0); + + /* Go through the image descriptor array and create the list */ + for (; index < bl_mem_params_desc_num; index++) { + + /* Populate the image information */ + bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; + bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; + + /* Link next image if present */ + if ((index + 1) < bl_mem_params_desc_num) { + /* Get the memory and link the next node */ + bl_node_info->next_load_info = + &bl_mem_params_desc_ptr[index + 1].load_node_mem; + bl_node_info = bl_node_info->next_load_info; + } + } + + return &bl_load_info; +} + +/******************************************************************************* + * This function creates the list of executable images, by populating and + * linking each `bl_params_node_t` type node, using the internal array of + * image descriptor provided by bl_mem_params_desc_ptr. It also populates + * and returns `bl_params_t` type structure that contains head of the list + * of executable images. + ******************************************************************************/ +bl_params_t *get_next_bl_params_from_mem_params_desc(void) +{ + int count; + unsigned int img_id = 0; + int link_index = 0; + bl_params_node_t *bl_current_exec_node = NULL; + bl_params_node_t *bl_last_exec_node = NULL; + bl_mem_params_node_t *desc_ptr; + + /* If there is no image to start with, return NULL */ + if (!bl_mem_params_desc_num) + return NULL; + + /* Get the list HEAD */ + for (count = 0; count < bl_mem_params_desc_num; count++) { + + desc_ptr = &bl_mem_params_desc_ptr[count]; + + if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && + (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { + next_bl_params.head = &desc_ptr->params_node_mem; + link_index = count; + break; + } + } + + /* Make sure we have a HEAD node */ + assert(next_bl_params.head != NULL); + + /* Populate the HEAD information */ + SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0); + + /* + * Go through the image descriptor array and create the list. + * This bounded loop is to make sure that we are not looping forever. + */ + for (count = 0 ; count < bl_mem_params_desc_num; count++) { + + desc_ptr = &bl_mem_params_desc_ptr[link_index]; + + /* Make sure the image is executable */ + assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); + + /* Get the memory for current node */ + bl_current_exec_node = &desc_ptr->params_node_mem; + + /* Populate the image information */ + bl_current_exec_node->image_id = desc_ptr->image_id; + bl_current_exec_node->image_info = &desc_ptr->image_info; + bl_current_exec_node->ep_info = &desc_ptr->ep_info; + + if (bl_last_exec_node) { + /* Assert if loop detected */ + assert(bl_last_exec_node->next_params_info == NULL); + + /* Link the previous node to the current one */ + bl_last_exec_node->next_params_info = bl_current_exec_node; + } + + /* Update the last node */ + bl_last_exec_node = bl_current_exec_node; + + /* If no next hand-off image then break out */ + img_id = desc_ptr->next_handoff_image_id; + if (img_id == INVALID_IMAGE_ID) + break; + + /* Get the index for the next hand-off image */ + link_index = get_bl_params_node_index(img_id); + assert((link_index > 0) && + (link_index < bl_mem_params_desc_num)); + } + + /* Invalid image is expected to terminate the loop */ + assert(img_id == INVALID_IMAGE_ID); + + /* Populate arg0 for the next BL image */ + next_bl_params.head->ep_info->args.arg0 = (unsigned long)&next_bl_params; + + /* Flush the parameters to be passed to the next BL image */ + flush_dcache_range((unsigned long)&next_bl_params, + sizeof(next_bl_params)); + + return &next_bl_params; +} diff --git a/docs/porting-guide.md b/docs/porting-guide.md index 195c9374d..f42ff6498 100644 --- a/docs/porting-guide.md +++ b/docs/porting-guide.md @@ -721,7 +721,6 @@ Firmware represents the power domain topology and how this relates to the linear CPU index, please refer [Power Domain Topology Design]. - 2.4 Common optional modifications --------------------------------- @@ -841,10 +840,37 @@ and must be implemented in assembly because it may be called before the C environment is initialized. Note: The address from where it was called is stored in x30 (Link Register). - The default implementation simply spins. +### Function : plat_get_bl_image_load_info() + + Argument : void + Return : bl_load_info_t * + +This function returns pointer to the list of images that the platform has +populated to load. This function is currently invoked in BL2 to load the +BL3xx images, when LOAD_IMAGE_V2 is enabled. + +### Function : plat_get_next_bl_params() + + Argument : void + Return : bl_params_t * + +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. This function is currently invoked in BL2 to pass this information to +the next BL image, when LOAD_IMAGE_V2 is enabled. + +### Function : plat_flush_next_bl_params() + + Argument : void + Return : void + +This function flushes to main memory all the image params that are passed to +next image. This function is currently invoked in BL2 to flush this information +to the next BL image, when LOAD_IMAGE_V2 is enabled. + 3. Modifications specific to a Boot Loader stage ------------------------------------------------- @@ -1175,6 +1201,20 @@ populated with the extents of secure RAM available for BL2 to use. See `bl2_early_platform_setup()` above. +Following function is required only when LOAD_IMAGE_V2 is enabled. + +### Function : bl2_plat_handle_post_image_load() [mandatory] + + Argument : unsigned int + Return : int + +This function can be used by the platforms to update/use image information +for given `image_id`. This function is currently invoked in BL2 to handle +BL image specific information based on the `image_id` passed, when +LOAD_IMAGE_V2 is enabled. + +Following functions are required only when LOAD_IMAGE_V2 is disabled. + ### Function : bl2_plat_get_scp_bl2_meminfo() [mandatory] Argument : meminfo * diff --git a/docs/user-guide.md b/docs/user-guide.md index d545262c3..d7d743acc 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -430,6 +430,12 @@ performed. pages" section in [Firmware Design]. This flag is disabled by default and affects all BL images. +* `LOAD_IMAGE_V2`: Boolean option to enable support for new version (v2) of + image loading, which provides more flexibility and scalability around what + images are loaded and executed during boot. Default is 0. + Note: `TRUSTED_BOARD_BOOT` is currently not supported when `LOAD_IMAGE_V2` + is enabled. + #### ARM development platform specific build options * `ARM_TSP_RAM_LOCATION`: location of the TSP binary. Options: diff --git a/include/common/bl_common.h b/include/common/bl_common.h index 942843cf1..9fa2a810e 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -93,11 +93,22 @@ #define EP_GET_EXE(x) (x & EP_EXE_MASK) #define EP_SET_EXE(x, ee) ((x) = ((x) & ~EP_EXE_MASK) | (ee)) +#define EP_FIRST_EXE_MASK 0x10 +#define EP_FIRST_EXE 0x10 +#define EP_GET_FIRST_EXE(x) ((x) & EP_FIRST_EXE_MASK) +#define EP_SET_FIRST_EXE(x, ee) ((x) = ((x) & ~EP_FIRST_EXE_MASK) | (ee)) + #define PARAM_EP 0x01 #define PARAM_IMAGE_BINARY 0x02 #define PARAM_BL31 0x03 +#define PARAM_BL_LOAD_INFO 0x04 +#define PARAM_BL_PARAMS 0x05 + +#define IMAGE_ATTRIB_SKIP_LOADING 0x02 +#define IMAGE_ATTRIB_PLAT_SETUP 0x04 #define VERSION_1 0x01 +#define VERSION_2 0x02 #define INVALID_IMAGE_ID (0xFFFFFFFF) @@ -181,8 +192,10 @@ extern uintptr_t __COHERENT_RAM_END__; typedef struct meminfo { uintptr_t total_base; size_t total_size; +#if !LOAD_IMAGE_V2 uintptr_t free_base; size_t free_size; +#endif } meminfo_t; typedef struct aapcs64_params { @@ -245,6 +258,9 @@ typedef struct image_info { param_header_t h; uintptr_t image_base; /* physical address of base of image */ uint32_t image_size; /* bytes read from image file */ +#if LOAD_IMAGE_V2 + uint32_t image_max_size; +#endif } image_info_t; /***************************************************************************** @@ -263,6 +279,39 @@ typedef struct image_desc { entry_point_info_t ep_info; } image_desc_t; +#if LOAD_IMAGE_V2 +/* BL image node in the BL image loading sequence */ +typedef struct bl_load_info_node { + unsigned int image_id; + image_info_t *image_info; + struct bl_load_info_node *next_load_info; +} bl_load_info_node_t; + +/* BL image head node in the BL image loading sequence */ +typedef struct bl_load_info { + param_header_t h; + bl_load_info_node_t *head; +} bl_load_info_t; + +/* BL image node in the BL image execution sequence */ +typedef struct bl_params_node { + unsigned int image_id; + image_info_t *image_info; + entry_point_info_t *ep_info; + struct bl_params_node *next_params_info; +} bl_params_node_t; + +/* + * BL image head node in the BL image execution sequence + * It is also used to pass information to next BL image. + */ +typedef struct bl_params { + param_header_t h; + bl_params_node_t *head; +} bl_params_t; + +#else /* LOAD_IMAGE_V2 */ + /******************************************************************************* * This structure represents the superset of information that can be passed to * BL31 e.g. while passing control to it from BL2. The BL32 parameters will be @@ -286,6 +335,7 @@ typedef struct bl31_params { image_info_t *bl33_image_info; } bl31_params_t; +#endif /* LOAD_IMAGE_V2 */ /* * Compile time assertions related to the 'entry_point_info' structure to @@ -308,24 +358,34 @@ CASSERT(sizeof(uintptr_t) == /******************************************************************************* * Function & variable prototypes ******************************************************************************/ -uintptr_t page_align(uintptr_t, unsigned); size_t image_size(unsigned int image_id); + +#if LOAD_IMAGE_V2 + +int load_image(unsigned int image_id, image_info_t *image_data); +int load_auth_image(unsigned int image_id, image_info_t *image_data); + +#else + +uintptr_t page_align(uintptr_t, unsigned); int load_image(meminfo_t *mem_layout, unsigned int image_id, uintptr_t image_base, image_info_t *image_data, entry_point_info_t *entry_point_info); int load_auth_image(meminfo_t *mem_layout, - unsigned int image_name, + unsigned int image_id, uintptr_t image_base, image_info_t *image_data, entry_point_info_t *entry_point_info); -extern const char build_message[]; -extern const char version_string[]; - void reserve_mem(uintptr_t *free_base, size_t *free_size, uintptr_t addr, size_t size); +#endif /* LOAD_IMAGE_V2 */ + +extern const char build_message[]; +extern const char version_string[]; + void print_entry_point_info(const entry_point_info_t *ep_info); #endif /*__ASSEMBLY__*/ diff --git a/include/common/desc_image_load.h b/include/common/desc_image_load.h new file mode 100644 index 000000000..78342627c --- /dev/null +++ b/include/common/desc_image_load.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __DESC_IMAGE_LOAD_H__ +#define __DESC_IMAGE_LOAD_H__ + +#include + +#if LOAD_IMAGE_V2 +/* Following structure is used to store BL ep/image info. */ +typedef struct bl_mem_params_node { + unsigned int image_id; + image_info_t image_info; + entry_point_info_t ep_info; + unsigned int next_handoff_image_id; + bl_load_info_node_t load_node_mem; + bl_params_node_t params_node_mem; +} bl_mem_params_node_t; + +/* + * Macro to register list of BL image descriptors, + * defined as an array of bl_mem_params_node_t. + */ +#define REGISTER_BL_IMAGE_DESCS(_img_desc) \ + bl_mem_params_node_t *bl_mem_params_desc_ptr = &_img_desc[0]; \ + unsigned int bl_mem_params_desc_num = ARRAY_SIZE(_img_desc); + +/* BL image loading utility functions */ +void flush_bl_params_desc(void); +int get_bl_params_node_index(unsigned int image_id); +bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id); +bl_load_info_t *get_bl_load_info_from_mem_params_desc(void); +bl_params_t *get_next_bl_params_from_mem_params_desc(void); + + +#endif /* LOAD_IMAGE_V2 */ +#endif /* __DESC_IMAGE_LOAD_H__ */ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 1d2a3739e..852ccbcd0 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -44,6 +44,8 @@ struct image_info; struct entry_point_info; struct bl31_params; struct image_desc; +struct bl_load_info; +struct bl_params; /******************************************************************************* * plat_get_rotpk_info() flags @@ -138,6 +140,15 @@ void bl2_plat_arch_setup(void); void bl2_platform_setup(void); struct meminfo *bl2_plat_sec_mem_layout(void); +#if LOAD_IMAGE_V2 +/* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + */ +int bl2_plat_handle_post_image_load(unsigned int image_id); + +#else /* LOAD_IMAGE_V2 */ + /* * This function returns a pointer to the shared memory that the platform has * kept aside to pass trusted firmware related information that BL31 @@ -194,6 +205,8 @@ void bl2_plat_set_bl32_ep_info(struct image_info *image, /* Gets the memory layout for BL32 */ void bl2_plat_get_bl32_meminfo(struct meminfo *mem_info); +#endif /* LOAD_IMAGE_V2 */ + /******************************************************************************* * Optional BL2 functions (may be overridden) ******************************************************************************/ @@ -218,8 +231,13 @@ int bl2u_plat_handle_scp_bl2u(void); /******************************************************************************* * Mandatory BL31 functions ******************************************************************************/ +#if LOAD_IMAGE_V2 +void bl31_early_platform_setup(void *from_bl2, + void *plat_params_from_bl2); +#else void bl31_early_platform_setup(struct bl31_params *from_bl2, void *plat_params_from_bl2); +#endif void bl31_plat_arch_setup(void); void bl31_platform_setup(void); void bl31_plat_runtime_setup(void); @@ -257,6 +275,31 @@ int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr); int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr); +#if LOAD_IMAGE_V2 +/******************************************************************************* + * Mandatory BL image load functions(may be overridden). + ******************************************************************************/ +/* + * This function returns pointer to the list of images that the + * platform has populated to load. + */ +struct bl_load_info *plat_get_bl_image_load_info(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 could need. + */ +struct bl_params *plat_get_next_bl_params(void); + +/* + * This function flushes to main memory all the params that are + * passed to next image. + */ +void plat_flush_next_bl_params(void); + +#endif /* LOAD_IMAGE_V2 */ + #if ENABLE_PLAT_COMPAT /* * The below declarations are to enable compatibility for the platform ports