Commit 8f403350 authored by Clement Leger's avatar Clement Leger Committed by Bjorn Andersson

remoteproc: Adapt coredump to generate correct elf type

Now that remoteproc can load an elf64, coredump elf class should be
the same as the loaded elf class. In order to do that, add a
elf_class field to rproc with default values. If an elf is loaded
successfully, this field will be updated with the loaded elf class.
Then, the coredump core code has been modified to use the generic elf
macro in order to create an elf file with correct class.
Reviewed-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: default avatarClement Leger <cleger@kalray.eu>
Link: https://lore.kernel.org/r/20200302093902.27849-9-cleger@kalray.euSigned-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
parent 12677467
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include "remoteproc_internal.h" #include "remoteproc_internal.h"
#include "remoteproc_elf_helpers.h"
#define HIGH_BITS_MASK 0xFFFFFFFF00000000ULL #define HIGH_BITS_MASK 0xFFFFFFFF00000000ULL
...@@ -1571,20 +1572,21 @@ EXPORT_SYMBOL(rproc_coredump_add_custom_segment); ...@@ -1571,20 +1572,21 @@ EXPORT_SYMBOL(rproc_coredump_add_custom_segment);
static void rproc_coredump(struct rproc *rproc) static void rproc_coredump(struct rproc *rproc)
{ {
struct rproc_dump_segment *segment; struct rproc_dump_segment *segment;
struct elf32_phdr *phdr; void *phdr;
struct elf32_hdr *ehdr; void *ehdr;
size_t data_size; size_t data_size;
size_t offset; size_t offset;
void *data; void *data;
void *ptr; void *ptr;
u8 class = rproc->elf_class;
int phnum = 0; int phnum = 0;
if (list_empty(&rproc->dump_segments)) if (list_empty(&rproc->dump_segments))
return; return;
data_size = sizeof(*ehdr); data_size = elf_size_of_hdr(class);
list_for_each_entry(segment, &rproc->dump_segments, node) { list_for_each_entry(segment, &rproc->dump_segments, node) {
data_size += sizeof(*phdr) + segment->size; data_size += elf_size_of_phdr(class) + segment->size;
phnum++; phnum++;
} }
...@@ -1595,33 +1597,33 @@ static void rproc_coredump(struct rproc *rproc) ...@@ -1595,33 +1597,33 @@ static void rproc_coredump(struct rproc *rproc)
ehdr = data; ehdr = data;
memset(ehdr, 0, sizeof(*ehdr)); memset(ehdr, 0, elf_size_of_hdr(class));
memcpy(ehdr->e_ident, ELFMAG, SELFMAG); /* e_ident field is common for both elf32 and elf64 */
ehdr->e_ident[EI_CLASS] = ELFCLASS32; elf_hdr_init_ident(ehdr, class);
ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
ehdr->e_ident[EI_VERSION] = EV_CURRENT; elf_hdr_set_e_type(class, ehdr, ET_CORE);
ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE; elf_hdr_set_e_machine(class, ehdr, EM_NONE);
ehdr->e_type = ET_CORE; elf_hdr_set_e_version(class, ehdr, EV_CURRENT);
ehdr->e_machine = EM_NONE; elf_hdr_set_e_entry(class, ehdr, rproc->bootaddr);
ehdr->e_version = EV_CURRENT; elf_hdr_set_e_phoff(class, ehdr, elf_size_of_hdr(class));
ehdr->e_entry = rproc->bootaddr; elf_hdr_set_e_ehsize(class, ehdr, elf_size_of_hdr(class));
ehdr->e_phoff = sizeof(*ehdr); elf_hdr_set_e_phentsize(class, ehdr, elf_size_of_phdr(class));
ehdr->e_ehsize = sizeof(*ehdr); elf_hdr_set_e_phnum(class, ehdr, phnum);
ehdr->e_phentsize = sizeof(*phdr);
ehdr->e_phnum = phnum; phdr = data + elf_hdr_get_e_phoff(class, ehdr);
offset = elf_hdr_get_e_phoff(class, ehdr);
phdr = data + ehdr->e_phoff; offset += elf_size_of_phdr(class) * elf_hdr_get_e_phnum(class, ehdr);
offset = ehdr->e_phoff + sizeof(*phdr) * ehdr->e_phnum;
list_for_each_entry(segment, &rproc->dump_segments, node) { list_for_each_entry(segment, &rproc->dump_segments, node) {
memset(phdr, 0, sizeof(*phdr)); memset(phdr, 0, elf_size_of_phdr(class));
phdr->p_type = PT_LOAD; elf_phdr_set_p_type(class, phdr, PT_LOAD);
phdr->p_offset = offset; elf_phdr_set_p_offset(class, phdr, offset);
phdr->p_vaddr = segment->da; elf_phdr_set_p_vaddr(class, phdr, segment->da);
phdr->p_paddr = segment->da; elf_phdr_set_p_paddr(class, phdr, segment->da);
phdr->p_filesz = segment->size; elf_phdr_set_p_filesz(class, phdr, segment->size);
phdr->p_memsz = segment->size; elf_phdr_set_p_memsz(class, phdr, segment->size);
phdr->p_flags = PF_R | PF_W | PF_X; elf_phdr_set_p_flags(class, phdr, PF_R | PF_W | PF_X);
phdr->p_align = 0; elf_phdr_set_p_align(class, phdr, 0);
if (segment->dump) { if (segment->dump) {
segment->dump(rproc, segment, data + offset); segment->dump(rproc, segment, data + offset);
...@@ -1637,8 +1639,8 @@ static void rproc_coredump(struct rproc *rproc) ...@@ -1637,8 +1639,8 @@ static void rproc_coredump(struct rproc *rproc)
} }
} }
offset += phdr->p_filesz; offset += elf_phdr_get_p_filesz(class, phdr);
phdr++; phdr += elf_size_of_phdr(class);
} }
dev_coredumpv(&rproc->dev, data, data_size, GFP_KERNEL); dev_coredumpv(&rproc->dev, data, data_size, GFP_KERNEL);
...@@ -2037,6 +2039,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, ...@@ -2037,6 +2039,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
rproc->name = name; rproc->name = name;
rproc->priv = &rproc[1]; rproc->priv = &rproc[1];
rproc->auto_boot = true; rproc->auto_boot = true;
rproc->elf_class = ELFCLASS32;
device_initialize(&rproc->dev); device_initialize(&rproc->dev);
rproc->dev.parent = dev; rproc->dev.parent = dev;
......
...@@ -248,6 +248,9 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) ...@@ -248,6 +248,9 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
memset(ptr + filesz, 0, memsz - filesz); memset(ptr + filesz, 0, memsz - filesz);
} }
if (ret == 0)
rproc->elf_class = class;
return ret; return ret;
} }
EXPORT_SYMBOL(rproc_elf_load_segments); EXPORT_SYMBOL(rproc_elf_load_segments);
......
...@@ -514,6 +514,7 @@ struct rproc { ...@@ -514,6 +514,7 @@ struct rproc {
bool auto_boot; bool auto_boot;
struct list_head dump_segments; struct list_head dump_segments;
int nb_vdev; int nb_vdev;
u8 elf_class;
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment