diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c index 2a3415d..44fe694 100644 --- a/bl1/bl1_main.c +++ b/bl1/bl1_main.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include #include "bl1_private.h" @@ -46,10 +48,10 @@ /* Tell next EL what we want done */ bl2_ep->args.arg0 = RUN_IMAGE; - if (bl2_ep->security_state == NON_SECURE) - change_security_state(bl2_ep->security_state); + if (GET_SECURITY_STATE(bl2_ep->h.attr) == NON_SECURE) + change_security_state(GET_SECURITY_STATE(bl2_ep->h.attr)); - drop_el(&bl2_ep->args, bl2_ep->spsr, bl2_ep->entrypoint); + drop_el(&bl2_ep->args, bl2_ep->spsr, bl2_ep->pc); } @@ -65,11 +67,12 @@ #if DEBUG unsigned long sctlr_el3 = read_sctlr_el3(); #endif - unsigned long bl2_base; unsigned int load_type = TOP_LOAD; + image_info_t bl2_image_info = { {0} }; + el_change_info_t bl2_ep = { {0} }; meminfo_t *bl1_tzram_layout; meminfo_t *bl2_tzram_layout = 0x0; - el_change_info_t bl2_ep = {0}; + int e; /* * Ensure that MMU/Caches and coherency are turned on @@ -88,15 +91,28 @@ printf(FIRMWARE_WELCOME_STR); printf("%s\n\r", build_message); + SET_PARAM_HEAD(&bl2_image_info, PARAM_IMAGE_BINARY, VERSION_1, 0); + SET_PARAM_HEAD(&bl2_ep, PARAM_EP, VERSION_1, 0); + /* * Find out how much free trusted ram remains after BL1 load * & load the BL2 image at its top */ bl1_tzram_layout = bl1_plat_sec_mem_layout(); - bl2_base = load_image(bl1_tzram_layout, + e = load_image(bl1_tzram_layout, (const char *) BL2_IMAGE_NAME, - load_type, BL2_BASE); - + load_type, + BL2_BASE, + &bl2_image_info, + &bl2_ep); + if (e) { + /* + * TODO: print failure to load BL2 but also add a tzwdog timer + * which will reset the system eventually. + */ + printf("Failed to load boot loader stage 2 (BL2) firmware.\n"); + panic(); + } /* * Create a new layout of memory for BL2 as seen by BL1 i.e. * tell it the amount of total and free memory available. @@ -108,30 +124,21 @@ init_bl2_mem_layout(bl1_tzram_layout, bl2_tzram_layout, load_type, - bl2_base); + bl2_image_info.image_base); - if (bl2_base) { - bl1_arch_next_el_setup(); - bl2_ep.spsr = - SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTION); - bl2_ep.entrypoint = bl2_base; - bl2_ep.security_state = SECURE; - bl2_ep.args.arg1 = (unsigned long)bl2_tzram_layout; - printf("Booting trusted firmware boot loader stage 2\n\r"); + bl1_arch_next_el_setup(); + bl1_plat_bl2_loaded(&bl2_image_info, &bl2_ep); + bl2_ep.args.arg1 = (unsigned long)bl2_tzram_layout; + printf("Booting trusted firmware boot loader stage 2\n"); #if DEBUG - printf("BL2 address = 0x%llx \n\r", (unsigned long long) bl2_base); - printf("BL2 cpsr = 0x%x \n\r", bl2_ep.spsr); - printf("BL2 memory layout address = 0x%llx \n\r", - (unsigned long long) bl2_tzram_layout); + printf("BL2 address = 0x%llx\n", + (unsigned long long) bl2_ep.pc); + printf("BL2 cpsr = 0x%x\n", bl2_ep.spsr); + printf("BL2 memory layout address = 0x%llx\n", + (unsigned long long) bl2_tzram_layout); #endif - bl1_run_bl2(&bl2_ep); - } + bl1_run_bl2(&bl2_ep); - /* - * TODO: print failure to load BL2 but also add a tzwdog timer - * which will reset the system eventually. - */ - printf("Failed to load boot loader stage 2 (BL2) firmware.\n\r"); return; } @@ -143,12 +150,12 @@ { printf("Booting trusted firmware boot loader stage 3\n\r"); #if DEBUG - printf("BL31 address = 0x%llx\n", - (unsigned long long)bl31_ep_info->entrypoint); - printf("BL31 cpsr = 0x%llx\n", - (unsigned long long)bl31_ep_info->spsr); - printf("BL31 args address = 0x%llx\n", + printf("BL31 address = 0x%llx\n", (unsigned long long)bl31_ep_info->pc); + printf("BL31 cpsr = 0x%llx\n", (unsigned long long)bl31_ep_info->spsr); + printf("BL31 TF params address = 0x%llx\n", (unsigned long long)bl31_ep_info->args.arg0); + printf("BL31 TF plat params address = 0x%llx\n", + (unsigned long long)bl31_ep_info->args.arg1); #endif return; } diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c index 42ccf69..97e1689 100644 --- a/bl2/bl2_main.c +++ b/bl2/bl2_main.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include "bl2_private.h" @@ -57,9 +58,11 @@ void bl2_main(void) { meminfo_t *bl2_tzram_layout; - bl31_args_t *bl2_to_bl31_args; - unsigned long bl31_base, bl32_base = 0, bl33_base, el_status; - unsigned int bl2_load, bl31_load, mode; + bl31_tf_params_t *bl2_to_bl31_params; + bl31_plat_params_t *bl2_to_bl31_plat_params; + unsigned int bl2_load, bl31_load; + el_change_info_t *bl31_ep_info; + int e; /* Perform remaining generic architectural setup in S-El1 */ bl2_arch_setup(); @@ -69,14 +72,17 @@ printf("BL2 %s\n\r", build_message); + + /* Find out how much free trusted ram remains after BL2 load */ + bl2_tzram_layout = bl2_plat_sec_mem_layout(); + /* * Get a pointer to the memory the platform has set aside to pass * information to BL31. */ - bl2_to_bl31_args = bl2_get_bl31_args_ptr(); - - /* Find out how much free trusted ram remains after BL2 load */ - bl2_tzram_layout = bl2_plat_sec_mem_layout(); + bl2_to_bl31_params = bl2_plat_get_bl31_params(); + bl2_to_bl31_plat_params = bl2_plat_get_bl31_plat_params(); + bl31_ep_info = bl2_plat_get_bl31_ep(); /* * Load BL31. BL1 tells BL2 whether it has been TOP or BOTTOM loaded. @@ -87,18 +93,46 @@ bl2_load = bl2_tzram_layout->attr & LOAD_MASK; assert((bl2_load == TOP_LOAD) || (bl2_load == BOT_LOAD)); bl31_load = (bl2_load == TOP_LOAD) ? BOT_LOAD : TOP_LOAD; - bl31_base = load_image(bl2_tzram_layout, BL31_IMAGE_NAME, - bl31_load, BL31_BASE); + e = load_image(bl2_tzram_layout, + BL31_IMAGE_NAME, + bl31_load, + BL31_BASE, + bl2_to_bl31_params->bl31_image, + bl31_ep_info); /* Assert if it has not been possible to load BL31 */ - if (bl31_base == 0) { + if (e) { ERROR("Failed to load BL3-1.\n"); panic(); } - bl2_to_bl31_args->bl31_image_info.entrypoint = bl31_base; - bl2_to_bl31_args->bl31_image_info.security_state = SECURE; - bl2_to_bl31_args->bl31_image_info.spsr = - SPSR_64(MODE_EL3, MODE_SP_ELX, DISABLE_ALL_EXCEPTION); + bl2_plat_bl31_loaded(bl2_to_bl31_params->bl31_image, + bl31_ep_info); + + + /* + * Create a new layout of memory for BL31 as seen by BL2. This + * will gobble up all the BL2 memory. + */ + init_bl31_mem_layout(bl2_tzram_layout, + &bl2_to_bl31_plat_params->bl31_meminfo, + bl31_load); + + /* Load the BL33 image in non-secure memory provided by the platform */ + e = load_image(&bl2_to_bl31_plat_params->bl33_meminfo, + BL33_IMAGE_NAME, + BOT_LOAD, + plat_get_ns_image_entrypoint(), + bl2_to_bl31_params->bl33_image, + bl2_to_bl31_params->bl33_ep); + + /* Halt if failed to load normal world firmware. */ + if (e) { + ERROR("Failed to load BL3-3.\n"); + panic(); + } + bl2_plat_bl33_loaded(bl2_to_bl31_params->bl33_image, + bl2_to_bl31_params->bl33_ep); + /* * Load the BL32 image if there's one. It is upto to platform @@ -107,81 +141,36 @@ * completely different memory. A zero size indicates that the * platform does not want to load a BL32 image. */ - if (bl2_to_bl31_args->bl32_meminfo.total_size) - bl32_base = load_image(&bl2_to_bl31_args->bl32_meminfo, - BL32_IMAGE_NAME, - bl2_to_bl31_args->bl32_meminfo.attr & - LOAD_MASK, - BL32_BASE); + if (bl2_to_bl31_plat_params->bl32_meminfo.total_size) { + e = load_image(&bl2_to_bl31_plat_params->bl32_meminfo, + BL32_IMAGE_NAME, + bl2_to_bl31_plat_params->bl32_meminfo.attr & + LOAD_MASK, + BL32_BASE, + bl2_to_bl31_params->bl32_image, + bl2_to_bl31_params->bl32_ep); - /* - * Create a new layout of memory for BL31 as seen by BL2. This - * will gobble up all the BL2 memory. - */ - init_bl31_mem_layout(bl2_tzram_layout, - &bl2_to_bl31_args->bl31_meminfo, - bl31_load); - - /* Load the BL33 image in non-secure memory provided by the platform */ - bl33_base = load_image(&bl2_to_bl31_args->bl33_meminfo, - BL33_IMAGE_NAME, - BOT_LOAD, - plat_get_ns_image_entrypoint()); - /* Halt if failed to load normal world firmware. */ - if (bl33_base == 0) { - ERROR("Failed to load BL3-3.\n"); - panic(); + /* Halt if failed to load normal world firmware. */ + if (e) { + ERROR("Failed to load BL3-2.\n"); + panic(); + } + bl2_plat_bl32_loaded(bl2_to_bl31_params->bl32_image, + bl2_to_bl31_params->bl32_ep); } - /* - * BL2 also needs to tell BL31 where the non-trusted software image - * is located. - */ - bl2_to_bl31_args->bl33_image_info.entrypoint = bl33_base; + /* Flush the params to be passed to memory */ + bl2_plat_flush_bl31_params(); - /* Figure out what mode we enter the non-secure world in */ - el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; - el_status &= ID_AA64PFR0_ELX_MASK; - if (el_status) - mode = MODE_EL2; - else - mode = MODE_EL1; - - /* - * TODO: Consider the possibility of specifying the SPSR in - * the FIP ToC and allowing the platform to have a say as - * well. - */ - bl2_to_bl31_args->bl33_image_info.spsr = - SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTION); - bl2_to_bl31_args->bl33_image_info.security_state = NON_SECURE; - - if (bl32_base) { - /* Fill BL32 image info */ - bl2_to_bl31_args->bl32_image_info.entrypoint = bl32_base; - bl2_to_bl31_args->bl32_image_info.security_state = SECURE; - - /* - * The Secure Payload Dispatcher service is responsible for - * setting the SPSR prior to entry into the BL32 image. - */ - bl2_to_bl31_args->bl32_image_info.spsr = 0; - } - - /* Flush the entire BL31 args buffer */ - flush_dcache_range((unsigned long) bl2_to_bl31_args, - sizeof(*bl2_to_bl31_args)); - - /* Set the args pointers for X0 and X1 to BL31 */ - bl2_to_bl31_args->bl31_image_info.args.arg0 = - (unsigned long)bl2_to_bl31_args; - bl2_to_bl31_args->bl31_image_info.args.arg1 = (unsigned long)0; + /* Set the args pointer */ + bl31_ep_info->args.arg0 = (unsigned long)bl2_to_bl31_params; + bl31_ep_info->args.arg1 = (unsigned long)bl2_to_bl31_plat_params; /* * Run BL31 via an SMC to BL1. Information on how to pass control to * the BL32 (if present) and BL33 software images will be passed to * BL31 as an argument. */ - bl2_run_bl31(&bl2_to_bl31_args->bl31_image_info); + bl2_run_bl31(bl31_ep_info); } diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S index 42ddb1b..803c097 100644 --- a/bl31/aarch64/bl31_entrypoint.S +++ b/bl31/aarch64/bl31_entrypoint.S @@ -45,8 +45,8 @@ func bl31_entrypoint /* --------------------------------------------- - * BL2 has populated x0 with a pointer to a 'bl31_args' structure & x2 - * with any other optional information + * BL2 has populated x0 with a pointer to a 'bl31_tf_params' + * structure & x1 with a pointer to platform specific structure * --------------------------------------------- */ mov x20, x0 diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c index 5a09829..2a9cae3 100644 --- a/bl31/bl31_main.c +++ b/bl31/bl31_main.c @@ -176,13 +176,13 @@ * Tell the context mgmt. library to ensure that SP_EL3 points to * the right context to exit from EL3 correctly. */ - cm_set_el3_eret_context(next_image_info->security_state, - next_image_info->entrypoint, + cm_set_el3_eret_context(GET_SECURITY_STATE(next_image_info->h.attr), + next_image_info->pc, next_image_info->spsr, scr); /* Finally set the next context */ - cm_set_next_eret_context(next_image_info->security_state); + cm_set_next_eret_context(GET_SECURITY_STATE(next_image_info->h.attr)); } /******************************************************************************* diff --git a/common/bl_common.c b/common/bl_common.c index 2f3f989..d0d36c8 100644 --- a/common/bl_common.c +++ b/common/bl_common.c @@ -35,6 +35,7 @@ #include #include #include +#include #include unsigned long page_align(unsigned long value, unsigned dir) @@ -244,12 +245,15 @@ * Generic function to load an image into the trusted RAM, * given a name, extents of free memory & whether the image should be loaded at * the bottom or top of the free memory. It updates the memory layout if the - * load is successful. + * load is successful. It also update image information and the entry point + * information in the params passed ******************************************************************************/ -unsigned long load_image(meminfo_t *mem_layout, +int load_image(meminfo_t *mem_layout, const char *image_name, unsigned int load_type, - unsigned long fixed_addr) + unsigned long fixed_addr, + image_info_t *image_data, + el_change_info_t *entry_point_info) { uintptr_t dev_handle; uintptr_t image_handle; @@ -263,6 +267,7 @@ assert(mem_layout != NULL); assert(image_name != NULL); + 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_name, &dev_handle, &image_spec); @@ -285,7 +290,7 @@ if ((io_result != IO_SUCCESS) || (image_size == 0)) { WARN("Failed to determine the size of the image '%s' file (%i)\n", image_name, io_result); - goto fail; + goto exit; } /* See if we have enough space */ @@ -293,7 +298,7 @@ WARN("Cannot load '%s' file: Not enough space.\n", image_name); dump_load_info(0, image_size, mem_layout); - goto fail; + goto exit; } switch (load_type) { @@ -312,7 +317,8 @@ WARN("Cannot load '%s' file: Not enough space.\n", image_name); dump_load_info(image_base, image_size, mem_layout); - goto fail; + io_result = -ENOMEM; + goto exit; } /* Calculate the amount of extra memory used due to alignment */ @@ -330,10 +336,11 @@ /* Page align base address and check whether the image still fits */ if (image_base + image_size > mem_layout->free_base + mem_layout->free_size) { - WARN("Cannot load '%s' file: Not enough space.\n", - image_name); - dump_load_info(image_base, image_size, mem_layout); - goto fail; + WARN("Cannot load '%s' file: Not enough space.\n", + image_name); + dump_load_info(image_base, image_size, mem_layout); + io_result = -ENOMEM; + goto exit; } /* Calculate the amount of extra memory used due to alignment */ @@ -398,14 +405,16 @@ WARN("Cannot load '%s' file: Not enough space.\n", image_name); dump_load_info(image_base, image_size, mem_layout); - goto fail; + io_result = -ENOMEM; + goto exit; } /* Check whether the fixed load address is page-aligned. */ if (!is_page_aligned(image_base)) { WARN("Cannot load '%s' file at unaligned address 0x%lx\n", image_name, fixed_addr); - goto fail; + io_result = -ENOMEM; + goto exit; } /* @@ -455,9 +464,14 @@ io_result = io_read(image_handle, image_base, image_size, &bytes_read); if ((io_result != IO_SUCCESS) || (bytes_read < image_size)) { WARN("Failed to load '%s' file (%i)\n", image_name, io_result); - goto fail; + goto exit; } + image_data->image_base = image_base; + image_data->image_size = image_size; + + entry_point_info->pc = image_base; + /* * File has been successfully loaded. Update the free memory * data structure & flush the contents of the TZRAM so that @@ -473,15 +487,12 @@ mem_layout->free_base += offset + image_size; exit: - io_result = io_close(image_handle); + io_close(image_handle); /* Ignore improbable/unrecoverable error in 'close' */ /* TODO: Consider maintaining open device connection from this bootloader stage */ - io_result = io_dev_close(dev_handle); + io_dev_close(dev_handle); /* Ignore improbable/unrecoverable error in 'dev_close' */ - return image_base; - -fail: image_base = 0; - goto exit; + return io_result; } diff --git a/include/bl2/bl2.h b/include/bl2/bl2.h index 25b6f9c..0548999 100644 --- a/include/bl2/bl2.h +++ b/include/bl2/bl2.h @@ -47,6 +47,32 @@ *****************************************/ extern void bl2_platform_setup(void); extern struct meminfo *bl2_plat_sec_mem_layout(void); -extern struct bl31_args *bl2_get_bl31_args_ptr(void); + +/******************************************************************************* + * This function returns a pointer to the shared memory that the platform has + * kept aside to pass trusted firmware related information that BL3-1 + * could need + ******************************************************************************/ +extern struct bl31_tf_params *bl2_plat_get_bl31_params(void); + +/******************************************************************************* + * This function returns a pointer to the shared memory that the platform has + * kept aside to pass platform related information that BL3-1 could need + ******************************************************************************/ +extern struct bl31_plat_params *bl2_plat_get_bl31_plat_params(void); + +/******************************************************************************* + * This function returns a pointer to the shared memory that the platform + * has kept to point to entry point information of BL31 to BL2 + ******************************************************************************/ +extern struct el_change_info *bl2_plat_get_bl31_ep(void); + + +/************************************************************************ + * This function flushes to main memory all the params that are + * passed to BL3-1 + **************************************************************************/ +extern void bl2_plat_flush_bl31_params(void); + #endif /* __BL2_H__ */ diff --git a/include/common/bl_common.h b/include/common/bl_common.h index 19e5cf6..e67c1a0 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -31,8 +31,9 @@ #ifndef __BL_COMMON_H__ #define __BL_COMMON_H__ -#define SECURE 0 -#define NON_SECURE 1 +#define SECURE 0x0 +#define NON_SECURE 0x1 +#define PARAM_EP_SECURITY_MASK 0x1 #define UP 1 #define DOWN 0 @@ -58,15 +59,32 @@ /******************************************************************************* * Constants that allow assembler code to access members of and the - * 'el_change_info' structure at their correct offsets. + * 'el_change_info' structure at their correct offsets. ******************************************************************************/ -#define EL_CHANGE_INFO_PC_OFFSET 0x0 -#define EL_CHANGE_INFO_ARGS_OFFSET 0x18 +#define EL_CHANGE_INFO_PC_OFFSET 0x08 +#define EL_CHANGE_INFO_ARGS_OFFSET 0x18 + +#define GET_SECURITY_STATE(x) (x & PARAM_EP_SECURITY_MASK) +#define SET_SECURITY_STATE(x, security) \ + ((x) = ((x) & ~PARAM_EP_SECURITY_MASK) | (security)) + +#define PARAM_EP 0x01 +#define PARAM_IMAGE_BINARY 0x02 +#define PARAM_BL31 0x03 + +#define VERSION_1 0x01 + +#define SET_PARAM_HEAD(_p, _type, _ver, _attr) do { \ + (_p)->h.type = (uint8_t)(_type); \ + (_p)->h.version = (uint8_t)(_ver); \ + (_p)->h.size = (uint16_t)sizeof(*_p); \ + (_p)->h.attr = (uint32_t)(_attr) ; \ + } while (0) #ifndef __ASSEMBLY__ - #include /* For __dead2 */ #include +#include /******************************************************************************* * Structure used for telling the next BL how much of a particular type of @@ -92,33 +110,77 @@ unsigned long arg7; } aapcs64_params_t; -/******************************************************************************* - * This structure represents the superset of information needed while switching - * exception levels. The only two mechanisms to do so are ERET & SMC. In case of - * SMC all members apart from 'aapcs64_params' will be ignored. - * NOTE: BL1 expects entrypoint followed by spsr while processing SMC to jump - * to BL31 from the start of el_change_info - ******************************************************************************/ +/*************************************************************************** + * This structure provides version information and the size of the + * structure, attributes for the structure it represents + ***************************************************************************/ +typedef struct param_header { + uint8_t type; /* type of the structure */ + uint8_t version; /* version of this structure */ + uint16_t size; /* size of this structure in bytes */ + uint32_t attr; /* attributes: unused bits SBZ */ +} param_header_t; + +/***************************************************************************** + * This structure represents the superset of information needed while + * switching exception levels. The only two mechanisms to do so are + * ERET & SMC. In case of SMC all members apart from indicated + * using bit 0 of the header attributes + *****************************************************************************/ typedef struct el_change_info { - unsigned long entrypoint; - unsigned long spsr; - unsigned long security_state; + param_header_t h; + uintptr_t pc; + uint32_t spsr; aapcs64_params_t args; } el_change_info_t; +/***************************************************************************** + * Image info binary provides information from the image loader that + * can be used by the firmware to manage available trusted RAM. + * More advanced firmware image formats can provide additional + * information that enables optimization or greater flexibility in the + * common firmware code + *****************************************************************************/ +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 */ +} image_info_t; + /******************************************************************************* * 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 - * populated only if BL2 detects its presence. + * populated only if BL2 detects its presence. A pointer to a structure of this + * type should be passed in X3 to BL31's cold boot entrypoint + * + * Use of this structure and the X3 parameter is not mandatory: the BL3-1 + * platform code can use other mechanisms to provide the necessary information + * about BL3-2 and BL3-3 to the common and SPD code. + * + * BL3-1 image information is mandatory if this structure is used. If either of + * the optional BL3-2 and BL3-3 image information is not provided, this is + * indicated by the respective image_info pointers being zero. ******************************************************************************/ -typedef struct bl31_args { - el_change_info_t bl31_image_info; +typedef struct bl31_tf_params { + param_header_t h; + image_info_t *bl31_image; + el_change_info_t *bl32_ep; + image_info_t *bl32_image; + el_change_info_t *bl33_ep; + image_info_t *bl33_image; +} bl31_tf_params_t; + + +/*************************************************************************** + * This structure provides platform specific data that needs to be known to + * BL31. Currently, The loader updates the memory information available for each + * binary + ***************************************************************************/ +typedef struct bl31_plat_params { meminfo_t bl31_meminfo; - el_change_info_t bl32_image_info; meminfo_t bl32_meminfo; - el_change_info_t bl33_image_info; meminfo_t bl33_meminfo; -} bl31_args_t; +} bl31_plat_params_t; /* @@ -126,15 +188,14 @@ * ensure that the assembler and the compiler view of the offsets of * the structure members is the same. */ -CASSERT(EL_CHANGE_INFO_PC_OFFSET == \ - __builtin_offsetof(el_change_info_t, entrypoint), \ - assert_BL31_pc_offset_mismatch); +CASSERT(EL_CHANGE_INFO_PC_OFFSET == + __builtin_offsetof(el_change_info_t, pc), \ + assert_BL31_pc_offset_mismatch); CASSERT(EL_CHANGE_INFO_ARGS_OFFSET == \ __builtin_offsetof(el_change_info_t, args), \ assert_BL31_args_offset_mismatch); - /******************************************************************************* * Function & variable prototypes ******************************************************************************/ @@ -149,10 +210,12 @@ meminfo_t *, unsigned int) __attribute__((weak)); extern unsigned long image_size(const char *); -extern unsigned long load_image(meminfo_t *, +extern int load_image(meminfo_t *, const char *, unsigned int, - unsigned long); + unsigned long, + image_info_t *, + el_change_info_t *); extern unsigned long *get_el_change_mem_ptr(void); extern const char build_message[]; diff --git a/plat/fvp/bl1_plat_setup.c b/plat/fvp/bl1_plat_setup.c index edd3f7b..7652cae 100644 --- a/plat/fvp/bl1_plat_setup.c +++ b/plat/fvp/bl1_plat_setup.c @@ -144,3 +144,13 @@ BL1_COHERENT_RAM_BASE, BL1_COHERENT_RAM_LIMIT); } + + +/******************************************************************************* + * Update SPSR and secure state for BL2 image + ******************************************************************************/ +void bl1_plat_bl2_loaded(image_info_t *bl2_image, el_change_info_t *bl2_ep) +{ + SET_SECURITY_STATE(bl2_ep->h.attr, SECURE); + bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTION); +} diff --git a/plat/fvp/bl2_plat_setup.c b/plat/fvp/bl2_plat_setup.c index ddd3b01..30c410f 100644 --- a/plat/fvp/bl2_plat_setup.c +++ b/plat/fvp/bl2_plat_setup.c @@ -34,6 +34,7 @@ #include #include #include +#include /******************************************************************************* * Declarations of linker defined symbols which will help us find the layout @@ -73,10 +74,12 @@ section("tzfw_coherent_mem"))); /******************************************************************************* - * Reference to structure which holds the arguments which need to be passed + * Reference to structures which holds the arguments which need to be passed * to BL31 ******************************************************************************/ -static bl31_args_t *bl2_to_bl31_args; +static bl31_tf_params_t *bl2_to_bl31_params; +static bl31_plat_params_t *bl2_to_bl31_plat_params; +static el_change_info_t *bl31_ep_info; meminfo_t *bl2_plat_sec_mem_layout(void) { @@ -84,15 +87,102 @@ } /******************************************************************************* - * This function returns a pointer to the memory that the platform has kept - * aside to pass all the information that BL31 could need. + * This function assigns a pointer to the memory that the platform has kept + * aside to pass platform specific and trusted firmware related information + * to BL31. This memory is allocated by allocating memory to + * bl2_to_bl31_params_mem_t structure which is a superset of all the + * structure whose information is passed to BL31 + * NOTE: This function should be called only once and should be done + * before generating params to BL31 ******************************************************************************/ -bl31_args_t *bl2_get_bl31_args_ptr(void) +bl31_tf_params_t *bl2_plat_get_bl31_params(void) { - return bl2_to_bl31_args; + bl2_to_bl31_params_mem_t *bl31_params_mem; + + /* + * Ensure that the secure DRAM memory used for passing BL31 arguments + * does not overlap with the BL32_BASE. + */ + assert(BL32_BASE > PARAMS_BASE + sizeof(bl2_to_bl31_params_mem_t)); + + /* + * Allocate the memory for all the arguments that needs to + * be passed to BL31 + */ + bl31_params_mem = (bl2_to_bl31_params_mem_t *)PARAMS_BASE; + memset((void *)PARAMS_BASE, 0, sizeof(bl2_to_bl31_params_mem_t)); + + /* Assign memory for TF related information */ + bl2_to_bl31_params = &bl31_params_mem->bl31_tf_params; + SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0); + + /* Assign memory for platform specific information */ + bl2_to_bl31_plat_params = &bl31_params_mem->bl31_plat_params; + + /* Fill BL31 related information */ + bl31_ep_info = &bl31_params_mem->bl31_ep; + bl2_to_bl31_params->bl31_image = &bl31_params_mem->bl31_image; + SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image, PARAM_IMAGE_BINARY, + VERSION_1, 0); + + /* Fill BL32 related information if it exists */ + if (BL32_BASE) { + bl2_to_bl31_params->bl32_ep = &bl31_params_mem->bl32_ep; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep, + PARAM_EP, VERSION_1, 0); + bl2_to_bl31_params->bl32_image = &bl31_params_mem->bl32_image; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image, + PARAM_IMAGE_BINARY, + VERSION_1, 0); + /* + * Populate the extents of memory available for loading BL32. + * TODO: We are temporarily executing BL2 from TZDRAM; + * will eventually move to Trusted SRAM + */ + bl2_to_bl31_plat_params->bl32_meminfo.total_base = BL32_BASE; + bl2_to_bl31_plat_params->bl32_meminfo.free_base = BL32_BASE; + bl2_to_bl31_plat_params->bl32_meminfo.total_size = + (TZDRAM_BASE + TZDRAM_SIZE) - BL32_BASE; + bl2_to_bl31_plat_params->bl32_meminfo.free_size = + (TZDRAM_BASE + TZDRAM_SIZE) - BL32_BASE; + bl2_to_bl31_plat_params->bl32_meminfo.attr = BOT_LOAD; + } + + /* Fill BL33 related information */ + bl2_to_bl31_params->bl33_ep = &bl31_params_mem->bl33_ep; + SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep, PARAM_EP, VERSION_1, 0); + bl2_to_bl31_params->bl33_image = &bl31_params_mem->bl33_image; + SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image, PARAM_IMAGE_BINARY, + VERSION_1, 0); + /* Populate the extents of memory available for loading BL33 */ + bl2_to_bl31_plat_params->bl33_meminfo.total_base = DRAM_BASE; + bl2_to_bl31_plat_params->bl33_meminfo.total_size = DRAM_SIZE; + bl2_to_bl31_plat_params->bl33_meminfo.free_base = DRAM_BASE; + bl2_to_bl31_plat_params->bl33_meminfo.free_size = DRAM_SIZE; + + return bl2_to_bl31_params; } /******************************************************************************* + * This function returns a pointer to the memory that the platform has kept + * aside to pass platform related information that BL31 could need + ******************************************************************************/ +bl31_plat_params_t *bl2_plat_get_bl31_plat_params(void) +{ + return bl2_to_bl31_plat_params; +} + +/******************************************************************************* + * This function returns a pointer to the shared memory that the platform + * has kept to point to entry point information of BL31 to BL2 + ******************************************************************************/ +struct el_change_info *bl2_plat_get_bl31_ep(void) +{ + return bl31_ep_info; +} + + +/******************************************************************************* * BL1 has passed the extents of the trusted SRAM that should be visible to BL2 * in x0. This memory layout is sitting at the base of the free trusted SRAM. * Copy it to a safe loaction before its reclaimed by later BL2 functionality. @@ -118,7 +208,7 @@ * Perform platform specific setup. For now just initialize the memory location * to use for passing arguments to BL31. ******************************************************************************/ -void bl2_platform_setup() +void bl2_platform_setup(void) { /* * Do initial security configuration to allow DRAM/device access. On @@ -130,41 +220,16 @@ /* Initialise the IO layer and register platform IO devices */ io_setup(); - - /* - * Ensure that the secure DRAM memory used for passing BL31 arguments - * does not overlap with the BL32_BASE. - */ - assert (BL32_BASE > TZDRAM_BASE + sizeof(bl31_args_t)); - - /* Use the Trusted DRAM for passing args to BL31 */ - bl2_to_bl31_args = (bl31_args_t *) TZDRAM_BASE; - - /* Populate the extents of memory available for loading BL33 */ - bl2_to_bl31_args->bl33_meminfo.total_base = DRAM_BASE; - bl2_to_bl31_args->bl33_meminfo.total_size = DRAM_SIZE; - bl2_to_bl31_args->bl33_meminfo.free_base = DRAM_BASE; - bl2_to_bl31_args->bl33_meminfo.free_size = DRAM_SIZE; - bl2_to_bl31_args->bl33_meminfo.attr = 0; - bl2_to_bl31_args->bl33_meminfo.next = 0; - - /* - * Populate the extents of memory available for loading BL32. - * TODO: We are temporarily executing BL2 from TZDRAM; will eventually - * move to Trusted SRAM - */ - bl2_to_bl31_args->bl32_meminfo.total_base = BL32_BASE; - bl2_to_bl31_args->bl32_meminfo.free_base = BL32_BASE; - - bl2_to_bl31_args->bl32_meminfo.total_size = - (TZDRAM_BASE + TZDRAM_SIZE) - BL32_BASE; - bl2_to_bl31_args->bl32_meminfo.free_size = - (TZDRAM_BASE + TZDRAM_SIZE) - BL32_BASE; - - bl2_to_bl31_args->bl32_meminfo.attr = BOT_LOAD; - bl2_to_bl31_args->bl32_meminfo.next = 0; } +/* Flush the TF params and the TF plat params */ +extern void bl2_plat_flush_bl31_params(void) +{ + flush_dcache_range((unsigned long)PARAMS_BASE, \ + sizeof(bl2_to_bl31_params_mem_t)); +} + + /******************************************************************************* * Perform the very early platform specific architectural setup here. At the * moment this is only intializes the mmu in a quick and dirty way. @@ -177,3 +242,52 @@ BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT); } + +/******************************************************************************* + * Update SPSR and secure state for BL31 image + ******************************************************************************/ +void bl2_plat_bl31_loaded(image_info_t *bl31_image, el_change_info_t *bl31_ep) +{ + SET_SECURITY_STATE(bl31_ep->h.attr, SECURE); + bl31_ep->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, DISABLE_ALL_EXCEPTION); +} + + +/******************************************************************************* + * Update SPSR and secure state for BL32 image + ******************************************************************************/ +void bl2_plat_bl32_loaded(image_info_t *bl32_image, el_change_info_t *bl32_ep) +{ + SET_SECURITY_STATE(bl32_ep->h.attr, SECURE); + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + bl32_ep->spsr = 0; +} + +/******************************************************************************* + * Update SPSR and secure state for BL33 image + ******************************************************************************/ +void bl2_plat_bl33_loaded(image_info_t *image, el_change_info_t *bl33_ep) +{ + unsigned long el_status; + unsigned int mode; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + if (el_status) + mode = MODE_EL2; + else + mode = MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + bl33_ep->spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTION); + SET_SECURITY_STATE(bl33_ep->h.attr, NON_SECURE); +} diff --git a/plat/fvp/bl31_plat_setup.c b/plat/fvp/bl31_plat_setup.c index baf7df1..191e156 100644 --- a/plat/fvp/bl31_plat_setup.c +++ b/plat/fvp/bl31_plat_setup.c @@ -29,6 +29,7 @@ */ #include +#include #include #include #include @@ -70,16 +71,17 @@ * Reference to structure which holds the arguments that have been passed to * BL31 from BL2. ******************************************************************************/ -static bl31_args_t *bl2_to_bl31_args; +static bl31_tf_params_t *bl2_to_bl31_params; +static bl31_plat_params_t *bl2_to_bl31_plat_params; meminfo_t *bl31_plat_sec_mem_layout(void) { - return &bl2_to_bl31_args->bl31_meminfo; + return &bl2_to_bl31_plat_params->bl31_meminfo; } meminfo_t *bl31_plat_get_bl32_mem_layout(void) { - return &bl2_to_bl31_args->bl32_meminfo; + return &bl2_to_bl31_plat_params->bl32_meminfo; } /******************************************************************************* @@ -93,11 +95,11 @@ el_change_info_t *next_image_info; next_image_info = (type == NON_SECURE) ? - &bl2_to_bl31_args->bl33_image_info : - &bl2_to_bl31_args->bl32_image_info; + bl2_to_bl31_params->bl33_ep : + bl2_to_bl31_params->bl32_ep; /* None of the images on this platform can have 0x0 as the entrypoint */ - if (next_image_info->entrypoint) + if (next_image_info->pc) return next_image_info; else return NULL; @@ -114,10 +116,15 @@ * has flushed this information to memory, so we are guaranteed to pick up good * data ******************************************************************************/ -void bl31_early_platform_setup(bl31_args_t *from_bl2, - void *data) +void bl31_early_platform_setup(bl31_tf_params_t *from_bl2, + bl31_plat_params_t *plat_info_from_bl2) { - bl2_to_bl31_args = from_bl2; + assert(from_bl2->h.type == PARAM_BL31); + assert(from_bl2->h.version >= VERSION_1); + + bl2_to_bl31_params = from_bl2; + bl2_to_bl31_plat_params = plat_info_from_bl2; + /* Initialize the console to provide early debug support */ console_init(PL011_UART0_BASE); @@ -172,7 +179,7 @@ ******************************************************************************/ void bl31_plat_arch_setup() { - configure_mmu_el3(&bl2_to_bl31_args->bl31_meminfo, + configure_mmu_el3(&bl2_to_bl31_plat_params->bl31_meminfo, BL31_RO_BASE, BL31_RO_LIMIT, BL31_COHERENT_RAM_BASE, diff --git a/plat/fvp/platform.h b/plat/fvp/platform.h index 40f780e..44e6d31 100644 --- a/plat/fvp/platform.h +++ b/plat/fvp/platform.h @@ -134,6 +134,10 @@ #define TZDRAM_SIZE 0x02000000 #define MBOX_OFF 0x1000 +/* Base address where parameters to BL31 are stored */ +#define PARAMS_BASE TZDRAM_BASE + + #define DRAM_BASE 0x80000000ull #define DRAM_SIZE 0x80000000ull @@ -339,6 +343,7 @@ #ifndef __ASSEMBLY__ #include +#include typedef volatile struct mailbox { @@ -347,6 +352,23 @@ } mailbox_t; /******************************************************************************* + * This structure represents the superset of information that is passed to + * BL31 e.g. while passing control to it from BL2 which is bl31_tf_params + * and bl31_plat_params and its elements + ******************************************************************************/ +typedef struct bl2_to_bl31_params_mem { + bl31_tf_params_t bl31_tf_params; + bl31_plat_params_t bl31_plat_params; + image_info_t bl31_image; + image_info_t bl32_image; + image_info_t bl33_image; + el_change_info_t bl33_ep; + el_change_info_t bl32_ep; + el_change_info_t bl31_ep; +} bl2_to_bl31_params_mem_t; + + +/******************************************************************************* * Forward declarations ******************************************************************************/ struct plat_pm_ops; @@ -412,6 +434,18 @@ /* Declarations for plat_security.c */ extern void plat_security_setup(void); +/* Do adjustments to the entrypoint, mode etc for BL2 */ +extern void bl1_plat_bl2_loaded(image_info_t *image, el_change_info_t *ep); + +/* Do adjustments to the entrypoint, mode etc for BL31 */ +extern void bl2_plat_bl31_loaded(image_info_t *image, el_change_info_t *ep); + +/* Do adjustments to the entrypoint, mode etc for BL32 */ +extern void bl2_plat_bl32_loaded(image_info_t *image, el_change_info_t *ep); + +/* Do adjustments to the entrypoint, mode etc for BL33 */ +extern void bl2_plat_bl33_loaded(image_info_t *image, el_change_info_t *ep); + #endif /*__ASSEMBLY__*/ diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c index 9fda307..d5f1163 100644 --- a/services/spd/tspd/tspd_main.c +++ b/services/spd/tspd/tspd_main.c @@ -96,7 +96,7 @@ * signalling failure initializing the service. We bail out without * registering any handlers */ - if (!image_info->entrypoint) + if (!image_info->pc) return 1; /* @@ -104,7 +104,7 @@ * state i.e whether AArch32 or AArch64. Assuming it's AArch64 * for the time being. */ - rc = tspd_init_secure_context(image_info->entrypoint, + rc = tspd_init_secure_context(image_info->pc, TSP_AARCH64, mpidr, &tspd_sp_context[linear_id]);