mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v2 0/4] MIPS: provide basic ELF support
@ 2018-06-03  6:23 Oleksij Rempel
  2018-06-03  6:23 ` [PATCH v2 1/4] filetype: add ELF type Oleksij Rempel
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Oleksij Rempel @ 2018-06-03  6:23 UTC (permalink / raw)
  To: barebox; +Cc: Oleksij Rempel

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/lib/bootm.c |  56 ++++++++++++++++
 common/Kconfig        |   5 ++
 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 +
 9 files changed, 257 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 v2 1/4] filetype: add ELF type
  2018-06-03  6:23 [PATCH v2 0/4] MIPS: provide basic ELF support Oleksij Rempel
@ 2018-06-03  6:23 ` Oleksij Rempel
  2018-06-03  6:23 ` [PATCH v2 2/4] add basic ELF parser Oleksij Rempel
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Oleksij Rempel @ 2018-06-03  6:23 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 v2 2/4] add basic ELF parser
  2018-06-03  6:23 [PATCH v2 0/4] MIPS: provide basic ELF support Oleksij Rempel
  2018-06-03  6:23 ` [PATCH v2 1/4] filetype: add ELF type Oleksij Rempel
@ 2018-06-03  6:23 ` Oleksij Rempel
  2018-06-04  7:07   ` Sascha Hauer
  2018-06-03  6:23 ` [PATCH v2 3/4] bootm: split split bootm_load_devicetree function Oleksij Rempel
  2018-06-03  6:23 ` [PATCH v2 4/4] MIPS: bootm: add ELF handler Oleksij Rempel
  3 siblings, 1 reply; 6+ messages in thread
From: Oleksij Rempel @ 2018-06-03  6:23 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  |   5 ++
 common/Makefile |   1 +
 common/elf.c    | 145 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/elf.h   |  10 ++++
 4 files changed, 161 insertions(+)
 create mode 100644 common/elf.c

diff --git a/common/Kconfig b/common/Kconfig
index b7000c4d7..b9adc4c39 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -46,6 +46,10 @@ config BLOCK
 config BLOCK_WRITE
 	bool
 
+config ELF
+	bool
+	depends on MIPS
+
 config FILETYPE
 	bool
 
@@ -548,6 +552,7 @@ config TIMESTAMP
 	  automatically enabled when you select CFG_CMD_DATE .
 
 menuconfig BOOTM
+	select ELF
 	select UIMAGE
 	default y if COMMAND_SUPPORT
 	bool "bootm support"
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 v2 3/4] bootm: split split bootm_load_devicetree function
  2018-06-03  6:23 [PATCH v2 0/4] MIPS: provide basic ELF support Oleksij Rempel
  2018-06-03  6:23 ` [PATCH v2 1/4] filetype: add ELF type Oleksij Rempel
  2018-06-03  6:23 ` [PATCH v2 2/4] add basic ELF parser Oleksij Rempel
@ 2018-06-03  6:23 ` Oleksij Rempel
  2018-06-03  6:23 ` [PATCH v2 4/4] MIPS: bootm: add ELF handler Oleksij Rempel
  3 siblings, 0 replies; 6+ messages in thread
From: Oleksij Rempel @ 2018-06-03  6:23 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 v2 4/4] MIPS: bootm: add ELF handler
  2018-06-03  6:23 [PATCH v2 0/4] MIPS: provide basic ELF support Oleksij Rempel
                   ` (2 preceding siblings ...)
  2018-06-03  6:23 ` [PATCH v2 3/4] bootm: split split bootm_load_devicetree function Oleksij Rempel
@ 2018-06-03  6:23 ` Oleksij Rempel
  3 siblings, 0 replies; 6+ messages in thread
From: Oleksij Rempel @ 2018-06-03  6:23 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/lib/bootm.c | 56 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

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 v2 2/4] add basic ELF parser
  2018-06-03  6:23 ` [PATCH v2 2/4] add basic ELF parser Oleksij Rempel
@ 2018-06-04  7:07   ` Sascha Hauer
  0 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2018-06-04  7:07 UTC (permalink / raw)
  To: Oleksij Rempel; +Cc: barebox

On Sun, Jun 03, 2018 at 08:23:12AM +0200, Oleksij Rempel wrote:
> 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  |   5 ++
>  common/Makefile |   1 +
>  common/elf.c    | 145 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/elf.h   |  10 ++++
>  4 files changed, 161 insertions(+)
>  create mode 100644 common/elf.c
> 
> diff --git a/common/Kconfig b/common/Kconfig
> index b7000c4d7..b9adc4c39 100644
> --- a/common/Kconfig
> +++ b/common/Kconfig
> @@ -46,6 +46,10 @@ config BLOCK
>  config BLOCK_WRITE
>  	bool
>  
> +config ELF
> +	bool
> +	depends on MIPS

The ELF parser itself has nothing MIPS specific in it, so drop this
dependency here.

> +
>  config FILETYPE
>  	bool
>  
> @@ -548,6 +552,7 @@ config TIMESTAMP
>  	  automatically enabled when you select CFG_CMD_DATE .
>  
>  menuconfig BOOTM
> +	select ELF

The bootm code doesn't need ELF, only the MIPS specific bootm code does,
so this should be selected somewhere in arch/mips/

Sascha

-- 
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-04  7:08 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-03  6:23 [PATCH v2 0/4] MIPS: provide basic ELF support Oleksij Rempel
2018-06-03  6:23 ` [PATCH v2 1/4] filetype: add ELF type Oleksij Rempel
2018-06-03  6:23 ` [PATCH v2 2/4] add basic ELF parser Oleksij Rempel
2018-06-04  7:07   ` Sascha Hauer
2018-06-03  6:23 ` [PATCH v2 3/4] bootm: split split bootm_load_devicetree function Oleksij Rempel
2018-06-03  6:23 ` [PATCH v2 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