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(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN), 223 roundup((shdr->sh_addr + shdr->sh_size), 224 ARCH_DMA_MINALIGN) - 225 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN)); 226 } 227 228 return ehdr->e_entry; 229 } 230 231 /* Allow ports to override the default behavior */ 232 static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]), 233 int argc, char * const argv[]) 234 { 235 unsigned long ret; 236 237 /* 238 * pass address parameter as argv[0] (aka command name), 239 * and all remaining args 240 */ 241 ret = entry(argc, argv); 242 243 return ret; 244 } 245 246 /* 247 * Determine if a valid ELF image exists at the given memory location. 248 * First look at the ELF header magic field, then make sure that it is 249 * executable. 250 */ 251 int valid_elf_image(unsigned long addr) 252 { 253 Elf32_Ehdr *ehdr; /* Elf header structure pointer */ 254 255 ehdr = (Elf32_Ehdr *)addr; 256 257 if (!IS_ELF(*ehdr)) { 258 printf("## No elf image at address 0x%08lx\n", addr); 259 return 0; 260 } 261 262 if (ehdr->e_type != ET_EXEC) { 263 printf("## Not a 32-bit elf image at address 0x%08lx\n", addr); 264 return 0; 265 } 266 267 return 1; 268 } 269 270 /* Interpreter command to boot an arbitrary ELF image from memory */ 271 int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 272 { 273 unsigned long addr; /* Address of the ELF image */ 274 unsigned long rc; /* Return value from user code */ 275 char *sload = NULL; 276 const char *ep = env_get("autostart"); 277 int rcode = 0; 278 279 /* Consume 'bootelf' */ 280 argc--; argv++; 281 282 /* Check for flag. */ 283 if (argc >= 1 && (argv[0][0] == '-' && \ 284 (argv[0][1] == 'p' || argv[0][1] == 's'))) { 285 sload = argv[0]; 286 /* Consume flag. */ 287 argc--; argv++; 288 } 289 /* Check for address. */ 290 if (argc >= 1 && strict_strtoul(argv[0], 16, &addr) != -EINVAL) { 291 /* Consume address */ 292 argc--; argv++; 293 } else 294 addr = load_addr; 295 296 if (!valid_elf_image(addr)) 297 return 1; 298 299 if (sload && sload[1] == 'p') 300 addr = load_elf_image_phdr(addr); 301 else 302 addr = load_elf_image_shdr(addr); 303 304 if (ep && !strcmp(ep, "no")) 305 return rcode; 306 307 printf("## Starting application at 0x%08lx ...\n", addr); 308 309 /* 310 * pass address parameter as argv[0] (aka command name), 311 * and all remaining args 312 */ 313 rc = do_bootelf_exec((void *)addr, argc, argv); 314 if (rc != 0) 315 rcode = 1; 316 317 printf("## Application terminated, rc = 0x%lx\n", rc); 318 319 return rcode; 320 } 321 322 /* 323 * Interpreter command to boot VxWorks from a memory image. The image can 324 * be either an ELF image or a raw binary. Will attempt to setup the 325 * bootline and other parameters correctly. 326 */ 327 int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 328 { 329 unsigned long addr; /* Address of image */ 330 unsigned long bootaddr = 0; /* Address to put the bootline */ 331 char *bootline; /* Text of the bootline */ 332 char *tmp; /* Temporary char pointer */ 333 char build_buf[128]; /* Buffer for building the bootline */ 334 int ptr = 0; 335 #ifdef CONFIG_X86 336 ulong base; 337 struct e820_info *info; 338 struct e820_entry *data; 339 struct efi_gop_info *gop; 340 struct vesa_mode_info *vesa = &mode_info.vesa; 341 #endif 342 343 /* 344 * Check the loadaddr variable. 345 * If we don't know where the image is then we're done. 346 */ 347 if (argc < 2) 348 addr = load_addr; 349 else 350 addr = simple_strtoul(argv[1], NULL, 16); 351 352 #if defined(CONFIG_CMD_NET) 353 /* 354 * Check to see if we need to tftp the image ourselves 355 * before starting 356 */ 357 if ((argc == 2) && (strcmp(argv[1], "tftp") == 0)) { 358 if (net_loop(TFTPGET) <= 0) 359 return 1; 360 printf("Automatic boot of VxWorks image at address 0x%08lx ...\n", 361 addr); 362 } 363 #endif 364 365 /* 366 * This should equate to 367 * NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET 368 * from the VxWorks BSP header files. 369 * This will vary from board to board 370 */ 371 #if defined(CONFIG_SYS_VXWORKS_MAC_PTR) 372 tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR; 373 eth_env_get_enetaddr("ethaddr", (uchar *)build_buf); 374 memcpy(tmp, build_buf, 6); 375 #else 376 puts("## Ethernet MAC address not copied to NV RAM\n"); 377 #endif 378 379 #ifdef CONFIG_X86 380 /* 381 * Get VxWorks's physical memory base address from environment, 382 * if we don't specify it in the environment, use a default one. 383 */ 384 base = env_get_hex("vx_phys_mem_base", VXWORKS_PHYS_MEM_BASE); 385 data = (struct e820_entry *)(base + E820_DATA_OFFSET); 386 info = (struct e820_info *)(base + E820_INFO_OFFSET); 387 388 memset(info, 0, sizeof(struct e820_info)); 389 info->sign = E820_SIGNATURE; 390 info->entries = install_e820_map(E820MAX, data); 391 info->addr = (info->entries - 1) * sizeof(struct e820_entry) + 392 E820_DATA_OFFSET; 393 394 /* 395 * Explicitly clear the bootloader image size otherwise if memory 396 * at this offset happens to contain some garbage data, the final 397 * available memory size for the kernel is insane. 398 */ 399 *(u32 *)(base + BOOT_IMAGE_SIZE_OFFSET) = 0; 400 401 /* 402 * Prepare compatible framebuffer information block. 403 * The VESA mode has to be 32-bit RGBA. 404 */ 405 if (vesa->x_resolution && vesa->y_resolution) { 406 gop = (struct efi_gop_info *)(base + EFI_GOP_INFO_OFFSET); 407 gop->magic = EFI_GOP_INFO_MAGIC; 408 gop->info.version = 0; 409 gop->info.width = vesa->x_resolution; 410 gop->info.height = vesa->y_resolution; 411 gop->info.pixel_format = EFI_GOT_RGBA8; 412 gop->info.pixels_per_scanline = vesa->bytes_per_scanline / 4; 413 gop->fb_base = vesa->phys_base_ptr; 414 gop->fb_size = vesa->bytes_per_scanline * vesa->y_resolution; 415 } 416 #endif 417 418 /* 419 * Use bootaddr to find the location in memory that VxWorks 420 * will look for the bootline string. The default value is 421 * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by 422 * VxWorks BSP. For example, on PowerPC it defaults to 0x4200. 423 */ 424 tmp = env_get("bootaddr"); 425 if (!tmp) { 426 #ifdef CONFIG_X86 427 bootaddr = base + X86_BOOT_LINE_OFFSET; 428 #else 429 printf("## VxWorks bootline address not specified\n"); 430 return 1; 431 #endif 432 } 433 434 if (!bootaddr) 435 bootaddr = simple_strtoul(tmp, NULL, 16); 436 437 /* 438 * Check to see if the bootline is defined in the 'bootargs' parameter. 439 * If it is not defined, we may be able to construct the info. 440 */ 441 bootline = env_get("bootargs"); 442 if (!bootline) { 443 tmp = env_get("bootdev"); 444 if (tmp) { 445 strcpy(build_buf, tmp); 446 ptr = strlen(tmp); 447 } else { 448 printf("## VxWorks boot device not specified\n"); 449 } 450 451 tmp = env_get("bootfile"); 452 if (tmp) 453 ptr += sprintf(build_buf + ptr, "host:%s ", tmp); 454 else 455 ptr += sprintf(build_buf + ptr, "host:vxWorks "); 456 457 /* 458 * The following parameters are only needed if 'bootdev' 459 * is an ethernet device, otherwise they are optional. 460 */ 461 tmp = env_get("ipaddr"); 462 if (tmp) { 463 ptr += sprintf(build_buf + ptr, "e=%s", tmp); 464 tmp = env_get("netmask"); 465 if (tmp) { 466 u32 mask = env_get_ip("netmask").s_addr; 467 ptr += sprintf(build_buf + ptr, 468 ":%08x ", ntohl(mask)); 469 } else { 470 ptr += sprintf(build_buf + ptr, " "); 471 } 472 } 473 474 tmp = env_get("serverip"); 475 if (tmp) 476 ptr += sprintf(build_buf + ptr, "h=%s ", tmp); 477 478 tmp = env_get("gatewayip"); 479 if (tmp) 480 ptr += sprintf(build_buf + ptr, "g=%s ", tmp); 481 482 tmp = env_get("hostname"); 483 if (tmp) 484 ptr += sprintf(build_buf + ptr, "tn=%s ", tmp); 485 486 tmp = env_get("othbootargs"); 487 if (tmp) { 488 strcpy(build_buf + ptr, tmp); 489 ptr += strlen(tmp); 490 } 491 492 bootline = build_buf; 493 } 494 495 memcpy((void *)bootaddr, bootline, max(strlen(bootline), (size_t)255)); 496 flush_cache(bootaddr, max(strlen(bootline), (size_t)255)); 497 printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, (char *)bootaddr); 498 499 /* 500 * If the data at the load address is an elf image, then 501 * treat it like an elf image. Otherwise, assume that it is a 502 * binary image. 503 */ 504 if (valid_elf_image(addr)) 505 addr = load_elf_image_phdr(addr); 506 else 507 puts("## Not an ELF image, assuming binary\n"); 508 509 printf("## Starting vxWorks at 0x%08lx ...\n", addr); 510 511 dcache_disable(); 512 #if defined(CONFIG_ARM64) && defined(CONFIG_ARMV8_PSCI) 513 armv8_setup_psci(); 514 smp_kick_all_cpus(); 515 #endif 516 517 #ifdef CONFIG_X86 518 /* VxWorks on x86 uses stack to pass parameters */ 519 ((asmlinkage void (*)(int))addr)(0); 520 #else 521 ((void (*)(int))addr)(0); 522 #endif 523 524 puts("## vxWorks terminated\n"); 525 526 return 1; 527 } 528 529 U_BOOT_CMD( 530 bootelf, CONFIG_SYS_MAXARGS, 0, do_bootelf, 531 "Boot from an ELF image in memory", 532 "[-p|-s] [address]\n" 533 "\t- load ELF image at [address] via program headers (-p)\n" 534 "\t or via section headers (-s)" 535 ); 536 537 U_BOOT_CMD( 538 bootvx, 2, 0, do_bootvx, 539 "Boot vxWorks from an ELF image", 540 " [address] - load address of vxWorks ELF image." 541 ); 542