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