1// SPDX-License-Identifier: BSD-2-Clause 2/* 3 Copyright (c) 2001 William L. Pitts 4*/ 5 6#include <command.h> 7#include <cpu_func.h> 8#include <elf.h> 9#include <env.h> 10#include <net.h> 11#include <vxworks.h> 12#ifdef CONFIG_X86 13#include <vesa.h> 14#include <asm/e820.h> 15#include <linux/linkage.h> 16#endif 17 18/* 19 * A very simple ELF64 loader, assumes the image is valid, returns the 20 * entry point address. 21 * 22 * Note if U-Boot is 32-bit, the loader assumes the to segment's 23 * physical address and size is within the lower 32-bit address space. 24 */ 25unsigned long load_elf64_image_phdr(unsigned long addr) 26{ 27 Elf64_Ehdr *ehdr; /* Elf header structure pointer */ 28 Elf64_Phdr *phdr; /* Program header structure pointer */ 29 int i; 30 31 ehdr = (Elf64_Ehdr *)addr; 32 phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff); 33 34 /* Load each program header */ 35 for (i = 0; i < ehdr->e_phnum; ++i) { 36 void *dst = (void *)(ulong)phdr->p_paddr; 37 void *src = (void *)addr + phdr->p_offset; 38 39 debug("Loading phdr %i to 0x%p (%lu bytes)\n", 40 i, dst, (ulong)phdr->p_filesz); 41 if (phdr->p_filesz) 42 memcpy(dst, src, phdr->p_filesz); 43 if (phdr->p_filesz != phdr->p_memsz) 44 memset(dst + phdr->p_filesz, 0x00, 45 phdr->p_memsz - phdr->p_filesz); 46 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), 47 roundup(phdr->p_memsz, ARCH_DMA_MINALIGN)); 48 ++phdr; 49 } 50 51 if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags & 52 EF_PPC64_ELFV1_ABI)) { 53 /* 54 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function 55 * descriptor pointer with the first double word being the 56 * address of the entry point of the function. 57 */ 58 uintptr_t addr = ehdr->e_entry; 59 60 return *(Elf64_Addr *)addr; 61 } 62 63 return ehdr->e_entry; 64} 65 66unsigned long load_elf64_image_shdr(unsigned long addr) 67{ 68 Elf64_Ehdr *ehdr; /* Elf header structure pointer */ 69 Elf64_Shdr *shdr; /* Section header structure pointer */ 70 unsigned char *strtab = 0; /* String table pointer */ 71 unsigned char *image; /* Binary image pointer */ 72 int i; /* Loop counter */ 73 74 ehdr = (Elf64_Ehdr *)addr; 75 76 /* Find the section header string table for output info */ 77 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff + 78 (ehdr->e_shstrndx * sizeof(Elf64_Shdr))); 79 80 if (shdr->sh_type == SHT_STRTAB) 81 strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset); 82 83 /* Load each appropriate section */ 84 for (i = 0; i < ehdr->e_shnum; ++i) { 85 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff + 86 (i * sizeof(Elf64_Shdr))); 87 88 if (!(shdr->sh_flags & SHF_ALLOC) || 89 shdr->sh_addr == 0 || shdr->sh_size == 0) { 90 continue; 91 } 92 93 if (strtab) { 94 debug("%sing %s @ 0x%08lx (%ld bytes)\n", 95 (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", 96 &strtab[shdr->sh_name], 97 (unsigned long)shdr->sh_addr, 98 (long)shdr->sh_size); 99 } 100 101 if (shdr->sh_type == SHT_NOBITS) { 102 memset((void *)(uintptr_t)shdr->sh_addr, 0, 103 shdr->sh_size); 104 } else { 105 image = (unsigned char *)addr + (ulong)shdr->sh_offset; 106 memcpy((void *)(uintptr_t)shdr->sh_addr, 107 (const void *)image, shdr->sh_size); 108 } 109 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN), 110 roundup((shdr->sh_addr + shdr->sh_size), 111 ARCH_DMA_MINALIGN) - 112 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN)); 113 } 114 115 if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags & 116 EF_PPC64_ELFV1_ABI)) { 117 /* 118 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function 119 * descriptor pointer with the first double word being the 120 * address of the entry point of the function. 121 */ 122 uintptr_t addr = ehdr->e_entry; 123 124 return *(Elf64_Addr *)addr; 125 } 126 127 return ehdr->e_entry; 128} 129 130/* 131 * A very simple ELF loader, assumes the image is valid, returns the 132 * entry point address. 133 * 134 * The loader firstly reads the EFI class to see if it's a 64-bit image. 135 * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader. 136 */ 137unsigned long load_elf_image_phdr(unsigned long addr) 138{ 139 Elf32_Ehdr *ehdr; /* Elf header structure pointer */ 140 Elf32_Phdr *phdr; /* Program header structure pointer */ 141 int i; 142 143 ehdr = (Elf32_Ehdr *)addr; 144 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) 145 return load_elf64_image_phdr(addr); 146 147 phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); 148 149 /* Load each program header */ 150 for (i = 0; i < ehdr->e_phnum; ++i) { 151 void *dst = (void *)(uintptr_t)phdr->p_paddr; 152 void *src = (void *)addr + phdr->p_offset; 153 154 debug("Loading phdr %i to 0x%p (%i bytes)\n", 155 i, dst, phdr->p_filesz); 156 if (phdr->p_filesz) 157 memcpy(dst, src, phdr->p_filesz); 158 if (phdr->p_filesz != phdr->p_memsz) 159 memset(dst + phdr->p_filesz, 0x00, 160 phdr->p_memsz - phdr->p_filesz); 161 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), 162 roundup(phdr->p_memsz, ARCH_DMA_MINALIGN)); 163 ++phdr; 164 } 165 166 return ehdr->e_entry; 167} 168 169unsigned long load_elf_image_shdr(unsigned long addr) 170{ 171 Elf32_Ehdr *ehdr; /* Elf header structure pointer */ 172 Elf32_Shdr *shdr; /* Section header structure pointer */ 173 unsigned char *strtab = 0; /* String table pointer */ 174 unsigned char *image; /* Binary image pointer */ 175 int i; /* Loop counter */ 176 177 ehdr = (Elf32_Ehdr *)addr; 178 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) 179 return load_elf64_image_shdr(addr); 180 181 /* Find the section header string table for output info */ 182 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + 183 (ehdr->e_shstrndx * sizeof(Elf32_Shdr))); 184 185 if (shdr->sh_type == SHT_STRTAB) 186 strtab = (unsigned char *)(addr + shdr->sh_offset); 187 188 /* Load each appropriate section */ 189 for (i = 0; i < ehdr->e_shnum; ++i) { 190 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + 191 (i * sizeof(Elf32_Shdr))); 192 193 if (!(shdr->sh_flags & SHF_ALLOC) || 194 shdr->sh_addr == 0 || shdr->sh_size == 0) { 195 continue; 196 } 197 198 if (strtab) { 199 debug("%sing %s @ 0x%08lx (%ld bytes)\n", 200 (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", 201 &strtab[shdr->sh_name], 202 (unsigned long)shdr->sh_addr, 203 (long)shdr->sh_size); 204 } 205 206 if (shdr->sh_type == SHT_NOBITS) { 207 memset((void *)(uintptr_t)shdr->sh_addr, 0, 208 shdr->sh_size); 209 } else { 210 image = (unsigned char *)addr + shdr->sh_offset; 211 memcpy((void *)(uintptr_t)shdr->sh_addr, 212 (const void *)image, shdr->sh_size); 213 } 214 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN), 215 roundup((shdr->sh_addr + shdr->sh_size), 216 ARCH_DMA_MINALIGN) - 217 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN)); 218 } 219 220 return ehdr->e_entry; 221} 222 223/* 224 * Determine if a valid ELF image exists at the given memory location. 225 * First look at the ELF header magic field, then make sure that it is 226 * executable. 227 */ 228int valid_elf_image(unsigned long addr) 229{ 230 Elf32_Ehdr *ehdr; /* Elf header structure pointer */ 231 232 ehdr = (Elf32_Ehdr *)addr; 233 234 if (!IS_ELF(*ehdr)) { 235 printf("## No elf image at address 0x%08lx\n", addr); 236 return 0; 237 } 238 239 if (ehdr->e_type != ET_EXEC) { 240 printf("## Not a 32-bit elf image at address 0x%08lx\n", addr); 241 return 0; 242 } 243 244 return 1; 245} 246