"Das U-Boot" Source Tree
at master 305 lines 8.4 kB view raw
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 <errno.h> 11#include <net.h> 12#include <vxworks.h> 13#ifdef CONFIG_X86 14#include <vesa.h> 15#include <asm/e820.h> 16#include <linux/linkage.h> 17#endif 18 19/** 20 * bootelf_exec() - start the ELF image execution. 21 * 22 * @entry: address of entry point of ELF. 23 * 24 * May by used to allow ports to override the default behavior. 25 */ 26unsigned long bootelf_exec(ulong (*entry)(int, char * const[]), 27 int argc, char *const argv[]) 28{ 29 return entry(argc, argv); 30} 31 32/** 33 * bootelf() - Boot ELF from memory. 34 * 35 * @addr: Loading address of ELF in memory. 36 * @flags: Bits like ELF_PHDR to control boot details. 37 * @argc: May be used to pass command line arguments (maybe unused). 38 * Necessary for backward compatibility with the CLI command. 39 * If unused, must be 0. 40 * @argv: see @argc. If unused, must be NULL. 41 * Return: Number returned by ELF application. 42 * 43 * Sets errno = ENOEXEC if the ELF image is not valid. 44 */ 45unsigned long bootelf(unsigned long addr, Bootelf_flags flags, 46 int argc, char *const argv[]) 47{ 48 unsigned long entry_addr; 49 char *args[] = {"", NULL}; 50 51 errno = 0; 52 53 if (!valid_elf_image(addr)) { 54 errno = ENOEXEC; 55 return 1; 56 } 57 58 entry_addr = flags.phdr ? load_elf_image_phdr(addr) 59 : load_elf_image_shdr(addr); 60 61 if (!flags.autostart) 62 return 0; 63 64 if (!argc && !argv) { 65 argc = 1; 66 argv = args; 67 } 68 69 return bootelf_exec((void *)entry_addr, argc, argv); 70} 71 72/* 73 * A very simple ELF64 loader, assumes the image is valid, returns the 74 * entry point address. 75 * 76 * Note if U-Boot is 32-bit, the loader assumes the to segment's 77 * physical address and size is within the lower 32-bit address space. 78 */ 79unsigned long load_elf64_image_phdr(unsigned long addr) 80{ 81 Elf64_Ehdr *ehdr; /* Elf header structure pointer */ 82 Elf64_Phdr *phdr; /* Program header structure pointer */ 83 int i; 84 85 ehdr = (Elf64_Ehdr *)addr; 86 phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff); 87 88 /* Load each program header */ 89 for (i = 0; i < ehdr->e_phnum; ++i, ++phdr) { 90 void *dst = (void *)(ulong)phdr->p_paddr; 91 void *src = (void *)addr + phdr->p_offset; 92 93 /* Only load PT_LOAD program header */ 94 if (phdr->p_type != PT_LOAD) 95 continue; 96 97 debug("Loading phdr %i to 0x%p (%lu bytes)\n", 98 i, dst, (ulong)phdr->p_filesz); 99 if (phdr->p_filesz) 100 memcpy(dst, src, phdr->p_filesz); 101 if (phdr->p_filesz != phdr->p_memsz) 102 memset(dst + phdr->p_filesz, 0x00, 103 phdr->p_memsz - phdr->p_filesz); 104 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), 105 roundup(phdr->p_memsz, ARCH_DMA_MINALIGN)); 106 } 107 108 if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags & 109 EF_PPC64_ELFV1_ABI)) { 110 /* 111 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function 112 * descriptor pointer with the first double word being the 113 * address of the entry point of the function. 114 */ 115 uintptr_t addr = ehdr->e_entry; 116 117 return *(Elf64_Addr *)addr; 118 } 119 120 return ehdr->e_entry; 121} 122 123unsigned long load_elf64_image_shdr(unsigned long addr) 124{ 125 Elf64_Ehdr *ehdr; /* Elf header structure pointer */ 126 Elf64_Shdr *shdr; /* Section header structure pointer */ 127 unsigned char *strtab = 0; /* String table pointer */ 128 unsigned char *image; /* Binary image pointer */ 129 int i; /* Loop counter */ 130 131 ehdr = (Elf64_Ehdr *)addr; 132 133 /* Find the section header string table for output info */ 134 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff + 135 (ehdr->e_shstrndx * sizeof(Elf64_Shdr))); 136 137 if (shdr->sh_type == SHT_STRTAB) 138 strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset); 139 140 /* Load each appropriate section */ 141 for (i = 0; i < ehdr->e_shnum; ++i) { 142 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff + 143 (i * sizeof(Elf64_Shdr))); 144 145 if (!(shdr->sh_flags & SHF_ALLOC) || 146 shdr->sh_addr == 0 || shdr->sh_size == 0) { 147 continue; 148 } 149 150 if (strtab) { 151 debug("%sing %s @ 0x%08lx (%ld bytes)\n", 152 (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", 153 &strtab[shdr->sh_name], 154 (unsigned long)shdr->sh_addr, 155 (long)shdr->sh_size); 156 } 157 158 if (shdr->sh_type == SHT_NOBITS) { 159 memset((void *)(uintptr_t)shdr->sh_addr, 0, 160 shdr->sh_size); 161 } else { 162 image = (unsigned char *)addr + (ulong)shdr->sh_offset; 163 memcpy((void *)(uintptr_t)shdr->sh_addr, 164 (const void *)image, shdr->sh_size); 165 } 166 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN), 167 roundup((shdr->sh_addr + shdr->sh_size), 168 ARCH_DMA_MINALIGN) - 169 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN)); 170 } 171 172 if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags & 173 EF_PPC64_ELFV1_ABI)) { 174 /* 175 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function 176 * descriptor pointer with the first double word being the 177 * address of the entry point of the function. 178 */ 179 uintptr_t addr = ehdr->e_entry; 180 181 return *(Elf64_Addr *)addr; 182 } 183 184 return ehdr->e_entry; 185} 186 187/* 188 * A very simple ELF loader, assumes the image is valid, returns the 189 * entry point address. 190 * 191 * The loader firstly reads the EFI class to see if it's a 64-bit image. 192 * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader. 193 */ 194unsigned long load_elf_image_phdr(unsigned long addr) 195{ 196 Elf32_Ehdr *ehdr; /* Elf header structure pointer */ 197 Elf32_Phdr *phdr; /* Program header structure pointer */ 198 int i; 199 200 ehdr = (Elf32_Ehdr *)addr; 201 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) 202 return load_elf64_image_phdr(addr); 203 204 phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); 205 206 /* Load each program header */ 207 for (i = 0; i < ehdr->e_phnum; ++i, ++phdr) { 208 void *dst = (void *)(uintptr_t)phdr->p_paddr; 209 void *src = (void *)addr + phdr->p_offset; 210 211 /* Only load PT_LOAD program header */ 212 if (phdr->p_type != PT_LOAD) 213 continue; 214 215 debug("Loading phdr %i to 0x%p (%i bytes)\n", 216 i, dst, phdr->p_filesz); 217 if (phdr->p_filesz) 218 memcpy(dst, src, phdr->p_filesz); 219 if (phdr->p_filesz != phdr->p_memsz) 220 memset(dst + phdr->p_filesz, 0x00, 221 phdr->p_memsz - phdr->p_filesz); 222 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), 223 roundup(phdr->p_memsz, ARCH_DMA_MINALIGN)); 224 } 225 226 return ehdr->e_entry; 227} 228 229unsigned long load_elf_image_shdr(unsigned long addr) 230{ 231 Elf32_Ehdr *ehdr; /* Elf header structure pointer */ 232 Elf32_Shdr *shdr; /* Section header structure pointer */ 233 unsigned char *strtab = 0; /* String table pointer */ 234 unsigned char *image; /* Binary image pointer */ 235 int i; /* Loop counter */ 236 237 ehdr = (Elf32_Ehdr *)addr; 238 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) 239 return load_elf64_image_shdr(addr); 240 241 /* Find the section header string table for output info */ 242 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + 243 (ehdr->e_shstrndx * sizeof(Elf32_Shdr))); 244 245 if (shdr->sh_type == SHT_STRTAB) 246 strtab = (unsigned char *)(addr + shdr->sh_offset); 247 248 /* Load each appropriate section */ 249 for (i = 0; i < ehdr->e_shnum; ++i) { 250 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + 251 (i * sizeof(Elf32_Shdr))); 252 253 if (!(shdr->sh_flags & SHF_ALLOC) || 254 shdr->sh_addr == 0 || shdr->sh_size == 0) { 255 continue; 256 } 257 258 if (strtab) { 259 debug("%sing %s @ 0x%08lx (%ld bytes)\n", 260 (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", 261 &strtab[shdr->sh_name], 262 (unsigned long)shdr->sh_addr, 263 (long)shdr->sh_size); 264 } 265 266 if (shdr->sh_type == SHT_NOBITS) { 267 memset((void *)(uintptr_t)shdr->sh_addr, 0, 268 shdr->sh_size); 269 } else { 270 image = (unsigned char *)addr + shdr->sh_offset; 271 memcpy((void *)(uintptr_t)shdr->sh_addr, 272 (const void *)image, shdr->sh_size); 273 } 274 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN), 275 roundup((shdr->sh_addr + shdr->sh_size), 276 ARCH_DMA_MINALIGN) - 277 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN)); 278 } 279 280 return ehdr->e_entry; 281} 282 283/* 284 * Determine if a valid ELF image exists at the given memory location. 285 * First look at the ELF header magic field, then make sure that it is 286 * executable. 287 */ 288int valid_elf_image(unsigned long addr) 289{ 290 Elf32_Ehdr *ehdr; /* Elf header structure pointer */ 291 292 ehdr = (Elf32_Ehdr *)addr; 293 294 if (!IS_ELF(*ehdr)) { 295 printf("## No elf image at address 0x%08lx\n", addr); 296 return 0; 297 } 298 299 if (ehdr->e_type != ET_EXEC) { 300 printf("## Not a 32-bit elf image at address 0x%08lx\n", addr); 301 return 0; 302 } 303 304 return 1; 305}