X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=cmd%2Felf.c;h=10e8264d3c7d14e5e09ed5ed3511848b4e7458ee;hb=ca0c52710c14e9d38f8e493625a3a51147ebddcc;hp=19479bb706e06c9ccd97f6c855e39d54778c7c5e;hpb=3194daa10ba642269a0948282423c48fd02fadce;p=oweals%2Fu-boot.git diff --git a/cmd/elf.c b/cmd/elf.c index 19479bb706..10e8264d3c 100644 --- a/cmd/elf.c +++ b/cmd/elf.c @@ -1,109 +1,23 @@ +// 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 #ifdef CONFIG_X86 +#include #include #include #endif -/* - * A very simple elf loader, assumes the image is valid, returns the - * entry point address. - */ -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 *)(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[]) @@ -119,30 +33,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[]) { @@ -167,7 +57,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; @@ -203,14 +93,17 @@ int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const 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 */ + 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 */ int ptr = 0; #ifdef CONFIG_X86 - struct e820info *info; - struct e820entry *data; + ulong base; + struct e820_info *info; + struct e820_entry *data; + struct efi_gop_info *gop; + struct vesa_mode_info *vesa = &mode_info.vesa; #endif /* @@ -218,7 +111,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); @@ -249,6 +142,45 @@ 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 +#ifdef CONFIG_X86 + /* + * Get VxWorks's physical memory base address from environment, + * if we don't specify it in the environment, use a default one. + */ + base = env_get_hex("vx_phys_mem_base", VXWORKS_PHYS_MEM_BASE); + data = (struct e820_entry *)(base + E820_DATA_OFFSET); + info = (struct e820_info *)(base + E820_INFO_OFFSET); + + memset(info, 0, sizeof(struct e820_info)); + info->sign = E820_SIGNATURE; + info->entries = install_e820_map(E820MAX, data); + info->addr = (info->entries - 1) * sizeof(struct e820_entry) + + E820_DATA_OFFSET; + + /* + * Explicitly clear the bootloader image size otherwise if memory + * at this offset happens to contain some garbage data, the final + * available memory size for the kernel is insane. + */ + *(u32 *)(base + BOOT_IMAGE_SIZE_OFFSET) = 0; + + /* + * Prepare compatible framebuffer information block. + * The VESA mode has to be 32-bit RGBA. + */ + if (vesa->x_resolution && vesa->y_resolution) { + gop = (struct efi_gop_info *)(base + EFI_GOP_INFO_OFFSET); + gop->magic = EFI_GOP_INFO_MAGIC; + gop->info.version = 0; + gop->info.width = vesa->x_resolution; + gop->info.height = vesa->y_resolution; + gop->info.pixel_format = EFI_GOT_RGBA8; + gop->info.pixels_per_scanline = vesa->bytes_per_scanline / 4; + gop->fb_base = vesa->phys_base_ptr; + gop->fb_size = vesa->bytes_per_scanline * vesa->y_resolution; + } +#endif + /* * Use bootaddr to find the location in memory that VxWorks * will look for the bootline string. The default value is @@ -257,104 +189,78 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) */ tmp = env_get("bootaddr"); if (!tmp) { +#ifdef CONFIG_X86 + bootaddr = base + X86_BOOT_LINE_OFFSET; +#else printf("## VxWorks bootline address not specified\n"); - } else { + 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) { - memcpy((void *)bootaddr, bootline, - max(strlen(bootline), (size_t)255)); - flush_cache(bootaddr, max(strlen(bootline), - (size_t)255)); + /* + * 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 { - tmp = env_get("bootdev"); - if (tmp) { - strcpy(build_buf, tmp); - ptr = strlen(tmp); - } else - printf("## VxWorks boot device not specified\n"); + 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 "); + 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"); + /* + * 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) { - 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, " "); - } + 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("serverip"); + if (tmp) + ptr += sprintf(build_buf + ptr, "h=%s ", tmp); - tmp = env_get("hostname"); - if (tmp) - ptr += sprintf(build_buf + ptr, "tn=%s ", tmp); + tmp = env_get("gatewayip"); + if (tmp) + ptr += sprintf(build_buf + ptr, "g=%s ", tmp); - tmp = env_get("othbootargs"); - if (tmp) { - strcpy(build_buf + ptr, tmp); - ptr += strlen(tmp); - } + tmp = env_get("hostname"); + if (tmp) + ptr += sprintf(build_buf + ptr, "tn=%s ", tmp); - memcpy((void *)bootaddr, build_buf, - max(strlen(build_buf), (size_t)255)); - flush_cache(bootaddr, max(strlen(build_buf), - (size_t)255)); + tmp = env_get("othbootargs"); + if (tmp) { + strcpy(build_buf + ptr, tmp); + ptr += strlen(tmp); } - printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, - (char *)bootaddr); + bootline = build_buf; } -#ifdef CONFIG_X86 - /* - * Since E820 information is critical to the kernel, if we don't - * specify these in the environments, use a default one. - */ - tmp = env_get("e820data"); - if (tmp) - data = (struct e820entry *)simple_strtoul(tmp, NULL, 16); - else - data = (struct e820entry *)VXWORKS_E820_DATA_ADDR; - tmp = env_get("e820info"); - if (tmp) - info = (struct e820info *)simple_strtoul(tmp, NULL, 16); - else - info = (struct e820info *)VXWORKS_E820_INFO_ADDR; - - memset(info, 0, sizeof(struct e820info)); - info->sign = E820_SIGNATURE; - info->entries = install_e820_map(E820MAX, data); - info->addr = (info->entries - 1) * sizeof(struct e820entry) + - VXWORKS_E820_DATA_ADDR; -#endif + 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