X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=cmd%2Felf.c;h=d44b95d90339e7d9c6b54a16a557c50db36d2b15;hb=ebdd07f5b2e4b00eee7f8630b3b026a65c3f51c4;hp=30c845833b6f6030545bb33a273f061867e0b3c1;hpb=447ae4f7adb2c667eec1e0861e2346694c57a2e0;p=oweals%2Fu-boot.git diff --git a/cmd/elf.c b/cmd/elf.c index 30c845833b..d44b95d903 100644 --- a/cmd/elf.c +++ b/cmd/elf.c @@ -1,155 +1,28 @@ +// SPDX-License-Identifier: BSD-2-Clause /* * 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 #include +#include #include -#include +#include +#include +#include #include #include #ifdef CONFIG_X86 #include +#include #include #include #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((unsigned long)dst, phdr->p_filesz); - ++phdr; - } - - 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((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 */ - unsigned char *strtab = 0; /* String table pointer */ - unsigned char *image; /* Binary image pointer */ - int i; /* Loop counter */ - - ehdr = (Elf32_Ehdr *)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(shdr->sh_addr, shdr->sh_size); - } - - 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[]) + int argc, char *const argv[]) { unsigned long ret; @@ -162,32 +35,8 @@ 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[]) +int do_bootelf(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { unsigned long addr; /* Address of the ELF image */ unsigned long rc; /* Return value from user code */ @@ -210,7 +59,7 @@ int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* Consume address */ argc--; argv++; } else - addr = load_addr; + addr = image_load_addr; if (!valid_elf_image(addr)) return 1; @@ -243,10 +92,10 @@ int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const 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 * const argv[]) +int do_bootvx(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { unsigned long addr; /* Address of image */ - unsigned long bootaddr; /* Address to put the bootline */ + unsigned long bootaddr = 0; /* Address to put the bootline */ char *bootline; /* Text of the bootline */ char *tmp; /* Temporary char pointer */ char build_buf[128]; /* Buffer for building the bootline */ @@ -264,7 +113,7 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * If we don't know where the image is then we're done. */ if (argc < 2) - addr = load_addr; + addr = image_load_addr; else addr = simple_strtoul(argv[1], NULL, 16); @@ -295,90 +144,6 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) puts("## Ethernet MAC address not copied to NV RAM\n"); #endif - /* - * Use bootaddr to find the location in memory that VxWorks - * will look for the bootline string. The default value is - * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by - * VxWorks BSP. For example, on PowerPC it defaults to 0x4200. - */ - tmp = env_get("bootaddr"); - if (!tmp) { - printf("## VxWorks bootline address not specified\n"); - } else { - bootaddr = simple_strtoul(tmp, NULL, 16); - - /* - * Check to see if the bootline is defined in the 'bootargs' - * parameter. If it is not defined, we may be able to - * construct the info. - */ - bootline = env_get("bootargs"); - if (bootline) { - memcpy((void *)bootaddr, bootline, - max(strlen(bootline), (size_t)255)); - flush_cache(bootaddr, max(strlen(bootline), - (size_t)255)); - } else { - tmp = env_get("bootdev"); - if (tmp) { - strcpy(build_buf, tmp); - ptr = strlen(tmp); - } else - printf("## VxWorks boot device not specified\n"); - - tmp = env_get("bootfile"); - if (tmp) - ptr += sprintf(build_buf + ptr, - "host:%s ", tmp); - else - ptr += sprintf(build_buf + ptr, - "host:vxWorks "); - - /* - * The following parameters are only needed if 'bootdev' - * is an ethernet device, otherwise they are optional. - */ - tmp = env_get("ipaddr"); - if (tmp) { - ptr += sprintf(build_buf + ptr, "e=%s", tmp); - tmp = env_get("netmask"); - if (tmp) { - u32 mask = env_get_ip("netmask").s_addr; - ptr += sprintf(build_buf + ptr, - ":%08x ", ntohl(mask)); - } else { - ptr += sprintf(build_buf + ptr, " "); - } - } - - tmp = env_get("serverip"); - if (tmp) - ptr += sprintf(build_buf + ptr, "h=%s ", tmp); - - tmp = env_get("gatewayip"); - if (tmp) - ptr += sprintf(build_buf + ptr, "g=%s ", tmp); - - tmp = env_get("hostname"); - if (tmp) - ptr += sprintf(build_buf + ptr, "tn=%s ", tmp); - - tmp = env_get("othbootargs"); - if (tmp) { - strcpy(build_buf + ptr, tmp); - ptr += strlen(tmp); - } - - memcpy((void *)bootaddr, build_buf, - max(strlen(build_buf), (size_t)255)); - flush_cache(bootaddr, max(strlen(build_buf), - (size_t)255)); - } - - printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, - (char *)bootaddr); - } - #ifdef CONFIG_X86 /* * Get VxWorks's physical memory base address from environment, @@ -418,6 +183,87 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #endif + /* + * Use bootaddr to find the location in memory that VxWorks + * will look for the bootline string. The default value is + * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by + * VxWorks BSP. For example, on PowerPC it defaults to 0x4200. + */ + tmp = env_get("bootaddr"); + if (!tmp) { +#ifdef CONFIG_X86 + bootaddr = base + X86_BOOT_LINE_OFFSET; +#else + printf("## VxWorks bootline address not specified\n"); + return 1; +#endif + } + + if (!bootaddr) + bootaddr = simple_strtoul(tmp, NULL, 16); + + /* + * Check to see if the bootline is defined in the 'bootargs' parameter. + * If it is not defined, we may be able to construct the info. + */ + bootline = env_get("bootargs"); + if (!bootline) { + tmp = env_get("bootdev"); + if (tmp) { + strcpy(build_buf, tmp); + ptr = strlen(tmp); + } else { + printf("## VxWorks boot device not specified\n"); + } + + tmp = env_get("bootfile"); + if (tmp) + ptr += sprintf(build_buf + ptr, "host:%s ", tmp); + else + ptr += sprintf(build_buf + ptr, "host:vxWorks "); + + /* + * The following parameters are only needed if 'bootdev' + * is an ethernet device, otherwise they are optional. + */ + tmp = env_get("ipaddr"); + if (tmp) { + ptr += sprintf(build_buf + ptr, "e=%s", tmp); + tmp = env_get("netmask"); + if (tmp) { + u32 mask = env_get_ip("netmask").s_addr; + ptr += sprintf(build_buf + ptr, + ":%08x ", ntohl(mask)); + } else { + ptr += sprintf(build_buf + ptr, " "); + } + } + + tmp = env_get("serverip"); + if (tmp) + ptr += sprintf(build_buf + ptr, "h=%s ", tmp); + + tmp = env_get("gatewayip"); + if (tmp) + ptr += sprintf(build_buf + ptr, "g=%s ", tmp); + + tmp = env_get("hostname"); + if (tmp) + ptr += sprintf(build_buf + ptr, "tn=%s ", tmp); + + tmp = env_get("othbootargs"); + if (tmp) { + strcpy(build_buf + ptr, tmp); + ptr += strlen(tmp); + } + + bootline = build_buf; + } + + memcpy((void *)bootaddr, bootline, max(strlen(bootline), (size_t)255)); + flush_cache(bootaddr, max(strlen(bootline), (size_t)255)); + printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, (char *)bootaddr); + /* * If the data at the load address is an elf image, then * treat it like an elf image. Otherwise, assume that it is a