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