xref: /OK3568_Linux_fs/u-boot/cmd/elf.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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