Message ID | 20200113055453.8812-2-j-keerthy@ti.com |
---|---|
State | Superseded |
Headers | show |
Series | k3: Add support for loading main_r5fss0_core0 | expand |
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; > +} >
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; > > +} > >
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 --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; +}
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