* [PATCH v3 0/4] MIPS: provide basic ELF support
@ 2018-06-04 10:05 Oleksij Rempel
2018-06-04 10:05 ` [PATCH v3 1/4] filetype: add ELF type Oleksij Rempel
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Oleksij Rempel @ 2018-06-04 10:05 UTC (permalink / raw)
To: barebox; +Cc: Oleksij Rempel
changes v3:
- select ELF by MIPS
changes v2:
- add dryrun support
- some style fixes
- enable ELF parser only on supported platform (currently only MIPS)
Antony Pavlov (1):
filetype: add ELF type
Oleksij Rempel (3):
add basic ELF parser
bootm: split split bootm_load_devicetree function
MIPS: bootm: add ELF handler
arch/mips/Kconfig | 1 +
arch/mips/lib/bootm.c | 56 ++++++++++++++++
common/Kconfig | 3 +
common/Makefile | 1 +
common/bootm.c | 39 ++++++++++--
common/elf.c | 145 ++++++++++++++++++++++++++++++++++++++++++
common/filetype.c | 5 ++
include/bootm.h | 1 +
include/elf.h | 10 +++
include/filetype.h | 1 +
10 files changed, 256 insertions(+), 6 deletions(-)
create mode 100644 common/elf.c
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 1/4] filetype: add ELF type
2018-06-04 10:05 [PATCH v3 0/4] MIPS: provide basic ELF support Oleksij Rempel
@ 2018-06-04 10:05 ` Oleksij Rempel
2018-06-04 10:05 ` [PATCH v3 2/4] add basic ELF parser Oleksij Rempel
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Oleksij Rempel @ 2018-06-04 10:05 UTC (permalink / raw)
To: barebox
From: Antony Pavlov <antonynpavlov@gmail.com>
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
---
common/filetype.c | 5 +++++
include/filetype.h | 1 +
2 files changed, 6 insertions(+)
diff --git a/common/filetype.c b/common/filetype.c
index 444ec14cc..77cf9a105 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -27,6 +27,7 @@
#include <envfs.h>
#include <disks.h>
#include <image-sparse.h>
+#include <elf.h>
struct filetype_str {
const char *name; /* human readable filetype */
@@ -68,6 +69,7 @@ static const struct filetype_str filetype_str[] = {
[filetype_kwbimage_v1] = { "MVEBU kwbimage (v1)", "kwb" },
[filetype_android_sparse] = { "Android sparse image", "sparse" },
[filetype_arm64_linux_image] = { "ARM aarch64 Linux image", "aarch64-linux" },
+ [filetype_elf] = { "ELF", "elf" },
};
const char *file_type_to_string(enum filetype f)
@@ -344,6 +346,9 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
buf[7] == 0x47530000)
return filetype_ch_image_be;
+ if (strncmp(buf8, ELFMAG, 4) == 0)
+ return filetype_elf;
+
return filetype_unknown;
}
diff --git a/include/filetype.h b/include/filetype.h
index 9986938dd..3b930bf94 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -41,6 +41,7 @@ enum filetype {
filetype_kwbimage_v1,
filetype_android_sparse,
filetype_arm64_linux_image,
+ filetype_elf,
filetype_max,
};
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 2/4] add basic ELF parser
2018-06-04 10:05 [PATCH v3 0/4] MIPS: provide basic ELF support Oleksij Rempel
2018-06-04 10:05 ` [PATCH v3 1/4] filetype: add ELF type Oleksij Rempel
@ 2018-06-04 10:05 ` Oleksij Rempel
2018-06-04 10:05 ` [PATCH v3 3/4] bootm: split split bootm_load_devicetree function Oleksij Rempel
2018-06-04 10:05 ` [PATCH v3 4/4] MIPS: bootm: add ELF handler Oleksij Rempel
3 siblings, 0 replies; 6+ messages in thread
From: Oleksij Rempel @ 2018-06-04 10:05 UTC (permalink / raw)
To: barebox; +Cc: Oleksij Rempel
This parser is needed for kernel boot support on MIPS
and can potentially reused on other platforms.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
common/Kconfig | 3 +
common/Makefile | 1 +
common/elf.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++
include/elf.h | 10 ++++
4 files changed, 159 insertions(+)
create mode 100644 common/elf.c
diff --git a/common/Kconfig b/common/Kconfig
index b7000c4d7..afb150193 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -46,6 +46,9 @@ config BLOCK
config BLOCK_WRITE
bool
+config ELF
+ bool
+
config FILETYPE
bool
diff --git a/common/Makefile b/common/Makefile
index 1ff7d2370..b6284c255 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -8,6 +8,7 @@ obj-y += misc.o
obj-pbl-y += memsize.o
obj-y += resource.o
obj-y += bootsource.o
+obj-$(CONFIG_ELF) += elf.o
obj-y += restart.o
obj-y += poweroff.o
obj-$(CONFIG_AUTO_COMPLETE) += complete.o
diff --git a/common/elf.c b/common/elf.c
new file mode 100644
index 000000000..51b29b145
--- /dev/null
+++ b/common/elf.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
+ */
+
+#include <common.h>
+#include <elf.h>
+#include <memory.h>
+
+struct elf_section {
+ struct list_head list;
+ struct resource *r;
+};
+
+static int elf_request_region(struct elf_image *elf, resource_size_t start,
+ resource_size_t size)
+{
+ struct list_head *list = &elf->list;
+ struct resource *r_new;
+ struct elf_section *r;
+
+ r = xzalloc(sizeof(*r));
+ r_new = request_sdram_region("elf_section", start, size);
+ if (!r_new) {
+ pr_err("Failed to request region: %pa %pa\n", start, size);
+ return -EINVAL;
+ }
+
+ r->r = r_new;
+ list_add_tail(&r->list, list);
+
+ return 0;
+}
+
+static void elf_release_regions(struct elf_image *elf)
+{
+ struct list_head *list = &elf->list;
+ struct elf_section *r, *r_tmp;
+
+ list_for_each_entry_safe(r, r_tmp, list, list) {
+ release_sdram_region(r->r);
+ free(r);
+ }
+}
+
+
+static int load_elf_phdr_segment(struct elf_image *elf, void *src,
+ Elf32_Phdr *phdr)
+{
+ void *dst = (void *)phdr->p_paddr;
+ int ret;
+
+ /* we care only about PT_LOAD segments */
+ if (phdr->p_type != PT_LOAD)
+ return 0;
+
+ if (!phdr->p_filesz)
+ return 0;
+
+ pr_debug("Loading phdr to 0x%p (%i bytes)\n", dst, phdr->p_filesz);
+
+ ret = elf_request_region(elf, (resource_size_t)dst, phdr->p_filesz);
+ if (ret)
+ return ret;
+
+ memcpy(dst, src, phdr->p_filesz);
+
+ if (phdr->p_filesz < phdr->p_memsz)
+ memset(dst + phdr->p_filesz, 0x00,
+ phdr->p_memsz - phdr->p_filesz);
+
+ return 0;
+}
+
+static int load_elf_image_phdr(struct elf_image *elf)
+{
+ void *buf = elf->buf;
+ Elf32_Ehdr *ehdr = buf;
+ Elf32_Phdr *phdr = (Elf32_Phdr *)(buf + ehdr->e_phoff);
+ int i, ret;
+
+ elf->entry = ehdr->e_entry;
+
+ for (i = 0; i < ehdr->e_phnum; ++i) {
+ void *src = buf + phdr->p_offset;
+
+ ret = load_elf_phdr_segment(elf, src, phdr);
+ /* in case of error elf_load_image() caller should clean up and
+ * call elf_release_image() */
+ if (ret)
+ return ret;
+
+ ++phdr;
+ }
+
+ return 0;
+}
+
+static int elf_check_image(void *buf)
+{
+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)buf;
+
+ if (strncmp(buf, ELFMAG, SELFMAG)) {
+ pr_err("ELF magic not found.\n");
+ return -EINVAL;
+ }
+
+ if (ehdr->e_type != ET_EXEC) {
+ pr_err("Non EXEC ELF image.\n");
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+struct elf_image *elf_load_image(void *buf)
+{
+ struct elf_image *elf;
+ int ret;
+
+ elf = xzalloc(sizeof(*elf));
+
+ INIT_LIST_HEAD(&elf->list);
+
+ elf->buf = buf;
+
+ ret = elf_check_image(buf);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = load_elf_image_phdr(elf);
+ if (ret) {
+ elf_release_image(elf);
+ return ERR_PTR(ret);
+ }
+
+ return elf;
+}
+
+void elf_release_image(struct elf_image *elf)
+{
+ elf_release_regions(elf);
+
+ free(elf);
+}
diff --git a/include/elf.h b/include/elf.h
index ebcec7db0..92c8d9c12 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -2,6 +2,7 @@
#define _LINUX_ELF_H
#include <linux/types.h>
+#include <linux/list.h>
//#include <linux/auxvec.h>
//#include <linux/elf-em.h>
#include <asm/elf.h>
@@ -397,4 +398,13 @@ static inline void arch_write_notes(struct file *file) { }
#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file)
#endif /* ARCH_HAVE_EXTRA_ELF_NOTES */
+struct elf_image {
+ struct list_head list;
+ unsigned long entry;
+ void *buf;
+};
+
+struct elf_image *elf_load_image(void *buf);
+void elf_release_image(struct elf_image *elf);
+
#endif /* _LINUX_ELF_H */
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 3/4] bootm: split split bootm_load_devicetree function
2018-06-04 10:05 [PATCH v3 0/4] MIPS: provide basic ELF support Oleksij Rempel
2018-06-04 10:05 ` [PATCH v3 1/4] filetype: add ELF type Oleksij Rempel
2018-06-04 10:05 ` [PATCH v3 2/4] add basic ELF parser Oleksij Rempel
@ 2018-06-04 10:05 ` Oleksij Rempel
2018-06-06 7:12 ` Sascha Hauer
2018-06-04 10:05 ` [PATCH v3 4/4] MIPS: bootm: add ELF handler Oleksij Rempel
3 siblings, 1 reply; 6+ messages in thread
From: Oleksij Rempel @ 2018-06-04 10:05 UTC (permalink / raw)
To: barebox; +Cc: Oleksij Rempel
In some cases we don't won't to load devicetree some where in free ram
area, it is easier to keep it withing allocated area of barebox
and then give the pointer to the kernel.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
common/bootm.c | 39 +++++++++++++++++++++++++++++++++------
include/bootm.h | 1 +
2 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/common/bootm.c b/common/bootm.c
index 5ff6683fe..a9d18fb57 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -320,20 +320,17 @@ static int bootm_open_oftree_uimage(struct image_data *data, size_t *size,
}
/*
- * bootm_load_devicetree() - load devicetree
+ * bootm_get_devicetree() - get devicetree
*
* @data: image data context
- * @load_address: The address where the devicetree should be loaded to
*
- * This loads the devicetree to a RAM location. load_address must be a valid
- * address. The resulting devicetree will be found at data->oftree.
+ * Prepare devicetree for later use by boot handler.
*
* Return: 0 on success, negative error code otherwise
*/
-int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
+int bootm_get_devicetree(struct image_data *data)
{
enum filetype type;
- int fdt_size;
struct fdt_header *oftree;
int ret;
@@ -410,6 +407,36 @@ int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
if (!oftree)
return -EINVAL;
+ data->oftree = oftree;
+
+ return 0;
+}
+
+/*
+ * bootm_load_devicetree() - load devicetree
+ *
+ * @data: image data context
+ * @load_address: The address where the devicetree should be loaded to
+ *
+ * This loads the devicetree to a RAM location. load_address must be a valid
+ * address. The resulting devicetree will be found at data->oftree.
+ *
+ * Return: 0 on success, negative error code otherwise
+ */
+
+int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
+{
+ struct fdt_header *oftree;
+ int fdt_size;
+ int ret;
+
+ ret = bootm_get_devicetree(data);
+ if (ret)
+ return ret;
+
+ oftree = data->oftree;
+
+
fdt_size = be32_to_cpu(oftree->totalsize);
data->oftree_res = request_sdram_region("oftree", load_address,
diff --git a/include/bootm.h b/include/bootm.h
index 62951d605..410b42cde 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -126,6 +126,7 @@ int bootm_load_os(struct image_data *data, unsigned long load_address);
bool bootm_has_initrd(struct image_data *data);
int bootm_load_initrd(struct image_data *data, unsigned long load_address);
+int bootm_get_devicetree(struct image_data *data);
int bootm_load_devicetree(struct image_data *data, unsigned long load_address);
int bootm_get_os_size(struct image_data *data);
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 4/4] MIPS: bootm: add ELF handler
2018-06-04 10:05 [PATCH v3 0/4] MIPS: provide basic ELF support Oleksij Rempel
` (2 preceding siblings ...)
2018-06-04 10:05 ` [PATCH v3 3/4] bootm: split split bootm_load_devicetree function Oleksij Rempel
@ 2018-06-04 10:05 ` Oleksij Rempel
3 siblings, 0 replies; 6+ messages in thread
From: Oleksij Rempel @ 2018-06-04 10:05 UTC (permalink / raw)
To: barebox; +Cc: Oleksij Rempel
With this handler barebox will be able to start linux kernel as
is, without additional image conversation.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
arch/mips/Kconfig | 1 +
arch/mips/lib/bootm.c | 56 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 359f67883..9aedf9a77 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -7,6 +7,7 @@ config MIPS
select HAVE_CONFIGURABLE_MEMORY_LAYOUT
select HAVE_CONFIGURABLE_TEXT_BASE
select HAS_DMA
+ select ELF
default y
config SYS_SUPPORTS_BIG_ENDIAN
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 91e7e1c68..70ab3b157 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -10,6 +10,7 @@
#include <restart.h>
#include <asm/byteorder.h>
+#include <asm/io.h>
static int do_bootm_barebox(struct image_data *data)
{
@@ -42,11 +43,66 @@ static struct binfmt_hook binfmt_barebox_hook = {
.exec = "bootm",
};
+static int do_bootm_elf(struct image_data *data)
+{
+ void (*entry)(int, void *);
+ struct elf_image *elf;
+ void *buf;
+ int ret;
+
+ buf = read_file(data->os_file, NULL);
+ if (!buf)
+ return -EINVAL;
+
+ elf = elf_load_image(buf);
+ if (IS_ERR(elf))
+ return PTR_ERR(elf);
+
+ ret = bootm_get_devicetree(data);
+ if (ret)
+ goto bootm_elf_done;
+
+ pr_info("Starting application at 0x%08lx, dts 0x%08lx...\n",
+ phys_to_virt(elf->entry), data->of_root_node);
+
+ if (data->dryrun)
+ goto bootm_elf_done;
+
+ shutdown_barebox();
+
+ entry = (void *)elf->entry;
+
+ entry(-2, phys_to_virt((unsigned long)data->oftree));
+
+ pr_err("ELF application terminated\n");
+ ret = -EINVAL;
+
+bootm_elf_done:
+ elf_release_image(elf);
+ free(buf);
+
+ return ret;
+}
+
+static struct image_handler elf_handler = {
+ .name = "ELF",
+ .bootm = do_bootm_elf,
+ .filetype = filetype_elf,
+};
+
+static struct binfmt_hook binfmt_elf_hook = {
+ .type = filetype_elf,
+ .exec = "bootm",
+};
+
static int mips_register_image_handler(void)
{
register_image_handler(&barebox_handler);
binfmt_register(&binfmt_barebox_hook);
+ register_image_handler(&elf_handler);
+ binfmt_register(&binfmt_elf_hook);
+
return 0;
}
late_initcall(mips_register_image_handler);
--
2.17.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 3/4] bootm: split split bootm_load_devicetree function
2018-06-04 10:05 ` [PATCH v3 3/4] bootm: split split bootm_load_devicetree function Oleksij Rempel
@ 2018-06-06 7:12 ` Sascha Hauer
0 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2018-06-06 7:12 UTC (permalink / raw)
To: Oleksij Rempel; +Cc: barebox
On Mon, Jun 04, 2018 at 12:05:45PM +0200, Oleksij Rempel wrote:
> In some cases we don't won't to load devicetree some where in free ram
> area, it is easier to keep it withing allocated area of barebox
> and then give the pointer to the kernel.
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
> common/bootm.c | 39 +++++++++++++++++++++++++++++++++------
> include/bootm.h | 1 +
> 2 files changed, 34 insertions(+), 6 deletions(-)
Unfortunately this split is not so easy because it opens some memory
leaks. Please drop this patch and rebaase on the series I just sent.
Sascha
>
> diff --git a/common/bootm.c b/common/bootm.c
> index 5ff6683fe..a9d18fb57 100644
> --- a/common/bootm.c
> +++ b/common/bootm.c
> @@ -320,20 +320,17 @@ static int bootm_open_oftree_uimage(struct image_data *data, size_t *size,
> }
>
> /*
> - * bootm_load_devicetree() - load devicetree
> + * bootm_get_devicetree() - get devicetree
> *
> * @data: image data context
> - * @load_address: The address where the devicetree should be loaded to
> *
> - * This loads the devicetree to a RAM location. load_address must be a valid
> - * address. The resulting devicetree will be found at data->oftree.
> + * Prepare devicetree for later use by boot handler.
> *
> * Return: 0 on success, negative error code otherwise
> */
> -int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
> +int bootm_get_devicetree(struct image_data *data)
> {
> enum filetype type;
> - int fdt_size;
> struct fdt_header *oftree;
> int ret;
>
> @@ -410,6 +407,36 @@ int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
> if (!oftree)
> return -EINVAL;
>
> + data->oftree = oftree;
> +
> + return 0;
> +}
> +
> +/*
> + * bootm_load_devicetree() - load devicetree
> + *
> + * @data: image data context
> + * @load_address: The address where the devicetree should be loaded to
> + *
> + * This loads the devicetree to a RAM location. load_address must be a valid
> + * address. The resulting devicetree will be found at data->oftree.
> + *
> + * Return: 0 on success, negative error code otherwise
> + */
> +
> +int bootm_load_devicetree(struct image_data *data, unsigned long load_address)
> +{
> + struct fdt_header *oftree;
> + int fdt_size;
> + int ret;
> +
> + ret = bootm_get_devicetree(data);
> + if (ret)
> + return ret;
> +
> + oftree = data->oftree;
> +
> +
> fdt_size = be32_to_cpu(oftree->totalsize);
>
> data->oftree_res = request_sdram_region("oftree", load_address,
> diff --git a/include/bootm.h b/include/bootm.h
> index 62951d605..410b42cde 100644
> --- a/include/bootm.h
> +++ b/include/bootm.h
> @@ -126,6 +126,7 @@ int bootm_load_os(struct image_data *data, unsigned long load_address);
> bool bootm_has_initrd(struct image_data *data);
> int bootm_load_initrd(struct image_data *data, unsigned long load_address);
>
> +int bootm_get_devicetree(struct image_data *data);
> int bootm_load_devicetree(struct image_data *data, unsigned long load_address);
> int bootm_get_os_size(struct image_data *data);
>
> --
> 2.17.1
>
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 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] 6+ messages in thread
end of thread, other threads:[~2018-06-06 7:13 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-04 10:05 [PATCH v3 0/4] MIPS: provide basic ELF support Oleksij Rempel
2018-06-04 10:05 ` [PATCH v3 1/4] filetype: add ELF type Oleksij Rempel
2018-06-04 10:05 ` [PATCH v3 2/4] add basic ELF parser Oleksij Rempel
2018-06-04 10:05 ` [PATCH v3 3/4] bootm: split split bootm_load_devicetree function Oleksij Rempel
2018-06-06 7:12 ` Sascha Hauer
2018-06-04 10:05 ` [PATCH v3 4/4] MIPS: bootm: add ELF handler Oleksij Rempel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox