* [PATCH v5 0/7] elf: add better bootm support @ 2020-06-11 8:02 Clement Leger 2020-06-11 8:02 ` [PATCH v5 1/7] common: elf: fix warning on 32 bits architectures Clement Leger ` (7 more replies) 0 siblings, 8 replies; 11+ messages in thread From: Clement Leger @ 2020-06-11 8:02 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 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 (7): 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 | 226 +++++++++++++++++++++++++++++++++++------- include/bootm.h | 3 + include/elf.h | 9 +- 6 files changed, 248 insertions(+), 56 deletions(-) -- 2.17.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v5 1/7] common: elf: fix warning on 32 bits architectures 2020-06-11 8:02 [PATCH v5 0/7] elf: add better bootm support Clement Leger @ 2020-06-11 8:02 ` Clement Leger 2020-06-11 8:02 ` [PATCH v5 2/7] common: elf: use calloc instead of xzalloc Clement Leger ` (6 subsequent siblings) 7 siblings, 0 replies; 11+ messages in thread From: Clement Leger @ 2020-06-11 8:02 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] 11+ messages in thread
* [PATCH v5 2/7] common: elf: use calloc instead of xzalloc 2020-06-11 8:02 [PATCH v5 0/7] elf: add better bootm support Clement Leger 2020-06-11 8:02 ` [PATCH v5 1/7] common: elf: fix warning on 32 bits architectures Clement Leger @ 2020-06-11 8:02 ` Clement Leger 2020-06-11 8:02 ` [PATCH v5 3/7] common: elf: check number of elf program headers Clement Leger ` (5 subsequent siblings) 7 siblings, 0 replies; 11+ messages in thread From: Clement Leger @ 2020-06-11 8:02 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] 11+ messages in thread
* [PATCH v5 3/7] common: elf: check number of elf program headers 2020-06-11 8:02 [PATCH v5 0/7] elf: add better bootm support Clement Leger 2020-06-11 8:02 ` [PATCH v5 1/7] common: elf: fix warning on 32 bits architectures Clement Leger 2020-06-11 8:02 ` [PATCH v5 2/7] common: elf: use calloc instead of xzalloc Clement Leger @ 2020-06-11 8:02 ` Clement Leger 2020-06-11 8:02 ` [PATCH v5 4/7] common: elf: load elf directly from file Clement Leger ` (4 subsequent siblings) 7 siblings, 0 replies; 11+ messages in thread From: Clement Leger @ 2020-06-11 8:02 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] 11+ messages in thread
* [PATCH v5 4/7] common: elf: load elf directly from file 2020-06-11 8:02 [PATCH v5 0/7] elf: add better bootm support Clement Leger ` (2 preceding siblings ...) 2020-06-11 8:02 ` [PATCH v5 3/7] common: elf: check number of elf program headers Clement Leger @ 2020-06-11 8:02 ` Clement Leger 2020-06-11 8:02 ` [PATCH v5 5/7] common: elf: add elf_open, elf_close and elf_load Clement Leger ` (3 subsequent siblings) 7 siblings, 0 replies; 11+ messages in thread From: Clement Leger @ 2020-06-11 8:02 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..ad0db13ec 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 program headers: %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] 11+ messages in thread
* [PATCH v5 5/7] common: elf: add elf_open, elf_close and elf_load 2020-06-11 8:02 [PATCH v5 0/7] elf: add better bootm support Clement Leger ` (3 preceding siblings ...) 2020-06-11 8:02 ` [PATCH v5 4/7] common: elf: load elf directly from file Clement Leger @ 2020-06-11 8:02 ` Clement Leger 2020-06-11 8:02 ` [PATCH v5 6/7] common: bootm: add support for elf file loading Clement Leger ` (2 subsequent siblings) 7 siblings, 0 replies; 11+ messages in thread From: Clement Leger @ 2020-06-11 8:02 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 ad0db13ec..a00fc8f0d 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] 11+ messages in thread
* [PATCH v5 6/7] common: bootm: add support for elf file loading 2020-06-11 8:02 [PATCH v5 0/7] elf: add better bootm support Clement Leger ` (4 preceding siblings ...) 2020-06-11 8:02 ` [PATCH v5 5/7] common: elf: add elf_open, elf_close and elf_load Clement Leger @ 2020-06-11 8:02 ` Clement Leger 2020-06-11 8:02 ` [PATCH v5 7/7] mips: lib: bootm: use bootm elf loading capabilities Clement Leger 2020-06-12 5:22 ` [PATCH v5 0/7] elf: add better bootm support Oleksij Rempel 7 siblings, 0 replies; 11+ messages in thread From: Clement Leger @ 2020-06-11 8:02 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 460ac487c..21e79982e 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -593,6 +593,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] 11+ messages in thread
* [PATCH v5 7/7] mips: lib: bootm: use bootm elf loading capabilities 2020-06-11 8:02 [PATCH v5 0/7] elf: add better bootm support Clement Leger ` (5 preceding siblings ...) 2020-06-11 8:02 ` [PATCH v5 6/7] common: bootm: add support for elf file loading Clement Leger @ 2020-06-11 8:02 ` Clement Leger 2020-06-12 5:22 ` [PATCH v5 0/7] elf: add better bootm support Oleksij Rempel 7 siblings, 0 replies; 11+ messages in thread From: Clement Leger @ 2020-06-11 8:02 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] 11+ messages in thread
* Re: [PATCH v5 0/7] elf: add better bootm support 2020-06-11 8:02 [PATCH v5 0/7] elf: add better bootm support Clement Leger ` (6 preceding siblings ...) 2020-06-11 8:02 ` [PATCH v5 7/7] mips: lib: bootm: use bootm elf loading capabilities Clement Leger @ 2020-06-12 5:22 ` Oleksij Rempel 2020-06-12 6:55 ` Clément Leger 7 siblings, 1 reply; 11+ messages in thread From: Oleksij Rempel @ 2020-06-12 5:22 UTC (permalink / raw) To: Clement Leger; +Cc: barebox, Oleksij Rempel [-- Attachment #1.1: Type: text/plain, Size: 3473 bytes --] Hi Clement, suddenly I was not able to apply you changes on current barebox/master branch. There seems to be some missing changes? For example, you patch is changing this struct: @@ -405,7 +405,8 @@ struct elf_image { u64 entry; void *low_addr; void *high_addr; - void *buf; + void *hdr_buf; + char *filename; }; But, current version of it is: struct elf_image { struct list_head list; u8 class; u64 entry; void *buf; }; On Thu, Jun 11, 2020 at 10:02:00AM +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 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 (7): > 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 | 226 +++++++++++++++++++++++++++++++++++------- > include/bootm.h | 3 + > include/elf.h | 9 +- > 6 files changed, 248 insertions(+), 56 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] 11+ messages in thread
* Re: [PATCH v5 0/7] elf: add better bootm support 2020-06-12 5:22 ` [PATCH v5 0/7] elf: add better bootm support Oleksij Rempel @ 2020-06-12 6:55 ` Clément Leger 2020-06-12 6:57 ` Oleksij Rempel 0 siblings, 1 reply; 11+ messages in thread From: Clément Leger @ 2020-06-12 6:55 UTC (permalink / raw) To: Oleksij Rempel; +Cc: Barebox List, Oleksij Rempel Hi Oleksij, ----- On 12 Jun, 2020, at 07:22, Oleksij Rempel o.rempel@pengutronix.de wrote: > Hi Clement, > > suddenly I was not able to apply you changes on current barebox/master > branch. There seems to be some missing changes? Sorry, I forgot the '^' on the base sha1 during my git format-patch. So patch 1 adding elf boundary computation is missing in this serie. Should I resend a V5 [RESEND] or a V6 ? > > For example, you patch is changing this struct: > @@ -405,7 +405,8 @@ struct elf_image { > u64 entry; > void *low_addr; > void *high_addr; > - void *buf; > + void *hdr_buf; > + char *filename; > }; > > But, current version of it is: > struct elf_image { > struct list_head list; > u8 class; > u64 entry; > void *buf; > }; > > On Thu, Jun 11, 2020 at 10:02:00AM +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 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 (7): >> 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 | 226 +++++++++++++++++++++++++++++++++++------- >> include/bootm.h | 3 + >> include/elf.h | 9 +- >> 6 files changed, 248 insertions(+), 56 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] 11+ messages in thread
* Re: [PATCH v5 0/7] elf: add better bootm support 2020-06-12 6:55 ` Clément Leger @ 2020-06-12 6:57 ` Oleksij Rempel 0 siblings, 0 replies; 11+ messages in thread From: Oleksij Rempel @ 2020-06-12 6:57 UTC (permalink / raw) To: Clément Leger; +Cc: Barebox List, Oleksij Rempel [-- Attachment #1.1: Type: text/plain, Size: 4645 bytes --] On Fri, Jun 12, 2020 at 08:55:21AM +0200, Clément Leger wrote: > Hi Oleksij, > > ----- On 12 Jun, 2020, at 07:22, Oleksij Rempel o.rempel@pengutronix.de wrote: > > > Hi Clement, > > > > suddenly I was not able to apply you changes on current barebox/master > > branch. There seems to be some missing changes? > > Sorry, I forgot the '^' on the base sha1 during my git format-patch. > So patch 1 adding elf boundary computation is missing in this serie. > Should I resend a V5 [RESEND] or a V6 ? Better V6, to avoid confusion. > > > > For example, you patch is changing this struct: > > @@ -405,7 +405,8 @@ struct elf_image { > > u64 entry; > > void *low_addr; > > void *high_addr; > > - void *buf; > > + void *hdr_buf; > > + char *filename; > > }; > > > > But, current version of it is: > > struct elf_image { > > struct list_head list; > > u8 class; > > u64 entry; > > void *buf; > > }; > > > > On Thu, Jun 11, 2020 at 10:02:00AM +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 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 (7): > >> 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 | 226 +++++++++++++++++++++++++++++++++++------- > >> include/bootm.h | 3 + > >> include/elf.h | 9 +- > >> 6 files changed, 248 insertions(+), 56 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 > -- 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] 11+ messages in thread
end of thread, other threads:[~2020-06-12 6:57 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-06-11 8:02 [PATCH v5 0/7] elf: add better bootm support Clement Leger 2020-06-11 8:02 ` [PATCH v5 1/7] common: elf: fix warning on 32 bits architectures Clement Leger 2020-06-11 8:02 ` [PATCH v5 2/7] common: elf: use calloc instead of xzalloc Clement Leger 2020-06-11 8:02 ` [PATCH v5 3/7] common: elf: check number of elf program headers Clement Leger 2020-06-11 8:02 ` [PATCH v5 4/7] common: elf: load elf directly from file Clement Leger 2020-06-11 8:02 ` [PATCH v5 5/7] common: elf: add elf_open, elf_close and elf_load Clement Leger 2020-06-11 8:02 ` [PATCH v5 6/7] common: bootm: add support for elf file loading Clement Leger 2020-06-11 8:02 ` [PATCH v5 7/7] mips: lib: bootm: use bootm elf loading capabilities Clement Leger 2020-06-12 5:22 ` [PATCH v5 0/7] elf: add better bootm support Oleksij Rempel 2020-06-12 6:55 ` Clément Leger 2020-06-12 6:57 ` Oleksij Rempel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox