diff options
Diffstat (limited to 'common/spl')
-rw-r--r-- | common/spl/Kconfig | 18 | ||||
-rw-r--r-- | common/spl/spl.c | 20 | ||||
-rw-r--r-- | common/spl/spl_atf.c | 129 | ||||
-rw-r--r-- | common/spl/spl_fit.c | 47 |
4 files changed, 181 insertions, 33 deletions
diff --git a/common/spl/Kconfig b/common/spl/Kconfig index d8086bd9e8..6b0186763b 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -113,6 +113,15 @@ config SPL_FSL_PBL Create boot binary having SPL binary in PBI format concatenated with u-boot binary. +config SPL_ALLOC_BD + bool "Allocate memory for bd_info" + default y if X86 || SANDBOX + help + Some boards don't allocate space for this in their board_init_f() + code. In this case U-Boot can allocate space for gd->bd in the + standard SPL flow (board_init_r()). Enable this option to support + this feature. + endmenu config HANDOFF @@ -1276,6 +1285,15 @@ config SPL_ATF is loaded by SPL (which is considered as BL2 in ATF terminology). More detail at: https://github.com/ARM-software/arm-trusted-firmware +config SPL_ATF_LOAD_IMAGE_V2 + bool "Use the new LOAD_IMAGE_V2 parameter passing" + depends on SPL_ATF + help + Some platforms use the newer LOAD_IMAGE_V2 parameter passing. + + If you want to load a bl31 image from the SPL and need the new + method, say Y. + config SPL_ATF_NO_PLATFORM_PARAM bool "Pass no platform parameter" depends on SPL_ATF diff --git a/common/spl/spl.c b/common/spl/spl.c index 63c48fbf33..835c53deaa 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -53,9 +53,6 @@ binman_sym_declare(ulong, spl, image_pos); binman_sym_declare(ulong, spl, size); #endif -/* Define board data structure */ -static struct bd_info bdata __attribute__ ((section(".data"))); - /* * Board-specific Platform code can reimplement show_boot_progress () if needed */ @@ -443,14 +440,19 @@ static int spl_common_init(bool setup_malloc) return 0; } -void spl_set_bd(void) +int spl_alloc_bd(void) { /* * NOTE: On some platforms (e.g. x86) bdata may be in flash and not * writeable. */ - if (!gd->bd) - gd->bd = &bdata; + if (!gd->bd) { + gd->bd = malloc(sizeof(*gd->bd)); + if (!gd->bd) + return -ENOMEM; + } + + return 0; } int spl_early_init(void) @@ -600,8 +602,6 @@ void board_init_r(gd_t *dummy1, ulong dummy2) debug(">>" SPL_TPL_PROMPT "board_init_r()\n"); - spl_set_bd(); - #if defined(CONFIG_SYS_SPL_MALLOC_START) mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START, CONFIG_SYS_SPL_MALLOC_SIZE); @@ -611,6 +611,10 @@ void board_init_r(gd_t *dummy1, ulong dummy2) if (spl_init()) hang(); } + if (IS_ENABLED(CONFIG_SPL_ALLOC_BD) && spl_alloc_bd()) { + puts("Cannot alloc bd\n"); + hang(); + } #if !defined(CONFIG_PPC) && !defined(CONFIG_ARCH_MX6) /* * timer_init() does not exist on PPC systems. The timer is initialized diff --git a/common/spl/spl_atf.c b/common/spl/spl_atf.c index 9bd25f6b32..e1b68dd561 100644 --- a/common/spl/spl_atf.c +++ b/common/spl/spl_atf.c @@ -18,13 +18,36 @@ #include <spl.h> #include <asm/cache.h> -static struct bl2_to_bl31_params_mem bl31_params_mem; -static struct bl31_params *bl2_to_bl31_params; - -__weak struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry, - uintptr_t bl33_entry, - uintptr_t fdt_addr) +/* Holds all the structures we need for bl31 parameter passing */ +struct bl2_to_bl31_params_mem { + struct bl31_params bl31_params; + struct atf_image_info bl31_image_info; + struct atf_image_info bl32_image_info; + struct atf_image_info bl33_image_info; + struct entry_point_info bl33_ep_info; + struct entry_point_info bl32_ep_info; + struct entry_point_info bl31_ep_info; +}; + +struct bl2_to_bl31_params_mem_v2 { + struct bl_params bl_params; + struct bl_params_node bl31_params_node; + struct bl_params_node bl32_params_node; + struct bl_params_node bl33_params_node; + struct atf_image_info bl31_image_info; + struct atf_image_info bl32_image_info; + struct atf_image_info bl33_image_info; + struct entry_point_info bl33_ep_info; + struct entry_point_info bl32_ep_info; + struct entry_point_info bl31_ep_info; +}; + +struct bl31_params *bl2_plat_get_bl31_params_default(uintptr_t bl32_entry, + uintptr_t bl33_entry, + uintptr_t fdt_addr) { + static struct bl2_to_bl31_params_mem bl31_params_mem; + struct bl31_params *bl2_to_bl31_params; struct entry_point_info *bl32_ep_info; struct entry_point_info *bl33_ep_info; @@ -78,6 +101,87 @@ __weak struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry, return bl2_to_bl31_params; } +__weak struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry, + uintptr_t bl33_entry, + uintptr_t fdt_addr) +{ + return bl2_plat_get_bl31_params_default(bl32_entry, bl33_entry, + fdt_addr); +} + +struct bl_params *bl2_plat_get_bl31_params_v2_default(uintptr_t bl32_entry, + uintptr_t bl33_entry, + uintptr_t fdt_addr) +{ + static struct bl2_to_bl31_params_mem_v2 bl31_params_mem; + struct bl_params *bl_params; + struct bl_params_node *bl_params_node; + + /* + * Initialise the memory for all the arguments that needs to + * be passed to BL31 + */ + memset(&bl31_params_mem, 0, sizeof(bl31_params_mem)); + + /* Assign memory for TF related information */ + bl_params = &bl31_params_mem.bl_params; + SET_PARAM_HEAD(bl_params, ATF_PARAM_BL_PARAMS, ATF_VERSION_2, 0); + bl_params->head = &bl31_params_mem.bl31_params_node; + + /* Fill BL31 related information */ + bl_params_node = &bl31_params_mem.bl31_params_node; + bl_params_node->image_id = ATF_BL31_IMAGE_ID; + bl_params_node->image_info = &bl31_params_mem.bl31_image_info; + bl_params_node->ep_info = &bl31_params_mem.bl31_ep_info; + bl_params_node->next_params_info = &bl31_params_mem.bl32_params_node; + SET_PARAM_HEAD(bl_params_node->image_info, ATF_PARAM_IMAGE_BINARY, + ATF_VERSION_2, 0); + + /* Fill BL32 related information */ + bl_params_node = &bl31_params_mem.bl32_params_node; + bl_params_node->image_id = ATF_BL32_IMAGE_ID; + bl_params_node->image_info = &bl31_params_mem.bl32_image_info; + bl_params_node->ep_info = &bl31_params_mem.bl32_ep_info; + bl_params_node->next_params_info = &bl31_params_mem.bl33_params_node; + SET_PARAM_HEAD(bl_params_node->ep_info, ATF_PARAM_EP, + ATF_VERSION_2, ATF_EP_SECURE); + + /* secure payload is optional, so set pc to 0 if absent */ + bl_params_node->ep_info->args.arg3 = fdt_addr; + bl_params_node->ep_info->pc = bl32_entry ? bl32_entry : 0; + bl_params_node->ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXECPTIONS); + SET_PARAM_HEAD(bl_params_node->image_info, ATF_PARAM_IMAGE_BINARY, + ATF_VERSION_2, 0); + + /* Fill BL33 related information */ + bl_params_node = &bl31_params_mem.bl33_params_node; + bl_params_node->image_id = ATF_BL33_IMAGE_ID; + bl_params_node->image_info = &bl31_params_mem.bl33_image_info; + bl_params_node->ep_info = &bl31_params_mem.bl33_ep_info; + bl_params_node->next_params_info = NULL; + SET_PARAM_HEAD(bl_params_node->ep_info, ATF_PARAM_EP, + ATF_VERSION_2, ATF_EP_NON_SECURE); + + /* BL33 expects to receive the primary CPU MPID (through x0) */ + bl_params_node->ep_info->args.arg0 = 0xffff & read_mpidr(); + bl_params_node->ep_info->pc = bl33_entry; + bl_params_node->ep_info->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXECPTIONS); + SET_PARAM_HEAD(bl_params_node->image_info, ATF_PARAM_IMAGE_BINARY, + ATF_VERSION_2, 0); + + return bl_params; +} + +__weak struct bl_params *bl2_plat_get_bl31_params_v2(uintptr_t bl32_entry, + uintptr_t bl33_entry, + uintptr_t fdt_addr) +{ + return bl2_plat_get_bl31_params_v2_default(bl32_entry, bl33_entry, + fdt_addr); +} + static inline void raw_write_daif(unsigned int daif) { __asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory"); @@ -88,16 +192,21 @@ typedef void (*atf_entry_t)(struct bl31_params *params, void *plat_params); static void bl31_entry(uintptr_t bl31_entry, uintptr_t bl32_entry, uintptr_t bl33_entry, uintptr_t fdt_addr) { - struct bl31_params *bl31_params; atf_entry_t atf_entry = (atf_entry_t)bl31_entry; + void *bl31_params; - bl31_params = bl2_plat_get_bl31_params(bl32_entry, bl33_entry, - fdt_addr); + if (CONFIG_IS_ENABLED(ATF_LOAD_IMAGE_V2)) + bl31_params = bl2_plat_get_bl31_params_v2(bl32_entry, + bl33_entry, + fdt_addr); + else + bl31_params = bl2_plat_get_bl31_params(bl32_entry, bl33_entry, + fdt_addr); raw_write_daif(SPSR_EXCEPTION_MASK); dcache_disable(); - atf_entry((void *)bl31_params, (void *)fdt_addr); + atf_entry(bl31_params, (void *)fdt_addr); } static int spl_fit_images_find(void *blob, int os) diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 6418062b93..795e2922ce 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -495,6 +495,23 @@ static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os) } /* + * The purpose of the FIT load buffer is to provide a memory location that is + * independent of the load address of any FIT component. + */ +static void *spl_get_fit_load_buffer(size_t size) +{ + void *buf; + + buf = malloc(size); + if (!buf) { + pr_err("Could not get FIT buffer of %lu bytes\n", (ulong)size); + pr_err("\tcheck CONFIG_SYS_SPL_MALLOC_SIZE\n"); + buf = spl_get_load_buffer(0, size); + } + return buf; +} + +/* * Weak default function to allow customizing SPL fit loading for load-only * use cases by allowing to skip the parsing/processing of the FIT contents * (so that this can be done separately in a more customized fashion) @@ -508,12 +525,12 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, struct spl_load_info *info, ulong sector, void *fit) { int sectors; - ulong size; + ulong size, hsize; unsigned long count; struct spl_image_info image_info; int node = -1; int images, ret; - int base_offset, hsize, align_len = ARCH_DMA_MINALIGN - 1; + int base_offset; int index = 0; int firmware_node; @@ -529,24 +546,14 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, /* * So far we only have one block of data from the FIT. Read the entire - * thing, including that first block, placing it so it finishes before - * where we will load the image. - * - * Note that we will load the image such that its first byte will be - * at the load address. Since that byte may be part-way through a - * block, we may load the image up to one block before the load - * address. So take account of that here by subtracting an addition - * block length from the FIT start position. - * - * In fact the FIT has its own load address, but we assume it cannot - * be before CONFIG_SYS_TEXT_BASE. + * thing, including that first block. * * For FIT with data embedded, data is loaded as part of FIT image. * For FIT with external data, data is not loaded in this step. */ - hsize = (size + info->bl_len + align_len) & ~align_len; - fit = spl_get_load_buffer(-hsize, hsize); sectors = get_aligned_image_size(info, size, 0); + hsize = sectors * info->bl_len; + fit = spl_get_fit_load_buffer(hsize); count = info->read(info, sector, sectors, fit); debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu, size=0x%lx\n", sector, sectors, fit, count, size); @@ -558,6 +565,16 @@ int spl_load_simple_fit(struct spl_image_info *spl_image, if (spl_load_simple_fit_skip_processing()) return 0; + if (IS_ENABLED(CONFIG_SPL_FIT_SIGNATURE)) { + int conf_offset = fit_find_config_node(fit); + + printf("## Checking hash(es) for config %s ... ", + fit_get_name(fit, conf_offset, NULL)); + if (fit_config_verify(fit, conf_offset)) + return -EPERM; + puts("OK\n"); + } + /* find the node holding the images information */ images = fdt_path_offset(fit, FIT_IMAGES_PATH); if (images < 0) { |