From: Clement Leger <cleger@kalray.eu> To: Ohad Ben-Cohen <ohad@wizery.com>, Bjorn Andersson <bjorn.andersson@linaro.org>, Jonathan Corbet <corbet@lwn.net>, Shawn Guo <shawnguo@kernel.org>, Sascha Hauer <s.hauer@pengutronix.de>, linux-remoteproc@vger.kernel.org Cc: Pengutronix Kernel Team <kernel@pengutronix.de>, Fabio Estevam <festevam@gmail.com>, NXP Linux Team <linux-imx@nxp.com>, Andy Gross <agross@kernel.org>, Patrice Chotard <patrice.chotard@st.com>, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, Arnaud Pouliquen <arnaud.pouliquen@st.com>, Loic PALLARDY <loic.pallardy@st.com>, s-anna <s-anna@ti.com>, Mathieu Poirier <mathieu.poirier@linaro.org>, Clement Leger <cleger@kalray.eu> Subject: [PATCH v5 6/8] remoteproc: Add elf64 support in elf loader Date: Mon, 2 Mar 2020 10:39:00 +0100 [thread overview] Message-ID: <20200302093902.27849-7-cleger@kalray.eu> (raw) In-Reply-To: <20200302093902.27849-1-cleger@kalray.eu> In order to support elf64, use macros from remoteproc_elf_helpers.h to access elf headers depending on elf class. To allow new drivers to support elf64, add rproc_elf_sanity_check function which make more sense than adding a elf64 named one since it will support both elf versions. Driver which need to support both elf32/elf64 should use this new function for elf sanity check instead of the elf32 one. Signed-off-by: Clement Leger <cleger@kalray.eu> Tested-by: Arnaud POULIQUEN <arnaud.pouliquen@st.com> --- Documentation/remoteproc.txt | 2 +- drivers/remoteproc/remoteproc_elf_loader.c | 186 ++++++++++++++++++++--------- drivers/remoteproc/remoteproc_internal.h | 10 ++ 3 files changed, 141 insertions(+), 57 deletions(-) diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt index 03c3d2e568b0..2be1147256e0 100644 --- a/Documentation/remoteproc.txt +++ b/Documentation/remoteproc.txt @@ -230,7 +230,7 @@ in the used rings. Binary Firmware Structure ========================= -At this point remoteproc only supports ELF32 firmware binaries. However, +At this point remoteproc supports ELF32 and ELF64 firmware binaries. However, it is quite expected that other platforms/devices which we'd want to support with this framework will be based on different binary formats. diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c index 5a67745f2638..4869fb7d8fe4 100644 --- a/drivers/remoteproc/remoteproc_elf_loader.c +++ b/drivers/remoteproc/remoteproc_elf_loader.c @@ -23,20 +23,29 @@ #include <linux/elf.h> #include "remoteproc_internal.h" +#include "remoteproc_elf_helpers.h" /** - * rproc_elf_sanity_check() - Sanity Check ELF32 firmware image + * rproc_elf_sanity_check() - Sanity Check for ELF32/ELF64 firmware image * @rproc: the remote processor handle * @fw: the ELF firmware image * - * Make sure this fw image is sane. + * Make sure this fw image is sane (ie a correct ELF32/ELF64 file). */ -int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw) +int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw) { const char *name = rproc->firmware; struct device *dev = &rproc->dev; + /* + * Elf files are beginning with the same structure. Thus, to simplify + * header parsing, we can use the elf32_hdr one for both elf64 and + * elf32. + */ struct elf32_hdr *ehdr; + u32 elf_shdr_get_size; + u64 phoff, shoff; char class; + u16 phnum; if (!fw) { dev_err(dev, "failed to load %s\n", name); @@ -50,13 +59,22 @@ int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw) ehdr = (struct elf32_hdr *)fw->data; - /* We only support ELF32 at this point */ + if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { + dev_err(dev, "Image is corrupted (bad magic)\n"); + return -EINVAL; + } + class = ehdr->e_ident[EI_CLASS]; - if (class != ELFCLASS32) { + if (class != ELFCLASS32 && class != ELFCLASS64) { dev_err(dev, "Unsupported class: %d\n", class); return -EINVAL; } + if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) { + dev_err(dev, "elf64 header is too small\n"); + return -EINVAL; + } + /* We assume the firmware has the same endianness as the host */ # ifdef __LITTLE_ENDIAN if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) { @@ -67,28 +85,52 @@ int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw) return -EINVAL; } - if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) { - dev_err(dev, "Image is too small\n"); - return -EINVAL; - } + phoff = elf_hdr_get_e_phoff(class, fw->data); + shoff = elf_hdr_get_e_shoff(class, fw->data); + phnum = elf_hdr_get_e_phnum(class, fw->data); + elf_shdr_get_size = elf_size_of_shdr(class); - if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { - dev_err(dev, "Image is corrupted (bad magic)\n"); + if (fw->size < shoff + elf_shdr_get_size) { + dev_err(dev, "Image is too small\n"); return -EINVAL; } - if (ehdr->e_phnum == 0) { + if (phnum == 0) { dev_err(dev, "No loadable segments\n"); return -EINVAL; } - if (ehdr->e_phoff > fw->size) { + if (phoff > fw->size) { dev_err(dev, "Firmware size is too small\n"); return -EINVAL; } + dev_dbg(dev, "Firmware is an elf%d file\n", + class == ELFCLASS32 ? 32 : 64); + return 0; } +EXPORT_SYMBOL(rproc_elf_sanity_check); + +/** + * rproc_elf_sanity_check() - Sanity Check ELF32 firmware image + * @rproc: the remote processor handle + * @fw: the ELF32 firmware image + * + * Make sure this fw image is sane. + */ +int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw) +{ + int ret = rproc_elf_sanity_check(rproc, fw); + + if (ret) + return ret; + + if (fw_elf_get_class(fw) == ELFCLASS32) + return 0; + + return -EINVAL; +} EXPORT_SYMBOL(rproc_elf32_sanity_check); /** @@ -104,9 +146,7 @@ EXPORT_SYMBOL(rproc_elf32_sanity_check); */ u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw) { - struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data; - - return ehdr->e_entry; + return elf_hdr_get_e_entry(fw_elf_get_class(fw), fw->data); } EXPORT_SYMBOL(rproc_elf_get_boot_addr); @@ -137,53 +177,65 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr); int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) { struct device *dev = &rproc->dev; - struct elf32_hdr *ehdr; - struct elf32_phdr *phdr; + const void *ehdr, *phdr; int i, ret = 0; + u16 phnum; const u8 *elf_data = fw->data; + u8 class = fw_elf_get_class(fw); + u32 elf_phdr_get_size = elf_size_of_phdr(class); - ehdr = (struct elf32_hdr *)elf_data; - phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff); + ehdr = elf_data; + phnum = elf_hdr_get_e_phnum(class, ehdr); + phdr = elf_data + elf_hdr_get_e_phoff(class, ehdr); /* go through the available ELF segments */ - for (i = 0; i < ehdr->e_phnum; i++, phdr++) { - u32 da = phdr->p_paddr; - u32 memsz = phdr->p_memsz; - u32 filesz = phdr->p_filesz; - u32 offset = phdr->p_offset; + for (i = 0; i < phnum; i++, phdr += elf_phdr_get_size) { + u64 da = elf_phdr_get_p_paddr(class, phdr); + u64 memsz = elf_phdr_get_p_memsz(class, phdr); + u64 filesz = elf_phdr_get_p_filesz(class, phdr); + u64 offset = elf_phdr_get_p_offset(class, phdr); + u32 type = elf_phdr_get_p_type(class, phdr); void *ptr; - if (phdr->p_type != PT_LOAD) + if (type != PT_LOAD) continue; - dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n", - phdr->p_type, da, memsz, filesz); + dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n", + type, da, memsz, filesz); if (filesz > memsz) { - dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n", + dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n", filesz, memsz); ret = -EINVAL; break; } if (offset + filesz > fw->size) { - dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n", + dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n", offset + filesz, fw->size); ret = -EINVAL; break; } + if (!rproc_u64_fit_in_size_t(memsz)) { + dev_err(dev, "size (%llx) does not fit in size_t type\n", + memsz); + ret = -EOVERFLOW; + break; + } + /* grab the kernel address for this device address */ ptr = rproc_da_to_va(rproc, da, memsz); if (!ptr) { - dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz); + dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da, + memsz); ret = -EINVAL; break; } /* put the segment where the remote processor expects it */ - if (phdr->p_filesz) - memcpy(ptr, elf_data + phdr->p_offset, filesz); + if (filesz) + memcpy(ptr, elf_data + offset, filesz); /* * Zero out remaining memory for this segment. @@ -200,24 +252,35 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) } EXPORT_SYMBOL(rproc_elf_load_segments); -static struct elf32_shdr * -find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size) +static const void * +find_table(struct device *dev, const struct firmware *fw) { - struct elf32_shdr *shdr; + const void *shdr, *name_table_shdr; int i; const char *name_table; struct resource_table *table = NULL; - const u8 *elf_data = (void *)ehdr; + const u8 *elf_data = (void *)fw->data; + u8 class = fw_elf_get_class(fw); + size_t fw_size = fw->size; + const void *ehdr = elf_data; + u16 shnum = elf_hdr_get_e_shnum(class, ehdr); + u32 elf_shdr_get_size = elf_size_of_shdr(class); + u16 shstrndx = elf_hdr_get_e_shstrndx(class, ehdr); /* look for the resource table and handle it */ - shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff); - name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset; - - for (i = 0; i < ehdr->e_shnum; i++, shdr++) { - u32 size = shdr->sh_size; - u32 offset = shdr->sh_offset; - - if (strcmp(name_table + shdr->sh_name, ".resource_table")) + /* First, get the section header according to the elf class */ + shdr = elf_data + elf_hdr_get_e_shoff(class, ehdr); + /* Compute name table section header entry in shdr array */ + name_table_shdr = shdr + (shstrndx * elf_shdr_get_size); + /* Finally, compute the name table section address in elf */ + name_table = elf_data + elf_shdr_get_sh_offset(class, name_table_shdr); + + for (i = 0; i < shnum; i++, shdr += elf_shdr_get_size) { + u64 size = elf_shdr_get_sh_size(class, shdr); + u64 offset = elf_shdr_get_sh_offset(class, shdr); + u32 name = elf_shdr_get_sh_name(class, shdr); + + if (strcmp(name_table + name, ".resource_table")) continue; table = (struct resource_table *)(elf_data + offset); @@ -270,21 +333,21 @@ find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size) */ int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw) { - struct elf32_hdr *ehdr; - struct elf32_shdr *shdr; + const void *shdr; struct device *dev = &rproc->dev; struct resource_table *table = NULL; const u8 *elf_data = fw->data; size_t tablesz; + u8 class = fw_elf_get_class(fw); + u64 sh_offset; - ehdr = (struct elf32_hdr *)elf_data; - - shdr = find_table(dev, ehdr, fw->size); + shdr = find_table(dev, fw); if (!shdr) return -EINVAL; - table = (struct resource_table *)(elf_data + shdr->sh_offset); - tablesz = shdr->sh_size; + sh_offset = elf_shdr_get_sh_offset(class, shdr); + table = (struct resource_table *)(elf_data + sh_offset); + tablesz = elf_shdr_get_sh_size(class, shdr); /* * Create a copy of the resource table. When a virtio device starts @@ -317,13 +380,24 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table); struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, const struct firmware *fw) { - struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data; - struct elf32_shdr *shdr; + const void *shdr; + u64 sh_addr, sh_size; + u8 class = fw_elf_get_class(fw); + struct device *dev = &rproc->dev; - shdr = find_table(&rproc->dev, ehdr, fw->size); + shdr = find_table(&rproc->dev, fw); if (!shdr) return NULL; - return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size); + sh_addr = elf_shdr_get_sh_addr(class, shdr); + sh_size = elf_shdr_get_sh_size(class, shdr); + + if (!rproc_u64_fit_in_size_t(sh_size)) { + dev_err(dev, "size (%llx) does not fit in size_t type\n", + sh_size); + return NULL; + } + + return rproc_da_to_va(rproc, sh_addr, sh_size); } EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table); diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 28639c588d58..10bb7f57d54e 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -55,6 +55,7 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr); int rproc_trigger_recovery(struct rproc *rproc); int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw); +int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw); u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw); int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw); int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw); @@ -119,4 +120,13 @@ struct resource_table *rproc_find_loaded_rsc_table(struct rproc *rproc, return NULL; } +static inline +bool rproc_u64_fit_in_size_t(u64 val) +{ + if (sizeof(size_t) == sizeof(u64)) + return true; + + return (val <= (size_t) -1); +} + #endif /* REMOTEPROC_INTERNAL_H */ -- 2.15.0.276.g89ea799
WARNING: multiple messages have this Message-ID (diff)
From: Clement Leger <cleger@kalray.eu> To: Ohad Ben-Cohen <ohad@wizery.com>, Bjorn Andersson <bjorn.andersson@linaro.org>, Jonathan Corbet <corbet@lwn.net>, Shawn Guo <shawnguo@kernel.org>, Sascha Hauer <s.hauer@pengutronix.de>, linux-remoteproc@vger.kernel.org Cc: Mathieu Poirier <mathieu.poirier@linaro.org>, Loic PALLARDY <loic.pallardy@st.com>, linux-doc@vger.kernel.org, linux-arm-msm@vger.kernel.org, Arnaud Pouliquen <arnaud.pouliquen@st.com>, Patrice Chotard <patrice.chotard@st.com>, linux-kernel@vger.kernel.org, Clement Leger <cleger@kalray.eu>, Andy Gross <agross@kernel.org>, NXP Linux Team <linux-imx@nxp.com>, Pengutronix Kernel Team <kernel@pengutronix.de>, s-anna <s-anna@ti.com>, Fabio Estevam <festevam@gmail.com>, linux-arm-kernel@lists.infradead.org Subject: [PATCH v5 6/8] remoteproc: Add elf64 support in elf loader Date: Mon, 2 Mar 2020 10:39:00 +0100 [thread overview] Message-ID: <20200302093902.27849-7-cleger@kalray.eu> (raw) In-Reply-To: <20200302093902.27849-1-cleger@kalray.eu> In order to support elf64, use macros from remoteproc_elf_helpers.h to access elf headers depending on elf class. To allow new drivers to support elf64, add rproc_elf_sanity_check function which make more sense than adding a elf64 named one since it will support both elf versions. Driver which need to support both elf32/elf64 should use this new function for elf sanity check instead of the elf32 one. Signed-off-by: Clement Leger <cleger@kalray.eu> Tested-by: Arnaud POULIQUEN <arnaud.pouliquen@st.com> --- Documentation/remoteproc.txt | 2 +- drivers/remoteproc/remoteproc_elf_loader.c | 186 ++++++++++++++++++++--------- drivers/remoteproc/remoteproc_internal.h | 10 ++ 3 files changed, 141 insertions(+), 57 deletions(-) diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt index 03c3d2e568b0..2be1147256e0 100644 --- a/Documentation/remoteproc.txt +++ b/Documentation/remoteproc.txt @@ -230,7 +230,7 @@ in the used rings. Binary Firmware Structure ========================= -At this point remoteproc only supports ELF32 firmware binaries. However, +At this point remoteproc supports ELF32 and ELF64 firmware binaries. However, it is quite expected that other platforms/devices which we'd want to support with this framework will be based on different binary formats. diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c index 5a67745f2638..4869fb7d8fe4 100644 --- a/drivers/remoteproc/remoteproc_elf_loader.c +++ b/drivers/remoteproc/remoteproc_elf_loader.c @@ -23,20 +23,29 @@ #include <linux/elf.h> #include "remoteproc_internal.h" +#include "remoteproc_elf_helpers.h" /** - * rproc_elf_sanity_check() - Sanity Check ELF32 firmware image + * rproc_elf_sanity_check() - Sanity Check for ELF32/ELF64 firmware image * @rproc: the remote processor handle * @fw: the ELF firmware image * - * Make sure this fw image is sane. + * Make sure this fw image is sane (ie a correct ELF32/ELF64 file). */ -int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw) +int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw) { const char *name = rproc->firmware; struct device *dev = &rproc->dev; + /* + * Elf files are beginning with the same structure. Thus, to simplify + * header parsing, we can use the elf32_hdr one for both elf64 and + * elf32. + */ struct elf32_hdr *ehdr; + u32 elf_shdr_get_size; + u64 phoff, shoff; char class; + u16 phnum; if (!fw) { dev_err(dev, "failed to load %s\n", name); @@ -50,13 +59,22 @@ int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw) ehdr = (struct elf32_hdr *)fw->data; - /* We only support ELF32 at this point */ + if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { + dev_err(dev, "Image is corrupted (bad magic)\n"); + return -EINVAL; + } + class = ehdr->e_ident[EI_CLASS]; - if (class != ELFCLASS32) { + if (class != ELFCLASS32 && class != ELFCLASS64) { dev_err(dev, "Unsupported class: %d\n", class); return -EINVAL; } + if (class == ELFCLASS64 && fw->size < sizeof(struct elf64_hdr)) { + dev_err(dev, "elf64 header is too small\n"); + return -EINVAL; + } + /* We assume the firmware has the same endianness as the host */ # ifdef __LITTLE_ENDIAN if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) { @@ -67,28 +85,52 @@ int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw) return -EINVAL; } - if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) { - dev_err(dev, "Image is too small\n"); - return -EINVAL; - } + phoff = elf_hdr_get_e_phoff(class, fw->data); + shoff = elf_hdr_get_e_shoff(class, fw->data); + phnum = elf_hdr_get_e_phnum(class, fw->data); + elf_shdr_get_size = elf_size_of_shdr(class); - if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { - dev_err(dev, "Image is corrupted (bad magic)\n"); + if (fw->size < shoff + elf_shdr_get_size) { + dev_err(dev, "Image is too small\n"); return -EINVAL; } - if (ehdr->e_phnum == 0) { + if (phnum == 0) { dev_err(dev, "No loadable segments\n"); return -EINVAL; } - if (ehdr->e_phoff > fw->size) { + if (phoff > fw->size) { dev_err(dev, "Firmware size is too small\n"); return -EINVAL; } + dev_dbg(dev, "Firmware is an elf%d file\n", + class == ELFCLASS32 ? 32 : 64); + return 0; } +EXPORT_SYMBOL(rproc_elf_sanity_check); + +/** + * rproc_elf_sanity_check() - Sanity Check ELF32 firmware image + * @rproc: the remote processor handle + * @fw: the ELF32 firmware image + * + * Make sure this fw image is sane. + */ +int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw) +{ + int ret = rproc_elf_sanity_check(rproc, fw); + + if (ret) + return ret; + + if (fw_elf_get_class(fw) == ELFCLASS32) + return 0; + + return -EINVAL; +} EXPORT_SYMBOL(rproc_elf32_sanity_check); /** @@ -104,9 +146,7 @@ EXPORT_SYMBOL(rproc_elf32_sanity_check); */ u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw) { - struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data; - - return ehdr->e_entry; + return elf_hdr_get_e_entry(fw_elf_get_class(fw), fw->data); } EXPORT_SYMBOL(rproc_elf_get_boot_addr); @@ -137,53 +177,65 @@ EXPORT_SYMBOL(rproc_elf_get_boot_addr); int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) { struct device *dev = &rproc->dev; - struct elf32_hdr *ehdr; - struct elf32_phdr *phdr; + const void *ehdr, *phdr; int i, ret = 0; + u16 phnum; const u8 *elf_data = fw->data; + u8 class = fw_elf_get_class(fw); + u32 elf_phdr_get_size = elf_size_of_phdr(class); - ehdr = (struct elf32_hdr *)elf_data; - phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff); + ehdr = elf_data; + phnum = elf_hdr_get_e_phnum(class, ehdr); + phdr = elf_data + elf_hdr_get_e_phoff(class, ehdr); /* go through the available ELF segments */ - for (i = 0; i < ehdr->e_phnum; i++, phdr++) { - u32 da = phdr->p_paddr; - u32 memsz = phdr->p_memsz; - u32 filesz = phdr->p_filesz; - u32 offset = phdr->p_offset; + for (i = 0; i < phnum; i++, phdr += elf_phdr_get_size) { + u64 da = elf_phdr_get_p_paddr(class, phdr); + u64 memsz = elf_phdr_get_p_memsz(class, phdr); + u64 filesz = elf_phdr_get_p_filesz(class, phdr); + u64 offset = elf_phdr_get_p_offset(class, phdr); + u32 type = elf_phdr_get_p_type(class, phdr); void *ptr; - if (phdr->p_type != PT_LOAD) + if (type != PT_LOAD) continue; - dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n", - phdr->p_type, da, memsz, filesz); + dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n", + type, da, memsz, filesz); if (filesz > memsz) { - dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n", + dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n", filesz, memsz); ret = -EINVAL; break; } if (offset + filesz > fw->size) { - dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n", + dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n", offset + filesz, fw->size); ret = -EINVAL; break; } + if (!rproc_u64_fit_in_size_t(memsz)) { + dev_err(dev, "size (%llx) does not fit in size_t type\n", + memsz); + ret = -EOVERFLOW; + break; + } + /* grab the kernel address for this device address */ ptr = rproc_da_to_va(rproc, da, memsz); if (!ptr) { - dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz); + dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da, + memsz); ret = -EINVAL; break; } /* put the segment where the remote processor expects it */ - if (phdr->p_filesz) - memcpy(ptr, elf_data + phdr->p_offset, filesz); + if (filesz) + memcpy(ptr, elf_data + offset, filesz); /* * Zero out remaining memory for this segment. @@ -200,24 +252,35 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) } EXPORT_SYMBOL(rproc_elf_load_segments); -static struct elf32_shdr * -find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size) +static const void * +find_table(struct device *dev, const struct firmware *fw) { - struct elf32_shdr *shdr; + const void *shdr, *name_table_shdr; int i; const char *name_table; struct resource_table *table = NULL; - const u8 *elf_data = (void *)ehdr; + const u8 *elf_data = (void *)fw->data; + u8 class = fw_elf_get_class(fw); + size_t fw_size = fw->size; + const void *ehdr = elf_data; + u16 shnum = elf_hdr_get_e_shnum(class, ehdr); + u32 elf_shdr_get_size = elf_size_of_shdr(class); + u16 shstrndx = elf_hdr_get_e_shstrndx(class, ehdr); /* look for the resource table and handle it */ - shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff); - name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset; - - for (i = 0; i < ehdr->e_shnum; i++, shdr++) { - u32 size = shdr->sh_size; - u32 offset = shdr->sh_offset; - - if (strcmp(name_table + shdr->sh_name, ".resource_table")) + /* First, get the section header according to the elf class */ + shdr = elf_data + elf_hdr_get_e_shoff(class, ehdr); + /* Compute name table section header entry in shdr array */ + name_table_shdr = shdr + (shstrndx * elf_shdr_get_size); + /* Finally, compute the name table section address in elf */ + name_table = elf_data + elf_shdr_get_sh_offset(class, name_table_shdr); + + for (i = 0; i < shnum; i++, shdr += elf_shdr_get_size) { + u64 size = elf_shdr_get_sh_size(class, shdr); + u64 offset = elf_shdr_get_sh_offset(class, shdr); + u32 name = elf_shdr_get_sh_name(class, shdr); + + if (strcmp(name_table + name, ".resource_table")) continue; table = (struct resource_table *)(elf_data + offset); @@ -270,21 +333,21 @@ find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size) */ int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw) { - struct elf32_hdr *ehdr; - struct elf32_shdr *shdr; + const void *shdr; struct device *dev = &rproc->dev; struct resource_table *table = NULL; const u8 *elf_data = fw->data; size_t tablesz; + u8 class = fw_elf_get_class(fw); + u64 sh_offset; - ehdr = (struct elf32_hdr *)elf_data; - - shdr = find_table(dev, ehdr, fw->size); + shdr = find_table(dev, fw); if (!shdr) return -EINVAL; - table = (struct resource_table *)(elf_data + shdr->sh_offset); - tablesz = shdr->sh_size; + sh_offset = elf_shdr_get_sh_offset(class, shdr); + table = (struct resource_table *)(elf_data + sh_offset); + tablesz = elf_shdr_get_sh_size(class, shdr); /* * Create a copy of the resource table. When a virtio device starts @@ -317,13 +380,24 @@ EXPORT_SYMBOL(rproc_elf_load_rsc_table); struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, const struct firmware *fw) { - struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data; - struct elf32_shdr *shdr; + const void *shdr; + u64 sh_addr, sh_size; + u8 class = fw_elf_get_class(fw); + struct device *dev = &rproc->dev; - shdr = find_table(&rproc->dev, ehdr, fw->size); + shdr = find_table(&rproc->dev, fw); if (!shdr) return NULL; - return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size); + sh_addr = elf_shdr_get_sh_addr(class, shdr); + sh_size = elf_shdr_get_sh_size(class, shdr); + + if (!rproc_u64_fit_in_size_t(sh_size)) { + dev_err(dev, "size (%llx) does not fit in size_t type\n", + sh_size); + return NULL; + } + + return rproc_da_to_va(rproc, sh_addr, sh_size); } EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table); diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 28639c588d58..10bb7f57d54e 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -55,6 +55,7 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr); int rproc_trigger_recovery(struct rproc *rproc); int rproc_elf32_sanity_check(struct rproc *rproc, const struct firmware *fw); +int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw); u64 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw); int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw); int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw); @@ -119,4 +120,13 @@ struct resource_table *rproc_find_loaded_rsc_table(struct rproc *rproc, return NULL; } +static inline +bool rproc_u64_fit_in_size_t(u64 val) +{ + if (sizeof(size_t) == sizeof(u64)) + return true; + + return (val <= (size_t) -1); +} + #endif /* REMOTEPROC_INTERNAL_H */ -- 2.15.0.276.g89ea799 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2020-03-02 9:39 UTC|newest] Thread overview: 164+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-04-02 8:28 [RFC PATCH] rproc: Add elf64 support in elf loader Clément Leger 2019-05-07 12:09 ` Clément Leger 2019-05-07 13:37 ` Arnaud Pouliquen 2019-05-09 8:59 ` Clément Leger 2019-08-19 11:45 ` [PATCH] " Clement Leger 2019-09-13 10:58 ` Clément Leger 2019-10-04 8:27 ` Clément Leger 2019-10-04 18:42 ` [PATCH v2] remoteproc: " Clement Leger 2020-01-09 9:31 ` Clément Leger 2020-01-24 0:53 ` Mathieu Poirier 2020-01-24 8:24 ` Clément Leger 2020-01-24 18:10 ` Mathieu Poirier 2020-01-24 18:10 ` Mathieu Poirier 2020-01-24 21:58 ` Mathieu Poirier 2020-01-24 21:58 ` Mathieu Poirier 2020-01-27 8:33 ` Clément Leger 2020-01-28 17:14 ` Mathieu Poirier 2020-01-29 8:55 ` Clément Leger 2020-01-29 16:30 ` Mathieu Poirier 2020-01-29 16:30 ` Mathieu Poirier 2020-02-04 14:33 ` [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va Clement Leger 2020-02-04 14:33 ` Clement Leger 2020-02-04 14:33 ` [PATCH v2 2/2] remoteproc: Add elf64 support in elf loader Clement Leger 2020-02-04 14:33 ` Clement Leger 2020-02-04 16:27 ` [PATCH v2 1/2] remoteproc: Use u64 len for da_to_va Arnaud POULIQUEN 2020-02-04 16:27 ` Arnaud POULIQUEN 2020-02-04 16:27 ` Arnaud POULIQUEN 2020-02-04 17:10 ` Clément Leger 2020-02-04 17:10 ` Clément Leger 2020-02-04 17:42 ` Arnaud POULIQUEN 2020-02-04 17:42 ` Arnaud POULIQUEN 2020-02-04 17:42 ` Arnaud POULIQUEN 2020-02-04 17:44 ` [PATCH v3 0/2] remoteproc: Add elf64 support to elf loader Clement Leger 2020-02-04 17:44 ` Clement Leger 2020-02-04 17:44 ` [PATCH v3 1/2] remoteproc: Use u64 len for da_to_va Clement Leger 2020-02-04 17:44 ` Clement Leger 2020-02-05 21:06 ` Mathieu Poirier 2020-02-05 21:06 ` Mathieu Poirier 2020-02-04 17:44 ` [PATCH v3 2/2] remoteproc: Add elf64 support in elf loader Clement Leger 2020-02-04 17:44 ` Clement Leger 2020-02-05 22:49 ` Mathieu Poirier 2020-02-05 22:49 ` Mathieu Poirier 2020-02-06 8:37 ` Clément Leger 2020-02-06 8:37 ` Clément Leger 2020-02-06 15:05 ` Clément Leger 2020-02-06 15:05 ` Clément Leger 2020-02-06 17:48 ` Mathieu Poirier 2020-02-06 17:48 ` Mathieu Poirier 2020-02-06 17:48 ` Mathieu Poirier 2020-02-07 7:57 ` Clément Leger 2020-02-07 7:57 ` Clément Leger 2020-02-10 16:22 ` [PATCH v4 0/5] remoteproc: Add elf64 support Clement Leger 2020-02-10 16:22 ` Clement Leger 2020-02-10 16:22 ` [PATCH v4 1/5] remoteproc: Use u64 len for da_to_va Clement Leger 2020-02-10 16:22 ` Clement Leger 2020-02-11 15:53 ` Arnaud POULIQUEN 2020-02-11 15:53 ` Arnaud POULIQUEN 2020-02-11 15:53 ` Arnaud POULIQUEN 2020-02-11 16:39 ` Clément Leger 2020-02-11 16:39 ` Clément Leger 2020-02-11 17:24 ` Arnaud POULIQUEN 2020-02-11 17:24 ` Arnaud POULIQUEN 2020-02-11 22:37 ` Mathieu Poirier 2020-02-11 22:37 ` Mathieu Poirier 2020-02-11 22:37 ` Mathieu Poirier 2020-02-12 10:37 ` Clément Leger 2020-02-12 10:37 ` Clément Leger 2020-02-12 21:59 ` Mathieu Poirier 2020-02-12 21:59 ` Mathieu Poirier 2020-02-18 10:10 ` Clément Leger 2020-02-18 10:10 ` Clément Leger 2020-02-18 17:01 ` Mathieu Poirier 2020-02-18 17:01 ` Mathieu Poirier 2020-02-10 16:22 ` [PATCH v4 2/5] remoteproc: Use u64 type for boot_addr Clement Leger 2020-02-10 16:22 ` Clement Leger 2020-02-10 16:22 ` [PATCH v4 3/5] remoteproc: Add elf helpers to access elf64 and elf32 fields Clement Leger 2020-02-10 16:22 ` Clement Leger 2020-02-10 16:22 ` [PATCH v4 4/5] remoteproc: Add elf64 support in elf loader Clement Leger 2020-02-10 16:22 ` Clement Leger 2020-02-10 16:22 ` [PATCH v4 5/5] remoteproc: Adapt coredump to generate correct elf type Clement Leger 2020-02-10 16:22 ` Clement Leger 2020-02-11 23:11 ` Mathieu Poirier 2020-02-11 23:11 ` Mathieu Poirier 2020-02-11 15:57 ` [PATCH v4 0/5] remoteproc: Add elf64 support Arnaud POULIQUEN 2020-02-11 15:57 ` Arnaud POULIQUEN 2020-02-11 15:57 ` Arnaud POULIQUEN 2020-02-11 23:12 ` Mathieu Poirier 2020-02-11 23:12 ` Mathieu Poirier 2020-02-12 8:15 ` Arnaud POULIQUEN 2020-02-12 8:15 ` Arnaud POULIQUEN 2020-02-12 8:15 ` Arnaud POULIQUEN 2020-03-02 9:38 ` [PATCH v5 0/8] " Clement Leger 2020-03-02 9:38 ` Clement Leger 2020-03-02 9:38 ` [PATCH v5 1/8] remoteproc: Use size_t type for len in da_to_va Clement Leger 2020-03-02 9:38 ` Clement Leger 2020-03-02 23:06 ` Bjorn Andersson 2020-03-02 23:06 ` Bjorn Andersson 2020-03-02 23:06 ` Bjorn Andersson 2020-03-09 17:52 ` Mathieu Poirier 2020-03-09 17:52 ` Mathieu Poirier 2020-03-27 7:37 ` Oleksij Rempel 2020-03-27 7:37 ` Oleksij Rempel 2020-03-02 9:38 ` [PATCH v5 2/8] remoteproc: Use size_t instead of int for rproc_mem_entry len Clement Leger 2020-03-02 9:38 ` Clement Leger 2020-03-02 23:07 ` Bjorn Andersson 2020-03-02 23:07 ` Bjorn Andersson 2020-03-02 23:07 ` Bjorn Andersson 2020-03-09 19:21 ` Mathieu Poirier 2020-03-09 19:21 ` Mathieu Poirier 2020-03-02 9:38 ` [PATCH v5 3/8] remoteproc: Use u64 type for boot_addr Clement Leger 2020-03-02 9:38 ` Clement Leger 2020-03-02 23:08 ` Bjorn Andersson 2020-03-02 23:08 ` Bjorn Andersson 2020-03-02 23:08 ` Bjorn Andersson 2020-03-09 19:52 ` Mathieu Poirier 2020-03-09 19:52 ` Mathieu Poirier 2020-03-10 7:59 ` Clément Leger 2020-03-10 7:59 ` Clément Leger 2020-03-10 19:32 ` Bjorn Andersson 2020-03-10 19:32 ` Bjorn Andersson 2020-03-10 19:32 ` Bjorn Andersson 2020-03-02 9:38 ` [PATCH v5 4/8] remoteproc: Add elf helpers to access elf64 and elf32 fields Clement Leger 2020-03-02 9:38 ` Clement Leger 2020-03-02 23:12 ` Bjorn Andersson 2020-03-02 23:12 ` Bjorn Andersson 2020-03-02 23:12 ` Bjorn Andersson 2020-03-09 19:56 ` Mathieu Poirier 2020-03-09 19:56 ` Mathieu Poirier 2020-03-02 9:38 ` [PATCH v5 5/8] remoteproc: Rename rproc_elf_sanity_check for elf32 Clement Leger 2020-03-02 9:38 ` Clement Leger 2020-03-02 23:13 ` Bjorn Andersson 2020-03-02 23:13 ` Bjorn Andersson 2020-03-02 23:13 ` Bjorn Andersson 2020-03-03 8:02 ` Clément Leger 2020-03-03 8:02 ` Clément Leger 2020-03-10 0:00 ` Bjorn Andersson 2020-03-10 0:00 ` Bjorn Andersson 2020-03-10 0:00 ` Bjorn Andersson 2020-03-10 15:20 ` Mathieu Poirier 2020-03-10 15:20 ` Mathieu Poirier 2020-03-10 15:20 ` Mathieu Poirier 2020-03-10 15:38 ` Clément Leger 2020-03-10 15:38 ` Clément Leger 2020-03-10 19:18 ` Mathieu Poirier 2020-03-10 19:18 ` Mathieu Poirier 2020-03-10 19:30 ` Bjorn Andersson 2020-03-10 19:30 ` Bjorn Andersson 2020-03-10 19:30 ` Bjorn Andersson 2020-03-02 9:39 ` Clement Leger [this message] 2020-03-02 9:39 ` [PATCH v5 6/8] remoteproc: Add elf64 support in elf loader Clement Leger 2020-03-02 9:39 ` [PATCH v5 7/8] remoteproc: Allow overriding only sanity_check Clement Leger 2020-03-02 9:39 ` Clement Leger 2020-03-02 9:39 ` [PATCH v5 8/8] remoteproc: Adapt coredump to generate correct elf type Clement Leger 2020-03-02 9:39 ` Clement Leger 2020-03-03 22:01 ` Bjorn Andersson 2020-03-03 22:01 ` Bjorn Andersson 2020-03-03 22:01 ` Bjorn Andersson 2020-03-09 20:32 ` Mathieu Poirier 2020-03-09 20:32 ` Mathieu Poirier 2020-03-09 23:57 ` Bjorn Andersson 2020-03-09 23:57 ` Bjorn Andersson 2020-03-09 23:57 ` Bjorn Andersson 2020-03-10 8:12 ` Clément Leger 2020-03-10 8:12 ` Clément Leger
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200302093902.27849-7-cleger@kalray.eu \ --to=cleger@kalray.eu \ --cc=agross@kernel.org \ --cc=arnaud.pouliquen@st.com \ --cc=bjorn.andersson@linaro.org \ --cc=corbet@lwn.net \ --cc=festevam@gmail.com \ --cc=kernel@pengutronix.de \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-arm-msm@vger.kernel.org \ --cc=linux-doc@vger.kernel.org \ --cc=linux-imx@nxp.com \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-remoteproc@vger.kernel.org \ --cc=loic.pallardy@st.com \ --cc=mathieu.poirier@linaro.org \ --cc=ohad@wizery.com \ --cc=patrice.chotard@st.com \ --cc=s-anna@ti.com \ --cc=s.hauer@pengutronix.de \ --cc=shawnguo@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.