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