1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <common.h>
17#include <command.h>
18#include <elf.h>
19#include <environment.h>
20#include <net.h>
21#include <vxworks.h>
22#ifdef CONFIG_X86
23#include <vbe.h>
24#include <asm/e820.h>
25#include <linux/linkage.h>
26#endif
27
28
29
30
31
32
33
34
35static unsigned long load_elf64_image_phdr(unsigned long addr)
36{
37 Elf64_Ehdr *ehdr;
38 Elf64_Phdr *phdr;
39 int i;
40
41 ehdr = (Elf64_Ehdr *)addr;
42 phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
43
44
45 for (i = 0; i < ehdr->e_phnum; ++i) {
46 void *dst = (void *)(ulong)phdr->p_paddr;
47 void *src = (void *)addr + phdr->p_offset;
48
49 debug("Loading phdr %i to 0x%p (%lu bytes)\n",
50 i, dst, (ulong)phdr->p_filesz);
51 if (phdr->p_filesz)
52 memcpy(dst, src, phdr->p_filesz);
53 if (phdr->p_filesz != phdr->p_memsz)
54 memset(dst + phdr->p_filesz, 0x00,
55 phdr->p_memsz - phdr->p_filesz);
56 flush_cache((unsigned long)dst, phdr->p_filesz);
57 ++phdr;
58 }
59
60 if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
61 EF_PPC64_ELFV1_ABI)) {
62
63
64
65
66
67 uintptr_t addr = ehdr->e_entry;
68
69 return *(Elf64_Addr *)addr;
70 }
71
72 return ehdr->e_entry;
73}
74
75static unsigned long load_elf64_image_shdr(unsigned long addr)
76{
77 Elf64_Ehdr *ehdr;
78 Elf64_Shdr *shdr;
79 unsigned char *strtab = 0;
80 unsigned char *image;
81 int i;
82
83 ehdr = (Elf64_Ehdr *)addr;
84
85
86 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
87 (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
88
89 if (shdr->sh_type == SHT_STRTAB)
90 strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
91
92
93 for (i = 0; i < ehdr->e_shnum; ++i) {
94 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
95 (i * sizeof(Elf64_Shdr)));
96
97 if (!(shdr->sh_flags & SHF_ALLOC) ||
98 shdr->sh_addr == 0 || shdr->sh_size == 0) {
99 continue;
100 }
101
102 if (strtab) {
103 debug("%sing %s @ 0x%08lx (%ld bytes)\n",
104 (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
105 &strtab[shdr->sh_name],
106 (unsigned long)shdr->sh_addr,
107 (long)shdr->sh_size);
108 }
109
110 if (shdr->sh_type == SHT_NOBITS) {
111 memset((void *)(uintptr_t)shdr->sh_addr, 0,
112 shdr->sh_size);
113 } else {
114 image = (unsigned char *)addr + (ulong)shdr->sh_offset;
115 memcpy((void *)(uintptr_t)shdr->sh_addr,
116 (const void *)image, shdr->sh_size);
117 }
118 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
119 roundup((shdr->sh_addr + shdr->sh_size),
120 ARCH_DMA_MINALIGN) -
121 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
122 }
123
124 if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
125 EF_PPC64_ELFV1_ABI)) {
126
127
128
129
130
131 uintptr_t addr = ehdr->e_entry;
132
133 return *(Elf64_Addr *)addr;
134 }
135
136 return ehdr->e_entry;
137}
138
139
140
141
142
143
144
145
146static unsigned long load_elf_image_phdr(unsigned long addr)
147{
148 Elf32_Ehdr *ehdr;
149 Elf32_Phdr *phdr;
150 int i;
151
152 ehdr = (Elf32_Ehdr *)addr;
153 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
154 return load_elf64_image_phdr(addr);
155
156 phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
157
158
159 for (i = 0; i < ehdr->e_phnum; ++i) {
160 void *dst = (void *)(uintptr_t)phdr->p_paddr;
161 void *src = (void *)addr + phdr->p_offset;
162
163 debug("Loading phdr %i to 0x%p (%i bytes)\n",
164 i, dst, phdr->p_filesz);
165 if (phdr->p_filesz)
166 memcpy(dst, src, phdr->p_filesz);
167 if (phdr->p_filesz != phdr->p_memsz)
168 memset(dst + phdr->p_filesz, 0x00,
169 phdr->p_memsz - phdr->p_filesz);
170 flush_cache((unsigned long)dst, phdr->p_filesz);
171 ++phdr;
172 }
173
174 return ehdr->e_entry;
175}
176
177static unsigned long load_elf_image_shdr(unsigned long addr)
178{
179 Elf32_Ehdr *ehdr;
180 Elf32_Shdr *shdr;
181 unsigned char *strtab = 0;
182 unsigned char *image;
183 int i;
184
185 ehdr = (Elf32_Ehdr *)addr;
186 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
187 return load_elf64_image_shdr(addr);
188
189
190 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
191 (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
192
193 if (shdr->sh_type == SHT_STRTAB)
194 strtab = (unsigned char *)(addr + shdr->sh_offset);
195
196
197 for (i = 0; i < ehdr->e_shnum; ++i) {
198 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
199 (i * sizeof(Elf32_Shdr)));
200
201 if (!(shdr->sh_flags & SHF_ALLOC) ||
202 shdr->sh_addr == 0 || shdr->sh_size == 0) {
203 continue;
204 }
205
206 if (strtab) {
207 debug("%sing %s @ 0x%08lx (%ld bytes)\n",
208 (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
209 &strtab[shdr->sh_name],
210 (unsigned long)shdr->sh_addr,
211 (long)shdr->sh_size);
212 }
213
214 if (shdr->sh_type == SHT_NOBITS) {
215 memset((void *)(uintptr_t)shdr->sh_addr, 0,
216 shdr->sh_size);
217 } else {
218 image = (unsigned char *)addr + shdr->sh_offset;
219 memcpy((void *)(uintptr_t)shdr->sh_addr,
220 (const void *)image, shdr->sh_size);
221 }
222 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
223 roundup((shdr->sh_addr + shdr->sh_size),
224 ARCH_DMA_MINALIGN) -
225 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
226 }
227
228 return ehdr->e_entry;
229}
230
231
232static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
233 int argc, char * const argv[])
234{
235 unsigned long ret;
236
237
238
239
240
241 ret = entry(argc, argv);
242
243 return ret;
244}
245
246
247
248
249
250
251int valid_elf_image(unsigned long addr)
252{
253 Elf32_Ehdr *ehdr;
254
255 ehdr = (Elf32_Ehdr *)addr;
256
257 if (!IS_ELF(*ehdr)) {
258 printf("## No elf image at address 0x%08lx\n", addr);
259 return 0;
260 }
261
262 if (ehdr->e_type != ET_EXEC) {
263 printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
264 return 0;
265 }
266
267 return 1;
268}
269
270
271int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
272{
273 unsigned long addr;
274 unsigned long rc;
275 char *sload = NULL;
276 const char *ep = env_get("autostart");
277 int rcode = 0;
278
279
280 argc--; argv++;
281
282
283 if (argc >= 1 && (argv[0][0] == '-' && \
284 (argv[0][1] == 'p' || argv[0][1] == 's'))) {
285 sload = argv[0];
286
287 argc--; argv++;
288 }
289
290 if (argc >= 1 && strict_strtoul(argv[0], 16, &addr) != -EINVAL) {
291
292 argc--; argv++;
293 } else
294 addr = load_addr;
295
296 if (!valid_elf_image(addr))
297 return 1;
298
299 if (sload && sload[1] == 'p')
300 addr = load_elf_image_phdr(addr);
301 else
302 addr = load_elf_image_shdr(addr);
303
304 if (ep && !strcmp(ep, "no"))
305 return rcode;
306
307 printf("## Starting application at 0x%08lx ...\n", addr);
308
309
310
311
312
313 rc = do_bootelf_exec((void *)addr, argc, argv);
314 if (rc != 0)
315 rcode = 1;
316
317 printf("## Application terminated, rc = 0x%lx\n", rc);
318
319 return rcode;
320}
321
322
323
324
325
326
327int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
328{
329 unsigned long addr;
330 unsigned long bootaddr = 0;
331 char *bootline;
332 char *tmp;
333 char build_buf[128];
334 int ptr = 0;
335#ifdef CONFIG_X86
336 ulong base;
337 struct e820_info *info;
338 struct e820_entry *data;
339 struct efi_gop_info *gop;
340 struct vesa_mode_info *vesa = &mode_info.vesa;
341#endif
342
343
344
345
346
347 if (argc < 2)
348 addr = load_addr;
349 else
350 addr = simple_strtoul(argv[1], NULL, 16);
351
352#if defined(CONFIG_CMD_NET)
353
354
355
356
357 if ((argc == 2) && (strcmp(argv[1], "tftp") == 0)) {
358 if (net_loop(TFTPGET) <= 0)
359 return 1;
360 printf("Automatic boot of VxWorks image at address 0x%08lx ...\n",
361 addr);
362 }
363#endif
364
365
366
367
368
369
370
371#if defined(CONFIG_SYS_VXWORKS_MAC_PTR)
372 tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR;
373 eth_env_get_enetaddr("ethaddr", (uchar *)build_buf);
374 memcpy(tmp, build_buf, 6);
375#else
376 puts("## Ethernet MAC address not copied to NV RAM\n");
377#endif
378
379#ifdef CONFIG_X86
380
381
382
383
384 base = env_get_hex("vx_phys_mem_base", VXWORKS_PHYS_MEM_BASE);
385 data = (struct e820_entry *)(base + E820_DATA_OFFSET);
386 info = (struct e820_info *)(base + E820_INFO_OFFSET);
387
388 memset(info, 0, sizeof(struct e820_info));
389 info->sign = E820_SIGNATURE;
390 info->entries = install_e820_map(E820MAX, data);
391 info->addr = (info->entries - 1) * sizeof(struct e820_entry) +
392 E820_DATA_OFFSET;
393
394
395
396
397
398
399 *(u32 *)(base + BOOT_IMAGE_SIZE_OFFSET) = 0;
400
401
402
403
404
405 if (vesa->x_resolution && vesa->y_resolution) {
406 gop = (struct efi_gop_info *)(base + EFI_GOP_INFO_OFFSET);
407 gop->magic = EFI_GOP_INFO_MAGIC;
408 gop->info.version = 0;
409 gop->info.width = vesa->x_resolution;
410 gop->info.height = vesa->y_resolution;
411 gop->info.pixel_format = EFI_GOT_RGBA8;
412 gop->info.pixels_per_scanline = vesa->bytes_per_scanline / 4;
413 gop->fb_base = vesa->phys_base_ptr;
414 gop->fb_size = vesa->bytes_per_scanline * vesa->y_resolution;
415 }
416#endif
417
418
419
420
421
422
423
424 tmp = env_get("bootaddr");
425 if (!tmp) {
426#ifdef CONFIG_X86
427 bootaddr = base + X86_BOOT_LINE_OFFSET;
428#else
429 printf("## VxWorks bootline address not specified\n");
430 return 1;
431#endif
432 }
433
434 if (!bootaddr)
435 bootaddr = simple_strtoul(tmp, NULL, 16);
436
437
438
439
440
441 bootline = env_get("bootargs");
442 if (!bootline) {
443 tmp = env_get("bootdev");
444 if (tmp) {
445 strcpy(build_buf, tmp);
446 ptr = strlen(tmp);
447 } else {
448 printf("## VxWorks boot device not specified\n");
449 }
450
451 tmp = env_get("bootfile");
452 if (tmp)
453 ptr += sprintf(build_buf + ptr, "host:%s ", tmp);
454 else
455 ptr += sprintf(build_buf + ptr, "host:vxWorks ");
456
457
458
459
460
461 tmp = env_get("ipaddr");
462 if (tmp) {
463 ptr += sprintf(build_buf + ptr, "e=%s", tmp);
464 tmp = env_get("netmask");
465 if (tmp) {
466 u32 mask = env_get_ip("netmask").s_addr;
467 ptr += sprintf(build_buf + ptr,
468 ":%08x ", ntohl(mask));
469 } else {
470 ptr += sprintf(build_buf + ptr, " ");
471 }
472 }
473
474 tmp = env_get("serverip");
475 if (tmp)
476 ptr += sprintf(build_buf + ptr, "h=%s ", tmp);
477
478 tmp = env_get("gatewayip");
479 if (tmp)
480 ptr += sprintf(build_buf + ptr, "g=%s ", tmp);
481
482 tmp = env_get("hostname");
483 if (tmp)
484 ptr += sprintf(build_buf + ptr, "tn=%s ", tmp);
485
486 tmp = env_get("othbootargs");
487 if (tmp) {
488 strcpy(build_buf + ptr, tmp);
489 ptr += strlen(tmp);
490 }
491
492 bootline = build_buf;
493 }
494
495 memcpy((void *)bootaddr, bootline, max(strlen(bootline), (size_t)255));
496 flush_cache(bootaddr, max(strlen(bootline), (size_t)255));
497 printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, (char *)bootaddr);
498
499
500
501
502
503
504 if (valid_elf_image(addr))
505 addr = load_elf_image_phdr(addr);
506 else
507 puts("## Not an ELF image, assuming binary\n");
508
509 printf("## Starting vxWorks at 0x%08lx ...\n", addr);
510
511 dcache_disable();
512#if defined(CONFIG_ARM64) && defined(CONFIG_ARMV8_PSCI)
513 armv8_setup_psci();
514 smp_kick_all_cpus();
515#endif
516
517#ifdef CONFIG_X86
518
519 ((asmlinkage void (*)(int))addr)(0);
520#else
521 ((void (*)(int))addr)(0);
522#endif
523
524 puts("## vxWorks terminated\n");
525
526 return 1;
527}
528
529U_BOOT_CMD(
530 bootelf, CONFIG_SYS_MAXARGS, 0, do_bootelf,
531 "Boot from an ELF image in memory",
532 "[-p|-s] [address]\n"
533 "\t- load ELF image at [address] via program headers (-p)\n"
534 "\t or via section headers (-s)"
535);
536
537U_BOOT_CMD(
538 bootvx, 2, 0, do_bootvx,
539 "Boot vxWorks from an ELF image",
540 " [address] - load address of vxWorks ELF image."
541);
542