elf.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // SPDX-License-Identifier: BSD-2-Clause
  2. /*
  3. * Copyright (c) 2001 William L. Pitts
  4. * All rights reserved.
  5. */
  6. #include <common.h>
  7. #include <command.h>
  8. #include <cpu_func.h>
  9. #include <elf.h>
  10. #include <env.h>
  11. #include <image.h>
  12. #include <log.h>
  13. #include <net.h>
  14. #include <vxworks.h>
  15. #ifdef CONFIG_X86
  16. #include <vbe.h>
  17. #include <asm/cache.h>
  18. #include <asm/e820.h>
  19. #include <linux/linkage.h>
  20. #endif
  21. /* Allow ports to override the default behavior */
  22. static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
  23. int argc, char *const argv[])
  24. {
  25. unsigned long ret;
  26. /*
  27. * pass address parameter as argv[0] (aka command name),
  28. * and all remaining args
  29. */
  30. ret = entry(argc, argv);
  31. return ret;
  32. }
  33. /* Interpreter command to boot an arbitrary ELF image from memory */
  34. int do_bootelf(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
  35. {
  36. unsigned long addr; /* Address of the ELF image */
  37. unsigned long rc; /* Return value from user code */
  38. char *sload = NULL;
  39. const char *ep = env_get("autostart");
  40. int rcode = 0;
  41. /* Consume 'bootelf' */
  42. argc--; argv++;
  43. /* Check for flag. */
  44. if (argc >= 1 && (argv[0][0] == '-' && \
  45. (argv[0][1] == 'p' || argv[0][1] == 's'))) {
  46. sload = argv[0];
  47. /* Consume flag. */
  48. argc--; argv++;
  49. }
  50. /* Check for address. */
  51. if (argc >= 1 && strict_strtoul(argv[0], 16, &addr) != -EINVAL) {
  52. /* Consume address */
  53. argc--; argv++;
  54. } else
  55. addr = image_load_addr;
  56. if (!valid_elf_image(addr))
  57. return 1;
  58. if (sload && sload[1] == 'p')
  59. addr = load_elf_image_phdr(addr);
  60. else
  61. addr = load_elf_image_shdr(addr);
  62. if (ep && !strcmp(ep, "no"))
  63. return rcode;
  64. printf("## Starting application at 0x%08lx ...\n", addr);
  65. /*
  66. * pass address parameter as argv[0] (aka command name),
  67. * and all remaining args
  68. */
  69. rc = do_bootelf_exec((void *)addr, argc, argv);
  70. if (rc != 0)
  71. rcode = 1;
  72. printf("## Application terminated, rc = 0x%lx\n", rc);
  73. return rcode;
  74. }
  75. /*
  76. * Interpreter command to boot VxWorks from a memory image. The image can
  77. * be either an ELF image or a raw binary. Will attempt to setup the
  78. * bootline and other parameters correctly.
  79. */
  80. int do_bootvx(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
  81. {
  82. unsigned long addr; /* Address of image */
  83. unsigned long bootaddr = 0; /* Address to put the bootline */
  84. char *bootline; /* Text of the bootline */
  85. char *tmp; /* Temporary char pointer */
  86. char build_buf[128]; /* Buffer for building the bootline */
  87. int ptr = 0;
  88. #ifdef CONFIG_X86
  89. ulong base;
  90. struct e820_info *info;
  91. struct e820_entry *data;
  92. struct efi_gop_info *gop;
  93. struct vesa_mode_info *vesa = &mode_info.vesa;
  94. #endif
  95. /*
  96. * Check the loadaddr variable.
  97. * If we don't know where the image is then we're done.
  98. */
  99. if (argc < 2)
  100. addr = image_load_addr;
  101. else
  102. addr = hextoul(argv[1], NULL);
  103. #if defined(CONFIG_CMD_NET)
  104. /*
  105. * Check to see if we need to tftp the image ourselves
  106. * before starting
  107. */
  108. if ((argc == 2) && (strcmp(argv[1], "tftp") == 0)) {
  109. if (net_loop(TFTPGET) <= 0)
  110. return 1;
  111. printf("Automatic boot of VxWorks image at address 0x%08lx ...\n",
  112. addr);
  113. }
  114. #endif
  115. /*
  116. * This should equate to
  117. * NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
  118. * from the VxWorks BSP header files.
  119. * This will vary from board to board
  120. */
  121. #if defined(CONFIG_SYS_VXWORKS_MAC_PTR)
  122. tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR;
  123. eth_env_get_enetaddr("ethaddr", (uchar *)build_buf);
  124. memcpy(tmp, build_buf, 6);
  125. #else
  126. puts("## Ethernet MAC address not copied to NV RAM\n");
  127. #endif
  128. #ifdef CONFIG_X86
  129. /*
  130. * Get VxWorks's physical memory base address from environment,
  131. * if we don't specify it in the environment, use a default one.
  132. */
  133. base = env_get_hex("vx_phys_mem_base", VXWORKS_PHYS_MEM_BASE);
  134. data = (struct e820_entry *)(base + E820_DATA_OFFSET);
  135. info = (struct e820_info *)(base + E820_INFO_OFFSET);
  136. memset(info, 0, sizeof(struct e820_info));
  137. info->sign = E820_SIGNATURE;
  138. info->entries = install_e820_map(E820MAX, data);
  139. info->addr = (info->entries - 1) * sizeof(struct e820_entry) +
  140. E820_DATA_OFFSET;
  141. /*
  142. * Explicitly clear the bootloader image size otherwise if memory
  143. * at this offset happens to contain some garbage data, the final
  144. * available memory size for the kernel is insane.
  145. */
  146. *(u32 *)(base + BOOT_IMAGE_SIZE_OFFSET) = 0;
  147. /*
  148. * Prepare compatible framebuffer information block.
  149. * The VESA mode has to be 32-bit RGBA.
  150. */
  151. if (vesa->x_resolution && vesa->y_resolution) {
  152. gop = (struct efi_gop_info *)(base + EFI_GOP_INFO_OFFSET);
  153. gop->magic = EFI_GOP_INFO_MAGIC;
  154. gop->info.version = 0;
  155. gop->info.width = vesa->x_resolution;
  156. gop->info.height = vesa->y_resolution;
  157. gop->info.pixel_format = EFI_GOT_RGBA8;
  158. gop->info.pixels_per_scanline = vesa->bytes_per_scanline / 4;
  159. gop->fb_base = vesa->phys_base_ptr;
  160. gop->fb_size = vesa->bytes_per_scanline * vesa->y_resolution;
  161. }
  162. #endif
  163. /*
  164. * Use bootaddr to find the location in memory that VxWorks
  165. * will look for the bootline string. The default value is
  166. * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by
  167. * VxWorks BSP. For example, on PowerPC it defaults to 0x4200.
  168. */
  169. tmp = env_get("bootaddr");
  170. if (!tmp) {
  171. #ifdef CONFIG_X86
  172. bootaddr = base + X86_BOOT_LINE_OFFSET;
  173. #else
  174. printf("## VxWorks bootline address not specified\n");
  175. return 1;
  176. #endif
  177. }
  178. if (!bootaddr)
  179. bootaddr = hextoul(tmp, NULL);
  180. /*
  181. * Check to see if the bootline is defined in the 'bootargs' parameter.
  182. * If it is not defined, we may be able to construct the info.
  183. */
  184. bootline = env_get("bootargs");
  185. if (!bootline) {
  186. tmp = env_get("bootdev");
  187. if (tmp) {
  188. strcpy(build_buf, tmp);
  189. ptr = strlen(tmp);
  190. } else {
  191. printf("## VxWorks boot device not specified\n");
  192. }
  193. tmp = env_get("bootfile");
  194. if (tmp)
  195. ptr += sprintf(build_buf + ptr, "host:%s ", tmp);
  196. else
  197. ptr += sprintf(build_buf + ptr, "host:vxWorks ");
  198. /*
  199. * The following parameters are only needed if 'bootdev'
  200. * is an ethernet device, otherwise they are optional.
  201. */
  202. tmp = env_get("ipaddr");
  203. if (tmp) {
  204. ptr += sprintf(build_buf + ptr, "e=%s", tmp);
  205. tmp = env_get("netmask");
  206. if (tmp) {
  207. u32 mask = env_get_ip("netmask").s_addr;
  208. ptr += sprintf(build_buf + ptr,
  209. ":%08x ", ntohl(mask));
  210. } else {
  211. ptr += sprintf(build_buf + ptr, " ");
  212. }
  213. }
  214. tmp = env_get("serverip");
  215. if (tmp)
  216. ptr += sprintf(build_buf + ptr, "h=%s ", tmp);
  217. tmp = env_get("gatewayip");
  218. if (tmp)
  219. ptr += sprintf(build_buf + ptr, "g=%s ", tmp);
  220. tmp = env_get("hostname");
  221. if (tmp)
  222. ptr += sprintf(build_buf + ptr, "tn=%s ", tmp);
  223. tmp = env_get("othbootargs");
  224. if (tmp) {
  225. strcpy(build_buf + ptr, tmp);
  226. ptr += strlen(tmp);
  227. }
  228. bootline = build_buf;
  229. }
  230. memcpy((void *)bootaddr, bootline, max(strlen(bootline), (size_t)255));
  231. flush_cache(bootaddr, max(strlen(bootline), (size_t)255));
  232. printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, (char *)bootaddr);
  233. /*
  234. * If the data at the load address is an elf image, then
  235. * treat it like an elf image. Otherwise, assume that it is a
  236. * binary image.
  237. */
  238. if (valid_elf_image(addr))
  239. addr = load_elf_image_phdr(addr);
  240. else
  241. puts("## Not an ELF image, assuming binary\n");
  242. printf("## Starting vxWorks at 0x%08lx ...\n", addr);
  243. dcache_disable();
  244. #if defined(CONFIG_ARM64) && defined(CONFIG_ARMV8_PSCI)
  245. armv8_setup_psci();
  246. smp_kick_all_cpus();
  247. #endif
  248. #ifdef CONFIG_X86
  249. /* VxWorks on x86 uses stack to pass parameters */
  250. ((asmlinkage void (*)(int))addr)(0);
  251. #else
  252. ((void (*)(int))addr)(0);
  253. #endif
  254. puts("## vxWorks terminated\n");
  255. return 1;
  256. }
  257. U_BOOT_CMD(
  258. bootelf, CONFIG_SYS_MAXARGS, 0, do_bootelf,
  259. "Boot from an ELF image in memory",
  260. "[-p|-s] [address]\n"
  261. "\t- load ELF image at [address] via program headers (-p)\n"
  262. "\t or via section headers (-s)"
  263. );
  264. U_BOOT_CMD(
  265. bootvx, 2, 0, do_bootvx,
  266. "Boot vxWorks from an ELF image",
  267. " [address] - load address of vxWorks ELF image."
  268. );