[PATCH v2 3/3] mach-imx: bootaux: elf firmware support

Stefano Babic sbabic at denx.de
Mon Dec 30 13:23:07 CET 2019


On 30/12/19 13:04, Igor Opaniuk wrote:
> Hi Stefano,
> 
> On Sat, Dec 28, 2019 at 2:33 PM Stefano Babic <sbabic at denx.de> wrote:
>>
>>
>>
>> On 28/11/19 14:56, Igor Opaniuk wrote:
>>> From: Igor Opaniuk <igor.opaniuk at 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.opaniuk at toradex.com>
>>> Signed-off-by: Stefan Agner <stefan.agner at 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;
>>> +
>>
>> This generates a warning on 64bit targets (like imx8mq_evk):
>>
>>    aarch64:  w+   imx8mq_evk
>> +WARNING 'signed_hdmi_imx8m.bin' not found, resulting binary is
>> not-functional
>> +   dst = (void *)(phdr->p_paddr) ;//- mmap->da + mmap->sa;
>> +         ^
>> w+arch/arm/mach-imx/imx_bootaux.c: In function 'load_elf_image_phdr':
>> w+arch/arm/mach-imx/imx_bootaux.c:58:9: warning: cast to pointer from
>> integer of different size [-Wint-to-pointer-cast]
>>
>> Can you take a look ? I merge 1/3 and 2/3, no need to repost the whole
>> series - thanks !
> 
> Thanks for reporting the issue.
> 
> I've decided to disable ELF support for now for imx8mq in v3 patch [1], as
> it needs a bit different implementation pf loader for ELF64 binaries.

Right, I took a look, too, and changes are not trivial - it is fine for
me how to solve it and to enable for mx8m only.

> It makes sense to do refactoring of cmd/elf.c and move common code
> (ELF loading etc.) to a different file 

Fully agree.

>(I'll do that for the next
> U-boot release),

...well, this is already next release. Series flew into my -next branch,
I am allowed to push just fixes for 2020.01. I pick up your V3, too,
into my -next.

Regards,
Stefano

> which can be then re-used from bootaux command implementation.
> 
> v3 currently builds with one un-related to this patch warning:
> u-boot-imx.git$ ./tools/buildman/buildman -f -j10 -d imx8mq_evk -v
> ../boards.cfg is up to date. Nothing to do.
> Building current source for 1 boards (1 thread, 10 jobs per thread)
>    aarch64:  w+   imx8mq_evk
> +WARNING 'signed_hdmi_imx8m.bin' not found, resulting binary is not-functional
>     0    1    0 /1      imx8mq_evk
> 
> [1] https://patchwork.ozlabs.org/patch/1216413/
>>
>> Best regards,
>> Stefano
>>
>>> +             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)
>>>
>>
>> --
>> =====================================================================
>> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
>> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
>> Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
>> =====================================================================
> 
> 
> 


-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================


More information about the U-Boot mailing list