On Thu, Nov 28, 2019 at 3:57 PM Igor Opaniuk <igor.opan...@gmail.com> wrote: > > From: Igor Opaniuk <igor.opan...@toradex.com> > > Currently imx-specific bootaux command doesn't support ELF format > firmware for Cortex-M4 core. > > This patches introduces a PoC implementation of handling elf firmware > (load_elf_image_phdr() was copy-pasted from elf.c just for PoC). > > This has the advantage that the user does not need to know to which > address the binary has been linked to. However, in order to handle > and load the elf sections to the right address, we need to translate the > Cortex-M4 core memory addresses to primary/host CPU memory > addresses (Cortex A7/A9 cores). > > This allows to boot firmwares from any location with just using > bootaux, e.g.: > > tftp ${loadaddr} hello_world.elf && bootaux ${loadaddr} > > Similar translation table can be found in the Linux remoteproc > driver [1]. > > [1] > https://elixir.bootlin.com/linux/latest/source/drivers/remoteproc/imx_rproc.c > > Signed-off-by: Igor Opaniuk <igor.opan...@toradex.com> > Signed-off-by: Stefan Agner <stefan.ag...@toradex.com>
Reviewed-by: Oleksandr Suvorov <oleksandr.suvo...@toradex.com> > --- > > arch/arm/include/asm/mach-imx/sys_proto.h | 7 ++ > arch/arm/mach-imx/imx_bootaux.c | 84 +++++++++++++++++++++-- > arch/arm/mach-imx/mx7/soc.c | 28 ++++++++ > 3 files changed, 115 insertions(+), 4 deletions(-) > > diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h > b/arch/arm/include/asm/mach-imx/sys_proto.h > index 1e627c8fc3..ed5d9a1667 100644 > --- a/arch/arm/include/asm/mach-imx/sys_proto.h > +++ b/arch/arm/include/asm/mach-imx/sys_proto.h > @@ -104,6 +104,13 @@ void gpr_init(void); > > #endif /* CONFIG_MX6 */ > > +/* address translation table */ > +struct rproc_att { > + u32 da; /* device address (From Cortex M4 view) */ > + u32 sa; /* system bus address */ > + u32 size; /* size of reg range */ > +}; > + > u32 get_nr_cpus(void); > u32 get_cpu_rev(void); > u32 get_cpu_speed_grade_hz(void); > diff --git a/arch/arm/mach-imx/imx_bootaux.c b/arch/arm/mach-imx/imx_bootaux.c > index c750cee60c..871169e771 100644 > --- a/arch/arm/mach-imx/imx_bootaux.c > +++ b/arch/arm/mach-imx/imx_bootaux.c > @@ -7,18 +7,94 @@ > #include <asm/io.h> > #include <asm/mach-imx/sys_proto.h> > #include <command.h> > +#include <elf.h> > #include <imx_sip.h> > #include <linux/compiler.h> > > -int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) > +const __weak struct rproc_att hostmap[] = { }; > + > +static const struct rproc_att *get_host_mapping(unsigned long auxcore) > +{ > + const struct rproc_att *mmap = hostmap; > + > + while (mmap && mmap->size) { > + if (mmap->da <= auxcore && > + mmap->da + mmap->size > auxcore) > + return mmap; > + mmap++; > + } > + > + return NULL; > +} > + > +/* > + * A very simple elf loader, assumes the image is valid, returns the > + * entry point address. > + */ > +static unsigned long load_elf_image_phdr(unsigned long addr) > +{ > + Elf32_Ehdr *ehdr; /* ELF header structure pointer */ > + Elf32_Phdr *phdr; /* Program header structure pointer */ > + int i; > + > + ehdr = (Elf32_Ehdr *)addr; > + phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); > + > + /* Load each program header */ > + for (i = 0; i < ehdr->e_phnum; ++i, ++phdr) { > + const struct rproc_att *mmap = > get_host_mapping(phdr->p_paddr); > + void *dst, *src; > + > + if (phdr->p_type != PT_LOAD) > + continue; > + > + if (!mmap) { > + printf("Invalid aux core address: %08x", > + phdr->p_paddr); > + return 0; > + } > + > + dst = (void *)(phdr->p_paddr - mmap->da) + mmap->sa; > + src = (void *)addr + phdr->p_offset; > + > + debug("Loading phdr %i to 0x%p (%i bytes)\n", > + i, dst, phdr->p_filesz); > + > + if (phdr->p_filesz) > + memcpy(dst, src, phdr->p_filesz); > + if (phdr->p_filesz != phdr->p_memsz) > + memset(dst + phdr->p_filesz, 0x00, > + phdr->p_memsz - phdr->p_filesz); > + flush_cache((unsigned long)dst & > + ~(CONFIG_SYS_CACHELINE_SIZE - 1), > + ALIGN(phdr->p_filesz, CONFIG_SYS_CACHELINE_SIZE)); > + } > + > + return ehdr->e_entry; > +} > + > +int arch_auxiliary_core_up(u32 core_id, ulong addr) > { > ulong stack, pc; > > - if (!boot_private_data) > + if (!addr) > return -EINVAL; > > - stack = *(u32 *)boot_private_data; > - pc = *(u32 *)(boot_private_data + 4); > + if (valid_elf_image(addr)) { > + stack = 0x0; > + pc = load_elf_image_phdr(addr); > + if (!pc) > + return CMD_RET_FAILURE; > + > + } else { > + /* > + * Assume binary file with vector table at the beginning. > + * Cortex-M4 vector tables start with the stack pointer (SP) > + * and reset vector (initial PC). > + */ > + stack = *(u32 *)addr; > + pc = *(u32 *)(addr + 4); > + } > > printf("## Starting auxiliary core stack = 0x%08lX, pc = > 0x%08lX...\n", > stack, pc); > diff --git a/arch/arm/mach-imx/mx7/soc.c b/arch/arm/mach-imx/mx7/soc.c > index 35160f4b37..4aafeed188 100644 > --- a/arch/arm/mach-imx/mx7/soc.c > +++ b/arch/arm/mach-imx/mx7/soc.c > @@ -193,6 +193,34 @@ static void init_cpu_basic(void) > #endif > } > > +#ifdef CONFIG_IMX_BOOTAUX > +/* > + * Table of mappings of physical mem regions in both > + * Cortex-A7 and Cortex-M4 address spaces. > + * > + * For additional details check sections 2.1.2 and 2.1.3 in > + * i.MX7Dual Applications Processor Reference Manual > + * > + */ > +const struct rproc_att hostmap[] = { > + /* aux core , host core, size */ > + { 0x00000000, 0x00180000, 0x8000 }, /* OCRAM_S */ > + { 0x00180000, 0x00180000, 0x8000 }, /* OCRAM_S */ > + { 0x20180000, 0x00180000, 0x8000 }, /* OCRAM_S */ > + { 0x1fff8000, 0x007f8000, 0x8000 }, /* TCML */ > + { 0x20000000, 0x00800000, 0x8000 }, /* TCMU */ > + { 0x00900000, 0x00900000, 0x20000 }, /* OCRAM_128KB */ > + { 0x20200000, 0x00900000, 0x20000 }, /* OCRAM_128KB */ > + { 0x00920000, 0x00920000, 0x20000 }, /* OCRAM_EPDC */ > + { 0x20220000, 0x00920000, 0x20000 }, /* OCRAM_EPDC */ > + { 0x00940000, 0x00940000, 0x20000 }, /* OCRAM_PXP */ > + { 0x20240000, 0x00940000, 0x20000 }, /* OCRAM_PXP */ > + { 0x10000000, 0x80000000, 0x0fff0000 }, /* DDR Code alias */ > + { 0x80000000, 0x80000000, 0xe0000000 }, /* DDRC */ > + { /* sentinel */ } > +}; > +#endif > + > #ifndef CONFIG_SKIP_LOWLEVEL_INIT > /* enable all periherial can be accessed in nosec mode */ > static void init_csu(void) > -- > 2.17.1 > > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > https://lists.denx.de/listinfo/u-boot -- Best regards Oleksandr Suvorov Toradex AG Altsagenstrasse 5 | 6048 Horw/Luzern | Switzerland | T: +41 41 500 4800 (main line)