aboutsummaryrefslogtreecommitdiff
path: root/common/spl
diff options
context:
space:
mode:
Diffstat (limited to 'common/spl')
-rw-r--r--common/spl/Kconfig18
-rw-r--r--common/spl/spl.c20
-rw-r--r--common/spl/spl_atf.c129
-rw-r--r--common/spl/spl_fit.c47
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) {