diff options
| -rw-r--r-- | common/cmd_elf.c | 62 | 
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( |