
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@ti.com Suggested-by: Simon Goldschmidt simon.k.r.goldschmidt@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;
+}