1 // SPDX-License-Identifier: BSD-2-Clause
3 * Copyright (c) 2001 William L. Pitts
18 #include <asm/cache.h>
20 #include <linux/linkage.h>
23 /* Allow ports to override the default behavior */
24 static unsigned long do_bootelf_exec(ulong (*entry
)(int, char * const[]),
25 int argc
, char *const argv
[])
30 * pass address parameter as argv[0] (aka command name),
31 * and all remaining args
33 ret
= entry(argc
, argv
);
38 /* Interpreter command to boot an arbitrary ELF image from memory */
39 int do_bootelf(struct cmd_tbl
*cmdtp
, int flag
, int argc
, char *const argv
[])
41 #if CONFIG_IS_ENABLED(CMD_ELF_FDT_SETUP)
42 struct bootm_headers img
= {0};
43 unsigned long fdt_addr
= 0; /* Address of the FDT */
45 unsigned long addr
; /* Address of the ELF image */
46 unsigned long rc
; /* Return value from user code */
50 /* Consume 'bootelf' */
53 /* Check for [-p|-s] flag. */
54 if (argc
>= 1 && (argv
[0][0] == '-' && \
55 (argv
[0][1] == 'p' || argv
[0][1] == 's'))) {
61 #if CONFIG_IS_ENABLED(CMD_ELF_FDT_SETUP)
62 /* Check for [-d fdt_addr_r] option. */
63 if ((argc
>= 2) && (argv
[0][0] == '-') && (argv
[0][1] == 'd')) {
64 if (strict_strtoul(argv
[1], 16, &fdt_addr
) != 0)
72 /* Check for address. */
73 if (argc
>= 1 && strict_strtoul(argv
[0], 16, &addr
) != -EINVAL
) {
77 addr
= image_load_addr
;
79 if (!valid_elf_image(addr
))
82 if (sload
&& sload
[1] == 'p')
83 addr
= load_elf_image_phdr(addr
);
85 addr
= load_elf_image_shdr(addr
);
87 #if CONFIG_IS_ENABLED(CMD_ELF_FDT_SETUP)
89 printf("## Setting up FDT at 0x%08lx ...\n", fdt_addr
);
92 if (image_setup_libfdt(&img
, (void *)fdt_addr
, NULL
))
97 if (!env_get_autostart())
100 printf("## Starting application at 0x%08lx ...\n", addr
);
104 * pass address parameter as argv[0] (aka command name),
105 * and all remaining args
107 rc
= do_bootelf_exec((void *)addr
, argc
, argv
);
111 printf("## Application terminated, rc = 0x%lx\n", rc
);
117 * Interpreter command to boot VxWorks from a memory image. The image can
118 * be either an ELF image or a raw binary. Will attempt to setup the
119 * bootline and other parameters correctly.
121 int do_bootvx(struct cmd_tbl
*cmdtp
, int flag
, int argc
, char *const argv
[])
123 unsigned long addr
; /* Address of image */
124 unsigned long bootaddr
= 0; /* Address to put the bootline */
125 char *bootline
; /* Text of the bootline */
126 char *tmp
; /* Temporary char pointer */
127 char build_buf
[128]; /* Buffer for building the bootline */
131 struct e820_info
*info
;
132 struct e820_entry
*data
;
133 struct efi_gop_info
*gop
;
134 struct vesa_mode_info
*vesa
= &mode_info
.vesa
;
138 * Check the loadaddr variable.
139 * If we don't know where the image is then we're done.
142 addr
= image_load_addr
;
144 addr
= hextoul(argv
[1], NULL
);
146 #if defined(CONFIG_CMD_NET)
148 * Check to see if we need to tftp the image ourselves
151 if ((argc
== 2) && (strcmp(argv
[1], "tftp") == 0)) {
152 if (net_loop(TFTPGET
) <= 0)
154 printf("Automatic boot of VxWorks image at address 0x%08lx ...\n",
160 * This should equate to
161 * NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
162 * from the VxWorks BSP header files.
163 * This will vary from board to board
165 #if defined(CONFIG_SYS_VXWORKS_MAC_PTR)
166 tmp
= (char *)CONFIG_SYS_VXWORKS_MAC_PTR
;
167 eth_env_get_enetaddr("ethaddr", (uchar
*)build_buf
);
168 memcpy(tmp
, build_buf
, 6);
170 puts("## Ethernet MAC address not copied to NV RAM\n");
175 * Get VxWorks's physical memory base address from environment,
176 * if we don't specify it in the environment, use a default one.
178 base
= env_get_hex("vx_phys_mem_base", VXWORKS_PHYS_MEM_BASE
);
179 data
= (struct e820_entry
*)(base
+ E820_DATA_OFFSET
);
180 info
= (struct e820_info
*)(base
+ E820_INFO_OFFSET
);
182 memset(info
, 0, sizeof(struct e820_info
));
183 info
->sign
= E820_SIGNATURE
;
184 info
->entries
= install_e820_map(E820MAX
, data
);
185 info
->addr
= (info
->entries
- 1) * sizeof(struct e820_entry
) +
189 * Explicitly clear the bootloader image size otherwise if memory
190 * at this offset happens to contain some garbage data, the final
191 * available memory size for the kernel is insane.
193 *(u32
*)(base
+ BOOT_IMAGE_SIZE_OFFSET
) = 0;
196 * Prepare compatible framebuffer information block.
197 * The VESA mode has to be 32-bit RGBA.
199 if (vesa
->x_resolution
&& vesa
->y_resolution
) {
200 gop
= (struct efi_gop_info
*)(base
+ EFI_GOP_INFO_OFFSET
);
201 gop
->magic
= EFI_GOP_INFO_MAGIC
;
202 gop
->info
.version
= 0;
203 gop
->info
.width
= vesa
->x_resolution
;
204 gop
->info
.height
= vesa
->y_resolution
;
205 gop
->info
.pixel_format
= EFI_GOT_RGBA8
;
206 gop
->info
.pixels_per_scanline
= vesa
->bytes_per_scanline
/ 4;
207 gop
->fb_base
= vesa
->phys_base_ptr
;
208 gop
->fb_size
= vesa
->bytes_per_scanline
* vesa
->y_resolution
;
213 * Use bootaddr to find the location in memory that VxWorks
214 * will look for the bootline string. The default value is
215 * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by
216 * VxWorks BSP. For example, on PowerPC it defaults to 0x4200.
218 tmp
= env_get("bootaddr");
221 bootaddr
= base
+ X86_BOOT_LINE_OFFSET
;
223 printf("## VxWorks bootline address not specified\n");
229 bootaddr
= hextoul(tmp
, NULL
);
232 * Check to see if the bootline is defined in the 'bootargs' parameter.
233 * If it is not defined, we may be able to construct the info.
235 bootline
= env_get("bootargs");
237 tmp
= env_get("bootdev");
239 strcpy(build_buf
, tmp
);
242 printf("## VxWorks boot device not specified\n");
245 tmp
= env_get("bootfile");
247 ptr
+= sprintf(build_buf
+ ptr
, "host:%s ", tmp
);
249 ptr
+= sprintf(build_buf
+ ptr
, "host:vxWorks ");
252 * The following parameters are only needed if 'bootdev'
253 * is an ethernet device, otherwise they are optional.
255 tmp
= env_get("ipaddr");
257 ptr
+= sprintf(build_buf
+ ptr
, "e=%s", tmp
);
258 tmp
= env_get("netmask");
260 u32 mask
= env_get_ip("netmask").s_addr
;
261 ptr
+= sprintf(build_buf
+ ptr
,
262 ":%08x ", ntohl(mask
));
264 ptr
+= sprintf(build_buf
+ ptr
, " ");
268 tmp
= env_get("serverip");
270 ptr
+= sprintf(build_buf
+ ptr
, "h=%s ", tmp
);
272 tmp
= env_get("gatewayip");
274 ptr
+= sprintf(build_buf
+ ptr
, "g=%s ", tmp
);
276 tmp
= env_get("hostname");
278 ptr
+= sprintf(build_buf
+ ptr
, "tn=%s ", tmp
);
280 tmp
= env_get("othbootargs");
282 strcpy(build_buf
+ ptr
, tmp
);
286 bootline
= build_buf
;
289 memcpy((void *)bootaddr
, bootline
, max(strlen(bootline
), (size_t)255));
290 flush_cache(bootaddr
, max(strlen(bootline
), (size_t)255));
291 printf("## Using bootline (@ 0x%lx): %s\n", bootaddr
, (char *)bootaddr
);
294 * If the data at the load address is an elf image, then
295 * treat it like an elf image. Otherwise, assume that it is a
298 if (valid_elf_image(addr
))
299 addr
= load_elf_image_phdr(addr
);
301 puts("## Not an ELF image, assuming binary\n");
303 printf("## Starting vxWorks at 0x%08lx ...\n", addr
);
307 #if defined(CONFIG_ARM64) && defined(CONFIG_ARMV8_PSCI)
313 /* VxWorks on x86 uses stack to pass parameters */
314 ((asmlinkage
void (*)(int))addr
)(0);
316 ((void (*)(int))addr
)(0);
319 puts("## vxWorks terminated\n");
325 bootelf
, CONFIG_SYS_MAXARGS
, 0, do_bootelf
,
326 "Boot from an ELF image in memory",
328 #if CONFIG_IS_ENABLED(CMD_ELF_FDT_SETUP)
332 "\t- load ELF image at [address] via program headers (-p)\n"
333 "\t or via section headers (-s)\n"
334 #if CONFIG_IS_ENABLED(CMD_ELF_FDT_SETUP)
335 "\t- setup FDT image at [fdt_addr_r] (-d)"
340 bootvx
, 2, 0, do_bootvx
,
341 "Boot vxWorks from an ELF image",
342 " [address] - load address of vxWorks ELF image."