1 /* 2 * Copyright (c) 2001 William L. Pitts 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are freely 6 * permitted provided that the above copyright notice and this 7 * paragraph and the following disclaimer are duplicated in all 8 * such forms. 9 * 10 * This software is provided "AS IS" and without any express or 11 * implied warranties, including, without limitation, the implied 12 * warranties of merchantability and fitness for a particular 13 * purpose. 14 */ 15 16 #include <common.h> 17 #include <command.h> 18 #include <elf.h> 19 #include <environment.h> 20 #include <net.h> 21 #include <vxworks.h> 22 #ifdef CONFIG_X86 23 #include <vbe.h> 24 #include <asm/e820.h> 25 #include <linux/linkage.h> 26 #endif 27 28 /* 29 * A very simple ELF64 loader, assumes the image is valid, returns the 30 * entry point address. 31 * 32 * Note if U-Boot is 32-bit, the loader assumes the to segment's 33 * physical address and size is within the lower 32-bit address space. 34 */ 35 static unsigned long load_elf64_image_phdr(unsigned long addr) 36 { 37 Elf64_Ehdr *ehdr; /* Elf header structure pointer */ 38 Elf64_Phdr *phdr; /* Program header structure pointer */ 39 int i; 40 41 ehdr = (Elf64_Ehdr *)addr; 42 phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff); 43 44 /* Load each program header */ 45 for (i = 0; i < ehdr->e_phnum; ++i) { 46 void *dst = (void *)(ulong)phdr->p_paddr; 47 void *src = (void *)addr + phdr->p_offset; 48 49 debug("Loading phdr %i to 0x%p (%lu bytes)\n", 50 i, dst, (ulong)phdr->p_filesz); 51 if (phdr->p_filesz) 52 memcpy(dst, src, phdr->p_filesz); 53 if (phdr->p_filesz != phdr->p_memsz) 54 memset(dst + phdr->p_filesz, 0x00, 55 phdr->p_memsz - phdr->p_filesz); 56 flush_cache((unsigned long)dst, phdr->p_filesz); 57 ++phdr; 58 } 59 60 if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags & 61 EF_PPC64_ELFV1_ABI)) { 62 /* 63 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function 64 * descriptor pointer with the first double word being the 65 * address of the entry point of the function. 66 */ 67 uintptr_t addr = ehdr->e_entry; 68 69 return *(Elf64_Addr *)addr; 70 } 71 72 return ehdr->e_entry; 73 } 74 75 static unsigned long load_elf64_image_shdr(unsigned long addr) 76 { 77 Elf64_Ehdr *ehdr; /* Elf header structure pointer */ 78 Elf64_Shdr *shdr; /* Section header structure pointer */ 79 unsigned char *strtab = 0; /* String table pointer */ 80 unsigned char *image; /* Binary image pointer */ 81 int i; /* Loop counter */ 82 83 ehdr = (Elf64_Ehdr *)addr; 84 85 /* Find the section header string table for output info */ 86 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff + 87 (ehdr->e_shstrndx * sizeof(Elf64_Shdr))); 88 89 if (shdr->sh_type == SHT_STRTAB) 90 strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset); 91 92 /* Load each appropriate section */ 93 for (i = 0; i < ehdr->e_shnum; ++i) { 94 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff + 95 (i * sizeof(Elf64_Shdr))); 96 97 if (!(shdr->sh_flags & SHF_ALLOC) || 98 shdr->sh_addr == 0 || shdr->sh_size == 0) { 99 continue; 100 } 101 102 if (strtab) { 103 debug("%sing %s @ 0x%08lx (%ld bytes)\n", 104 (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", 105 &strtab[shdr->sh_name], 106 (unsigned long)shdr->sh_addr, 107 (long)shdr->sh_size); 108 } 109 110 if (shdr->sh_type == SHT_NOBITS) { 111 memset((void *)(uintptr_t)shdr->sh_addr, 0, 112 shdr->sh_size); 113 } else { 114 image = (unsigned char *)addr + (ulong)shdr->sh_offset; 115 memcpy((void *)(uintptr_t)shdr->sh_addr, 116 (const void *)image, shdr->sh_size); 117 } 118 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN), 119 roundup((shdr->sh_addr + shdr->sh_size), 120 ARCH_DMA_MINALIGN) - 121 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN)); 122 } 123 124 if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags & 125 EF_PPC64_ELFV1_ABI)) { 126 /* 127 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function 128 * descriptor pointer with the first double word being the 129 * address of the entry point of the function. 130 */ 131 uintptr_t addr = ehdr->e_entry; 132 133 return *(Elf64_Addr *)addr; 134 } 135 136 return ehdr->e_entry; 137 } 138 139 /* 140 * A very simple ELF loader, assumes the image is valid, returns the 141 * entry point address. 142 * 143 * The loader firstly reads the EFI class to see if it's a 64-bit image. 144 * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader. 145 */ 146 static unsigned long load_elf_image_phdr(unsigned long addr) 147 { 148 Elf32_Ehdr *ehdr; /* Elf header structure pointer */ 149 Elf32_Phdr *phdr; /* Program header structure pointer */ 150 int i; 151 152 ehdr = (Elf32_Ehdr *)addr; 153 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) 154 return load_elf64_image_phdr(addr); 155 156 phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); 157 158 /* Load each program header */ 159 for (i = 0; i < ehdr->e_phnum; ++i) { 160 void *dst = (void *)(uintptr_t)phdr->p_paddr; 161 void *src = (void *)addr + phdr->p_offset; 162 163 debug("Loading phdr %i to 0x%p (%i bytes)\n", 164 i, dst, phdr->p_filesz); 165 if (phdr->p_filesz) 166 memcpy(dst, src, phdr->p_filesz); 167 if (phdr->p_filesz != phdr->p_memsz) 168 memset(dst + phdr->p_filesz, 0x00, 169 phdr->p_memsz - phdr->p_filesz); 170 flush_cache((unsigned long)dst, phdr->p_filesz); 171 ++phdr; 172 } 173 174 return ehdr->e_entry; 175 } 176 177 static unsigned long load_elf_image_shdr(unsigned long addr) 178 { 179 Elf32_Ehdr *ehdr; /* Elf header structure pointer */ 180 Elf32_Shdr *shdr; /* Section header structure pointer */ 181 unsigned char *strtab = 0; /* String table pointer */ 182 unsigned char *image; /* Binary image pointer */ 183 int i; /* Loop counter */ 184 185 ehdr = (Elf32_Ehdr *)addr; 186 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) 187 return load_elf64_image_shdr(addr); 188 189 /* Find the section header string table for output info */ 190 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + 191 (ehdr->e_shstrndx * sizeof(Elf32_Shdr))); 192 193 if (shdr->sh_type == SHT_STRTAB) 194 strtab = (unsigned char *)(addr + shdr->sh_offset); 195 196 /* Load each appropriate section */ 197 for (i = 0; i < ehdr->e_shnum; ++i) { 198 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + 199 (i * sizeof(Elf32_Shdr))); 200 201 if (!(shdr->sh_flags & SHF_ALLOC) || 202 shdr->sh_addr == 0 || shdr->sh_size == 0) { 203 continue; 204 } 205 206 if (strtab) { 207 debug("%sing %s @ 0x%08lx (%ld bytes)\n", 208 (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load", 209 &strtab[shdr->sh_name], 210 (unsigned long)shdr->sh_addr, 211 (long)shdr->sh_size); 212 } 213 214 if (shdr->sh_type == SHT_NOBITS) { 215 memset((void *)(uintptr_t)shdr->sh_addr, 0, 216 shdr->sh_size); 217 } else { 218 image = (unsigned char *)addr + shdr->sh_offset; 219 memcpy((void *)(uintptr_t)shdr->sh_addr, 220 (const void *)image, shdr->sh_size); 221 } 222 flush_cache(shdr->sh_addr, shdr->sh_size); 223 } 224 225 return ehdr->e_entry; 226 } 227 228 /* Allow ports to override the default behavior */ 229 static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]), 230 int argc, char * const argv[]) 231 { 232 unsigned long ret; 233 234 /* 235 * pass address parameter as argv[0] (aka command name), 236 * and all remaining args 237 */ 238 ret = entry(argc, argv); 239 240 return ret; 241 } 242 243 /* 244 * Determine if a valid ELF image exists at the given memory location. 245 * First look at the ELF header magic field, then make sure that it is 246 * executable. 247 */ 248 int valid_elf_image(unsigned long addr) 249 { 250 Elf32_Ehdr *ehdr; /* Elf header structure pointer */ 251 252 ehdr = (Elf32_Ehdr *)addr; 253 254 if (!IS_ELF(*ehdr)) { 255 printf("## No elf image at address 0x%08lx\n", addr); 256 return 0; 257 } 258 259 if (ehdr->e_type != ET_EXEC) { 260 printf("## Not a 32-bit elf image at address 0x%08lx\n", addr); 261 return 0; 262 } 263 264 return 1; 265 } 266 267 /* Interpreter command to boot an arbitrary ELF image from memory */ 268 int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 269 { 270 unsigned long addr; /* Address of the ELF image */ 271 unsigned long rc; /* Return value from user code */ 272 char *sload = NULL; 273 const char *ep = env_get("autostart"); 274 int rcode = 0; 275 276 /* Consume 'bootelf' */ 277 argc--; argv++; 278 279 /* Check for flag. */ 280 if (argc >= 1 && (argv[0][0] == '-' && \ 281 (argv[0][1] == 'p' || argv[0][1] == 's'))) { 282 sload = argv[0]; 283 /* Consume flag. */ 284 argc--; argv++; 285 } 286 /* Check for address. */ 287 if (argc >= 1 && strict_strtoul(argv[0], 16, &addr) != -EINVAL) { 288 /* Consume address */ 289 argc--; argv++; 290 } else 291 addr = load_addr; 292 293 if (!valid_elf_image(addr)) 294 return 1; 295 296 if (sload && sload[1] == 'p') 297 addr = load_elf_image_phdr(addr); 298 else 299 addr = load_elf_image_shdr(addr); 300 301 if (ep && !strcmp(ep, "no")) 302 return rcode; 303 304 printf("## Starting application at 0x%08lx ...\n", addr); 305 306 /* 307 * pass address parameter as argv[0] (aka command name), 308 * and all remaining args 309 */ 310 rc = do_bootelf_exec((void *)addr, argc, argv); 311 if (rc != 0) 312 rcode = 1; 313 314 printf("## Application terminated, rc = 0x%lx\n", rc); 315 316 return rcode; 317 } 318 319 /* 320 * Interpreter command to boot VxWorks from a memory image. The image can 321 * be either an ELF image or a raw binary. Will attempt to setup the 322 * bootline and other parameters correctly. 323 */ 324 int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 325 { 326 unsigned long addr; /* Address of image */ 327 unsigned long bootaddr = 0; /* Address to put the bootline */ 328 char *bootline; /* Text of the bootline */ 329 char *tmp; /* Temporary char pointer */ 330 char build_buf[128]; /* Buffer for building the bootline */ 331 int ptr = 0; 332 #ifdef CONFIG_X86 333 ulong base; 334 struct e820_info *info; 335 struct e820_entry *data; 336 struct efi_gop_info *gop; 337 struct vesa_mode_info *vesa = &mode_info.vesa; 338 #endif 339 340 /* 341 * Check the loadaddr variable. 342 * If we don't know where the image is then we're done. 343 */ 344 if (argc < 2) 345 addr = load_addr; 346 else 347 addr = simple_strtoul(argv[1], NULL, 16); 348 349 #if defined(CONFIG_CMD_NET) 350 /* 351 * Check to see if we need to tftp the image ourselves 352 * before starting 353 */ 354 if ((argc == 2) && (strcmp(argv[1], "tftp") == 0)) { 355 if (net_loop(TFTPGET) <= 0) 356 return 1; 357 printf("Automatic boot of VxWorks image at address 0x%08lx ...\n", 358 addr); 359 } 360 #endif 361 362 /* 363 * This should equate to 364 * NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET 365 * from the VxWorks BSP header files. 366 * This will vary from board to board 367 */ 368 #if defined(CONFIG_SYS_VXWORKS_MAC_PTR) 369 tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR; 370 eth_env_get_enetaddr("ethaddr", (uchar *)build_buf); 371 memcpy(tmp, build_buf, 6); 372 #else 373 puts("## Ethernet MAC address not copied to NV RAM\n"); 374 #endif 375 376 #ifdef CONFIG_X86 377 /* 378 * Get VxWorks's physical memory base address from environment, 379 * if we don't specify it in the environment, use a default one. 380 */ 381 base = env_get_hex("vx_phys_mem_base", VXWORKS_PHYS_MEM_BASE); 382 data = (struct e820_entry *)(base + E820_DATA_OFFSET); 383 info = (struct e820_info *)(base + E820_INFO_OFFSET); 384 385 memset(info, 0, sizeof(struct e820_info)); 386 info->sign = E820_SIGNATURE; 387 info->entries = install_e820_map(E820MAX, data); 388 info->addr = (info->entries - 1) * sizeof(struct e820_entry) + 389 E820_DATA_OFFSET; 390 391 /* 392 * Explicitly clear the bootloader image size otherwise if memory 393 * at this offset happens to contain some garbage data, the final 394 * available memory size for the kernel is insane. 395 */ 396 *(u32 *)(base + BOOT_IMAGE_SIZE_OFFSET) = 0; 397 398 /* 399 * Prepare compatible framebuffer information block. 400 * The VESA mode has to be 32-bit RGBA. 401 */ 402 if (vesa->x_resolution && vesa->y_resolution) { 403 gop = (struct efi_gop_info *)(base + EFI_GOP_INFO_OFFSET); 404 gop->magic = EFI_GOP_INFO_MAGIC; 405 gop->info.version = 0; 406 gop->info.width = vesa->x_resolution; 407 gop->info.height = vesa->y_resolution; 408 gop->info.pixel_format = EFI_GOT_RGBA8; 409 gop->info.pixels_per_scanline = vesa->bytes_per_scanline / 4; 410 gop->fb_base = vesa->phys_base_ptr; 411 gop->fb_size = vesa->bytes_per_scanline * vesa->y_resolution; 412 } 413 #endif 414 415 /* 416 * Use bootaddr to find the location in memory that VxWorks 417 * will look for the bootline string. The default value is 418 * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by 419 * VxWorks BSP. For example, on PowerPC it defaults to 0x4200. 420 */ 421 tmp = env_get("bootaddr"); 422 if (!tmp) { 423 #ifdef CONFIG_X86 424 bootaddr = base + X86_BOOT_LINE_OFFSET; 425 #else 426 printf("## VxWorks bootline address not specified\n"); 427 return 1; 428 #endif 429 } 430 431 if (!bootaddr) 432 bootaddr = simple_strtoul(tmp, NULL, 16); 433 434 /* 435 * Check to see if the bootline is defined in the 'bootargs' parameter. 436 * If it is not defined, we may be able to construct the info. 437 */ 438 bootline = env_get("bootargs"); 439 if (!bootline) { 440 tmp = env_get("bootdev"); 441 if (tmp) { 442 strcpy(build_buf, tmp); 443 ptr = strlen(tmp); 444 } else { 445 printf("## VxWorks boot device not specified\n"); 446 } 447 448 tmp = env_get("bootfile"); 449 if (tmp) 450 ptr += sprintf(build_buf + ptr, "host:%s ", tmp); 451 else 452 ptr += sprintf(build_buf + ptr, "host:vxWorks "); 453 454 /* 455 * The following parameters are only needed if 'bootdev' 456 * is an ethernet device, otherwise they are optional. 457 */ 458 tmp = env_get("ipaddr"); 459 if (tmp) { 460 ptr += sprintf(build_buf + ptr, "e=%s", tmp); 461 tmp = env_get("netmask"); 462 if (tmp) { 463 u32 mask = env_get_ip("netmask").s_addr; 464 ptr += sprintf(build_buf + ptr, 465 ":%08x ", ntohl(mask)); 466 } else { 467 ptr += sprintf(build_buf + ptr, " "); 468 } 469 } 470 471 tmp = env_get("serverip"); 472 if (tmp) 473 ptr += sprintf(build_buf + ptr, "h=%s ", tmp); 474 475 tmp = env_get("gatewayip"); 476 if (tmp) 477 ptr += sprintf(build_buf + ptr, "g=%s ", tmp); 478 479 tmp = env_get("hostname"); 480 if (tmp) 481 ptr += sprintf(build_buf + ptr, "tn=%s ", tmp); 482 483 tmp = env_get("othbootargs"); 484 if (tmp) { 485 strcpy(build_buf + ptr, tmp); 486 ptr += strlen(tmp); 487 } 488 489 bootline = build_buf; 490 } 491 492 memcpy((void *)bootaddr, bootline, max(strlen(bootline), (size_t)255)); 493 flush_cache(bootaddr, max(strlen(bootline), (size_t)255)); 494 printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, (char *)bootaddr); 495 496 /* 497 * If the data at the load address is an elf image, then 498 * treat it like an elf image. Otherwise, assume that it is a 499 * binary image. 500 */ 501 if (valid_elf_image(addr)) 502 addr = load_elf_image_phdr(addr); 503 else 504 puts("## Not an ELF image, assuming binary\n"); 505 506 printf("## Starting vxWorks at 0x%08lx ...\n", addr); 507 508 dcache_disable(); 509 #if defined(CONFIG_ARM64) && defined(CONFIG_ARMV8_PSCI) 510 armv8_setup_psci(); 511 smp_kick_all_cpus(); 512 #endif 513 514 #ifdef CONFIG_X86 515 /* VxWorks on x86 uses stack to pass parameters */ 516 ((asmlinkage void (*)(int))addr)(0); 517 #else 518 ((void (*)(int))addr)(0); 519 #endif 520 521 puts("## vxWorks terminated\n"); 522 523 return 1; 524 } 525 526 U_BOOT_CMD( 527 bootelf, CONFIG_SYS_MAXARGS, 0, do_bootelf, 528 "Boot from an ELF image in memory", 529 "[-p|-s] [address]\n" 530 "\t- load ELF image at [address] via program headers (-p)\n" 531 "\t or via section headers (-s)" 532 ); 533 534 U_BOOT_CMD( 535 bootvx, 2, 0, do_bootvx, 536 "Boot vxWorks from an ELF image", 537 " [address] - load address of vxWorks ELF image." 538 ); 539