* [PATCH v6 0/8] elf: add better bootm support
@ 2020-06-12 7:10 Clement Leger
2020-06-12 7:10 ` [PATCH v6 1/8] common: elf: add computation of elf boundaries Clement Leger
` (9 more replies)
0 siblings, 10 replies; 12+ messages in thread
From: Clement Leger @ 2020-06-12 7:10 UTC (permalink / raw)
To: Sascha Hauer, barebox; +Cc: Clement Leger, Oleksij Rempel
Currently, when booting an elf file using "bootm /dev/mtdx", bootm will
simply pass the file to the bootm handler and the read done on it will
read the entire flash partition. This series starts by some cleanup and
then modify the elf loader to load the elf file without copying the whole
elf file to an intermediate buffer. Only the elf header is copied in
order to parse the elf file into a list of segment and then, the segments
are loaded directly from the file.
A special handling for the elf file is also added in bootm data to allow
using directly the elf file structure. Finally the mips bootm handler is
modified to use bootm_load_os directly instead of manual elf loading.
Compilation for both mips and arm has been tested but run on qemu-malta was not
possible. Changes have been tested on kvx architecture for which bootm support
has been added and will be submitted.
Changes v5 -> v6
- Add missing elf boundaries computation patch
Changes v4 -> v5
- Rework elf loading to load from file rather than a buffer
- Use calloc instead of xzalloc in elf file loading
- Add check of program headers in elf check
Changes v3 -> v4
- Fix init of elf entry address to be used by bootm_load_elf
Changes v2 -> v3
- Integrate elf loading in bootm_load_os
- Add patch to remove now unused elf_load_image/elf_release_image
- Use malloc instead of xmalloc and check return value
Changes v1 -> v2
- Add BOOTM_ELF config to select elf support and add checks in code
- Add an elf_get_mem_size function to avoid computing elf size in bootm.c
- Use xmalloc and read_full in elf_open instead of xzalloc/read
- Fix data->elf NULL reset
- Remove elf struct entirely from mips bootm code
Clement Leger (8):
common: elf: add computation of elf boundaries
common: elf: fix warning on 32 bits architectures
common: elf: use calloc instead of xzalloc
common: elf: check number of elf program headers
common: elf: load elf directly from file
common: elf: add elf_open, elf_close and elf_load
common: bootm: add support for elf file loading
mips: lib: bootm: use bootm elf loading capabilities
arch/mips/lib/bootm.c | 25 ++---
common/Kconfig | 8 ++
common/bootm.c | 33 ++++++
common/elf.c | 231 +++++++++++++++++++++++++++++++++++-------
include/bootm.h | 3 +
include/elf.h | 16 ++-
6 files changed, 261 insertions(+), 55 deletions(-)
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 1/8] common: elf: add computation of elf boundaries
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
@ 2020-06-12 7:10 ` Clement Leger
2020-06-12 7:10 ` [PATCH v6 2/8] common: elf: fix warning on 32 bits architectures Clement Leger
` (8 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Clement Leger @ 2020-06-12 7:10 UTC (permalink / raw)
To: Sascha Hauer, barebox; +Cc: Clement Leger, Oleksij Rempel
In order to correctly load an initrd or a device tree after an elf file,
we need to know its boundaries. This commit adds support for that and
allow the bootm implementations to use it for memory loading.
Signed-off-by: Clement Leger <cleger@kalray.eu>
---
common/elf.c | 7 +++++++
include/elf.h | 7 +++++++
2 files changed, 14 insertions(+)
diff --git a/common/elf.c b/common/elf.c
index 4733accb0..d64de401c 100644
--- a/common/elf.c
+++ b/common/elf.c
@@ -59,6 +59,11 @@ static int load_elf_phdr_segment(struct elf_image *elf, void *src,
if (!p_filesz)
return 0;
+ if (dst < elf->low_addr)
+ elf->low_addr = dst;
+ if (dst + p_memsz > elf->high_addr)
+ elf->high_addr = dst + p_memsz;
+
pr_debug("Loading phdr to 0x%p (%llu bytes)\n", dst, p_filesz);
ret = elf_request_region(elf, (resource_size_t)dst, p_filesz);
@@ -124,6 +129,8 @@ struct elf_image *elf_load_image(void *buf)
INIT_LIST_HEAD(&elf->list);
elf->buf = buf;
+ elf->low_addr = (void *) (unsigned long) -1;
+ elf->high_addr = 0;
ret = elf_check_image(elf);
if (ret)
diff --git a/include/elf.h b/include/elf.h
index 113728f08..403412f3f 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -403,9 +403,16 @@ struct elf_image {
struct list_head list;
u8 class;
u64 entry;
+ void *low_addr;
+ void *high_addr;
void *buf;
};
+static inline size_t elf_get_mem_size(struct elf_image *elf)
+{
+ return elf->high_addr - elf->low_addr;
+}
+
struct elf_image *elf_load_image(void *buf);
void elf_release_image(struct elf_image *elf);
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 2/8] common: elf: fix warning on 32 bits architectures
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
2020-06-12 7:10 ` [PATCH v6 1/8] common: elf: add computation of elf boundaries Clement Leger
@ 2020-06-12 7:10 ` Clement Leger
2020-06-12 7:10 ` [PATCH v6 3/8] common: elf: use calloc instead of xzalloc Clement Leger
` (7 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Clement Leger @ 2020-06-12 7:10 UTC (permalink / raw)
To: Sascha Hauer, barebox; +Cc: Clement Leger, Oleksij Rempel
When pointers are 32 bits wide and we cast a potentially 64 bits
value in it, the compiler will yield an error. Cast that value first
into a phys_addr_t to match the architecture pointer size and then
in a void *.
Signed-off-by: Clement Leger <cleger@kalray.eu>
---
common/elf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/elf.c b/common/elf.c
index d64de401c..55f5bc645 100644
--- a/common/elf.c
+++ b/common/elf.c
@@ -47,7 +47,7 @@ static void elf_release_regions(struct elf_image *elf)
static int load_elf_phdr_segment(struct elf_image *elf, void *src,
void *phdr)
{
- void *dst = (void *) elf_phdr_p_paddr(elf, phdr);
+ void *dst = (void *) (phys_addr_t) elf_phdr_p_paddr(elf, phdr);
int ret;
u64 p_filesz = elf_phdr_p_filesz(elf, phdr);
u64 p_memsz = elf_phdr_p_memsz(elf, phdr);
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 3/8] common: elf: use calloc instead of xzalloc
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
2020-06-12 7:10 ` [PATCH v6 1/8] common: elf: add computation of elf boundaries Clement Leger
2020-06-12 7:10 ` [PATCH v6 2/8] common: elf: fix warning on 32 bits architectures Clement Leger
@ 2020-06-12 7:10 ` Clement Leger
2020-06-12 7:10 ` [PATCH v6 4/8] common: elf: check number of elf program headers Clement Leger
` (6 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Clement Leger @ 2020-06-12 7:10 UTC (permalink / raw)
To: Sascha Hauer, barebox; +Cc: Clement Leger, Oleksij Rempel
This failure can be handled grecefully, use standard calloc.
Signed-off-by: Clement Leger <cleger@kalray.eu>
---
common/elf.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/common/elf.c b/common/elf.c
index 55f5bc645..0e92661e1 100644
--- a/common/elf.c
+++ b/common/elf.c
@@ -19,7 +19,10 @@ static int elf_request_region(struct elf_image *elf, resource_size_t start,
struct resource *r_new;
struct elf_section *r;
- r = xzalloc(sizeof(*r));
+ r = calloc(1, sizeof(*r));
+ if (!r)
+ return -ENOMEM;
+
r_new = request_sdram_region("elf_section", start, size);
if (!r_new) {
pr_err("Failed to request region: %pa %pa\n", &start, &size);
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 4/8] common: elf: check number of elf program headers
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
` (2 preceding siblings ...)
2020-06-12 7:10 ` [PATCH v6 3/8] common: elf: use calloc instead of xzalloc Clement Leger
@ 2020-06-12 7:10 ` Clement Leger
2020-06-12 7:10 ` [PATCH v6 5/8] common: elf: load elf directly from file Clement Leger
` (5 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Clement Leger @ 2020-06-12 7:10 UTC (permalink / raw)
To: Sascha Hauer, barebox; +Cc: Clement Leger, Oleksij Rempel
An elf file without program headers should not be loaded. Add a check
for such cases.
Signed-off-by: Clement Leger <cleger@kalray.eu>
---
common/elf.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/common/elf.c b/common/elf.c
index 0e92661e1..bd97858c8 100644
--- a/common/elf.c
+++ b/common/elf.c
@@ -119,6 +119,11 @@ static int elf_check_image(struct elf_image *elf)
return -ENOEXEC;
}
+ if (!elf_hdr_e_phnum(elf, elf->buf)) {
+ pr_err("No phdr found.\n");
+ return -ENOEXEC;
+ }
+
return 0;
}
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 5/8] common: elf: load elf directly from file
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
` (3 preceding siblings ...)
2020-06-12 7:10 ` [PATCH v6 4/8] common: elf: check number of elf program headers Clement Leger
@ 2020-06-12 7:10 ` Clement Leger
2020-06-12 7:10 ` [PATCH v6 6/8] common: elf: add elf_open, elf_close and elf_load Clement Leger
` (4 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Clement Leger @ 2020-06-12 7:10 UTC (permalink / raw)
To: Sascha Hauer, barebox; +Cc: Clement Leger, Oleksij Rempel
Currently, elf file must be loaded into a buffer and then passed to
elf_load_image. This requires to copy the whole elf file before booting
it. This commit allows to pass the filename directly and will allocate
data only for the elf header (elf header + program headers). This will
then be used to load the elf data from the file without copying it in an
intermediate buffer. Elf segments are first parsed into a list and are
then loaded from the file in a second time.
Signed-off-by: Clement Leger <cleger@kalray.eu>
---
arch/mips/lib/bootm.c | 9 +-
common/elf.c | 220 +++++++++++++++++++++++++++++++++++-------
include/elf.h | 6 +-
3 files changed, 191 insertions(+), 44 deletions(-)
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 5bb09cc2d..b07884ae0 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -47,14 +47,10 @@ static int do_bootm_elf(struct image_data *data)
{
void (*entry)(int, void *);
struct elf_image *elf;
- void *fdt, *buf;
+ void *fdt;
int ret = 0;
- buf = read_file(data->os_file, NULL);
- if (!buf)
- return -EINVAL;
-
- elf = elf_load_image(buf);
+ elf = elf_load_image(data->os_file);
if (IS_ERR(elf))
return PTR_ERR(elf);
@@ -82,7 +78,6 @@ static int do_bootm_elf(struct image_data *data)
bootm_elf_done:
elf_release_image(elf);
free(fdt);
- free(buf);
return ret;
}
diff --git a/common/elf.c b/common/elf.c
index bd97858c8..1bcaafea7 100644
--- a/common/elf.c
+++ b/common/elf.c
@@ -5,15 +5,22 @@
#include <common.h>
#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libfile.h>
#include <memory.h>
+#include <unistd.h>
+#include <linux/fs.h>
+#include <linux/list_sort.h>
struct elf_section {
struct list_head list;
struct resource *r;
+ void *phdr;
};
static int elf_request_region(struct elf_image *elf, resource_size_t start,
- resource_size_t size)
+ resource_size_t size, void *phdr)
{
struct list_head *list = &elf->list;
struct resource *r_new;
@@ -30,6 +37,7 @@ static int elf_request_region(struct elf_image *elf, resource_size_t start,
}
r->r = r_new;
+ r->phdr = phdr;
list_add_tail(&r->list, list);
return 0;
@@ -42,13 +50,12 @@ static void elf_release_regions(struct elf_image *elf)
list_for_each_entry_safe(r, r_tmp, list, list) {
release_sdram_region(r->r);
+ list_del(&r->list);
free(r);
}
}
-
-static int load_elf_phdr_segment(struct elf_image *elf, void *src,
- void *phdr)
+static int request_elf_segment(struct elf_image *elf, void *phdr)
{
void *dst = (void *) (phys_addr_t) elf_phdr_p_paddr(elf, phdr);
int ret;
@@ -67,59 +74,127 @@ static int load_elf_phdr_segment(struct elf_image *elf, void *src,
if (dst + p_memsz > elf->high_addr)
elf->high_addr = dst + p_memsz;
- pr_debug("Loading phdr to 0x%p (%llu bytes)\n", dst, p_filesz);
+ pr_debug("Requesting segment 0x%p (%llu bytes)\n", dst, p_filesz);
- ret = elf_request_region(elf, (resource_size_t)dst, p_filesz);
+ ret = elf_request_region(elf, (resource_size_t)dst, p_filesz, phdr);
if (ret)
return ret;
- memcpy(dst, src, p_filesz);
+ return 0;
+}
+
+static int elf_section_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+ struct elf_image *elf = priv;
+ struct elf_section *elf_a, *elf_b;
+
+ if (a == b)
+ return 0;
+
+ elf_a = list_entry(a, struct elf_section, list);
+ elf_b = list_entry(b, struct elf_section, list);
+
+ return elf_phdr_p_offset(elf, elf_a->phdr) >
+ elf_phdr_p_offset(elf, elf_b->phdr);
+}
+
+static int load_elf_to_memory(struct elf_image *elf)
+{
+ void *dst;
+ int ret, fd;
+ u64 p_filesz, p_memsz, p_offset;
+ struct elf_section *r;
+ struct list_head *list = &elf->list;
+
+ fd = open(elf->filename, O_RDONLY);
+ if (fd < 0) {
+ pr_err("could not open: %s\n", errno_str());
+ return -errno;
+ }
- if (p_filesz < p_memsz)
- memset(dst + p_filesz, 0x00,
- p_memsz - p_filesz);
+ list_for_each_entry(r, list, list) {
+ p_offset = elf_phdr_p_offset(elf, r->phdr);
+ p_filesz = elf_phdr_p_filesz(elf, r->phdr);
+ p_memsz = elf_phdr_p_memsz(elf, r->phdr);
+ dst = (void *) (phys_addr_t) elf_phdr_p_paddr(elf, r->phdr);
+
+ ret = lseek(fd, p_offset, SEEK_SET);
+ if (ret == -1) {
+ pr_err("lseek at offset 0x%llx failed\n", p_offset);
+ close(fd);
+ return ret;
+ }
+
+ pr_debug("Loading phdr offset 0x%llx to 0x%p (%llu bytes)\n",
+ p_offset, dst, p_filesz);
+
+ if (read_full(fd, dst, p_filesz) < 0) {
+ pr_err("could not read elf segment: %s\n",
+ errno_str());
+ close(fd);
+ return -errno;
+ }
+
+ if (p_filesz < p_memsz)
+ memset(dst + p_filesz, 0x00, p_memsz - p_filesz);
+ }
+
+ close(fd);
return 0;
}
-static int load_elf_image_phdr(struct elf_image *elf)
+static int load_elf_image_segments(struct elf_image *elf)
{
- void *buf = elf->buf;
+ void *buf = elf->hdr_buf;
void *phdr = (void *) (buf + elf_hdr_e_phoff(elf, buf));
int i, ret;
- elf->entry = elf_hdr_e_entry(elf, buf);
+ /* File as already been loaded */
+ if (!list_empty(&elf->list))
+ return -EINVAL;
for (i = 0; i < elf_hdr_e_phnum(elf, buf) ; ++i) {
- void *src = buf + elf_phdr_p_offset(elf, phdr);
-
- ret = load_elf_phdr_segment(elf, src, phdr);
- /* in case of error elf_load_image() caller should clean up and
- * call elf_release_image() */
+ ret = request_elf_segment(elf, phdr);
if (ret)
- return ret;
+ goto elf_release_regions;
phdr += elf_size_of_phdr(elf);
}
+ /*
+ * Sort the list to avoid doing backward lseek while loading the elf
+ * segments from file to memory(some filesystems don't support it)
+ */
+ list_sort(elf, &elf->list, elf_section_cmp);
+
+ ret = load_elf_to_memory(elf);
+ if (ret)
+ goto elf_release_regions;
+
return 0;
+
+elf_release_regions:
+ elf_release_regions(elf);
+
+ return ret;
}
-static int elf_check_image(struct elf_image *elf)
+static int elf_check_image(struct elf_image *elf, void *buf)
{
- if (strncmp(elf->buf, ELFMAG, SELFMAG)) {
+ if (strncmp(buf, ELFMAG, SELFMAG)) {
pr_err("ELF magic not found.\n");
return -EINVAL;
}
- elf->class = ((char *) elf->buf)[EI_CLASS];
+ elf->class = ((char *) buf)[EI_CLASS];
- if (elf_hdr_e_type(elf, elf->buf) != ET_EXEC) {
+ if (elf_hdr_e_type(elf, buf) != ET_EXEC) {
pr_err("Non EXEC ELF image.\n");
return -ENOEXEC;
}
- if (!elf_hdr_e_phnum(elf, elf->buf)) {
+ if (!elf_hdr_e_phnum(elf, buf)) {
pr_err("No phdr found.\n");
return -ENOEXEC;
}
@@ -127,29 +202,102 @@ static int elf_check_image(struct elf_image *elf)
return 0;
}
-struct elf_image *elf_load_image(void *buf)
+static struct elf_image *elf_check_init(const char *filename)
{
+ int ret, fd;
+ int hdr_size;
+ struct elf64_hdr hdr;
struct elf_image *elf;
- int ret;
- elf = xzalloc(sizeof(*elf));
+ elf = calloc(1, sizeof(*elf));
+ if (!elf)
+ return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&elf->list);
-
- elf->buf = buf;
elf->low_addr = (void *) (unsigned long) -1;
elf->high_addr = 0;
- ret = elf_check_image(elf);
+ /* First pass is to read elf header only */
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ pr_err("could not open: %s\n", errno_str());
+ ret = -errno;
+ goto err_free_elf;
+ }
+
+ if (read_full(fd, &hdr, sizeof(hdr)) < 0) {
+ pr_err("could not read elf header: %s\n", errno_str());
+ close(fd);
+ ret = -errno;
+ goto err_free_elf;
+ }
+ close(fd);
+
+ ret = elf_check_image(elf, &hdr);
if (ret)
- return ERR_PTR(ret);
+ goto err_free_elf;
- ret = load_elf_image_phdr(elf);
- if (ret) {
- elf_release_image(elf);
- return ERR_PTR(ret);
+ hdr_size = elf_hdr_e_phoff(elf, &hdr) +
+ elf_hdr_e_phnum(elf, &hdr) *
+ elf_hdr_e_phentsize(elf, &hdr);
+
+ /* Second pass is to read the whole elf header and program headers */
+ elf->hdr_buf = malloc(hdr_size);
+ if (!elf->hdr_buf) {
+ ret = -ENOMEM;
+ goto err_free_elf;
+ }
+
+ /*
+ * We must open the file again since some fs (tftp) do not support
+ * backward lseek operations
+ */
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ pr_err("could not open: %s\n", errno_str());
+ ret = -errno;
+ goto err_free_hdr_buf;
+ }
+
+ if (read_full(fd, elf->hdr_buf, hdr_size) < 0) {
+ pr_err("could not read elf program headers: %s\n", errno_str());
+ ret = -errno;
+ close(fd);
+ goto err_free_hdr_buf;
+ }
+ close(fd);
+
+ elf->filename = strdup(filename);
+ if (!elf->filename) {
+ ret = -ENOMEM;
+ goto err_free_hdr_buf;
}
+ elf->entry = elf_hdr_e_entry(elf, elf->hdr_buf);
+
+ return elf;
+
+err_free_hdr_buf:
+ free(elf->hdr_buf);
+err_free_elf:
+ free(elf);
+
+ return ERR_PTR(ret);
+}
+
+struct elf_image *elf_load_image(const char *filename)
+{
+ int ret;
+ struct elf_image *elf;
+
+ elf = elf_check_init(filename);
+ if (IS_ERR(elf))
+ return elf;
+
+ ret = load_elf_image_segments(elf);
+ if (ret)
+ return ERR_PTR(ret);
+
return elf;
}
@@ -157,5 +305,7 @@ void elf_release_image(struct elf_image *elf)
{
elf_release_regions(elf);
+ free(elf->hdr_buf);
+ free(elf->filename);
free(elf);
}
diff --git a/include/elf.h b/include/elf.h
index 403412f3f..f1a80a20a 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -405,7 +405,8 @@ struct elf_image {
u64 entry;
void *low_addr;
void *high_addr;
- void *buf;
+ void *hdr_buf;
+ char *filename;
};
static inline size_t elf_get_mem_size(struct elf_image *elf)
@@ -413,7 +414,7 @@ static inline size_t elf_get_mem_size(struct elf_image *elf)
return elf->high_addr - elf->low_addr;
}
-struct elf_image *elf_load_image(void *buf);
+struct elf_image *elf_load_image(const char *filename);
void elf_release_image(struct elf_image *elf);
#define ELF_GET_FIELD(__s, __field, __type) \
@@ -427,6 +428,7 @@ static inline __type elf_##__s##_##__field(struct elf_image *elf, void *arg) { \
ELF_GET_FIELD(hdr, e_entry, u64)
ELF_GET_FIELD(hdr, e_phnum, u16)
ELF_GET_FIELD(hdr, e_phoff, u64)
+ELF_GET_FIELD(hdr, e_phentsize, u16)
ELF_GET_FIELD(hdr, e_type, u16)
ELF_GET_FIELD(phdr, p_paddr, u64)
ELF_GET_FIELD(phdr, p_filesz, u64)
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 6/8] common: elf: add elf_open, elf_close and elf_load
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
` (4 preceding siblings ...)
2020-06-12 7:10 ` [PATCH v6 5/8] common: elf: load elf directly from file Clement Leger
@ 2020-06-12 7:10 ` Clement Leger
2020-06-12 7:10 ` [PATCH v6 7/8] common: bootm: add support for elf file loading Clement Leger
` (3 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Clement Leger @ 2020-06-12 7:10 UTC (permalink / raw)
To: Sascha Hauer, barebox; +Cc: Clement Leger, Oleksij Rempel
In order to integrate elf loading into bootm command, split elf opening
from elf loading.
Signed-off-by: Clement Leger <cleger@kalray.eu>
---
arch/mips/lib/bootm.c | 8 ++++++--
common/elf.c | 20 +++++++-------------
include/elf.h | 5 +++--
3 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index b07884ae0..8e16994b6 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -50,10 +50,14 @@ static int do_bootm_elf(struct image_data *data)
void *fdt;
int ret = 0;
- elf = elf_load_image(data->os_file);
+ elf = elf_open(data->os_file);
if (IS_ERR(elf))
return PTR_ERR(elf);
+ ret = elf_load(elf);
+ if (ret)
+ goto bootm_elf_done;
+
fdt = bootm_get_devicetree(data);
if (IS_ERR(fdt)) {
ret = PTR_ERR(fdt);
@@ -76,7 +80,7 @@ static int do_bootm_elf(struct image_data *data)
ret = -EINVAL;
bootm_elf_done:
- elf_release_image(elf);
+ elf_close(elf);
free(fdt);
return ret;
diff --git a/common/elf.c b/common/elf.c
index 1bcaafea7..af22be37e 100644
--- a/common/elf.c
+++ b/common/elf.c
@@ -285,23 +285,17 @@ err_free_elf:
return ERR_PTR(ret);
}
-struct elf_image *elf_load_image(const char *filename)
+struct elf_image *elf_open(const char *filename)
{
- int ret;
- struct elf_image *elf;
-
- elf = elf_check_init(filename);
- if (IS_ERR(elf))
- return elf;
-
- ret = load_elf_image_segments(elf);
- if (ret)
- return ERR_PTR(ret);
+ return elf_check_init(filename);
+}
- return elf;
+int elf_load(struct elf_image *elf)
+{
+ return load_elf_image_segments(elf);
}
-void elf_release_image(struct elf_image *elf)
+void elf_close(struct elf_image *elf)
{
elf_release_regions(elf);
diff --git a/include/elf.h b/include/elf.h
index f1a80a20a..7970fd2c9 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -414,8 +414,9 @@ static inline size_t elf_get_mem_size(struct elf_image *elf)
return elf->high_addr - elf->low_addr;
}
-struct elf_image *elf_load_image(const char *filename);
-void elf_release_image(struct elf_image *elf);
+struct elf_image *elf_open(const char *filename);
+void elf_close(struct elf_image *elf);
+int elf_load(struct elf_image *elf);
#define ELF_GET_FIELD(__s, __field, __type) \
static inline __type elf_##__s##_##__field(struct elf_image *elf, void *arg) { \
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 7/8] common: bootm: add support for elf file loading
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
` (5 preceding siblings ...)
2020-06-12 7:10 ` [PATCH v6 6/8] common: elf: add elf_open, elf_close and elf_load Clement Leger
@ 2020-06-12 7:10 ` Clement Leger
2020-06-12 7:10 ` [PATCH v6 8/8] mips: lib: bootm: use bootm elf loading capabilities Clement Leger
` (2 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Clement Leger @ 2020-06-12 7:10 UTC (permalink / raw)
To: Sascha Hauer, barebox; +Cc: Clement Leger, Oleksij Rempel
This will allows elf loader to directly have an elf file available. Thus
filetype_elf bootm handlers will be able to use standard bootm functions
and data.
Signed-off-by: Clement Leger <cleger@kalray.eu>
---
common/Kconfig | 8 ++++++++
common/bootm.c | 33 +++++++++++++++++++++++++++++++++
include/bootm.h | 3 +++
3 files changed, 44 insertions(+)
diff --git a/common/Kconfig b/common/Kconfig
index ac282d895..d75b43dfc 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -597,6 +597,14 @@ config BOOTM_AIMAGE
help
Support using Android Images.
+config BOOTM_ELF
+ bool
+ depends on BOOTM
+ select ELF
+ prompt "elf loading support"
+ help
+ Add support to load elf file with bootm.
+
config BOOTM_FITIMAGE
bool
prompt "FIT image support"
diff --git a/common/bootm.c b/common/bootm.c
index 8fec1ee34..4110d8d6e 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -143,6 +143,9 @@ int bootm_load_os(struct image_data *data, unsigned long load_address)
return 0;
}
+ if (IS_ENABLED(CONFIG_ELF) && data->elf)
+ return elf_load(data->elf);
+
if (data->os_file) {
data->os_res = file_to_sdram(data->os_file, load_address);
if (!data->os_res)
@@ -470,6 +473,8 @@ int bootm_get_os_size(struct image_data *data)
{
int ret;
+ if (data->elf)
+ return elf_get_mem_size(data->elf);
if (data->os)
return uimage_get_size(data->os, uimage_part_num(data->os_part));
if (data->os_fit)
@@ -517,6 +522,22 @@ static int bootm_open_os_uimage(struct image_data *data)
return 0;
}
+static int bootm_open_elf(struct image_data *data)
+{
+ if (!IS_ENABLED(CONFIG_ELF))
+ return -ENOSYS;
+
+ data->elf = elf_open(data->os_file);
+ if (IS_ERR(data->elf))
+ return PTR_ERR(data->elf);
+
+ printf("Entry Point: %08llx\n", data->elf->entry);
+
+ data->os_address = data->elf->entry;
+
+ return 0;
+}
+
static void bootm_print_info(struct image_data *data)
{
if (data->os_res)
@@ -652,6 +673,16 @@ int bootm_boot(struct bootm_data *bootm_data)
}
}
+ if (os_type == filetype_elf) {
+ ret = bootm_open_elf(data);
+ if (ret) {
+ printf("Loading ELF image failed with: %s\n",
+ strerror(-ret));
+ data->elf = NULL;
+ goto err_out;
+ }
+ }
+
if (bootm_data->appendroot) {
char *rootarg;
@@ -721,6 +752,8 @@ err_out:
uimage_close(data->initrd);
if (data->os)
uimage_close(data->os);
+ if (IS_ENABLED(CONFIG_ELF) && data->elf)
+ elf_close(data->elf);
if (IS_ENABLED(CONFIG_FITIMAGE) && data->os_fit)
fit_close(data->os_fit);
if (data->of_root_node && data->of_root_node != of_get_root_node())
diff --git a/include/bootm.h b/include/bootm.h
index 7782de7a4..ef5148f31 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -46,6 +46,9 @@ struct image_data {
/* if os is an uImage this will be provided */
struct uimage_handle *os;
+ /* if os is an elf file this will be provided */
+ struct elf_image *elf;
+
/* if os is a FIT image this will be provided */
struct fit_handle *os_fit;
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 8/8] mips: lib: bootm: use bootm elf loading capabilities
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
` (6 preceding siblings ...)
2020-06-12 7:10 ` [PATCH v6 7/8] common: bootm: add support for elf file loading Clement Leger
@ 2020-06-12 7:10 ` Clement Leger
2020-06-12 7:41 ` [PATCH v6 0/8] elf: add better bootm support Oleksij Rempel
2020-06-15 14:15 ` Sascha Hauer
9 siblings, 0 replies; 12+ messages in thread
From: Clement Leger @ 2020-06-12 7:10 UTC (permalink / raw)
To: Sascha Hauer, barebox; +Cc: Clement Leger, Oleksij Rempel
Now that the elf file is loaded by the bootm core, there is no need for
elf pointer anymore. Thus all elf related fields can be removed and
bootm_load_os can be used.
Signed-off-by: Clement Leger <cleger@kalray.eu>
---
arch/mips/lib/bootm.c | 20 +++++++-------------
1 file changed, 7 insertions(+), 13 deletions(-)
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 8e16994b6..6c56202ea 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -46,41 +46,35 @@ static struct binfmt_hook binfmt_barebox_hook = {
static int do_bootm_elf(struct image_data *data)
{
void (*entry)(int, void *);
- struct elf_image *elf;
void *fdt;
int ret = 0;
- elf = elf_open(data->os_file);
- if (IS_ERR(elf))
- return PTR_ERR(elf);
-
- ret = elf_load(elf);
+ ret = bootm_load_os(data, data->os_address);
if (ret)
- goto bootm_elf_done;
+ return ret;
fdt = bootm_get_devicetree(data);
if (IS_ERR(fdt)) {
ret = PTR_ERR(fdt);
- goto bootm_elf_done;
+ goto bootm_free_fdt;
}
pr_info("Starting application at 0x%08lx, dts 0x%08lx...\n",
- phys_to_virt(elf->entry), data->of_root_node);
+ phys_to_virt(data->os_address), data->of_root_node);
if (data->dryrun)
- goto bootm_elf_done;
+ goto bootm_free_fdt;
shutdown_barebox();
- entry = (void *) (unsigned long) elf->entry;
+ entry = (void *) (unsigned long) data->os_address;
entry(-2, phys_to_virt((unsigned long)fdt));
pr_err("ELF application terminated\n");
ret = -EINVAL;
-bootm_elf_done:
- elf_close(elf);
+bootm_free_fdt:
free(fdt);
return ret;
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 0/8] elf: add better bootm support
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
` (7 preceding siblings ...)
2020-06-12 7:10 ` [PATCH v6 8/8] mips: lib: bootm: use bootm elf loading capabilities Clement Leger
@ 2020-06-12 7:41 ` Oleksij Rempel
2020-06-12 7:44 ` Clément Leger
2020-06-15 14:15 ` Sascha Hauer
9 siblings, 1 reply; 12+ messages in thread
From: Oleksij Rempel @ 2020-06-12 7:41 UTC (permalink / raw)
To: Clement Leger; +Cc: barebox, Oleksij Rempel
[-- Attachment #1.1: Type: text/plain, Size: 3316 bytes --]
Nice work. Thank you!
Following variants was tested:
- net boot
- boot from local ram copy
- boot from spi flash
Tested-by: Oleksij Rempel <o.rempel@pengutronix.de>
On Fri, Jun 12, 2020 at 09:10:28AM +0200, Clement Leger wrote:
> Currently, when booting an elf file using "bootm /dev/mtdx", bootm will
> simply pass the file to the bootm handler and the read done on it will
> read the entire flash partition. This series starts by some cleanup and
> then modify the elf loader to load the elf file without copying the whole
> elf file to an intermediate buffer. Only the elf header is copied in
> order to parse the elf file into a list of segment and then, the segments
> are loaded directly from the file.
>
> A special handling for the elf file is also added in bootm data to allow
> using directly the elf file structure. Finally the mips bootm handler is
> modified to use bootm_load_os directly instead of manual elf loading.
>
> Compilation for both mips and arm has been tested but run on qemu-malta was not
> possible. Changes have been tested on kvx architecture for which bootm support
> has been added and will be submitted.
>
> Changes v5 -> v6
> - Add missing elf boundaries computation patch
>
> Changes v4 -> v5
> - Rework elf loading to load from file rather than a buffer
> - Use calloc instead of xzalloc in elf file loading
> - Add check of program headers in elf check
>
> Changes v3 -> v4
> - Fix init of elf entry address to be used by bootm_load_elf
>
> Changes v2 -> v3
> - Integrate elf loading in bootm_load_os
> - Add patch to remove now unused elf_load_image/elf_release_image
> - Use malloc instead of xmalloc and check return value
>
> Changes v1 -> v2
> - Add BOOTM_ELF config to select elf support and add checks in code
> - Add an elf_get_mem_size function to avoid computing elf size in bootm.c
> - Use xmalloc and read_full in elf_open instead of xzalloc/read
> - Fix data->elf NULL reset
> - Remove elf struct entirely from mips bootm code
>
> Clement Leger (8):
> common: elf: add computation of elf boundaries
> common: elf: fix warning on 32 bits architectures
> common: elf: use calloc instead of xzalloc
> common: elf: check number of elf program headers
> common: elf: load elf directly from file
> common: elf: add elf_open, elf_close and elf_load
> common: bootm: add support for elf file loading
> mips: lib: bootm: use bootm elf loading capabilities
>
> arch/mips/lib/bootm.c | 25 ++---
> common/Kconfig | 8 ++
> common/bootm.c | 33 ++++++
> common/elf.c | 231 +++++++++++++++++++++++++++++++++++-------
> include/bootm.h | 3 +
> include/elf.h | 16 ++-
> 6 files changed, 261 insertions(+), 55 deletions(-)
>
> --
> 2.17.1
>
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #2: Type: text/plain, Size: 149 bytes --]
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 0/8] elf: add better bootm support
2020-06-12 7:41 ` [PATCH v6 0/8] elf: add better bootm support Oleksij Rempel
@ 2020-06-12 7:44 ` Clément Leger
0 siblings, 0 replies; 12+ messages in thread
From: Clément Leger @ 2020-06-12 7:44 UTC (permalink / raw)
To: Oleksij Rempel; +Cc: Barebox List, Oleksij Rempel
----- On 12 Jun, 2020, at 09:41, Oleksij Rempel o.rempel@pengutronix.de wrote:
> Nice work. Thank you!
> Following variants was tested:
> - net boot
> - boot from local ram copy
> - boot from spi flash
>
> Tested-by: Oleksij Rempel <o.rempel@pengutronix.de>
Finally ;) Thanks again for testing it on mips !
>
> On Fri, Jun 12, 2020 at 09:10:28AM +0200, Clement Leger wrote:
>> Currently, when booting an elf file using "bootm /dev/mtdx", bootm will
>> simply pass the file to the bootm handler and the read done on it will
>> read the entire flash partition. This series starts by some cleanup and
>> then modify the elf loader to load the elf file without copying the whole
>> elf file to an intermediate buffer. Only the elf header is copied in
>> order to parse the elf file into a list of segment and then, the segments
>> are loaded directly from the file.
>>
>> A special handling for the elf file is also added in bootm data to allow
>> using directly the elf file structure. Finally the mips bootm handler is
>> modified to use bootm_load_os directly instead of manual elf loading.
>>
>> Compilation for both mips and arm has been tested but run on qemu-malta was not
>> possible. Changes have been tested on kvx architecture for which bootm support
>> has been added and will be submitted.
>>
>> Changes v5 -> v6
>> - Add missing elf boundaries computation patch
>>
>> Changes v4 -> v5
>> - Rework elf loading to load from file rather than a buffer
>> - Use calloc instead of xzalloc in elf file loading
>> - Add check of program headers in elf check
>>
>> Changes v3 -> v4
>> - Fix init of elf entry address to be used by bootm_load_elf
>>
>> Changes v2 -> v3
>> - Integrate elf loading in bootm_load_os
>> - Add patch to remove now unused elf_load_image/elf_release_image
>> - Use malloc instead of xmalloc and check return value
>>
>> Changes v1 -> v2
>> - Add BOOTM_ELF config to select elf support and add checks in code
>> - Add an elf_get_mem_size function to avoid computing elf size in bootm.c
>> - Use xmalloc and read_full in elf_open instead of xzalloc/read
>> - Fix data->elf NULL reset
>> - Remove elf struct entirely from mips bootm code
>>
>> Clement Leger (8):
>> common: elf: add computation of elf boundaries
>> common: elf: fix warning on 32 bits architectures
>> common: elf: use calloc instead of xzalloc
>> common: elf: check number of elf program headers
>> common: elf: load elf directly from file
>> common: elf: add elf_open, elf_close and elf_load
>> common: bootm: add support for elf file loading
>> mips: lib: bootm: use bootm elf loading capabilities
>>
>> arch/mips/lib/bootm.c | 25 ++---
>> common/Kconfig | 8 ++
>> common/bootm.c | 33 ++++++
>> common/elf.c | 231 +++++++++++++++++++++++++++++++++++-------
>> include/bootm.h | 3 +
>> include/elf.h | 16 ++-
>> 6 files changed, 261 insertions(+), 55 deletions(-)
>>
>> --
>> 2.17.1
>>
>>
>> _______________________________________________
>> barebox mailing list
>> barebox@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/barebox
>>
>
> --
> Pengutronix e.K. | |
> Steuerwalder Str. 21 | http://www.pengutronix.de/ |
> 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 0/8] elf: add better bootm support
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
` (8 preceding siblings ...)
2020-06-12 7:41 ` [PATCH v6 0/8] elf: add better bootm support Oleksij Rempel
@ 2020-06-15 14:15 ` Sascha Hauer
9 siblings, 0 replies; 12+ messages in thread
From: Sascha Hauer @ 2020-06-15 14:15 UTC (permalink / raw)
To: Clement Leger; +Cc: barebox, Oleksij Rempel
On Fri, Jun 12, 2020 at 09:10:28AM +0200, Clement Leger wrote:
> Currently, when booting an elf file using "bootm /dev/mtdx", bootm will
> simply pass the file to the bootm handler and the read done on it will
> read the entire flash partition. This series starts by some cleanup and
> then modify the elf loader to load the elf file without copying the whole
> elf file to an intermediate buffer. Only the elf header is copied in
> order to parse the elf file into a list of segment and then, the segments
> are loaded directly from the file.
>
> A special handling for the elf file is also added in bootm data to allow
> using directly the elf file structure. Finally the mips bootm handler is
> modified to use bootm_load_os directly instead of manual elf loading.
>
> Compilation for both mips and arm has been tested but run on qemu-malta was not
> possible. Changes have been tested on kvx architecture for which bootm support
> has been added and will be submitted.
>
> Changes v5 -> v6
> - Add missing elf boundaries computation patch
Applied, thanks
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2020-06-15 14:15 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-12 7:10 [PATCH v6 0/8] elf: add better bootm support Clement Leger
2020-06-12 7:10 ` [PATCH v6 1/8] common: elf: add computation of elf boundaries Clement Leger
2020-06-12 7:10 ` [PATCH v6 2/8] common: elf: fix warning on 32 bits architectures Clement Leger
2020-06-12 7:10 ` [PATCH v6 3/8] common: elf: use calloc instead of xzalloc Clement Leger
2020-06-12 7:10 ` [PATCH v6 4/8] common: elf: check number of elf program headers Clement Leger
2020-06-12 7:10 ` [PATCH v6 5/8] common: elf: load elf directly from file Clement Leger
2020-06-12 7:10 ` [PATCH v6 6/8] common: elf: add elf_open, elf_close and elf_load Clement Leger
2020-06-12 7:10 ` [PATCH v6 7/8] common: bootm: add support for elf file loading Clement Leger
2020-06-12 7:10 ` [PATCH v6 8/8] mips: lib: bootm: use bootm elf loading capabilities Clement Leger
2020-06-12 7:41 ` [PATCH v6 0/8] elf: add better bootm support Oleksij Rempel
2020-06-12 7:44 ` Clément Leger
2020-06-15 14:15 ` Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox