Hi Igor. > Subject: [PATCH v1] imx: bootaux: elf firmware support
We also have similar support for i.MX8 DSP firmware loading. Good to see your patch. > > 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). Could an runtime check be added for those aux cores which has same mapping as host cores? Thanks, Peng > > 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://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Felixir.b > ootlin.com%2Flinux%2Flatest%2Fsource%2Fdrivers%2Fremoteproc%2Fimx_r > proc.c&data=02%7C01%7Cpeng.fan%40nxp.com%7Cb511f03c8e4e4265 > 154908d766b277aa%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7 > C637090789004070829&sdata=tJoptyJCnuKIersJt9KmhR8nNYEdnl4SxM > VKLvA7KNc%3D&reserved=0 > > Signed-off-by: Igor Opaniuk <igor.opan...@toradex.com> > Signed-off-by: Stefan Agner <stefan.ag...@toradex.com> > --- > > arch/arm/include/asm/mach-imx/sys_proto.h | 7 ++ > arch/arm/mach-imx/imx_bootaux.c | 87 > +++++++++++++++++++++-- > arch/arm/mach-imx/mx7/soc.c | 28 ++++++++ > 3 files changed, 118 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 52c83ba9e4..4428a7fa0b 100644 > --- a/arch/arm/include/asm/mach-imx/sys_proto.h > +++ b/arch/arm/include/asm/mach-imx/sys_proto.h > @@ -139,6 +139,13 @@ enum boot_dev_type_e { extern struct rom_api > *g_rom_api; #endif > > +/* 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 3d9422d5a2..7f4bbfe885 > 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); > + } > > /* Set the stack and pc to M4 bootROM */ > writel(stack, M4_BOOTROM_BASE_ADDR); > @@ -80,6 +156,9 @@ static int do_bootaux(cmd_tbl_t *cmdtp, int flag, int > argc, char * const argv[]) > > addr = simple_strtoul(argv[1], NULL, 16); > > + if (!addr) > + return CMD_RET_FAILURE; > + > printf("## Starting auxiliary core at 0x%08lX ...\n", addr); > > ret = arch_auxiliary_core_up(0, addr); 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