1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2001 William L. Pitts
3*4882a593Smuzhiyun * All rights reserved.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Redistribution and use in source and binary forms are freely
6*4882a593Smuzhiyun * permitted provided that the above copyright notice and this
7*4882a593Smuzhiyun * paragraph and the following disclaimer are duplicated in all
8*4882a593Smuzhiyun * such forms.
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * This software is provided "AS IS" and without any express or
11*4882a593Smuzhiyun * implied warranties, including, without limitation, the implied
12*4882a593Smuzhiyun * warranties of merchantability and fitness for a particular
13*4882a593Smuzhiyun * purpose.
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <common.h>
17*4882a593Smuzhiyun #include <command.h>
18*4882a593Smuzhiyun #include <elf.h>
19*4882a593Smuzhiyun #include <net.h>
20*4882a593Smuzhiyun #include <vxworks.h>
21*4882a593Smuzhiyun #ifdef CONFIG_X86
22*4882a593Smuzhiyun #include <asm/e820.h>
23*4882a593Smuzhiyun #include <linux/linkage.h>
24*4882a593Smuzhiyun #endif
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /*
27*4882a593Smuzhiyun * A very simple elf loader, assumes the image is valid, returns the
28*4882a593Smuzhiyun * entry point address.
29*4882a593Smuzhiyun */
load_elf_image_phdr(unsigned long addr)30*4882a593Smuzhiyun static unsigned long load_elf_image_phdr(unsigned long addr)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun Elf32_Ehdr *ehdr; /* Elf header structure pointer */
33*4882a593Smuzhiyun Elf32_Phdr *phdr; /* Program header structure pointer */
34*4882a593Smuzhiyun int i;
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun ehdr = (Elf32_Ehdr *)addr;
37*4882a593Smuzhiyun phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /* Load each program header */
40*4882a593Smuzhiyun for (i = 0; i < ehdr->e_phnum; ++i) {
41*4882a593Smuzhiyun void *dst = (void *)(uintptr_t)phdr->p_paddr;
42*4882a593Smuzhiyun void *src = (void *)addr + phdr->p_offset;
43*4882a593Smuzhiyun debug("Loading phdr %i to 0x%p (%i bytes)\n",
44*4882a593Smuzhiyun i, dst, phdr->p_filesz);
45*4882a593Smuzhiyun if (phdr->p_filesz)
46*4882a593Smuzhiyun memcpy(dst, src, phdr->p_filesz);
47*4882a593Smuzhiyun if (phdr->p_filesz != phdr->p_memsz)
48*4882a593Smuzhiyun memset(dst + phdr->p_filesz, 0x00,
49*4882a593Smuzhiyun phdr->p_memsz - phdr->p_filesz);
50*4882a593Smuzhiyun flush_cache((unsigned long)dst, phdr->p_filesz);
51*4882a593Smuzhiyun ++phdr;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun return ehdr->e_entry;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
load_elf_image_shdr(unsigned long addr)57*4882a593Smuzhiyun static unsigned long load_elf_image_shdr(unsigned long addr)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun Elf32_Ehdr *ehdr; /* Elf header structure pointer */
60*4882a593Smuzhiyun Elf32_Shdr *shdr; /* Section header structure pointer */
61*4882a593Smuzhiyun unsigned char *strtab = 0; /* String table pointer */
62*4882a593Smuzhiyun unsigned char *image; /* Binary image pointer */
63*4882a593Smuzhiyun int i; /* Loop counter */
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun ehdr = (Elf32_Ehdr *)addr;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun /* Find the section header string table for output info */
68*4882a593Smuzhiyun shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
69*4882a593Smuzhiyun (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun if (shdr->sh_type == SHT_STRTAB)
72*4882a593Smuzhiyun strtab = (unsigned char *)(addr + shdr->sh_offset);
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* Load each appropriate section */
75*4882a593Smuzhiyun for (i = 0; i < ehdr->e_shnum; ++i) {
76*4882a593Smuzhiyun shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
77*4882a593Smuzhiyun (i * sizeof(Elf32_Shdr)));
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun if (!(shdr->sh_flags & SHF_ALLOC) ||
80*4882a593Smuzhiyun shdr->sh_addr == 0 || shdr->sh_size == 0) {
81*4882a593Smuzhiyun continue;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun if (strtab) {
85*4882a593Smuzhiyun debug("%sing %s @ 0x%08lx (%ld bytes)\n",
86*4882a593Smuzhiyun (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
87*4882a593Smuzhiyun &strtab[shdr->sh_name],
88*4882a593Smuzhiyun (unsigned long)shdr->sh_addr,
89*4882a593Smuzhiyun (long)shdr->sh_size);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun if (shdr->sh_type == SHT_NOBITS) {
93*4882a593Smuzhiyun memset((void *)(uintptr_t)shdr->sh_addr, 0,
94*4882a593Smuzhiyun shdr->sh_size);
95*4882a593Smuzhiyun } else {
96*4882a593Smuzhiyun image = (unsigned char *)addr + shdr->sh_offset;
97*4882a593Smuzhiyun memcpy((void *)(uintptr_t)shdr->sh_addr,
98*4882a593Smuzhiyun (const void *)image, shdr->sh_size);
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun flush_cache(shdr->sh_addr, shdr->sh_size);
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun return ehdr->e_entry;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /* Allow ports to override the default behavior */
do_bootelf_exec(ulong (* entry)(int,char * const[]),int argc,char * const argv[])107*4882a593Smuzhiyun static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
108*4882a593Smuzhiyun int argc, char * const argv[])
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun unsigned long ret;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /*
113*4882a593Smuzhiyun * pass address parameter as argv[0] (aka command name),
114*4882a593Smuzhiyun * and all remaining args
115*4882a593Smuzhiyun */
116*4882a593Smuzhiyun ret = entry(argc, argv);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun return ret;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun /*
122*4882a593Smuzhiyun * Determine if a valid ELF image exists at the given memory location.
123*4882a593Smuzhiyun * First look at the ELF header magic field, then make sure that it is
124*4882a593Smuzhiyun * executable.
125*4882a593Smuzhiyun */
valid_elf_image(unsigned long addr)126*4882a593Smuzhiyun int valid_elf_image(unsigned long addr)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun Elf32_Ehdr *ehdr; /* Elf header structure pointer */
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun ehdr = (Elf32_Ehdr *)addr;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun if (!IS_ELF(*ehdr)) {
133*4882a593Smuzhiyun printf("## No elf image at address 0x%08lx\n", addr);
134*4882a593Smuzhiyun return 0;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun if (ehdr->e_type != ET_EXEC) {
138*4882a593Smuzhiyun printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
139*4882a593Smuzhiyun return 0;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun return 1;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun /* Interpreter command to boot an arbitrary ELF image from memory */
do_bootelf(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])146*4882a593Smuzhiyun int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun unsigned long addr; /* Address of the ELF image */
149*4882a593Smuzhiyun unsigned long rc; /* Return value from user code */
150*4882a593Smuzhiyun char *sload = NULL;
151*4882a593Smuzhiyun const char *ep = env_get("autostart");
152*4882a593Smuzhiyun int rcode = 0;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* Consume 'bootelf' */
155*4882a593Smuzhiyun argc--; argv++;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* Check for flag. */
158*4882a593Smuzhiyun if (argc >= 1 && (argv[0][0] == '-' && \
159*4882a593Smuzhiyun (argv[0][1] == 'p' || argv[0][1] == 's'))) {
160*4882a593Smuzhiyun sload = argv[0];
161*4882a593Smuzhiyun /* Consume flag. */
162*4882a593Smuzhiyun argc--; argv++;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun /* Check for address. */
165*4882a593Smuzhiyun if (argc >= 1 && strict_strtoul(argv[0], 16, &addr) != -EINVAL) {
166*4882a593Smuzhiyun /* Consume address */
167*4882a593Smuzhiyun argc--; argv++;
168*4882a593Smuzhiyun } else
169*4882a593Smuzhiyun addr = load_addr;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (!valid_elf_image(addr))
172*4882a593Smuzhiyun return 1;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun if (sload && sload[1] == 'p')
175*4882a593Smuzhiyun addr = load_elf_image_phdr(addr);
176*4882a593Smuzhiyun else
177*4882a593Smuzhiyun addr = load_elf_image_shdr(addr);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun if (ep && !strcmp(ep, "no"))
180*4882a593Smuzhiyun return rcode;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun printf("## Starting application at 0x%08lx ...\n", addr);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /*
185*4882a593Smuzhiyun * pass address parameter as argv[0] (aka command name),
186*4882a593Smuzhiyun * and all remaining args
187*4882a593Smuzhiyun */
188*4882a593Smuzhiyun rc = do_bootelf_exec((void *)addr, argc, argv);
189*4882a593Smuzhiyun if (rc != 0)
190*4882a593Smuzhiyun rcode = 1;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun printf("## Application terminated, rc = 0x%lx\n", rc);
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun return rcode;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /*
198*4882a593Smuzhiyun * Interpreter command to boot VxWorks from a memory image. The image can
199*4882a593Smuzhiyun * be either an ELF image or a raw binary. Will attempt to setup the
200*4882a593Smuzhiyun * bootline and other parameters correctly.
201*4882a593Smuzhiyun */
do_bootvx(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])202*4882a593Smuzhiyun int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun unsigned long addr; /* Address of image */
205*4882a593Smuzhiyun unsigned long bootaddr; /* Address to put the bootline */
206*4882a593Smuzhiyun char *bootline; /* Text of the bootline */
207*4882a593Smuzhiyun char *tmp; /* Temporary char pointer */
208*4882a593Smuzhiyun char build_buf[128]; /* Buffer for building the bootline */
209*4882a593Smuzhiyun int ptr = 0;
210*4882a593Smuzhiyun #ifdef CONFIG_X86
211*4882a593Smuzhiyun struct e820info *info;
212*4882a593Smuzhiyun struct e820entry *data;
213*4882a593Smuzhiyun #endif
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /*
216*4882a593Smuzhiyun * Check the loadaddr variable.
217*4882a593Smuzhiyun * If we don't know where the image is then we're done.
218*4882a593Smuzhiyun */
219*4882a593Smuzhiyun if (argc < 2)
220*4882a593Smuzhiyun addr = load_addr;
221*4882a593Smuzhiyun else
222*4882a593Smuzhiyun addr = simple_strtoul(argv[1], NULL, 16);
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun #if defined(CONFIG_CMD_NET)
225*4882a593Smuzhiyun /*
226*4882a593Smuzhiyun * Check to see if we need to tftp the image ourselves
227*4882a593Smuzhiyun * before starting
228*4882a593Smuzhiyun */
229*4882a593Smuzhiyun if ((argc == 2) && (strcmp(argv[1], "tftp") == 0)) {
230*4882a593Smuzhiyun if (net_loop(TFTPGET) <= 0)
231*4882a593Smuzhiyun return 1;
232*4882a593Smuzhiyun printf("Automatic boot of VxWorks image at address 0x%08lx ...\n",
233*4882a593Smuzhiyun addr);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun #endif
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun /*
238*4882a593Smuzhiyun * This should equate to
239*4882a593Smuzhiyun * NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
240*4882a593Smuzhiyun * from the VxWorks BSP header files.
241*4882a593Smuzhiyun * This will vary from board to board
242*4882a593Smuzhiyun */
243*4882a593Smuzhiyun #if defined(CONFIG_WALNUT)
244*4882a593Smuzhiyun tmp = (char *)CONFIG_SYS_NVRAM_BASE_ADDR + 0x500;
245*4882a593Smuzhiyun eth_env_get_enetaddr("ethaddr", (uchar *)build_buf);
246*4882a593Smuzhiyun memcpy(tmp, &build_buf[3], 3);
247*4882a593Smuzhiyun #elif defined(CONFIG_SYS_VXWORKS_MAC_PTR)
248*4882a593Smuzhiyun tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR;
249*4882a593Smuzhiyun eth_env_get_enetaddr("ethaddr", (uchar *)build_buf);
250*4882a593Smuzhiyun memcpy(tmp, build_buf, 6);
251*4882a593Smuzhiyun #else
252*4882a593Smuzhiyun puts("## Ethernet MAC address not copied to NV RAM\n");
253*4882a593Smuzhiyun #endif
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /*
256*4882a593Smuzhiyun * Use bootaddr to find the location in memory that VxWorks
257*4882a593Smuzhiyun * will look for the bootline string. The default value is
258*4882a593Smuzhiyun * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by
259*4882a593Smuzhiyun * VxWorks BSP. For example, on PowerPC it defaults to 0x4200.
260*4882a593Smuzhiyun */
261*4882a593Smuzhiyun tmp = env_get("bootaddr");
262*4882a593Smuzhiyun if (!tmp) {
263*4882a593Smuzhiyun printf("## VxWorks bootline address not specified\n");
264*4882a593Smuzhiyun } else {
265*4882a593Smuzhiyun bootaddr = simple_strtoul(tmp, NULL, 16);
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /*
268*4882a593Smuzhiyun * Check to see if the bootline is defined in the 'bootargs'
269*4882a593Smuzhiyun * parameter. If it is not defined, we may be able to
270*4882a593Smuzhiyun * construct the info.
271*4882a593Smuzhiyun */
272*4882a593Smuzhiyun bootline = env_get("bootargs");
273*4882a593Smuzhiyun if (bootline) {
274*4882a593Smuzhiyun memcpy((void *)bootaddr, bootline,
275*4882a593Smuzhiyun max(strlen(bootline), (size_t)255));
276*4882a593Smuzhiyun flush_cache(bootaddr, max(strlen(bootline),
277*4882a593Smuzhiyun (size_t)255));
278*4882a593Smuzhiyun } else {
279*4882a593Smuzhiyun tmp = env_get("bootdev");
280*4882a593Smuzhiyun if (tmp) {
281*4882a593Smuzhiyun strcpy(build_buf, tmp);
282*4882a593Smuzhiyun ptr = strlen(tmp);
283*4882a593Smuzhiyun } else
284*4882a593Smuzhiyun printf("## VxWorks boot device not specified\n");
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun tmp = env_get("bootfile");
287*4882a593Smuzhiyun if (tmp)
288*4882a593Smuzhiyun ptr += sprintf(build_buf + ptr,
289*4882a593Smuzhiyun "host:%s ", tmp);
290*4882a593Smuzhiyun else
291*4882a593Smuzhiyun ptr += sprintf(build_buf + ptr,
292*4882a593Smuzhiyun "host:vxWorks ");
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun /*
295*4882a593Smuzhiyun * The following parameters are only needed if 'bootdev'
296*4882a593Smuzhiyun * is an ethernet device, otherwise they are optional.
297*4882a593Smuzhiyun */
298*4882a593Smuzhiyun tmp = env_get("ipaddr");
299*4882a593Smuzhiyun if (tmp) {
300*4882a593Smuzhiyun ptr += sprintf(build_buf + ptr, "e=%s", tmp);
301*4882a593Smuzhiyun tmp = env_get("netmask");
302*4882a593Smuzhiyun if (tmp) {
303*4882a593Smuzhiyun u32 mask = env_get_ip("netmask").s_addr;
304*4882a593Smuzhiyun ptr += sprintf(build_buf + ptr,
305*4882a593Smuzhiyun ":%08x ", ntohl(mask));
306*4882a593Smuzhiyun } else {
307*4882a593Smuzhiyun ptr += sprintf(build_buf + ptr, " ");
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun tmp = env_get("serverip");
312*4882a593Smuzhiyun if (tmp)
313*4882a593Smuzhiyun ptr += sprintf(build_buf + ptr, "h=%s ", tmp);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun tmp = env_get("gatewayip");
316*4882a593Smuzhiyun if (tmp)
317*4882a593Smuzhiyun ptr += sprintf(build_buf + ptr, "g=%s ", tmp);
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun tmp = env_get("hostname");
320*4882a593Smuzhiyun if (tmp)
321*4882a593Smuzhiyun ptr += sprintf(build_buf + ptr, "tn=%s ", tmp);
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun tmp = env_get("othbootargs");
324*4882a593Smuzhiyun if (tmp) {
325*4882a593Smuzhiyun strcpy(build_buf + ptr, tmp);
326*4882a593Smuzhiyun ptr += strlen(tmp);
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun memcpy((void *)bootaddr, build_buf,
330*4882a593Smuzhiyun max(strlen(build_buf), (size_t)255));
331*4882a593Smuzhiyun flush_cache(bootaddr, max(strlen(build_buf),
332*4882a593Smuzhiyun (size_t)255));
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun printf("## Using bootline (@ 0x%lx): %s\n", bootaddr,
336*4882a593Smuzhiyun (char *)bootaddr);
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun #ifdef CONFIG_X86
340*4882a593Smuzhiyun /*
341*4882a593Smuzhiyun * Since E820 information is critical to the kernel, if we don't
342*4882a593Smuzhiyun * specify these in the environments, use a default one.
343*4882a593Smuzhiyun */
344*4882a593Smuzhiyun tmp = env_get("e820data");
345*4882a593Smuzhiyun if (tmp)
346*4882a593Smuzhiyun data = (struct e820entry *)simple_strtoul(tmp, NULL, 16);
347*4882a593Smuzhiyun else
348*4882a593Smuzhiyun data = (struct e820entry *)VXWORKS_E820_DATA_ADDR;
349*4882a593Smuzhiyun tmp = env_get("e820info");
350*4882a593Smuzhiyun if (tmp)
351*4882a593Smuzhiyun info = (struct e820info *)simple_strtoul(tmp, NULL, 16);
352*4882a593Smuzhiyun else
353*4882a593Smuzhiyun info = (struct e820info *)VXWORKS_E820_INFO_ADDR;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun memset(info, 0, sizeof(struct e820info));
356*4882a593Smuzhiyun info->sign = E820_SIGNATURE;
357*4882a593Smuzhiyun info->entries = install_e820_map(E820MAX, data);
358*4882a593Smuzhiyun info->addr = (info->entries - 1) * sizeof(struct e820entry) +
359*4882a593Smuzhiyun VXWORKS_E820_DATA_ADDR;
360*4882a593Smuzhiyun #endif
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun /*
363*4882a593Smuzhiyun * If the data at the load address is an elf image, then
364*4882a593Smuzhiyun * treat it like an elf image. Otherwise, assume that it is a
365*4882a593Smuzhiyun * binary image.
366*4882a593Smuzhiyun */
367*4882a593Smuzhiyun if (valid_elf_image(addr))
368*4882a593Smuzhiyun addr = load_elf_image_shdr(addr);
369*4882a593Smuzhiyun else
370*4882a593Smuzhiyun puts("## Not an ELF image, assuming binary\n");
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun printf("## Starting vxWorks at 0x%08lx ...\n", addr);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun dcache_disable();
375*4882a593Smuzhiyun #ifdef CONFIG_X86
376*4882a593Smuzhiyun /* VxWorks on x86 uses stack to pass parameters */
377*4882a593Smuzhiyun ((asmlinkage void (*)(int))addr)(0);
378*4882a593Smuzhiyun #else
379*4882a593Smuzhiyun ((void (*)(int))addr)(0);
380*4882a593Smuzhiyun #endif
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun puts("## vxWorks terminated\n");
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun return 1;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun U_BOOT_CMD(
388*4882a593Smuzhiyun bootelf, CONFIG_SYS_MAXARGS, 0, do_bootelf,
389*4882a593Smuzhiyun "Boot from an ELF image in memory",
390*4882a593Smuzhiyun "[-p|-s] [address]\n"
391*4882a593Smuzhiyun "\t- load ELF image at [address] via program headers (-p)\n"
392*4882a593Smuzhiyun "\t or via section headers (-s)"
393*4882a593Smuzhiyun );
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun U_BOOT_CMD(
396*4882a593Smuzhiyun bootvx, 2, 0, do_bootvx,
397*4882a593Smuzhiyun "Boot vxWorks from an ELF image",
398*4882a593Smuzhiyun " [address] - load address of vxWorks ELF image."
399*4882a593Smuzhiyun );
400