Re: [U-Boot] [PATCH v2 04/26] remoteproc: elf-loader: Add 64 bit elf loading support

2019-10-12 Thread Tom Rini
On Wed, Sep 04, 2019 at 04:01:29PM +0530, Lokesh Vutla wrote:

> The current rproc-elf-loader supports loading of only 32 bit elf files.
> Introduce support for loading of 64 bit elf files in rproc-elf-loader.
> 
> Signed-off-by: Lokesh Vutla 
> Reviewed-by: Fabien Dessenne 

Applied to u-boot/master, thanks!

-- 
Tom


signature.asc
Description: PGP signature
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v2 04/26] remoteproc: elf-loader: Add 64 bit elf loading support

2019-09-04 Thread Fabien DESSENNE
Hi Lokesh

Thank you for the patch.

BR

Fabien


On 04/09/2019 12:31 PM, Lokesh Vutla wrote:
> The current rproc-elf-loader supports loading of only 32 bit elf files.
> Introduce support for loading of 64 bit elf files in rproc-elf-loader.
>
> Signed-off-by: Lokesh Vutla 
Reviewed-by: Fabien Dessenne 
> ---
>   drivers/remoteproc/rproc-elf-loader.c | 110 ++
>   include/remoteproc.h  |  26 ++
>   2 files changed, 136 insertions(+)
>
> diff --git a/drivers/remoteproc/rproc-elf-loader.c 
> b/drivers/remoteproc/rproc-elf-loader.c
> index 238f51d3b5..1aece2fc31 100644
> --- a/drivers/remoteproc/rproc-elf-loader.c
> +++ b/drivers/remoteproc/rproc-elf-loader.c
> @@ -64,6 +64,62 @@ int rproc_elf32_sanity_check(ulong addr, ulong size)
>   return 0;
>   }
>   
> +/* Basic function to verify ELF64 image format */
> +int rproc_elf64_sanity_check(ulong addr, ulong size)
> +{
> + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)addr;
> + char class;
> +
> + if (!addr) {
> + pr_debug("Invalid fw address?\n");
> + return -EFAULT;
> + }
> +
> + if (size < sizeof(Elf64_Ehdr)) {
> + pr_debug("Image is too small\n");
> + return -ENOSPC;
> + }
> +
> + class = ehdr->e_ident[EI_CLASS];
> +
> + if (!IS_ELF(*ehdr) || ehdr->e_type != ET_EXEC || class != ELFCLASS64) {
> + pr_debug("Not an executable ELF64 image\n");
> + return -EPROTONOSUPPORT;
> + }
> +
> + /* We assume the firmware has the same endianness as the host */
> +# ifdef __LITTLE_ENDIAN
> + if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
> +# else /* BIG ENDIAN */
> + if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
> +# endif
> + pr_debug("Unsupported firmware endianness\n");
> + return -EILSEQ;
> + }
> +
> + if (size < ehdr->e_shoff + sizeof(Elf64_Shdr)) {
> + pr_debug("Image is too small\n");
> + return -ENOSPC;
> + }
> +
> + if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
> + pr_debug("Image is corrupted (bad magic)\n");
> + return -EBADF;
> + }
> +
> + if (ehdr->e_phnum == 0) {
> + pr_debug("No loadable segments\n");
> + return -ENOEXEC;
> + }
> +
> + if (ehdr->e_phoff > size) {
> + pr_debug("Firmware size is too small\n");
> + return -ENOSPC;
> + }
> +
> + return 0;
> +}
> +
>   int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong 
> size)
>   {
>   Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> @@ -110,3 +166,57 @@ int rproc_elf32_load_image(struct udevice *dev, unsigned 
> long addr, ulong size)
>   
>   return 0;
>   }
> +
> +int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size)
> +{
> + const struct dm_rproc_ops *ops = rproc_get_ops(dev);
> + u64 da, memsz, filesz, offset;
> + Elf64_Ehdr *ehdr;
> + Elf64_Phdr *phdr;
> + int i, ret = 0;
> + void *ptr;
> +
> + dev_dbg(dev, "%s: addr = 0x%lx size = 0x%lx\n", __func__, addr, size);
> +
> + if (rproc_elf64_sanity_check(addr, size))
> + return -EINVAL;
> +
> + ehdr = (Elf64_Ehdr *)addr;
> + phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
> +
> + /* go through the available ELF segments */
> + for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
> + da = phdr->p_paddr;
> + memsz = phdr->p_memsz;
> + filesz = phdr->p_filesz;
> + offset = phdr->p_offset;
> +
> + if (phdr->p_type != PT_LOAD)
> + continue;
> +
> + dev_dbg(dev, "%s:phdr: type %d da 0x%llx memsz 0x%llx filesz 
> 0x%llx\n",
> + __func__, phdr->p_type, da, memsz, filesz);
> +
> + ptr = (void *)(uintptr_t)da;
> + if (ops->device_to_virt) {
> + ptr = ops->device_to_virt(dev, da, phdr->p_memsz);
> + if (!ptr) {
> + dev_err(dev, "bad da 0x%llx mem 0x%llx\n", da,
> + memsz);
> + ret = -EINVAL;
> + break;
> + }
> + }
> +
> + if (filesz)
> + memcpy(ptr, (void *)addr + offset, filesz);
> + if (filesz != memsz)
> + memset(ptr + filesz, 0x00, memsz - filesz);
> +
> + flush_cache(rounddown((ulong)ptr, ARCH_DMA_MINALIGN),
> + roundup((ulong)ptr + filesz, ARCH_DMA_MINALIGN) -
> + rounddown((ulong)ptr, ARCH_DMA_MINALIGN));
> + }
> +
> + return ret;
> +}
> diff --git a/include/remoteproc.h b/include/remoteproc.h
> index 1ef88be7f7..56a11db6e3 100644
> --- a/include/remoteproc.h
> +++ b/include/remoteproc.h
> @@ -214,6 +214,18 @@ int rproc_is_running(int id);
>*/
>   int rproc_elf32_sanity_check(ulong addr, 

[U-Boot] [PATCH v2 04/26] remoteproc: elf-loader: Add 64 bit elf loading support

2019-09-04 Thread Lokesh Vutla
The current rproc-elf-loader supports loading of only 32 bit elf files.
Introduce support for loading of 64 bit elf files in rproc-elf-loader.

Signed-off-by: Lokesh Vutla 
---
 drivers/remoteproc/rproc-elf-loader.c | 110 ++
 include/remoteproc.h  |  26 ++
 2 files changed, 136 insertions(+)

diff --git a/drivers/remoteproc/rproc-elf-loader.c 
b/drivers/remoteproc/rproc-elf-loader.c
index 238f51d3b5..1aece2fc31 100644
--- a/drivers/remoteproc/rproc-elf-loader.c
+++ b/drivers/remoteproc/rproc-elf-loader.c
@@ -64,6 +64,62 @@ int rproc_elf32_sanity_check(ulong addr, ulong size)
return 0;
 }
 
+/* Basic function to verify ELF64 image format */
+int rproc_elf64_sanity_check(ulong addr, ulong size)
+{
+   Elf64_Ehdr *ehdr = (Elf64_Ehdr *)addr;
+   char class;
+
+   if (!addr) {
+   pr_debug("Invalid fw address?\n");
+   return -EFAULT;
+   }
+
+   if (size < sizeof(Elf64_Ehdr)) {
+   pr_debug("Image is too small\n");
+   return -ENOSPC;
+   }
+
+   class = ehdr->e_ident[EI_CLASS];
+
+   if (!IS_ELF(*ehdr) || ehdr->e_type != ET_EXEC || class != ELFCLASS64) {
+   pr_debug("Not an executable ELF64 image\n");
+   return -EPROTONOSUPPORT;
+   }
+
+   /* We assume the firmware has the same endianness as the host */
+# ifdef __LITTLE_ENDIAN
+   if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
+# else /* BIG ENDIAN */
+   if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
+# endif
+   pr_debug("Unsupported firmware endianness\n");
+   return -EILSEQ;
+   }
+
+   if (size < ehdr->e_shoff + sizeof(Elf64_Shdr)) {
+   pr_debug("Image is too small\n");
+   return -ENOSPC;
+   }
+
+   if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+   pr_debug("Image is corrupted (bad magic)\n");
+   return -EBADF;
+   }
+
+   if (ehdr->e_phnum == 0) {
+   pr_debug("No loadable segments\n");
+   return -ENOEXEC;
+   }
+
+   if (ehdr->e_phoff > size) {
+   pr_debug("Firmware size is too small\n");
+   return -ENOSPC;
+   }
+
+   return 0;
+}
+
 int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size)
 {
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
@@ -110,3 +166,57 @@ int rproc_elf32_load_image(struct udevice *dev, unsigned 
long addr, ulong size)
 
return 0;
 }
+
+int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size)
+{
+   const struct dm_rproc_ops *ops = rproc_get_ops(dev);
+   u64 da, memsz, filesz, offset;
+   Elf64_Ehdr *ehdr;
+   Elf64_Phdr *phdr;
+   int i, ret = 0;
+   void *ptr;
+
+   dev_dbg(dev, "%s: addr = 0x%lx size = 0x%lx\n", __func__, addr, size);
+
+   if (rproc_elf64_sanity_check(addr, size))
+   return -EINVAL;
+
+   ehdr = (Elf64_Ehdr *)addr;
+   phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
+
+   /* go through the available ELF segments */
+   for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
+   da = phdr->p_paddr;
+   memsz = phdr->p_memsz;
+   filesz = phdr->p_filesz;
+   offset = phdr->p_offset;
+
+   if (phdr->p_type != PT_LOAD)
+   continue;
+
+   dev_dbg(dev, "%s:phdr: type %d da 0x%llx memsz 0x%llx filesz 
0x%llx\n",
+   __func__, phdr->p_type, da, memsz, filesz);
+
+   ptr = (void *)(uintptr_t)da;
+   if (ops->device_to_virt) {
+   ptr = ops->device_to_virt(dev, da, phdr->p_memsz);
+   if (!ptr) {
+   dev_err(dev, "bad da 0x%llx mem 0x%llx\n", da,
+   memsz);
+   ret = -EINVAL;
+   break;
+   }
+   }
+
+   if (filesz)
+   memcpy(ptr, (void *)addr + offset, filesz);
+   if (filesz != memsz)
+   memset(ptr + filesz, 0x00, memsz - filesz);
+
+   flush_cache(rounddown((ulong)ptr, ARCH_DMA_MINALIGN),
+   roundup((ulong)ptr + filesz, ARCH_DMA_MINALIGN) -
+   rounddown((ulong)ptr, ARCH_DMA_MINALIGN));
+   }
+
+   return ret;
+}
diff --git a/include/remoteproc.h b/include/remoteproc.h
index 1ef88be7f7..56a11db6e3 100644
--- a/include/remoteproc.h
+++ b/include/remoteproc.h
@@ -214,6 +214,18 @@ int rproc_is_running(int id);
  */
 int rproc_elf32_sanity_check(ulong addr, ulong size);
 
+/**
+ * rproc_elf64_sanity_check() - Verify if an image is a valid ELF32 one
+ *
+ * Check if a valid ELF64 image exists at the given memory location. Verify
+ * basic ELF64 format requirements like magic number and sections size.
+ *
+ * @addr: