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