elf.c 7.7 KB

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