aboutsummaryrefslogtreecommitdiff
path: root/common/cmd_elf.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2010-10-02 15:44:53 -0400
committerWolfgang Denk <wd@denx.de>2010-10-06 22:42:14 +0200
commitf44a928e7ea0912f278f2cf8ba1354fccf2ba64e (patch)
treea1ae2a93af5f79f7b3893c9a36803ece28c6ebf4 /common/cmd_elf.c
parent76221a6cfaac9ff2680bfddde6d7d271ff70d7a0 (diff)
cmd_elf: add an option for loading ELFs according to PHDRs
The current ELF loading function does a lot of work above and beyond a simple "loading". It ignores the real load addresses and loads things into their virtual (runtime) address. This is undesirable when we just want it to load an ELF and let the ELF do the actual C runtime init. So add a command line option to let people choose to load via either the program or section headers. I'd prefer to have program header loading be the default, but this would break historical behavior, so I'll leave section header loading as the norm. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'common/cmd_elf.c')
-rw-r--r--common/cmd_elf.c62
1 files changed, 53 insertions, 9 deletions
diff --git a/common/cmd_elf.c b/common/cmd_elf.c
index 104d6e68b..bf3261256 100644
--- a/common/cmd_elf.c
+++ b/common/cmd_elf.c
@@ -25,7 +25,8 @@ DECLARE_GLOBAL_DATA_PTR;
#endif
int valid_elf_image (unsigned long addr);
-unsigned long load_elf_image (unsigned long addr);
+static unsigned long load_elf_image_phdr(unsigned long addr);
+static unsigned long load_elf_image_shdr(unsigned long addr);
/* Allow ports to override the default behavior */
__attribute__((weak))
@@ -61,19 +62,34 @@ int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned long addr; /* Address of the ELF image */
unsigned long rc; /* Return value from user code */
+ char *sload, *saddr;
/* -------------------------------------------------- */
int rcode = 0;
- if (argc < 2)
- addr = load_addr;
+ sload = saddr = NULL;
+ if (argc == 3) {
+ sload = argv[1];
+ saddr = argv[2];
+ } else if (argc == 2) {
+ if (argv[1][0] == '-')
+ sload = argv[1];
+ else
+ saddr = argv[1];
+ }
+
+ if (saddr)
+ addr = simple_strtoul(saddr, NULL, 16);
else
- addr = simple_strtoul (argv[1], NULL, 16);
+ addr = load_addr;
if (!valid_elf_image (addr))
return 1;
- addr = load_elf_image (addr);
+ if (sload && sload[1] == 'p')
+ addr = load_elf_image_phdr(addr);
+ else
+ addr = load_elf_image_shdr(addr);
printf ("## Starting application at 0x%08lx ...\n", addr);
@@ -204,7 +220,7 @@ int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
*/
if (valid_elf_image (addr)) {
- addr = load_elf_image (addr);
+ addr = load_elf_image_shdr (addr);
} else {
puts ("## Not an ELF image, assuming binary\n");
/* leave addr as load_addr */
@@ -258,7 +274,33 @@ int valid_elf_image (unsigned long addr)
* A very simple elf loader, assumes the image is valid, returns the
* entry point address.
* ====================================================================== */
-unsigned long load_elf_image (unsigned long addr)
+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;
+ phdr = (Elf32_Phdr *) (addr + ehdr->e_phoff);
+
+ /* Load each program header */
+ for (i = 0; i < ehdr->e_phnum; ++i) {
+ void *dst = (void *) 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((unsigned long)dst, phdr->p_filesz);
+ ++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 */
@@ -312,9 +354,11 @@ unsigned long load_elf_image (unsigned long addr)
/* ====================================================================== */
U_BOOT_CMD(
- bootelf, 2, 0, do_bootelf,
+ bootelf, 3, 0, do_bootelf,
"Boot from an ELF image in memory",
- " [address] - load address of ELF image."
+ "[-p|-s] [address]\n"
+ "\t- load ELF image at [address] via program headers (-p)\n"
+ "\t or via section headers (-s)"
);
U_BOOT_CMD(