diff options
Diffstat (limited to 'plat/juno/bl2_plat_setup.c')
-rw-r--r-- | plat/juno/bl2_plat_setup.c | 437 |
1 files changed, 437 insertions, 0 deletions
diff --git a/plat/juno/bl2_plat_setup.c b/plat/juno/bl2_plat_setup.c new file mode 100644 index 0000000..1a26e43 --- /dev/null +++ b/plat/juno/bl2_plat_setup.c @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2013-2014, 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 <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <console.h> +#include <debug.h> +#include <platform.h> +#include <platform_def.h> +#include <string.h> +#include "juno_def.h" +#include "juno_private.h" +#include "scp_bootloader.h" +#include <xlat_tables.h> +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted RAM + ******************************************************************************/ +extern unsigned long __RO_START__; +extern unsigned long __RO_END__; + +extern unsigned long __COHERENT_RAM_START__; +extern unsigned long __COHERENT_RAM_END__; + +/* + * The next 2 constants identify the extents of the code & RO data region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +#define BL2_RO_BASE (unsigned long)(&__RO_START__) +#define BL2_RO_LIMIT (unsigned long)(&__RO_END__) + +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to + * page-aligned addresses. + */ +#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) +#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) + +/* Data structure which holds the extents of the trusted RAM for BL2 */ +static meminfo_t bl2_tzram_layout +__attribute__ ((aligned(PLATFORM_CACHE_LINE_SIZE), + section("tzfw_coherent_mem"))); + +/******************************************************************************* + * Structure which holds the arguments which need to be passed to BL3-1 + ******************************************************************************/ +static bl2_to_bl31_params_mem_t bl31_params_mem; + +meminfo_t *bl2_plat_sec_mem_layout(void) +{ + return &bl2_tzram_layout; +} + +/******************************************************************************* + * 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_params_t *bl2_plat_get_bl31_params(void) +{ + bl31_params_t *bl2_to_bl31_params; + + /* + * Initialise the memory for all the arguments that needs to + * be passed to BL3-1 + */ + memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t)); + + /* Assign memory for TF related information */ + bl2_to_bl31_params = &bl31_params_mem.bl31_params; + SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0); + + /* Fill BL3-1 related information */ + bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY, + VERSION_1, 0); + + /* Fill BL3-2 related information if it exists */ +#if BL32_BASE + bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP, + VERSION_1, 0); + bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY, + VERSION_1, 0); +#endif + + /* Fill BL3-3 related information */ + bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info, + PARAM_EP, VERSION_1, 0); + /* UEFI expects to receive the primary CPU MPID (through x0) */ + bl2_to_bl31_params->bl33_ep_info->args.arg0 = PRIMARY_CPU; + + bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY, + VERSION_1, 0); + + return bl2_to_bl31_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 entry_point_info *bl2_plat_get_bl31_ep_info(void) +{ +#if DEBUG + bl31_params_mem.bl31_ep_info.args.arg1 = JUNO_BL31_PLAT_PARAM_VAL; +#endif + + return &bl31_params_mem.bl31_ep_info; +} + +/******************************************************************************* + * BL1 has passed the extents of the trusted RAM that should be visible to BL2 + * in x0. This memory layout is sitting at the base of the free trusted RAM. + * Copy it to a safe loaction before its reclaimed by later BL2 functionality. + ******************************************************************************/ +void bl2_early_platform_setup(meminfo_t *mem_layout) +{ + /* Initialize the console to provide early debug support */ + //console_init(PL011_UART0_BASE); + //char c; + console_init(52); //24M + +console_putc('h'); +console_putc('a'); +console_putc('h'); +console_putc('a'); + /* Setup the BL2 memory layout */ +#if 0 + bl2_tzram_layout.total_base = mem_layout->total_base; + bl2_tzram_layout.total_size = mem_layout->total_size; + bl2_tzram_layout.free_base = mem_layout->free_base; + bl2_tzram_layout.free_size = mem_layout->free_size; + bl2_tzram_layout.attr = mem_layout->attr; + bl2_tzram_layout.next = 0; +#endif + bl2_tzram_layout.total_base = TZRAM_BASE; + bl2_tzram_layout.total_size = TZRAM_SIZE; + bl2_tzram_layout.free_base = TZRAM_BASE; + bl2_tzram_layout.free_size = TZRAM_SIZE; + bl2_tzram_layout.attr = (unsigned long)0x0E939E2E8CF8EFFD; + bl2_tzram_layout.next = 0; +console_putc('h'); +console_putc('e'); +console_putc('h'); +console_putc('e'); +} + +/******************************************************************************* + * Load BL3-0 into Trusted RAM, then transfer it using the SCP Download + * protocol. The image is loaded into RAM in the same place that BL3-1 will be + * loaded later so here, we copy the RAM layout structure and use it to load + * the image into. When this function exits, the RAM layout remains untouched + * so the BL2 can load BL3-1 as normal. + ******************************************************************************/ +static int load_bl30(void) +{ + meminfo_t *bl2_tzram_layout; + meminfo_t tmp_tzram_layout; + uintptr_t bl30_base; + uint32_t bl30_size; + unsigned int bl2_load, bl30_load; + int ret; + int e; + image_info_t bl30_image_info; + + /* Find out how much free trusted ram remains after BL2 load */ + bl2_tzram_layout = bl2_plat_sec_mem_layout(); + + /* copy the TZRAM layout and use it */ + memcpy(&tmp_tzram_layout, bl2_tzram_layout, sizeof(meminfo_t)); + + /* Work out where to load BL3-0 before transferring to SCP */ + bl2_load = tmp_tzram_layout.attr & LOAD_MASK; + assert((bl2_load == TOP_LOAD) || (bl2_load == BOT_LOAD)); + bl30_load = (bl2_load == TOP_LOAD) ? BOT_LOAD : TOP_LOAD; + + SET_PARAM_HEAD(&bl30_image_info, PARAM_IMAGE_BINARY, VERSION_1, 0); + + /* Load the BL3-0 image */ + e = load_image(&tmp_tzram_layout, + BL30_IMAGE_NAME, + bl30_load, + BL30_BASE, + &bl30_image_info, + NULL); + + /* Panic if it has not been possible to load BL3-0 */ + if (e) { + ERROR("Failed to load BL3-0 image.\n"); + panic(); + } + + bl30_base = bl30_image_info.image_base; + bl30_size = bl30_image_info.image_size; + assert(bl30_base != 0); + assert(bl30_size != 0); + + INFO("BL2: BL3-0 loaded at 0x%lx, len=%d (0x%x)\n\r", bl30_base, + bl30_size, bl30_size); + flush_dcache_range(bl30_base, bl30_size); + ret = scp_bootloader_transfer((void *)bl30_base, bl30_size); + + if (ret == 0) + INFO("BL2: BL3-0 loaded and transferred to SCP\n\r"); + else + ERROR("BL2: BL3-0 load and transfer failure\n\r"); + + return ret; +} + +/******************************************************************************* + * Perform platform specific setup, i.e. initialize the IO layer, load BL3-0 + * image and initialise the memory location to use for passing arguments to + * BL3-1. + ******************************************************************************/ +void bl2_platform_setup(void) +{ + /* Initialise the IO layer and register platform IO devices */ + io_setup(); + + /* Load BL3-0 */ + if (load_bl30() != 0) + panic(); +} + +/* Flush the TF params and the TF plat params */ +void bl2_plat_flush_bl31_params(void) +{ + flush_dcache_range((unsigned long)&bl31_params_mem, + sizeof(bl2_to_bl31_params_mem_t)); +} + +/* + * Table of regions to map using the MMU. + * This doesn't include Trusted RAM as the 'mem_layout' argument passed to + * configure_mmu_elx() will give the available subset of that, + */ +static const mmap_region_t juno_mmap[] = { +#if 0 + { TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { MHU_SECURE_BASE, MHU_SECURE_SIZE, (MHU_PAYLOAD_CACHED ? MT_MEMORY : MT_DEVICE) + | MT_RW | MT_SECURE }, +// { TZRAM_BASE, TZRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, /* configure_mmu() meminfo arg sets subset of this */ + { FLASH_BASE, FLASH_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { EMMC_BASE, EMMC_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { PSRAM_BASE, PSRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, /* Used for 'TZDRAM' */ + { IOFPGA_BASE, IOFPGA_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, +// { NSROM_BASE, NSROM_SIZE, MT_MEMORY | MT_RW | MT_NS }, /* Eats a page table so leave it out for now */ + { DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { NSRAM_BASE, NSRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, + { DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, +#endif + + { TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, + { DEVICEG_BASE, DEVICEG_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + + {0} +}; +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl2_plat_arch_setup(void) +{ +console_putc('a'); +console_putc('r'); +console_putc('c'); +console_putc('h'); +/* + configure_mmu_el1(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + BL2_RO_BASE, + BL2_RO_LIMIT, + BL2_COHERENT_RAM_BASE, + BL2_COHERENT_RAM_LIMIT); +*/ + +mmap_add_region(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + MT_MEMORY | MT_RW | MT_SECURE); +console_putc('1'); +mmap_add_region(BL2_RO_BASE, BL2_RO_LIMIT - BL2_RO_BASE, + MT_MEMORY | MT_RO | MT_SECURE); +console_putc('2'); +mmap_add_region(BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT - BL2_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE); +console_putc('3'); +mmap_add(juno_mmap); +console_putc('4'); +init_xlat_tables(); +console_putc('5'); +//enable_mmu_el1(); + + +console_putc('o'); +console_putc('v'); +console_putc('e'); +console_putc('r'); +} + +/******************************************************************************* + * Before calling this function BL31 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL31 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + ******************************************************************************/ +void bl2_plat_set_bl31_ep_info(image_info_t *bl31_image_info, + entry_point_info_t *bl31_ep_info) +{ + SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE); + bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); +} + + +/******************************************************************************* + * Before calling this function BL32 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL32 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + ******************************************************************************/ +void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info, + entry_point_info_t *bl32_ep_info) +{ + SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE); + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + bl32_ep_info->spsr = 0; +} + +/******************************************************************************* + * Before calling this function BL33 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL33 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + ******************************************************************************/ +void bl2_plat_set_bl33_ep_info(image_info_t *image, + entry_point_info_t *bl33_ep_info) +{ + 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_info->spsr = SPSR_64(mode, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE); +} + +/******************************************************************************* + * Populate the extents of memory available for loading BL3-2 + ******************************************************************************/ +void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo) +{ + /* + * Populate the extents of memory available for loading BL3-2. + */ + bl32_meminfo->total_base = BL32_BASE; + bl32_meminfo->free_base = BL32_BASE; + bl32_meminfo->total_size = + (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; + bl32_meminfo->free_size = + (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; + bl32_meminfo->attr = BOT_LOAD; + bl32_meminfo->next = 0; +} + + +/******************************************************************************* + * Populate the extents of memory available for loading BL3-3 + ******************************************************************************/ +void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo) +{ + bl33_meminfo->total_base = DRAM_BASE; + bl33_meminfo->total_size = DRAM_SIZE; + bl33_meminfo->free_base = DRAM_BASE; + bl33_meminfo->free_size = DRAM_SIZE; + bl33_meminfo->attr = 0; + bl33_meminfo->attr = 0; +} |