diff mbox series

[v2,1/9] lib: elf: Move the generic elf loading/validating functions to lib

Message ID 20200113055453.8812-2-j-keerthy@ti.com
State Superseded
Headers show
Series k3: Add support for loading main_r5fss0_core0 | expand

Commit Message

J, KEERTHY Jan. 13, 2020, 5:54 a.m. UTC
Move the generic elf loading/validating functions to lib/
so that they can be re-used and accessed by code existing
outside cmd.

Signed-off-by: Keerthy <j-keerthy at ti.com>
Suggested-by: Simon Goldschmidt <simon.k.r.goldschmidt at gmail.com>
---
Changes in v2:

  * Factored out all the generic elf handling functions under lib/elf.c

 cmd/Kconfig   |   1 +
 cmd/elf.c     | 229 --------------------------------------------
 include/elf.h |   4 +
 lib/Kconfig   |   3 +
 lib/Makefile  |   1 +
 lib/elf.c     | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 265 insertions(+), 229 deletions(-)
 create mode 100644 lib/elf.c

Comments

Lokesh Vutla Jan. 17, 2020, 4:27 a.m. UTC | #1
Simon,

On 13/01/20 11:24 AM, Keerthy wrote:
> Move the generic elf loading/validating functions to lib/
> so that they can be re-used and accessed by code existing
> outside cmd.
> 
> Signed-off-by: Keerthy <j-keerthy at ti.com>
> Suggested-by: Simon Goldschmidt <simon.k.r.goldschmidt at gmail.com>

Are you okay with this patch? If yes, Ill apply to u-boot-ti along with other
patches in this series.

Thanks and regards,
Lokesh

> ---
> Changes in v2:
> 
>   * Factored out all the generic elf handling functions under lib/elf.c
> 
>  cmd/Kconfig   |   1 +
>  cmd/elf.c     | 229 --------------------------------------------
>  include/elf.h |   4 +
>  lib/Kconfig   |   3 +
>  lib/Makefile  |   1 +
>  lib/elf.c     | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 265 insertions(+), 229 deletions(-)
>  create mode 100644 lib/elf.c
> 
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 298feae24d..6f4f08d02a 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -375,6 +375,7 @@ config CMD_ADTIMG
>  config CMD_ELF
>  	bool "bootelf, bootvx"
>  	default y
> +	select ELF
>  	help
>  	  Boot an ELF/vxWorks image from the memory.
>  
> diff --git a/cmd/elf.c b/cmd/elf.c
> index 32f12a72b9..23cc17aebc 100644
> --- a/cmd/elf.c
> +++ b/cmd/elf.c
> @@ -26,211 +26,6 @@
>  #include <linux/linkage.h>
>  #endif
>  
> -/*
> - * A very simple ELF64 loader, assumes the image is valid, returns the
> - * entry point address.
> - *
> - * Note if U-Boot is 32-bit, the loader assumes the to segment's
> - * physical address and size is within the lower 32-bit address space.
> - */
> -static unsigned long load_elf64_image_phdr(unsigned long addr)
> -{
> -	Elf64_Ehdr *ehdr; /* Elf header structure pointer */
> -	Elf64_Phdr *phdr; /* Program header structure pointer */
> -	int i;
> -
> -	ehdr = (Elf64_Ehdr *)addr;
> -	phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
> -
> -	/* Load each program header */
> -	for (i = 0; i < ehdr->e_phnum; ++i) {
> -		void *dst = (void *)(ulong)phdr->p_paddr;
> -		void *src = (void *)addr + phdr->p_offset;
> -
> -		debug("Loading phdr %i to 0x%p (%lu bytes)\n",
> -		      i, dst, (ulong)phdr->p_filesz);
> -		if (phdr->p_filesz)
> -			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);
> -		flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
> -			    roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
> -		++phdr;
> -	}
> -
> -	if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
> -					    EF_PPC64_ELFV1_ABI)) {
> -		/*
> -		 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
> -		 * descriptor pointer with the first double word being the
> -		 * address of the entry point of the function.
> -		 */
> -		uintptr_t addr = ehdr->e_entry;
> -
> -		return *(Elf64_Addr *)addr;
> -	}
> -
> -	return ehdr->e_entry;
> -}
> -
> -static unsigned long load_elf64_image_shdr(unsigned long addr)
> -{
> -	Elf64_Ehdr *ehdr; /* Elf header structure pointer */
> -	Elf64_Shdr *shdr; /* Section header structure pointer */
> -	unsigned char *strtab = 0; /* String table pointer */
> -	unsigned char *image; /* Binary image pointer */
> -	int i; /* Loop counter */
> -
> -	ehdr = (Elf64_Ehdr *)addr;
> -
> -	/* Find the section header string table for output info */
> -	shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
> -			     (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
> -
> -	if (shdr->sh_type == SHT_STRTAB)
> -		strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
> -
> -	/* Load each appropriate section */
> -	for (i = 0; i < ehdr->e_shnum; ++i) {
> -		shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
> -				     (i * sizeof(Elf64_Shdr)));
> -
> -		if (!(shdr->sh_flags & SHF_ALLOC) ||
> -		    shdr->sh_addr == 0 || shdr->sh_size == 0) {
> -			continue;
> -		}
> -
> -		if (strtab) {
> -			debug("%sing %s @ 0x%08lx (%ld bytes)\n",
> -			      (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
> -			       &strtab[shdr->sh_name],
> -			       (unsigned long)shdr->sh_addr,
> -			       (long)shdr->sh_size);
> -		}
> -
> -		if (shdr->sh_type == SHT_NOBITS) {
> -			memset((void *)(uintptr_t)shdr->sh_addr, 0,
> -			       shdr->sh_size);
> -		} else {
> -			image = (unsigned char *)addr + (ulong)shdr->sh_offset;
> -			memcpy((void *)(uintptr_t)shdr->sh_addr,
> -			       (const void *)image, shdr->sh_size);
> -		}
> -		flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
> -			    roundup((shdr->sh_addr + shdr->sh_size),
> -				     ARCH_DMA_MINALIGN) -
> -			            rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
> -	}
> -
> -	if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
> -					    EF_PPC64_ELFV1_ABI)) {
> -		/*
> -		 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
> -		 * descriptor pointer with the first double word being the
> -		 * address of the entry point of the function.
> -		 */
> -		uintptr_t addr = ehdr->e_entry;
> -
> -		return *(Elf64_Addr *)addr;
> -	}
> -
> -	return ehdr->e_entry;
> -}
> -
> -/*
> - * A very simple ELF loader, assumes the image is valid, returns the
> - * entry point address.
> - *
> - * The loader firstly reads the EFI class to see if it's a 64-bit image.
> - * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
> - */
> -static unsigned long load_elf_image_phdr(unsigned long addr)
> -{
> -	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> -	Elf32_Phdr *phdr; /* Program header structure pointer */
> -	int i;
> -
> -	ehdr = (Elf32_Ehdr *)addr;
> -	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
> -		return load_elf64_image_phdr(addr);
> -
> -	phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
> -
> -	/* Load each program header */
> -	for (i = 0; i < ehdr->e_phnum; ++i) {
> -		void *dst = (void *)(uintptr_t)phdr->p_paddr;
> -		void *src = (void *)addr + phdr->p_offset;
> -
> -		debug("Loading phdr %i to 0x%p (%i bytes)\n",
> -		      i, dst, phdr->p_filesz);
> -		if (phdr->p_filesz)
> -			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);
> -		flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
> -			    roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
> -		++phdr;
> -	}
> -
> -	return ehdr->e_entry;
> -}
> -
> -static unsigned long load_elf_image_shdr(unsigned long addr)
> -{
> -	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> -	Elf32_Shdr *shdr; /* Section header structure pointer */
> -	unsigned char *strtab = 0; /* String table pointer */
> -	unsigned char *image; /* Binary image pointer */
> -	int i; /* Loop counter */
> -
> -	ehdr = (Elf32_Ehdr *)addr;
> -	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
> -		return load_elf64_image_shdr(addr);
> -
> -	/* Find the section header string table for output info */
> -	shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
> -			     (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
> -
> -	if (shdr->sh_type == SHT_STRTAB)
> -		strtab = (unsigned char *)(addr + shdr->sh_offset);
> -
> -	/* Load each appropriate section */
> -	for (i = 0; i < ehdr->e_shnum; ++i) {
> -		shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
> -				     (i * sizeof(Elf32_Shdr)));
> -
> -		if (!(shdr->sh_flags & SHF_ALLOC) ||
> -		    shdr->sh_addr == 0 || shdr->sh_size == 0) {
> -			continue;
> -		}
> -
> -		if (strtab) {
> -			debug("%sing %s @ 0x%08lx (%ld bytes)\n",
> -			      (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
> -			       &strtab[shdr->sh_name],
> -			       (unsigned long)shdr->sh_addr,
> -			       (long)shdr->sh_size);
> -		}
> -
> -		if (shdr->sh_type == SHT_NOBITS) {
> -			memset((void *)(uintptr_t)shdr->sh_addr, 0,
> -			       shdr->sh_size);
> -		} else {
> -			image = (unsigned char *)addr + shdr->sh_offset;
> -			memcpy((void *)(uintptr_t)shdr->sh_addr,
> -			       (const void *)image, shdr->sh_size);
> -		}
> -		flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
> -			    roundup((shdr->sh_addr + shdr->sh_size),
> -				    ARCH_DMA_MINALIGN) -
> -			    rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
> -	}
> -
> -	return ehdr->e_entry;
> -}
> -
>  /* Allow ports to override the default behavior */
>  static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
>  				     int argc, char * const argv[])
> @@ -246,30 +41,6 @@ static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
>  	return ret;
>  }
>  
> -/*
> - * Determine if a valid ELF image exists at the given memory location.
> - * First look at the ELF header magic field, then make sure that it is
> - * executable.
> - */
> -int valid_elf_image(unsigned long addr)
> -{
> -	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> -
> -	ehdr = (Elf32_Ehdr *)addr;
> -
> -	if (!IS_ELF(*ehdr)) {
> -		printf("## No elf image at address 0x%08lx\n", addr);
> -		return 0;
> -	}
> -
> -	if (ehdr->e_type != ET_EXEC) {
> -		printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
> -		return 0;
> -	}
> -
> -	return 1;
> -}
> -
>  /* Interpreter command to boot an arbitrary ELF image from memory */
>  int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>  {
> diff --git a/include/elf.h b/include/elf.h
> index 81f40191d7..e7c51986df 100644
> --- a/include/elf.h
> +++ b/include/elf.h
> @@ -692,6 +692,10 @@ unsigned long elf_hash(const unsigned char *name);
>  
>  #ifndef __ASSEMBLER__
>  int valid_elf_image(unsigned long addr);
> +unsigned long load_elf64_image_phdr(unsigned long addr);
> +unsigned long load_elf64_image_shdr(unsigned long addr);
> +unsigned long load_elf_image_phdr(unsigned long addr);
> +unsigned long load_elf_image_shdr(unsigned long addr);
>  #endif
>  
>  #endif /* _ELF_H */
> diff --git a/lib/Kconfig b/lib/Kconfig
> index d040a87d26..b155ced4b2 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -601,4 +601,7 @@ config TEST_FDTDEC
>  config LIB_DATE
>  	bool
>  
> +config ELF
> +	bool "enable basic elf loading/validating functions"
> +
>  endmenu
> diff --git a/lib/Makefile b/lib/Makefile
> index 6b7b9ce85c..93f22d210e 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -121,6 +121,7 @@ obj-y += vsprintf.o strto.o
>  endif
>  
>  obj-y += date.o
> +obj-$(CONFIG_ELF) += elf.o
>  
>  #
>  # Build a fast OID lookup registry from include/linux/oid_registry.h
> diff --git a/lib/elf.c b/lib/elf.c
> new file mode 100644
> index 0000000000..54ac4ee502
> --- /dev/null
> +++ b/lib/elf.c
> @@ -0,0 +1,256 @@
> +/*
> + * Copyright (c) 2001 William L. Pitts
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms are freely
> + * permitted provided that the above copyright notice and this
> + * paragraph and the following disclaimer are duplicated in all
> + * such forms.
> + *
> + * This software is provided "AS IS" and without any express or
> + * implied warranties, including, without limitation, the implied
> + * warranties of merchantability and fitness for a particular
> + * purpose.
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <cpu_func.h>
> +#include <elf.h>
> +#include <env.h>
> +#include <net.h>
> +#include <vxworks.h>
> +#ifdef CONFIG_X86
> +#include <vbe.h>
> +#include <asm/e820.h>
> +#include <linux/linkage.h>
> +#endif
> +
> +/*
> + * A very simple ELF64 loader, assumes the image is valid, returns the
> + * entry point address.
> + *
> + * Note if U-Boot is 32-bit, the loader assumes the to segment's
> + * physical address and size is within the lower 32-bit address space.
> + */
> +unsigned long load_elf64_image_phdr(unsigned long addr)
> +{
> +	Elf64_Ehdr *ehdr; /* Elf header structure pointer */
> +	Elf64_Phdr *phdr; /* Program header structure pointer */
> +	int i;
> +
> +	ehdr = (Elf64_Ehdr *)addr;
> +	phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
> +
> +	/* Load each program header */
> +	for (i = 0; i < ehdr->e_phnum; ++i) {
> +		void *dst = (void *)(ulong)phdr->p_paddr;
> +		void *src = (void *)addr + phdr->p_offset;
> +
> +		debug("Loading phdr %i to 0x%p (%lu bytes)\n",
> +		      i, dst, (ulong)phdr->p_filesz);
> +		if (phdr->p_filesz)
> +			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);
> +		flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
> +			    roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
> +		++phdr;
> +	}
> +
> +	if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
> +					    EF_PPC64_ELFV1_ABI)) {
> +		/*
> +		 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
> +		 * descriptor pointer with the first double word being the
> +		 * address of the entry point of the function.
> +		 */
> +		uintptr_t addr = ehdr->e_entry;
> +
> +		return *(Elf64_Addr *)addr;
> +	}
> +
> +	return ehdr->e_entry;
> +}
> +
> +unsigned long load_elf64_image_shdr(unsigned long addr)
> +{
> +	Elf64_Ehdr *ehdr; /* Elf header structure pointer */
> +	Elf64_Shdr *shdr; /* Section header structure pointer */
> +	unsigned char *strtab = 0; /* String table pointer */
> +	unsigned char *image; /* Binary image pointer */
> +	int i; /* Loop counter */
> +
> +	ehdr = (Elf64_Ehdr *)addr;
> +
> +	/* Find the section header string table for output info */
> +	shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
> +			     (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
> +
> +	if (shdr->sh_type == SHT_STRTAB)
> +		strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
> +
> +	/* Load each appropriate section */
> +	for (i = 0; i < ehdr->e_shnum; ++i) {
> +		shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
> +				     (i * sizeof(Elf64_Shdr)));
> +
> +		if (!(shdr->sh_flags & SHF_ALLOC) ||
> +		    shdr->sh_addr == 0 || shdr->sh_size == 0) {
> +			continue;
> +		}
> +
> +		if (strtab) {
> +			debug("%sing %s @ 0x%08lx (%ld bytes)\n",
> +			      (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
> +			       &strtab[shdr->sh_name],
> +			       (unsigned long)shdr->sh_addr,
> +			       (long)shdr->sh_size);
> +		}
> +
> +		if (shdr->sh_type == SHT_NOBITS) {
> +			memset((void *)(uintptr_t)shdr->sh_addr, 0,
> +			       shdr->sh_size);
> +		} else {
> +			image = (unsigned char *)addr + (ulong)shdr->sh_offset;
> +			memcpy((void *)(uintptr_t)shdr->sh_addr,
> +			       (const void *)image, shdr->sh_size);
> +		}
> +		flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
> +			    roundup((shdr->sh_addr + shdr->sh_size),
> +				     ARCH_DMA_MINALIGN) -
> +			            rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
> +	}
> +
> +	if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
> +					    EF_PPC64_ELFV1_ABI)) {
> +		/*
> +		 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
> +		 * descriptor pointer with the first double word being the
> +		 * address of the entry point of the function.
> +		 */
> +		uintptr_t addr = ehdr->e_entry;
> +
> +		return *(Elf64_Addr *)addr;
> +	}
> +
> +	return ehdr->e_entry;
> +}
> +
> +/*
> + * A very simple ELF loader, assumes the image is valid, returns the
> + * entry point address.
> + *
> + * The loader firstly reads the EFI class to see if it's a 64-bit image.
> + * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
> + */
> +unsigned long load_elf_image_phdr(unsigned long addr)
> +{
> +	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> +	Elf32_Phdr *phdr; /* Program header structure pointer */
> +	int i;
> +
> +	ehdr = (Elf32_Ehdr *)addr;
> +	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
> +		return load_elf64_image_phdr(addr);
> +
> +	phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
> +
> +	/* Load each program header */
> +	for (i = 0; i < ehdr->e_phnum; ++i) {
> +		void *dst = (void *)(uintptr_t)phdr->p_paddr;
> +		void *src = (void *)addr + phdr->p_offset;
> +
> +		debug("Loading phdr %i to 0x%p (%i bytes)\n",
> +		      i, dst, phdr->p_filesz);
> +		if (phdr->p_filesz)
> +			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);
> +		flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
> +			    roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
> +		++phdr;
> +	}
> +
> +	return ehdr->e_entry;
> +}
> +
> +unsigned long load_elf_image_shdr(unsigned long addr)
> +{
> +	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> +	Elf32_Shdr *shdr; /* Section header structure pointer */
> +	unsigned char *strtab = 0; /* String table pointer */
> +	unsigned char *image; /* Binary image pointer */
> +	int i; /* Loop counter */
> +
> +	ehdr = (Elf32_Ehdr *)addr;
> +	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
> +		return load_elf64_image_shdr(addr);
> +
> +	/* Find the section header string table for output info */
> +	shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
> +			     (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
> +
> +	if (shdr->sh_type == SHT_STRTAB)
> +		strtab = (unsigned char *)(addr + shdr->sh_offset);
> +
> +	/* Load each appropriate section */
> +	for (i = 0; i < ehdr->e_shnum; ++i) {
> +		shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
> +				     (i * sizeof(Elf32_Shdr)));
> +
> +		if (!(shdr->sh_flags & SHF_ALLOC) ||
> +		    shdr->sh_addr == 0 || shdr->sh_size == 0) {
> +			continue;
> +		}
> +
> +		if (strtab) {
> +			debug("%sing %s @ 0x%08lx (%ld bytes)\n",
> +			      (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
> +			       &strtab[shdr->sh_name],
> +			       (unsigned long)shdr->sh_addr,
> +			       (long)shdr->sh_size);
> +		}
> +
> +		if (shdr->sh_type == SHT_NOBITS) {
> +			memset((void *)(uintptr_t)shdr->sh_addr, 0,
> +			       shdr->sh_size);
> +		} else {
> +			image = (unsigned char *)addr + shdr->sh_offset;
> +			memcpy((void *)(uintptr_t)shdr->sh_addr,
> +			       (const void *)image, shdr->sh_size);
> +		}
> +		flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
> +			    roundup((shdr->sh_addr + shdr->sh_size),
> +				    ARCH_DMA_MINALIGN) -
> +			    rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
> +	}
> +
> +	return ehdr->e_entry;
> +}
> +
> +/*
> + * Determine if a valid ELF image exists at the given memory location.
> + * First look at the ELF header magic field, then make sure that it is
> + * executable.
> + */
> +int valid_elf_image(unsigned long addr)
> +{
> +	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> +
> +	ehdr = (Elf32_Ehdr *)addr;
> +
> +	if (!IS_ELF(*ehdr)) {
> +		printf("## No elf image at address 0x%08lx\n", addr);
> +		return 0;
> +	}
> +
> +	if (ehdr->e_type != ET_EXEC) {
> +		printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
> +		return 0;
> +	}
> +
> +	return 1;
> +}
>
Simon Goldschmidt Jan. 17, 2020, 7:49 a.m. UTC | #2
On Fri, Jan 17, 2020 at 5:27 AM Lokesh Vutla <lokeshvutla at ti.com> wrote:
>
> Simon,
>
> On 13/01/20 11:24 AM, Keerthy wrote:
> > Move the generic elf loading/validating functions to lib/
> > so that they can be re-used and accessed by code existing
> > outside cmd.
> >
> > Signed-off-by: Keerthy <j-keerthy at ti.com>
> > Suggested-by: Simon Goldschmidt <simon.k.r.goldschmidt at gmail.com>
>
> Are you okay with this patch? If yes, Ill apply to u-boot-ti along with other
> patches in this series.

Yes.

Reviewed-by: Simon Goldschmidt <simon.k.r.goldschmidt at gmail.com>

Regards,
Simon

>
> Thanks and regards,
> Lokesh
>
> > ---
> > Changes in v2:
> >
> >   * Factored out all the generic elf handling functions under lib/elf.c
> >
> >  cmd/Kconfig   |   1 +
> >  cmd/elf.c     | 229 --------------------------------------------
> >  include/elf.h |   4 +
> >  lib/Kconfig   |   3 +
> >  lib/Makefile  |   1 +
> >  lib/elf.c     | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  6 files changed, 265 insertions(+), 229 deletions(-)
> >  create mode 100644 lib/elf.c
> >
> > diff --git a/cmd/Kconfig b/cmd/Kconfig
> > index 298feae24d..6f4f08d02a 100644
> > --- a/cmd/Kconfig
> > +++ b/cmd/Kconfig
> > @@ -375,6 +375,7 @@ config CMD_ADTIMG
> >  config CMD_ELF
> >       bool "bootelf, bootvx"
> >       default y
> > +     select ELF
> >       help
> >         Boot an ELF/vxWorks image from the memory.
> >
> > diff --git a/cmd/elf.c b/cmd/elf.c
> > index 32f12a72b9..23cc17aebc 100644
> > --- a/cmd/elf.c
> > +++ b/cmd/elf.c
> > @@ -26,211 +26,6 @@
> >  #include <linux/linkage.h>
> >  #endif
> >
> > -/*
> > - * A very simple ELF64 loader, assumes the image is valid, returns the
> > - * entry point address.
> > - *
> > - * Note if U-Boot is 32-bit, the loader assumes the to segment's
> > - * physical address and size is within the lower 32-bit address space.
> > - */
> > -static unsigned long load_elf64_image_phdr(unsigned long addr)
> > -{
> > -     Elf64_Ehdr *ehdr; /* Elf header structure pointer */
> > -     Elf64_Phdr *phdr; /* Program header structure pointer */
> > -     int i;
> > -
> > -     ehdr = (Elf64_Ehdr *)addr;
> > -     phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
> > -
> > -     /* Load each program header */
> > -     for (i = 0; i < ehdr->e_phnum; ++i) {
> > -             void *dst = (void *)(ulong)phdr->p_paddr;
> > -             void *src = (void *)addr + phdr->p_offset;
> > -
> > -             debug("Loading phdr %i to 0x%p (%lu bytes)\n",
> > -                   i, dst, (ulong)phdr->p_filesz);
> > -             if (phdr->p_filesz)
> > -                     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);
> > -             flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
> > -                         roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
> > -             ++phdr;
> > -     }
> > -
> > -     if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
> > -                                         EF_PPC64_ELFV1_ABI)) {
> > -             /*
> > -              * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
> > -              * descriptor pointer with the first double word being the
> > -              * address of the entry point of the function.
> > -              */
> > -             uintptr_t addr = ehdr->e_entry;
> > -
> > -             return *(Elf64_Addr *)addr;
> > -     }
> > -
> > -     return ehdr->e_entry;
> > -}
> > -
> > -static unsigned long load_elf64_image_shdr(unsigned long addr)
> > -{
> > -     Elf64_Ehdr *ehdr; /* Elf header structure pointer */
> > -     Elf64_Shdr *shdr; /* Section header structure pointer */
> > -     unsigned char *strtab = 0; /* String table pointer */
> > -     unsigned char *image; /* Binary image pointer */
> > -     int i; /* Loop counter */
> > -
> > -     ehdr = (Elf64_Ehdr *)addr;
> > -
> > -     /* Find the section header string table for output info */
> > -     shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
> > -                          (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
> > -
> > -     if (shdr->sh_type == SHT_STRTAB)
> > -             strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
> > -
> > -     /* Load each appropriate section */
> > -     for (i = 0; i < ehdr->e_shnum; ++i) {
> > -             shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
> > -                                  (i * sizeof(Elf64_Shdr)));
> > -
> > -             if (!(shdr->sh_flags & SHF_ALLOC) ||
> > -                 shdr->sh_addr == 0 || shdr->sh_size == 0) {
> > -                     continue;
> > -             }
> > -
> > -             if (strtab) {
> > -                     debug("%sing %s @ 0x%08lx (%ld bytes)\n",
> > -                           (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
> > -                            &strtab[shdr->sh_name],
> > -                            (unsigned long)shdr->sh_addr,
> > -                            (long)shdr->sh_size);
> > -             }
> > -
> > -             if (shdr->sh_type == SHT_NOBITS) {
> > -                     memset((void *)(uintptr_t)shdr->sh_addr, 0,
> > -                            shdr->sh_size);
> > -             } else {
> > -                     image = (unsigned char *)addr + (ulong)shdr->sh_offset;
> > -                     memcpy((void *)(uintptr_t)shdr->sh_addr,
> > -                            (const void *)image, shdr->sh_size);
> > -             }
> > -             flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
> > -                         roundup((shdr->sh_addr + shdr->sh_size),
> > -                                  ARCH_DMA_MINALIGN) -
> > -                                 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
> > -     }
> > -
> > -     if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
> > -                                         EF_PPC64_ELFV1_ABI)) {
> > -             /*
> > -              * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
> > -              * descriptor pointer with the first double word being the
> > -              * address of the entry point of the function.
> > -              */
> > -             uintptr_t addr = ehdr->e_entry;
> > -
> > -             return *(Elf64_Addr *)addr;
> > -     }
> > -
> > -     return ehdr->e_entry;
> > -}
> > -
> > -/*
> > - * A very simple ELF loader, assumes the image is valid, returns the
> > - * entry point address.
> > - *
> > - * The loader firstly reads the EFI class to see if it's a 64-bit image.
> > - * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
> > - */
> > -static unsigned long load_elf_image_phdr(unsigned long addr)
> > -{
> > -     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> > -     Elf32_Phdr *phdr; /* Program header structure pointer */
> > -     int i;
> > -
> > -     ehdr = (Elf32_Ehdr *)addr;
> > -     if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
> > -             return load_elf64_image_phdr(addr);
> > -
> > -     phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
> > -
> > -     /* Load each program header */
> > -     for (i = 0; i < ehdr->e_phnum; ++i) {
> > -             void *dst = (void *)(uintptr_t)phdr->p_paddr;
> > -             void *src = (void *)addr + phdr->p_offset;
> > -
> > -             debug("Loading phdr %i to 0x%p (%i bytes)\n",
> > -                   i, dst, phdr->p_filesz);
> > -             if (phdr->p_filesz)
> > -                     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);
> > -             flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
> > -                         roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
> > -             ++phdr;
> > -     }
> > -
> > -     return ehdr->e_entry;
> > -}
> > -
> > -static unsigned long load_elf_image_shdr(unsigned long addr)
> > -{
> > -     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> > -     Elf32_Shdr *shdr; /* Section header structure pointer */
> > -     unsigned char *strtab = 0; /* String table pointer */
> > -     unsigned char *image; /* Binary image pointer */
> > -     int i; /* Loop counter */
> > -
> > -     ehdr = (Elf32_Ehdr *)addr;
> > -     if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
> > -             return load_elf64_image_shdr(addr);
> > -
> > -     /* Find the section header string table for output info */
> > -     shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
> > -                          (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
> > -
> > -     if (shdr->sh_type == SHT_STRTAB)
> > -             strtab = (unsigned char *)(addr + shdr->sh_offset);
> > -
> > -     /* Load each appropriate section */
> > -     for (i = 0; i < ehdr->e_shnum; ++i) {
> > -             shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
> > -                                  (i * sizeof(Elf32_Shdr)));
> > -
> > -             if (!(shdr->sh_flags & SHF_ALLOC) ||
> > -                 shdr->sh_addr == 0 || shdr->sh_size == 0) {
> > -                     continue;
> > -             }
> > -
> > -             if (strtab) {
> > -                     debug("%sing %s @ 0x%08lx (%ld bytes)\n",
> > -                           (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
> > -                            &strtab[shdr->sh_name],
> > -                            (unsigned long)shdr->sh_addr,
> > -                            (long)shdr->sh_size);
> > -             }
> > -
> > -             if (shdr->sh_type == SHT_NOBITS) {
> > -                     memset((void *)(uintptr_t)shdr->sh_addr, 0,
> > -                            shdr->sh_size);
> > -             } else {
> > -                     image = (unsigned char *)addr + shdr->sh_offset;
> > -                     memcpy((void *)(uintptr_t)shdr->sh_addr,
> > -                            (const void *)image, shdr->sh_size);
> > -             }
> > -             flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
> > -                         roundup((shdr->sh_addr + shdr->sh_size),
> > -                                 ARCH_DMA_MINALIGN) -
> > -                         rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
> > -     }
> > -
> > -     return ehdr->e_entry;
> > -}
> > -
> >  /* Allow ports to override the default behavior */
> >  static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
> >                                    int argc, char * const argv[])
> > @@ -246,30 +41,6 @@ static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
> >       return ret;
> >  }
> >
> > -/*
> > - * Determine if a valid ELF image exists at the given memory location.
> > - * First look at the ELF header magic field, then make sure that it is
> > - * executable.
> > - */
> > -int valid_elf_image(unsigned long addr)
> > -{
> > -     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> > -
> > -     ehdr = (Elf32_Ehdr *)addr;
> > -
> > -     if (!IS_ELF(*ehdr)) {
> > -             printf("## No elf image at address 0x%08lx\n", addr);
> > -             return 0;
> > -     }
> > -
> > -     if (ehdr->e_type != ET_EXEC) {
> > -             printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
> > -             return 0;
> > -     }
> > -
> > -     return 1;
> > -}
> > -
> >  /* Interpreter command to boot an arbitrary ELF image from memory */
> >  int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> >  {
> > diff --git a/include/elf.h b/include/elf.h
> > index 81f40191d7..e7c51986df 100644
> > --- a/include/elf.h
> > +++ b/include/elf.h
> > @@ -692,6 +692,10 @@ unsigned long elf_hash(const unsigned char *name);
> >
> >  #ifndef __ASSEMBLER__
> >  int valid_elf_image(unsigned long addr);
> > +unsigned long load_elf64_image_phdr(unsigned long addr);
> > +unsigned long load_elf64_image_shdr(unsigned long addr);
> > +unsigned long load_elf_image_phdr(unsigned long addr);
> > +unsigned long load_elf_image_shdr(unsigned long addr);
> >  #endif
> >
> >  #endif /* _ELF_H */
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index d040a87d26..b155ced4b2 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -601,4 +601,7 @@ config TEST_FDTDEC
> >  config LIB_DATE
> >       bool
> >
> > +config ELF
> > +     bool "enable basic elf loading/validating functions"
> > +
> >  endmenu
> > diff --git a/lib/Makefile b/lib/Makefile
> > index 6b7b9ce85c..93f22d210e 100644
> > --- a/lib/Makefile
> > +++ b/lib/Makefile
> > @@ -121,6 +121,7 @@ obj-y += vsprintf.o strto.o
> >  endif
> >
> >  obj-y += date.o
> > +obj-$(CONFIG_ELF) += elf.o
> >
> >  #
> >  # Build a fast OID lookup registry from include/linux/oid_registry.h
> > diff --git a/lib/elf.c b/lib/elf.c
> > new file mode 100644
> > index 0000000000..54ac4ee502
> > --- /dev/null
> > +++ b/lib/elf.c
> > @@ -0,0 +1,256 @@
> > +/*
> > + * Copyright (c) 2001 William L. Pitts
> > + * All rights reserved.
> > + *
> > + * Redistribution and use in source and binary forms are freely
> > + * permitted provided that the above copyright notice and this
> > + * paragraph and the following disclaimer are duplicated in all
> > + * such forms.
> > + *
> > + * This software is provided "AS IS" and without any express or
> > + * implied warranties, including, without limitation, the implied
> > + * warranties of merchantability and fitness for a particular
> > + * purpose.
> > + */
> > +
> > +#include <common.h>
> > +#include <command.h>
> > +#include <cpu_func.h>
> > +#include <elf.h>
> > +#include <env.h>
> > +#include <net.h>
> > +#include <vxworks.h>
> > +#ifdef CONFIG_X86
> > +#include <vbe.h>
> > +#include <asm/e820.h>
> > +#include <linux/linkage.h>
> > +#endif
> > +
> > +/*
> > + * A very simple ELF64 loader, assumes the image is valid, returns the
> > + * entry point address.
> > + *
> > + * Note if U-Boot is 32-bit, the loader assumes the to segment's
> > + * physical address and size is within the lower 32-bit address space.
> > + */
> > +unsigned long load_elf64_image_phdr(unsigned long addr)
> > +{
> > +     Elf64_Ehdr *ehdr; /* Elf header structure pointer */
> > +     Elf64_Phdr *phdr; /* Program header structure pointer */
> > +     int i;
> > +
> > +     ehdr = (Elf64_Ehdr *)addr;
> > +     phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
> > +
> > +     /* Load each program header */
> > +     for (i = 0; i < ehdr->e_phnum; ++i) {
> > +             void *dst = (void *)(ulong)phdr->p_paddr;
> > +             void *src = (void *)addr + phdr->p_offset;
> > +
> > +             debug("Loading phdr %i to 0x%p (%lu bytes)\n",
> > +                   i, dst, (ulong)phdr->p_filesz);
> > +             if (phdr->p_filesz)
> > +                     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);
> > +             flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
> > +                         roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
> > +             ++phdr;
> > +     }
> > +
> > +     if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
> > +                                         EF_PPC64_ELFV1_ABI)) {
> > +             /*
> > +              * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
> > +              * descriptor pointer with the first double word being the
> > +              * address of the entry point of the function.
> > +              */
> > +             uintptr_t addr = ehdr->e_entry;
> > +
> > +             return *(Elf64_Addr *)addr;
> > +     }
> > +
> > +     return ehdr->e_entry;
> > +}
> > +
> > +unsigned long load_elf64_image_shdr(unsigned long addr)
> > +{
> > +     Elf64_Ehdr *ehdr; /* Elf header structure pointer */
> > +     Elf64_Shdr *shdr; /* Section header structure pointer */
> > +     unsigned char *strtab = 0; /* String table pointer */
> > +     unsigned char *image; /* Binary image pointer */
> > +     int i; /* Loop counter */
> > +
> > +     ehdr = (Elf64_Ehdr *)addr;
> > +
> > +     /* Find the section header string table for output info */
> > +     shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
> > +                          (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
> > +
> > +     if (shdr->sh_type == SHT_STRTAB)
> > +             strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
> > +
> > +     /* Load each appropriate section */
> > +     for (i = 0; i < ehdr->e_shnum; ++i) {
> > +             shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
> > +                                  (i * sizeof(Elf64_Shdr)));
> > +
> > +             if (!(shdr->sh_flags & SHF_ALLOC) ||
> > +                 shdr->sh_addr == 0 || shdr->sh_size == 0) {
> > +                     continue;
> > +             }
> > +
> > +             if (strtab) {
> > +                     debug("%sing %s @ 0x%08lx (%ld bytes)\n",
> > +                           (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
> > +                            &strtab[shdr->sh_name],
> > +                            (unsigned long)shdr->sh_addr,
> > +                            (long)shdr->sh_size);
> > +             }
> > +
> > +             if (shdr->sh_type == SHT_NOBITS) {
> > +                     memset((void *)(uintptr_t)shdr->sh_addr, 0,
> > +                            shdr->sh_size);
> > +             } else {
> > +                     image = (unsigned char *)addr + (ulong)shdr->sh_offset;
> > +                     memcpy((void *)(uintptr_t)shdr->sh_addr,
> > +                            (const void *)image, shdr->sh_size);
> > +             }
> > +             flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
> > +                         roundup((shdr->sh_addr + shdr->sh_size),
> > +                                  ARCH_DMA_MINALIGN) -
> > +                                 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
> > +     }
> > +
> > +     if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
> > +                                         EF_PPC64_ELFV1_ABI)) {
> > +             /*
> > +              * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
> > +              * descriptor pointer with the first double word being the
> > +              * address of the entry point of the function.
> > +              */
> > +             uintptr_t addr = ehdr->e_entry;
> > +
> > +             return *(Elf64_Addr *)addr;
> > +     }
> > +
> > +     return ehdr->e_entry;
> > +}
> > +
> > +/*
> > + * A very simple ELF loader, assumes the image is valid, returns the
> > + * entry point address.
> > + *
> > + * The loader firstly reads the EFI class to see if it's a 64-bit image.
> > + * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
> > + */
> > +unsigned long load_elf_image_phdr(unsigned long addr)
> > +{
> > +     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> > +     Elf32_Phdr *phdr; /* Program header structure pointer */
> > +     int i;
> > +
> > +     ehdr = (Elf32_Ehdr *)addr;
> > +     if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
> > +             return load_elf64_image_phdr(addr);
> > +
> > +     phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
> > +
> > +     /* Load each program header */
> > +     for (i = 0; i < ehdr->e_phnum; ++i) {
> > +             void *dst = (void *)(uintptr_t)phdr->p_paddr;
> > +             void *src = (void *)addr + phdr->p_offset;
> > +
> > +             debug("Loading phdr %i to 0x%p (%i bytes)\n",
> > +                   i, dst, phdr->p_filesz);
> > +             if (phdr->p_filesz)
> > +                     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);
> > +             flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
> > +                         roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
> > +             ++phdr;
> > +     }
> > +
> > +     return ehdr->e_entry;
> > +}
> > +
> > +unsigned long load_elf_image_shdr(unsigned long addr)
> > +{
> > +     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> > +     Elf32_Shdr *shdr; /* Section header structure pointer */
> > +     unsigned char *strtab = 0; /* String table pointer */
> > +     unsigned char *image; /* Binary image pointer */
> > +     int i; /* Loop counter */
> > +
> > +     ehdr = (Elf32_Ehdr *)addr;
> > +     if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
> > +             return load_elf64_image_shdr(addr);
> > +
> > +     /* Find the section header string table for output info */
> > +     shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
> > +                          (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
> > +
> > +     if (shdr->sh_type == SHT_STRTAB)
> > +             strtab = (unsigned char *)(addr + shdr->sh_offset);
> > +
> > +     /* Load each appropriate section */
> > +     for (i = 0; i < ehdr->e_shnum; ++i) {
> > +             shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
> > +                                  (i * sizeof(Elf32_Shdr)));
> > +
> > +             if (!(shdr->sh_flags & SHF_ALLOC) ||
> > +                 shdr->sh_addr == 0 || shdr->sh_size == 0) {
> > +                     continue;
> > +             }
> > +
> > +             if (strtab) {
> > +                     debug("%sing %s @ 0x%08lx (%ld bytes)\n",
> > +                           (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
> > +                            &strtab[shdr->sh_name],
> > +                            (unsigned long)shdr->sh_addr,
> > +                            (long)shdr->sh_size);
> > +             }
> > +
> > +             if (shdr->sh_type == SHT_NOBITS) {
> > +                     memset((void *)(uintptr_t)shdr->sh_addr, 0,
> > +                            shdr->sh_size);
> > +             } else {
> > +                     image = (unsigned char *)addr + shdr->sh_offset;
> > +                     memcpy((void *)(uintptr_t)shdr->sh_addr,
> > +                            (const void *)image, shdr->sh_size);
> > +             }
> > +             flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
> > +                         roundup((shdr->sh_addr + shdr->sh_size),
> > +                                 ARCH_DMA_MINALIGN) -
> > +                         rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
> > +     }
> > +
> > +     return ehdr->e_entry;
> > +}
> > +
> > +/*
> > + * Determine if a valid ELF image exists at the given memory location.
> > + * First look at the ELF header magic field, then make sure that it is
> > + * executable.
> > + */
> > +int valid_elf_image(unsigned long addr)
> > +{
> > +     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
> > +
> > +     ehdr = (Elf32_Ehdr *)addr;
> > +
> > +     if (!IS_ELF(*ehdr)) {
> > +             printf("## No elf image at address 0x%08lx\n", addr);
> > +             return 0;
> > +     }
> > +
> > +     if (ehdr->e_type != ET_EXEC) {
> > +             printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
> > +             return 0;
> > +     }
> > +
> > +     return 1;
> > +}
> >
J, KEERTHY Jan. 17, 2020, 8:06 a.m. UTC | #3
On 17/01/20 1:19 pm, Simon Goldschmidt wrote:
> On Fri, Jan 17, 2020 at 5:27 AM Lokesh Vutla <lokeshvutla at ti.com> wrote:
>>
>> Simon,
>>
>> On 13/01/20 11:24 AM, Keerthy wrote:
>>> Move the generic elf loading/validating functions to lib/
>>> so that they can be re-used and accessed by code existing
>>> outside cmd.
>>>
>>> Signed-off-by: Keerthy <j-keerthy at ti.com>
>>> Suggested-by: Simon Goldschmidt <simon.k.r.goldschmidt at gmail.com>
>>
>> Are you okay with this patch? If yes, Ill apply to u-boot-ti along with other
>> patches in this series.
> 
> Yes.
> 
> Reviewed-by: Simon Goldschmidt <simon.k.r.goldschmidt at gmail.com>

Thanks Simon!

> 
> Regards,
> Simon
> 
>>
>> Thanks and regards,
>> Lokesh
>>
>>> ---
>>> Changes in v2:
>>>
>>>    * Factored out all the generic elf handling functions under lib/elf.c
>>>
>>>   cmd/Kconfig   |   1 +
>>>   cmd/elf.c     | 229 --------------------------------------------
>>>   include/elf.h |   4 +
>>>   lib/Kconfig   |   3 +
>>>   lib/Makefile  |   1 +
>>>   lib/elf.c     | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>>   6 files changed, 265 insertions(+), 229 deletions(-)
>>>   create mode 100644 lib/elf.c
>>>
>>> diff --git a/cmd/Kconfig b/cmd/Kconfig
>>> index 298feae24d..6f4f08d02a 100644
>>> --- a/cmd/Kconfig
>>> +++ b/cmd/Kconfig
>>> @@ -375,6 +375,7 @@ config CMD_ADTIMG
>>>   config CMD_ELF
>>>        bool "bootelf, bootvx"
>>>        default y
>>> +     select ELF
>>>        help
>>>          Boot an ELF/vxWorks image from the memory.
>>>
>>> diff --git a/cmd/elf.c b/cmd/elf.c
>>> index 32f12a72b9..23cc17aebc 100644
>>> --- a/cmd/elf.c
>>> +++ b/cmd/elf.c
>>> @@ -26,211 +26,6 @@
>>>   #include <linux/linkage.h>
>>>   #endif
>>>
>>> -/*
>>> - * A very simple ELF64 loader, assumes the image is valid, returns the
>>> - * entry point address.
>>> - *
>>> - * Note if U-Boot is 32-bit, the loader assumes the to segment's
>>> - * physical address and size is within the lower 32-bit address space.
>>> - */
>>> -static unsigned long load_elf64_image_phdr(unsigned long addr)
>>> -{
>>> -     Elf64_Ehdr *ehdr; /* Elf header structure pointer */
>>> -     Elf64_Phdr *phdr; /* Program header structure pointer */
>>> -     int i;
>>> -
>>> -     ehdr = (Elf64_Ehdr *)addr;
>>> -     phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
>>> -
>>> -     /* Load each program header */
>>> -     for (i = 0; i < ehdr->e_phnum; ++i) {
>>> -             void *dst = (void *)(ulong)phdr->p_paddr;
>>> -             void *src = (void *)addr + phdr->p_offset;
>>> -
>>> -             debug("Loading phdr %i to 0x%p (%lu bytes)\n",
>>> -                   i, dst, (ulong)phdr->p_filesz);
>>> -             if (phdr->p_filesz)
>>> -                     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);
>>> -             flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
>>> -                         roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
>>> -             ++phdr;
>>> -     }
>>> -
>>> -     if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
>>> -                                         EF_PPC64_ELFV1_ABI)) {
>>> -             /*
>>> -              * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
>>> -              * descriptor pointer with the first double word being the
>>> -              * address of the entry point of the function.
>>> -              */
>>> -             uintptr_t addr = ehdr->e_entry;
>>> -
>>> -             return *(Elf64_Addr *)addr;
>>> -     }
>>> -
>>> -     return ehdr->e_entry;
>>> -}
>>> -
>>> -static unsigned long load_elf64_image_shdr(unsigned long addr)
>>> -{
>>> -     Elf64_Ehdr *ehdr; /* Elf header structure pointer */
>>> -     Elf64_Shdr *shdr; /* Section header structure pointer */
>>> -     unsigned char *strtab = 0; /* String table pointer */
>>> -     unsigned char *image; /* Binary image pointer */
>>> -     int i; /* Loop counter */
>>> -
>>> -     ehdr = (Elf64_Ehdr *)addr;
>>> -
>>> -     /* Find the section header string table for output info */
>>> -     shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
>>> -                          (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
>>> -
>>> -     if (shdr->sh_type == SHT_STRTAB)
>>> -             strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
>>> -
>>> -     /* Load each appropriate section */
>>> -     for (i = 0; i < ehdr->e_shnum; ++i) {
>>> -             shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
>>> -                                  (i * sizeof(Elf64_Shdr)));
>>> -
>>> -             if (!(shdr->sh_flags & SHF_ALLOC) ||
>>> -                 shdr->sh_addr == 0 || shdr->sh_size == 0) {
>>> -                     continue;
>>> -             }
>>> -
>>> -             if (strtab) {
>>> -                     debug("%sing %s @ 0x%08lx (%ld bytes)\n",
>>> -                           (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
>>> -                            &strtab[shdr->sh_name],
>>> -                            (unsigned long)shdr->sh_addr,
>>> -                            (long)shdr->sh_size);
>>> -             }
>>> -
>>> -             if (shdr->sh_type == SHT_NOBITS) {
>>> -                     memset((void *)(uintptr_t)shdr->sh_addr, 0,
>>> -                            shdr->sh_size);
>>> -             } else {
>>> -                     image = (unsigned char *)addr + (ulong)shdr->sh_offset;
>>> -                     memcpy((void *)(uintptr_t)shdr->sh_addr,
>>> -                            (const void *)image, shdr->sh_size);
>>> -             }
>>> -             flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
>>> -                         roundup((shdr->sh_addr + shdr->sh_size),
>>> -                                  ARCH_DMA_MINALIGN) -
>>> -                                 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
>>> -     }
>>> -
>>> -     if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
>>> -                                         EF_PPC64_ELFV1_ABI)) {
>>> -             /*
>>> -              * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
>>> -              * descriptor pointer with the first double word being the
>>> -              * address of the entry point of the function.
>>> -              */
>>> -             uintptr_t addr = ehdr->e_entry;
>>> -
>>> -             return *(Elf64_Addr *)addr;
>>> -     }
>>> -
>>> -     return ehdr->e_entry;
>>> -}
>>> -
>>> -/*
>>> - * A very simple ELF loader, assumes the image is valid, returns the
>>> - * entry point address.
>>> - *
>>> - * The loader firstly reads the EFI class to see if it's a 64-bit image.
>>> - * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
>>> - */
>>> -static unsigned long load_elf_image_phdr(unsigned long addr)
>>> -{
>>> -     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
>>> -     Elf32_Phdr *phdr; /* Program header structure pointer */
>>> -     int i;
>>> -
>>> -     ehdr = (Elf32_Ehdr *)addr;
>>> -     if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
>>> -             return load_elf64_image_phdr(addr);
>>> -
>>> -     phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
>>> -
>>> -     /* Load each program header */
>>> -     for (i = 0; i < ehdr->e_phnum; ++i) {
>>> -             void *dst = (void *)(uintptr_t)phdr->p_paddr;
>>> -             void *src = (void *)addr + phdr->p_offset;
>>> -
>>> -             debug("Loading phdr %i to 0x%p (%i bytes)\n",
>>> -                   i, dst, phdr->p_filesz);
>>> -             if (phdr->p_filesz)
>>> -                     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);
>>> -             flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
>>> -                         roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
>>> -             ++phdr;
>>> -     }
>>> -
>>> -     return ehdr->e_entry;
>>> -}
>>> -
>>> -static unsigned long load_elf_image_shdr(unsigned long addr)
>>> -{
>>> -     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
>>> -     Elf32_Shdr *shdr; /* Section header structure pointer */
>>> -     unsigned char *strtab = 0; /* String table pointer */
>>> -     unsigned char *image; /* Binary image pointer */
>>> -     int i; /* Loop counter */
>>> -
>>> -     ehdr = (Elf32_Ehdr *)addr;
>>> -     if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
>>> -             return load_elf64_image_shdr(addr);
>>> -
>>> -     /* Find the section header string table for output info */
>>> -     shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
>>> -                          (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
>>> -
>>> -     if (shdr->sh_type == SHT_STRTAB)
>>> -             strtab = (unsigned char *)(addr + shdr->sh_offset);
>>> -
>>> -     /* Load each appropriate section */
>>> -     for (i = 0; i < ehdr->e_shnum; ++i) {
>>> -             shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
>>> -                                  (i * sizeof(Elf32_Shdr)));
>>> -
>>> -             if (!(shdr->sh_flags & SHF_ALLOC) ||
>>> -                 shdr->sh_addr == 0 || shdr->sh_size == 0) {
>>> -                     continue;
>>> -             }
>>> -
>>> -             if (strtab) {
>>> -                     debug("%sing %s @ 0x%08lx (%ld bytes)\n",
>>> -                           (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
>>> -                            &strtab[shdr->sh_name],
>>> -                            (unsigned long)shdr->sh_addr,
>>> -                            (long)shdr->sh_size);
>>> -             }
>>> -
>>> -             if (shdr->sh_type == SHT_NOBITS) {
>>> -                     memset((void *)(uintptr_t)shdr->sh_addr, 0,
>>> -                            shdr->sh_size);
>>> -             } else {
>>> -                     image = (unsigned char *)addr + shdr->sh_offset;
>>> -                     memcpy((void *)(uintptr_t)shdr->sh_addr,
>>> -                            (const void *)image, shdr->sh_size);
>>> -             }
>>> -             flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
>>> -                         roundup((shdr->sh_addr + shdr->sh_size),
>>> -                                 ARCH_DMA_MINALIGN) -
>>> -                         rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
>>> -     }
>>> -
>>> -     return ehdr->e_entry;
>>> -}
>>> -
>>>   /* Allow ports to override the default behavior */
>>>   static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
>>>                                     int argc, char * const argv[])
>>> @@ -246,30 +41,6 @@ static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
>>>        return ret;
>>>   }
>>>
>>> -/*
>>> - * Determine if a valid ELF image exists at the given memory location.
>>> - * First look at the ELF header magic field, then make sure that it is
>>> - * executable.
>>> - */
>>> -int valid_elf_image(unsigned long addr)
>>> -{
>>> -     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
>>> -
>>> -     ehdr = (Elf32_Ehdr *)addr;
>>> -
>>> -     if (!IS_ELF(*ehdr)) {
>>> -             printf("## No elf image at address 0x%08lx\n", addr);
>>> -             return 0;
>>> -     }
>>> -
>>> -     if (ehdr->e_type != ET_EXEC) {
>>> -             printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
>>> -             return 0;
>>> -     }
>>> -
>>> -     return 1;
>>> -}
>>> -
>>>   /* Interpreter command to boot an arbitrary ELF image from memory */
>>>   int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>>>   {
>>> diff --git a/include/elf.h b/include/elf.h
>>> index 81f40191d7..e7c51986df 100644
>>> --- a/include/elf.h
>>> +++ b/include/elf.h
>>> @@ -692,6 +692,10 @@ unsigned long elf_hash(const unsigned char *name);
>>>
>>>   #ifndef __ASSEMBLER__
>>>   int valid_elf_image(unsigned long addr);
>>> +unsigned long load_elf64_image_phdr(unsigned long addr);
>>> +unsigned long load_elf64_image_shdr(unsigned long addr);
>>> +unsigned long load_elf_image_phdr(unsigned long addr);
>>> +unsigned long load_elf_image_shdr(unsigned long addr);
>>>   #endif
>>>
>>>   #endif /* _ELF_H */
>>> diff --git a/lib/Kconfig b/lib/Kconfig
>>> index d040a87d26..b155ced4b2 100644
>>> --- a/lib/Kconfig
>>> +++ b/lib/Kconfig
>>> @@ -601,4 +601,7 @@ config TEST_FDTDEC
>>>   config LIB_DATE
>>>        bool
>>>
>>> +config ELF
>>> +     bool "enable basic elf loading/validating functions"
>>> +
>>>   endmenu
>>> diff --git a/lib/Makefile b/lib/Makefile
>>> index 6b7b9ce85c..93f22d210e 100644
>>> --- a/lib/Makefile
>>> +++ b/lib/Makefile
>>> @@ -121,6 +121,7 @@ obj-y += vsprintf.o strto.o
>>>   endif
>>>
>>>   obj-y += date.o
>>> +obj-$(CONFIG_ELF) += elf.o
>>>
>>>   #
>>>   # Build a fast OID lookup registry from include/linux/oid_registry.h
>>> diff --git a/lib/elf.c b/lib/elf.c
>>> new file mode 100644
>>> index 0000000000..54ac4ee502
>>> --- /dev/null
>>> +++ b/lib/elf.c
>>> @@ -0,0 +1,256 @@
>>> +/*
>>> + * Copyright (c) 2001 William L. Pitts
>>> + * All rights reserved.
>>> + *
>>> + * Redistribution and use in source and binary forms are freely
>>> + * permitted provided that the above copyright notice and this
>>> + * paragraph and the following disclaimer are duplicated in all
>>> + * such forms.
>>> + *
>>> + * This software is provided "AS IS" and without any express or
>>> + * implied warranties, including, without limitation, the implied
>>> + * warranties of merchantability and fitness for a particular
>>> + * purpose.
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <command.h>
>>> +#include <cpu_func.h>
>>> +#include <elf.h>
>>> +#include <env.h>
>>> +#include <net.h>
>>> +#include <vxworks.h>
>>> +#ifdef CONFIG_X86
>>> +#include <vbe.h>
>>> +#include <asm/e820.h>
>>> +#include <linux/linkage.h>
>>> +#endif
>>> +
>>> +/*
>>> + * A very simple ELF64 loader, assumes the image is valid, returns the
>>> + * entry point address.
>>> + *
>>> + * Note if U-Boot is 32-bit, the loader assumes the to segment's
>>> + * physical address and size is within the lower 32-bit address space.
>>> + */
>>> +unsigned long load_elf64_image_phdr(unsigned long addr)
>>> +{
>>> +     Elf64_Ehdr *ehdr; /* Elf header structure pointer */
>>> +     Elf64_Phdr *phdr; /* Program header structure pointer */
>>> +     int i;
>>> +
>>> +     ehdr = (Elf64_Ehdr *)addr;
>>> +     phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
>>> +
>>> +     /* Load each program header */
>>> +     for (i = 0; i < ehdr->e_phnum; ++i) {
>>> +             void *dst = (void *)(ulong)phdr->p_paddr;
>>> +             void *src = (void *)addr + phdr->p_offset;
>>> +
>>> +             debug("Loading phdr %i to 0x%p (%lu bytes)\n",
>>> +                   i, dst, (ulong)phdr->p_filesz);
>>> +             if (phdr->p_filesz)
>>> +                     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);
>>> +             flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
>>> +                         roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
>>> +             ++phdr;
>>> +     }
>>> +
>>> +     if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
>>> +                                         EF_PPC64_ELFV1_ABI)) {
>>> +             /*
>>> +              * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
>>> +              * descriptor pointer with the first double word being the
>>> +              * address of the entry point of the function.
>>> +              */
>>> +             uintptr_t addr = ehdr->e_entry;
>>> +
>>> +             return *(Elf64_Addr *)addr;
>>> +     }
>>> +
>>> +     return ehdr->e_entry;
>>> +}
>>> +
>>> +unsigned long load_elf64_image_shdr(unsigned long addr)
>>> +{
>>> +     Elf64_Ehdr *ehdr; /* Elf header structure pointer */
>>> +     Elf64_Shdr *shdr; /* Section header structure pointer */
>>> +     unsigned char *strtab = 0; /* String table pointer */
>>> +     unsigned char *image; /* Binary image pointer */
>>> +     int i; /* Loop counter */
>>> +
>>> +     ehdr = (Elf64_Ehdr *)addr;
>>> +
>>> +     /* Find the section header string table for output info */
>>> +     shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
>>> +                          (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
>>> +
>>> +     if (shdr->sh_type == SHT_STRTAB)
>>> +             strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
>>> +
>>> +     /* Load each appropriate section */
>>> +     for (i = 0; i < ehdr->e_shnum; ++i) {
>>> +             shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
>>> +                                  (i * sizeof(Elf64_Shdr)));
>>> +
>>> +             if (!(shdr->sh_flags & SHF_ALLOC) ||
>>> +                 shdr->sh_addr == 0 || shdr->sh_size == 0) {
>>> +                     continue;
>>> +             }
>>> +
>>> +             if (strtab) {
>>> +                     debug("%sing %s @ 0x%08lx (%ld bytes)\n",
>>> +                           (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
>>> +                            &strtab[shdr->sh_name],
>>> +                            (unsigned long)shdr->sh_addr,
>>> +                            (long)shdr->sh_size);
>>> +             }
>>> +
>>> +             if (shdr->sh_type == SHT_NOBITS) {
>>> +                     memset((void *)(uintptr_t)shdr->sh_addr, 0,
>>> +                            shdr->sh_size);
>>> +             } else {
>>> +                     image = (unsigned char *)addr + (ulong)shdr->sh_offset;
>>> +                     memcpy((void *)(uintptr_t)shdr->sh_addr,
>>> +                            (const void *)image, shdr->sh_size);
>>> +             }
>>> +             flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
>>> +                         roundup((shdr->sh_addr + shdr->sh_size),
>>> +                                  ARCH_DMA_MINALIGN) -
>>> +                                 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
>>> +     }
>>> +
>>> +     if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
>>> +                                         EF_PPC64_ELFV1_ABI)) {
>>> +             /*
>>> +              * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
>>> +              * descriptor pointer with the first double word being the
>>> +              * address of the entry point of the function.
>>> +              */
>>> +             uintptr_t addr = ehdr->e_entry;
>>> +
>>> +             return *(Elf64_Addr *)addr;
>>> +     }
>>> +
>>> +     return ehdr->e_entry;
>>> +}
>>> +
>>> +/*
>>> + * A very simple ELF loader, assumes the image is valid, returns the
>>> + * entry point address.
>>> + *
>>> + * The loader firstly reads the EFI class to see if it's a 64-bit image.
>>> + * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
>>> + */
>>> +unsigned long load_elf_image_phdr(unsigned long addr)
>>> +{
>>> +     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
>>> +     Elf32_Phdr *phdr; /* Program header structure pointer */
>>> +     int i;
>>> +
>>> +     ehdr = (Elf32_Ehdr *)addr;
>>> +     if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
>>> +             return load_elf64_image_phdr(addr);
>>> +
>>> +     phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
>>> +
>>> +     /* Load each program header */
>>> +     for (i = 0; i < ehdr->e_phnum; ++i) {
>>> +             void *dst = (void *)(uintptr_t)phdr->p_paddr;
>>> +             void *src = (void *)addr + phdr->p_offset;
>>> +
>>> +             debug("Loading phdr %i to 0x%p (%i bytes)\n",
>>> +                   i, dst, phdr->p_filesz);
>>> +             if (phdr->p_filesz)
>>> +                     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);
>>> +             flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
>>> +                         roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
>>> +             ++phdr;
>>> +     }
>>> +
>>> +     return ehdr->e_entry;
>>> +}
>>> +
>>> +unsigned long load_elf_image_shdr(unsigned long addr)
>>> +{
>>> +     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
>>> +     Elf32_Shdr *shdr; /* Section header structure pointer */
>>> +     unsigned char *strtab = 0; /* String table pointer */
>>> +     unsigned char *image; /* Binary image pointer */
>>> +     int i; /* Loop counter */
>>> +
>>> +     ehdr = (Elf32_Ehdr *)addr;
>>> +     if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
>>> +             return load_elf64_image_shdr(addr);
>>> +
>>> +     /* Find the section header string table for output info */
>>> +     shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
>>> +                          (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
>>> +
>>> +     if (shdr->sh_type == SHT_STRTAB)
>>> +             strtab = (unsigned char *)(addr + shdr->sh_offset);
>>> +
>>> +     /* Load each appropriate section */
>>> +     for (i = 0; i < ehdr->e_shnum; ++i) {
>>> +             shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
>>> +                                  (i * sizeof(Elf32_Shdr)));
>>> +
>>> +             if (!(shdr->sh_flags & SHF_ALLOC) ||
>>> +                 shdr->sh_addr == 0 || shdr->sh_size == 0) {
>>> +                     continue;
>>> +             }
>>> +
>>> +             if (strtab) {
>>> +                     debug("%sing %s @ 0x%08lx (%ld bytes)\n",
>>> +                           (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
>>> +                            &strtab[shdr->sh_name],
>>> +                            (unsigned long)shdr->sh_addr,
>>> +                            (long)shdr->sh_size);
>>> +             }
>>> +
>>> +             if (shdr->sh_type == SHT_NOBITS) {
>>> +                     memset((void *)(uintptr_t)shdr->sh_addr, 0,
>>> +                            shdr->sh_size);
>>> +             } else {
>>> +                     image = (unsigned char *)addr + shdr->sh_offset;
>>> +                     memcpy((void *)(uintptr_t)shdr->sh_addr,
>>> +                            (const void *)image, shdr->sh_size);
>>> +             }
>>> +             flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
>>> +                         roundup((shdr->sh_addr + shdr->sh_size),
>>> +                                 ARCH_DMA_MINALIGN) -
>>> +                         rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
>>> +     }
>>> +
>>> +     return ehdr->e_entry;
>>> +}
>>> +
>>> +/*
>>> + * Determine if a valid ELF image exists at the given memory location.
>>> + * First look at the ELF header magic field, then make sure that it is
>>> + * executable.
>>> + */
>>> +int valid_elf_image(unsigned long addr)
>>> +{
>>> +     Elf32_Ehdr *ehdr; /* Elf header structure pointer */
>>> +
>>> +     ehdr = (Elf32_Ehdr *)addr;
>>> +
>>> +     if (!IS_ELF(*ehdr)) {
>>> +             printf("## No elf image at address 0x%08lx\n", addr);
>>> +             return 0;
>>> +     }
>>> +
>>> +     if (ehdr->e_type != ET_EXEC) {
>>> +             printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
>>> +             return 0;
>>> +     }
>>> +
>>> +     return 1;
>>> +}
>>>
diff mbox series

Patch

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 298feae24d..6f4f08d02a 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -375,6 +375,7 @@  config CMD_ADTIMG
 config CMD_ELF
 	bool "bootelf, bootvx"
 	default y
+	select ELF
 	help
 	  Boot an ELF/vxWorks image from the memory.
 
diff --git a/cmd/elf.c b/cmd/elf.c
index 32f12a72b9..23cc17aebc 100644
--- a/cmd/elf.c
+++ b/cmd/elf.c
@@ -26,211 +26,6 @@ 
 #include <linux/linkage.h>
 #endif
 
-/*
- * A very simple ELF64 loader, assumes the image is valid, returns the
- * entry point address.
- *
- * Note if U-Boot is 32-bit, the loader assumes the to segment's
- * physical address and size is within the lower 32-bit address space.
- */
-static unsigned long load_elf64_image_phdr(unsigned long addr)
-{
-	Elf64_Ehdr *ehdr; /* Elf header structure pointer */
-	Elf64_Phdr *phdr; /* Program header structure pointer */
-	int i;
-
-	ehdr = (Elf64_Ehdr *)addr;
-	phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
-
-	/* Load each program header */
-	for (i = 0; i < ehdr->e_phnum; ++i) {
-		void *dst = (void *)(ulong)phdr->p_paddr;
-		void *src = (void *)addr + phdr->p_offset;
-
-		debug("Loading phdr %i to 0x%p (%lu bytes)\n",
-		      i, dst, (ulong)phdr->p_filesz);
-		if (phdr->p_filesz)
-			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);
-		flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
-			    roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
-		++phdr;
-	}
-
-	if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
-					    EF_PPC64_ELFV1_ABI)) {
-		/*
-		 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
-		 * descriptor pointer with the first double word being the
-		 * address of the entry point of the function.
-		 */
-		uintptr_t addr = ehdr->e_entry;
-
-		return *(Elf64_Addr *)addr;
-	}
-
-	return ehdr->e_entry;
-}
-
-static unsigned long load_elf64_image_shdr(unsigned long addr)
-{
-	Elf64_Ehdr *ehdr; /* Elf header structure pointer */
-	Elf64_Shdr *shdr; /* Section header structure pointer */
-	unsigned char *strtab = 0; /* String table pointer */
-	unsigned char *image; /* Binary image pointer */
-	int i; /* Loop counter */
-
-	ehdr = (Elf64_Ehdr *)addr;
-
-	/* Find the section header string table for output info */
-	shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
-			     (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
-
-	if (shdr->sh_type == SHT_STRTAB)
-		strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
-
-	/* Load each appropriate section */
-	for (i = 0; i < ehdr->e_shnum; ++i) {
-		shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
-				     (i * sizeof(Elf64_Shdr)));
-
-		if (!(shdr->sh_flags & SHF_ALLOC) ||
-		    shdr->sh_addr == 0 || shdr->sh_size == 0) {
-			continue;
-		}
-
-		if (strtab) {
-			debug("%sing %s @ 0x%08lx (%ld bytes)\n",
-			      (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
-			       &strtab[shdr->sh_name],
-			       (unsigned long)shdr->sh_addr,
-			       (long)shdr->sh_size);
-		}
-
-		if (shdr->sh_type == SHT_NOBITS) {
-			memset((void *)(uintptr_t)shdr->sh_addr, 0,
-			       shdr->sh_size);
-		} else {
-			image = (unsigned char *)addr + (ulong)shdr->sh_offset;
-			memcpy((void *)(uintptr_t)shdr->sh_addr,
-			       (const void *)image, shdr->sh_size);
-		}
-		flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
-			    roundup((shdr->sh_addr + shdr->sh_size),
-				     ARCH_DMA_MINALIGN) -
-			            rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
-	}
-
-	if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
-					    EF_PPC64_ELFV1_ABI)) {
-		/*
-		 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
-		 * descriptor pointer with the first double word being the
-		 * address of the entry point of the function.
-		 */
-		uintptr_t addr = ehdr->e_entry;
-
-		return *(Elf64_Addr *)addr;
-	}
-
-	return ehdr->e_entry;
-}
-
-/*
- * A very simple ELF loader, assumes the image is valid, returns the
- * entry point address.
- *
- * The loader firstly reads the EFI class to see if it's a 64-bit image.
- * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
- */
-static unsigned long load_elf_image_phdr(unsigned long addr)
-{
-	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
-	Elf32_Phdr *phdr; /* Program header structure pointer */
-	int i;
-
-	ehdr = (Elf32_Ehdr *)addr;
-	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
-		return load_elf64_image_phdr(addr);
-
-	phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
-
-	/* Load each program header */
-	for (i = 0; i < ehdr->e_phnum; ++i) {
-		void *dst = (void *)(uintptr_t)phdr->p_paddr;
-		void *src = (void *)addr + phdr->p_offset;
-
-		debug("Loading phdr %i to 0x%p (%i bytes)\n",
-		      i, dst, phdr->p_filesz);
-		if (phdr->p_filesz)
-			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);
-		flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
-			    roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
-		++phdr;
-	}
-
-	return ehdr->e_entry;
-}
-
-static unsigned long load_elf_image_shdr(unsigned long addr)
-{
-	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
-	Elf32_Shdr *shdr; /* Section header structure pointer */
-	unsigned char *strtab = 0; /* String table pointer */
-	unsigned char *image; /* Binary image pointer */
-	int i; /* Loop counter */
-
-	ehdr = (Elf32_Ehdr *)addr;
-	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
-		return load_elf64_image_shdr(addr);
-
-	/* Find the section header string table for output info */
-	shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
-			     (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
-
-	if (shdr->sh_type == SHT_STRTAB)
-		strtab = (unsigned char *)(addr + shdr->sh_offset);
-
-	/* Load each appropriate section */
-	for (i = 0; i < ehdr->e_shnum; ++i) {
-		shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
-				     (i * sizeof(Elf32_Shdr)));
-
-		if (!(shdr->sh_flags & SHF_ALLOC) ||
-		    shdr->sh_addr == 0 || shdr->sh_size == 0) {
-			continue;
-		}
-
-		if (strtab) {
-			debug("%sing %s @ 0x%08lx (%ld bytes)\n",
-			      (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
-			       &strtab[shdr->sh_name],
-			       (unsigned long)shdr->sh_addr,
-			       (long)shdr->sh_size);
-		}
-
-		if (shdr->sh_type == SHT_NOBITS) {
-			memset((void *)(uintptr_t)shdr->sh_addr, 0,
-			       shdr->sh_size);
-		} else {
-			image = (unsigned char *)addr + shdr->sh_offset;
-			memcpy((void *)(uintptr_t)shdr->sh_addr,
-			       (const void *)image, shdr->sh_size);
-		}
-		flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
-			    roundup((shdr->sh_addr + shdr->sh_size),
-				    ARCH_DMA_MINALIGN) -
-			    rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
-	}
-
-	return ehdr->e_entry;
-}
-
 /* Allow ports to override the default behavior */
 static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
 				     int argc, char * const argv[])
@@ -246,30 +41,6 @@  static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
 	return ret;
 }
 
-/*
- * Determine if a valid ELF image exists at the given memory location.
- * First look at the ELF header magic field, then make sure that it is
- * executable.
- */
-int valid_elf_image(unsigned long addr)
-{
-	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
-
-	ehdr = (Elf32_Ehdr *)addr;
-
-	if (!IS_ELF(*ehdr)) {
-		printf("## No elf image at address 0x%08lx\n", addr);
-		return 0;
-	}
-
-	if (ehdr->e_type != ET_EXEC) {
-		printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
-		return 0;
-	}
-
-	return 1;
-}
-
 /* Interpreter command to boot an arbitrary ELF image from memory */
 int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
diff --git a/include/elf.h b/include/elf.h
index 81f40191d7..e7c51986df 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -692,6 +692,10 @@  unsigned long elf_hash(const unsigned char *name);
 
 #ifndef __ASSEMBLER__
 int valid_elf_image(unsigned long addr);
+unsigned long load_elf64_image_phdr(unsigned long addr);
+unsigned long load_elf64_image_shdr(unsigned long addr);
+unsigned long load_elf_image_phdr(unsigned long addr);
+unsigned long load_elf_image_shdr(unsigned long addr);
 #endif
 
 #endif /* _ELF_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index d040a87d26..b155ced4b2 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -601,4 +601,7 @@  config TEST_FDTDEC
 config LIB_DATE
 	bool
 
+config ELF
+	bool "enable basic elf loading/validating functions"
+
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 6b7b9ce85c..93f22d210e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -121,6 +121,7 @@  obj-y += vsprintf.o strto.o
 endif
 
 obj-y += date.o
+obj-$(CONFIG_ELF) += elf.o
 
 #
 # Build a fast OID lookup registry from include/linux/oid_registry.h
diff --git a/lib/elf.c b/lib/elf.c
new file mode 100644
index 0000000000..54ac4ee502
--- /dev/null
+++ b/lib/elf.c
@@ -0,0 +1,256 @@ 
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <cpu_func.h>
+#include <elf.h>
+#include <env.h>
+#include <net.h>
+#include <vxworks.h>
+#ifdef CONFIG_X86
+#include <vbe.h>
+#include <asm/e820.h>
+#include <linux/linkage.h>
+#endif
+
+/*
+ * A very simple ELF64 loader, assumes the image is valid, returns the
+ * entry point address.
+ *
+ * Note if U-Boot is 32-bit, the loader assumes the to segment's
+ * physical address and size is within the lower 32-bit address space.
+ */
+unsigned long load_elf64_image_phdr(unsigned long addr)
+{
+	Elf64_Ehdr *ehdr; /* Elf header structure pointer */
+	Elf64_Phdr *phdr; /* Program header structure pointer */
+	int i;
+
+	ehdr = (Elf64_Ehdr *)addr;
+	phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
+
+	/* Load each program header */
+	for (i = 0; i < ehdr->e_phnum; ++i) {
+		void *dst = (void *)(ulong)phdr->p_paddr;
+		void *src = (void *)addr + phdr->p_offset;
+
+		debug("Loading phdr %i to 0x%p (%lu bytes)\n",
+		      i, dst, (ulong)phdr->p_filesz);
+		if (phdr->p_filesz)
+			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);
+		flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
+			    roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
+		++phdr;
+	}
+
+	if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
+					    EF_PPC64_ELFV1_ABI)) {
+		/*
+		 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
+		 * descriptor pointer with the first double word being the
+		 * address of the entry point of the function.
+		 */
+		uintptr_t addr = ehdr->e_entry;
+
+		return *(Elf64_Addr *)addr;
+	}
+
+	return ehdr->e_entry;
+}
+
+unsigned long load_elf64_image_shdr(unsigned long addr)
+{
+	Elf64_Ehdr *ehdr; /* Elf header structure pointer */
+	Elf64_Shdr *shdr; /* Section header structure pointer */
+	unsigned char *strtab = 0; /* String table pointer */
+	unsigned char *image; /* Binary image pointer */
+	int i; /* Loop counter */
+
+	ehdr = (Elf64_Ehdr *)addr;
+
+	/* Find the section header string table for output info */
+	shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
+			     (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
+
+	if (shdr->sh_type == SHT_STRTAB)
+		strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
+
+	/* Load each appropriate section */
+	for (i = 0; i < ehdr->e_shnum; ++i) {
+		shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
+				     (i * sizeof(Elf64_Shdr)));
+
+		if (!(shdr->sh_flags & SHF_ALLOC) ||
+		    shdr->sh_addr == 0 || shdr->sh_size == 0) {
+			continue;
+		}
+
+		if (strtab) {
+			debug("%sing %s @ 0x%08lx (%ld bytes)\n",
+			      (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
+			       &strtab[shdr->sh_name],
+			       (unsigned long)shdr->sh_addr,
+			       (long)shdr->sh_size);
+		}
+
+		if (shdr->sh_type == SHT_NOBITS) {
+			memset((void *)(uintptr_t)shdr->sh_addr, 0,
+			       shdr->sh_size);
+		} else {
+			image = (unsigned char *)addr + (ulong)shdr->sh_offset;
+			memcpy((void *)(uintptr_t)shdr->sh_addr,
+			       (const void *)image, shdr->sh_size);
+		}
+		flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
+			    roundup((shdr->sh_addr + shdr->sh_size),
+				     ARCH_DMA_MINALIGN) -
+			            rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
+	}
+
+	if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
+					    EF_PPC64_ELFV1_ABI)) {
+		/*
+		 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
+		 * descriptor pointer with the first double word being the
+		 * address of the entry point of the function.
+		 */
+		uintptr_t addr = ehdr->e_entry;
+
+		return *(Elf64_Addr *)addr;
+	}
+
+	return ehdr->e_entry;
+}
+
+/*
+ * A very simple ELF loader, assumes the image is valid, returns the
+ * entry point address.
+ *
+ * The loader firstly reads the EFI class to see if it's a 64-bit image.
+ * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
+ */
+unsigned long load_elf_image_phdr(unsigned long addr)
+{
+	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
+	Elf32_Phdr *phdr; /* Program header structure pointer */
+	int i;
+
+	ehdr = (Elf32_Ehdr *)addr;
+	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
+		return load_elf64_image_phdr(addr);
+
+	phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
+
+	/* Load each program header */
+	for (i = 0; i < ehdr->e_phnum; ++i) {
+		void *dst = (void *)(uintptr_t)phdr->p_paddr;
+		void *src = (void *)addr + phdr->p_offset;
+
+		debug("Loading phdr %i to 0x%p (%i bytes)\n",
+		      i, dst, phdr->p_filesz);
+		if (phdr->p_filesz)
+			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);
+		flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
+			    roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
+		++phdr;
+	}
+
+	return ehdr->e_entry;
+}
+
+unsigned long load_elf_image_shdr(unsigned long addr)
+{
+	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
+	Elf32_Shdr *shdr; /* Section header structure pointer */
+	unsigned char *strtab = 0; /* String table pointer */
+	unsigned char *image; /* Binary image pointer */
+	int i; /* Loop counter */
+
+	ehdr = (Elf32_Ehdr *)addr;
+	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
+		return load_elf64_image_shdr(addr);
+
+	/* Find the section header string table for output info */
+	shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
+			     (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
+
+	if (shdr->sh_type == SHT_STRTAB)
+		strtab = (unsigned char *)(addr + shdr->sh_offset);
+
+	/* Load each appropriate section */
+	for (i = 0; i < ehdr->e_shnum; ++i) {
+		shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
+				     (i * sizeof(Elf32_Shdr)));
+
+		if (!(shdr->sh_flags & SHF_ALLOC) ||
+		    shdr->sh_addr == 0 || shdr->sh_size == 0) {
+			continue;
+		}
+
+		if (strtab) {
+			debug("%sing %s @ 0x%08lx (%ld bytes)\n",
+			      (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
+			       &strtab[shdr->sh_name],
+			       (unsigned long)shdr->sh_addr,
+			       (long)shdr->sh_size);
+		}
+
+		if (shdr->sh_type == SHT_NOBITS) {
+			memset((void *)(uintptr_t)shdr->sh_addr, 0,
+			       shdr->sh_size);
+		} else {
+			image = (unsigned char *)addr + shdr->sh_offset;
+			memcpy((void *)(uintptr_t)shdr->sh_addr,
+			       (const void *)image, shdr->sh_size);
+		}
+		flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
+			    roundup((shdr->sh_addr + shdr->sh_size),
+				    ARCH_DMA_MINALIGN) -
+			    rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
+	}
+
+	return ehdr->e_entry;
+}
+
+/*
+ * Determine if a valid ELF image exists at the given memory location.
+ * First look at the ELF header magic field, then make sure that it is
+ * executable.
+ */
+int valid_elf_image(unsigned long addr)
+{
+	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
+
+	ehdr = (Elf32_Ehdr *)addr;
+
+	if (!IS_ELF(*ehdr)) {
+		printf("## No elf image at address 0x%08lx\n", addr);
+		return 0;
+	}
+
+	if (ehdr->e_type != ET_EXEC) {
+		printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
+		return 0;
+	}
+
+	return 1;
+}