Re: [PATCH 2/4] add basic ELF parser

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, May 31, 2018 at 10:48:49PM +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@xxxxxxxxxxxxxx>
> ---
>  common/Makefile |   1 +
>  common/elf.c    | 146 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/elf.h   |  10 ++++
>  3 files changed, 157 insertions(+)
>  create mode 100644 common/elf.c
> 
> diff --git a/common/Makefile b/common/Makefile
> index 1ff7d2370..4fe7eaaf6 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-y				+= 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..d6a1f8b6a
> --- /dev/null
> +++ b/common/elf.c
> @@ -0,0 +1,146 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@xxxxxxxxxxxxxx>
> + */
> +
> +#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: %x %x\n", start, size);

For resource_size_t type please use the %pa format specifier.

> +		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;
> +        }

Whitespace broken here

> +
> +	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->buf);

elf->buf hasn't been allocated by elf_load_image, so it shouldn't be
freed by elf_release_image.

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@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/barebox



[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux