X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=common%2Fcmd_elf.c;h=8266bba0e6935063263e4db3bb8c983316be5731;hb=2fb563f2f52d3e4c59c8f0c0309ea6a65c558878;hp=4a3fff1e8609e02a5ab7bd6c7b0325aaae4d11ed;hpb=8206bfae3ab7f99965136384360ba2de0c6f4c3b;p=karo-tx-uboot.git diff --git a/common/cmd_elf.c b/common/cmd_elf.c index 4a3fff1e86..8266bba0e6 100644 --- a/common/cmd_elf.c +++ b/common/cmd_elf.c @@ -25,11 +25,13 @@ 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)) -unsigned long do_bootelf_exec (ulong (*entry)(int, char *[]), int argc, char *argv[]) +unsigned long do_bootelf_exec (ulong (*entry)(int, char * const[]), + int argc, char * const argv[]) { unsigned long ret; @@ -56,23 +58,38 @@ unsigned long do_bootelf_exec (ulong (*entry)(int, char *[]), int argc, char *ar /* ====================================================================== * Interpreter command to boot an arbitrary ELF image from memory. * ====================================================================== */ -int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +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); @@ -93,7 +110,7 @@ int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) * be either an ELF image or a raw binary. Will attempt to setup the * bootline and other parameters correctly. * ====================================================================== */ -int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned long addr; /* Address of image */ unsigned long bootaddr; /* Address to put the bootline */ @@ -116,10 +133,10 @@ int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) /* Check to see if we need to tftp the image ourselves before starting */ if ((argc == 2) && (strcmp (argv[1], "tftp") == 0)) { - if (NetLoop (TFTP) <= 0) + if (NetLoop(TFTPGET) <= 0) return 1; - printf ("Automatic boot of VxWorks image at address 0x%08lx ... \n", - addr); + printf("Automatic boot of VxWorks image at address 0x%08lx " + "...\n", addr); } #endif @@ -131,11 +148,11 @@ int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_WALNUT) tmp = (char *) CONFIG_SYS_NVRAM_BASE_ADDR + 0x500; - eth_getenv_enetaddr("ethaddr", build_buf); + eth_getenv_enetaddr("ethaddr", (uchar *)build_buf); memcpy(tmp, &build_buf[3], 3); #elif defined(CONFIG_SYS_VXWORKS_MAC_PTR) tmp = (char *) CONFIG_SYS_VXWORKS_MAC_PTR; - eth_getenv_enetaddr("ethaddr", build_buf); + eth_getenv_enetaddr("ethaddr", (uchar *)build_buf); memcpy(tmp, build_buf, 6); #else puts ("## Ethernet MAC address not copied to NV RAM\n"); @@ -203,7 +220,7 @@ int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *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 */ @@ -213,7 +230,8 @@ int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) (char *) bootaddr); printf ("## Starting vxWorks at 0x%08lx ...\n", addr); - ((void (*)(void)) addr) (); + dcache_disable(); + ((void (*)(int)) addr) (0); puts ("## vxWorks terminated\n"); return 1; @@ -257,7 +275,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 */ @@ -287,7 +331,7 @@ unsigned long load_elf_image (unsigned long addr) } if (strtab) { - printf ("%sing %s @ 0x%08lx (%ld bytes)\n", + debug("%sing %s @ 0x%08lx (%ld bytes)\n", (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", &strtab[shdr->sh_name], @@ -311,13 +355,15 @@ 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.\n" + "[-p|-s] [address]\n" + "\t- load ELF image at [address] via program headers (-p)\n" + "\t or via section headers (-s)" ); U_BOOT_CMD( bootvx, 2, 0, do_bootvx, "Boot vxWorks from an ELF image", - " [address] - load address of vxWorks ELF image.\n" + " [address] - load address of vxWorks ELF image." );