image: Rename load_addr, save_addr, save_size
[oweals/u-boot.git] / cmd / elf.c
1 /*
2  * Copyright (c) 2001 William L. Pitts
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are freely
6  * permitted provided that the above copyright notice and this
7  * paragraph and the following disclaimer are duplicated in all
8  * such forms.
9  *
10  * This software is provided "AS IS" and without any express or
11  * implied warranties, including, without limitation, the implied
12  * warranties of merchantability and fitness for a particular
13  * purpose.
14  */
15
16 #include <common.h>
17 #include <command.h>
18 #include <cpu_func.h>
19 #include <elf.h>
20 #include <env.h>
21 #include <net.h>
22 #include <vxworks.h>
23 #ifdef CONFIG_X86
24 #include <vbe.h>
25 #include <asm/e820.h>
26 #include <linux/linkage.h>
27 #endif
28
29 /*
30  * A very simple ELF64 loader, assumes the image is valid, returns the
31  * entry point address.
32  *
33  * Note if U-Boot is 32-bit, the loader assumes the to segment's
34  * physical address and size is within the lower 32-bit address space.
35  */
36 static unsigned long load_elf64_image_phdr(unsigned long addr)
37 {
38         Elf64_Ehdr *ehdr; /* Elf header structure pointer */
39         Elf64_Phdr *phdr; /* Program header structure pointer */
40         int i;
41
42         ehdr = (Elf64_Ehdr *)addr;
43         phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
44
45         /* Load each program header */
46         for (i = 0; i < ehdr->e_phnum; ++i) {
47                 void *dst = (void *)(ulong)phdr->p_paddr;
48                 void *src = (void *)addr + phdr->p_offset;
49
50                 debug("Loading phdr %i to 0x%p (%lu bytes)\n",
51                       i, dst, (ulong)phdr->p_filesz);
52                 if (phdr->p_filesz)
53                         memcpy(dst, src, phdr->p_filesz);
54                 if (phdr->p_filesz != phdr->p_memsz)
55                         memset(dst + phdr->p_filesz, 0x00,
56                                phdr->p_memsz - phdr->p_filesz);
57                 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
58                             roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
59                 ++phdr;
60         }
61
62         if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
63                                             EF_PPC64_ELFV1_ABI)) {
64                 /*
65                  * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
66                  * descriptor pointer with the first double word being the
67                  * address of the entry point of the function.
68                  */
69                 uintptr_t addr = ehdr->e_entry;
70
71                 return *(Elf64_Addr *)addr;
72         }
73
74         return ehdr->e_entry;
75 }
76
77 static unsigned long load_elf64_image_shdr(unsigned long addr)
78 {
79         Elf64_Ehdr *ehdr; /* Elf header structure pointer */
80         Elf64_Shdr *shdr; /* Section header structure pointer */
81         unsigned char *strtab = 0; /* String table pointer */
82         unsigned char *image; /* Binary image pointer */
83         int i; /* Loop counter */
84
85         ehdr = (Elf64_Ehdr *)addr;
86
87         /* Find the section header string table for output info */
88         shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
89                              (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
90
91         if (shdr->sh_type == SHT_STRTAB)
92                 strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
93
94         /* Load each appropriate section */
95         for (i = 0; i < ehdr->e_shnum; ++i) {
96                 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
97                                      (i * sizeof(Elf64_Shdr)));
98
99                 if (!(shdr->sh_flags & SHF_ALLOC) ||
100                     shdr->sh_addr == 0 || shdr->sh_size == 0) {
101                         continue;
102                 }
103
104                 if (strtab) {
105                         debug("%sing %s @ 0x%08lx (%ld bytes)\n",
106                               (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
107                                &strtab[shdr->sh_name],
108                                (unsigned long)shdr->sh_addr,
109                                (long)shdr->sh_size);
110                 }
111
112                 if (shdr->sh_type == SHT_NOBITS) {
113                         memset((void *)(uintptr_t)shdr->sh_addr, 0,
114                                shdr->sh_size);
115                 } else {
116                         image = (unsigned char *)addr + (ulong)shdr->sh_offset;
117                         memcpy((void *)(uintptr_t)shdr->sh_addr,
118                                (const void *)image, shdr->sh_size);
119                 }
120                 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
121                             roundup((shdr->sh_addr + shdr->sh_size),
122                                      ARCH_DMA_MINALIGN) -
123                                     rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
124         }
125
126         if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
127                                             EF_PPC64_ELFV1_ABI)) {
128                 /*
129                  * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
130                  * descriptor pointer with the first double word being the
131                  * address of the entry point of the function.
132                  */
133                 uintptr_t addr = ehdr->e_entry;
134
135                 return *(Elf64_Addr *)addr;
136         }
137
138         return ehdr->e_entry;
139 }
140
141 /*
142  * A very simple ELF loader, assumes the image is valid, returns the
143  * entry point address.
144  *
145  * The loader firstly reads the EFI class to see if it's a 64-bit image.
146  * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
147  */
148 static unsigned long load_elf_image_phdr(unsigned long addr)
149 {
150         Elf32_Ehdr *ehdr; /* Elf header structure pointer */
151         Elf32_Phdr *phdr; /* Program header structure pointer */
152         int i;
153
154         ehdr = (Elf32_Ehdr *)addr;
155         if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
156                 return load_elf64_image_phdr(addr);
157
158         phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
159
160         /* Load each program header */
161         for (i = 0; i < ehdr->e_phnum; ++i) {
162                 void *dst = (void *)(uintptr_t)phdr->p_paddr;
163                 void *src = (void *)addr + phdr->p_offset;
164
165                 debug("Loading phdr %i to 0x%p (%i bytes)\n",
166                       i, dst, phdr->p_filesz);
167                 if (phdr->p_filesz)
168                         memcpy(dst, src, phdr->p_filesz);
169                 if (phdr->p_filesz != phdr->p_memsz)
170                         memset(dst + phdr->p_filesz, 0x00,
171                                phdr->p_memsz - phdr->p_filesz);
172                 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
173                             roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
174                 ++phdr;
175         }
176
177         return ehdr->e_entry;
178 }
179
180 static unsigned long load_elf_image_shdr(unsigned long addr)
181 {
182         Elf32_Ehdr *ehdr; /* Elf header structure pointer */
183         Elf32_Shdr *shdr; /* Section header structure pointer */
184         unsigned char *strtab = 0; /* String table pointer */
185         unsigned char *image; /* Binary image pointer */
186         int i; /* Loop counter */
187
188         ehdr = (Elf32_Ehdr *)addr;
189         if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
190                 return load_elf64_image_shdr(addr);
191
192         /* Find the section header string table for output info */
193         shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
194                              (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
195
196         if (shdr->sh_type == SHT_STRTAB)
197                 strtab = (unsigned char *)(addr + shdr->sh_offset);
198
199         /* Load each appropriate section */
200         for (i = 0; i < ehdr->e_shnum; ++i) {
201                 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
202                                      (i * sizeof(Elf32_Shdr)));
203
204                 if (!(shdr->sh_flags & SHF_ALLOC) ||
205                     shdr->sh_addr == 0 || shdr->sh_size == 0) {
206                         continue;
207                 }
208
209                 if (strtab) {
210                         debug("%sing %s @ 0x%08lx (%ld bytes)\n",
211                               (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
212                                &strtab[shdr->sh_name],
213                                (unsigned long)shdr->sh_addr,
214                                (long)shdr->sh_size);
215                 }
216
217                 if (shdr->sh_type == SHT_NOBITS) {
218                         memset((void *)(uintptr_t)shdr->sh_addr, 0,
219                                shdr->sh_size);
220                 } else {
221                         image = (unsigned char *)addr + shdr->sh_offset;
222                         memcpy((void *)(uintptr_t)shdr->sh_addr,
223                                (const void *)image, shdr->sh_size);
224                 }
225                 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
226                             roundup((shdr->sh_addr + shdr->sh_size),
227                                     ARCH_DMA_MINALIGN) -
228                             rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
229         }
230
231         return ehdr->e_entry;
232 }
233
234 /* Allow ports to override the default behavior */
235 static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
236                                      int argc, char * const argv[])
237 {
238         unsigned long ret;
239
240         /*
241          * pass address parameter as argv[0] (aka command name),
242          * and all remaining args
243          */
244         ret = entry(argc, argv);
245
246         return ret;
247 }
248
249 /*
250  * Determine if a valid ELF image exists at the given memory location.
251  * First look at the ELF header magic field, then make sure that it is
252  * executable.
253  */
254 int valid_elf_image(unsigned long addr)
255 {
256         Elf32_Ehdr *ehdr; /* Elf header structure pointer */
257
258         ehdr = (Elf32_Ehdr *)addr;
259
260         if (!IS_ELF(*ehdr)) {
261                 printf("## No elf image at address 0x%08lx\n", addr);
262                 return 0;
263         }
264
265         if (ehdr->e_type != ET_EXEC) {
266                 printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
267                 return 0;
268         }
269
270         return 1;
271 }
272
273 /* Interpreter command to boot an arbitrary ELF image from memory */
274 int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
275 {
276         unsigned long addr; /* Address of the ELF image */
277         unsigned long rc; /* Return value from user code */
278         char *sload = NULL;
279         const char *ep = env_get("autostart");
280         int rcode = 0;
281
282         /* Consume 'bootelf' */
283         argc--; argv++;
284
285         /* Check for flag. */
286         if (argc >= 1 && (argv[0][0] == '-' && \
287                                 (argv[0][1] == 'p' || argv[0][1] == 's'))) {
288                 sload = argv[0];
289                 /* Consume flag. */
290                 argc--; argv++;
291         }
292         /* Check for address. */
293         if (argc >= 1 && strict_strtoul(argv[0], 16, &addr) != -EINVAL) {
294                 /* Consume address */
295                 argc--; argv++;
296         } else
297                 addr = image_load_addr;
298
299         if (!valid_elf_image(addr))
300                 return 1;
301
302         if (sload && sload[1] == 'p')
303                 addr = load_elf_image_phdr(addr);
304         else
305                 addr = load_elf_image_shdr(addr);
306
307         if (ep && !strcmp(ep, "no"))
308                 return rcode;
309
310         printf("## Starting application at 0x%08lx ...\n", addr);
311
312         /*
313          * pass address parameter as argv[0] (aka command name),
314          * and all remaining args
315          */
316         rc = do_bootelf_exec((void *)addr, argc, argv);
317         if (rc != 0)
318                 rcode = 1;
319
320         printf("## Application terminated, rc = 0x%lx\n", rc);
321
322         return rcode;
323 }
324
325 /*
326  * Interpreter command to boot VxWorks from a memory image.  The image can
327  * be either an ELF image or a raw binary.  Will attempt to setup the
328  * bootline and other parameters correctly.
329  */
330 int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
331 {
332         unsigned long addr; /* Address of image */
333         unsigned long bootaddr = 0; /* Address to put the bootline */
334         char *bootline; /* Text of the bootline */
335         char *tmp; /* Temporary char pointer */
336         char build_buf[128]; /* Buffer for building the bootline */
337         int ptr = 0;
338 #ifdef CONFIG_X86
339         ulong base;
340         struct e820_info *info;
341         struct e820_entry *data;
342         struct efi_gop_info *gop;
343         struct vesa_mode_info *vesa = &mode_info.vesa;
344 #endif
345
346         /*
347          * Check the loadaddr variable.
348          * If we don't know where the image is then we're done.
349          */
350         if (argc < 2)
351                 addr = image_load_addr;
352         else
353                 addr = simple_strtoul(argv[1], NULL, 16);
354
355 #if defined(CONFIG_CMD_NET)
356         /*
357          * Check to see if we need to tftp the image ourselves
358          * before starting
359          */
360         if ((argc == 2) && (strcmp(argv[1], "tftp") == 0)) {
361                 if (net_loop(TFTPGET) <= 0)
362                         return 1;
363                 printf("Automatic boot of VxWorks image at address 0x%08lx ...\n",
364                         addr);
365         }
366 #endif
367
368         /*
369          * This should equate to
370          * NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
371          * from the VxWorks BSP header files.
372          * This will vary from board to board
373          */
374 #if defined(CONFIG_SYS_VXWORKS_MAC_PTR)
375         tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR;
376         eth_env_get_enetaddr("ethaddr", (uchar *)build_buf);
377         memcpy(tmp, build_buf, 6);
378 #else
379         puts("## Ethernet MAC address not copied to NV RAM\n");
380 #endif
381
382 #ifdef CONFIG_X86
383         /*
384          * Get VxWorks's physical memory base address from environment,
385          * if we don't specify it in the environment, use a default one.
386          */
387         base = env_get_hex("vx_phys_mem_base", VXWORKS_PHYS_MEM_BASE);
388         data = (struct e820_entry *)(base + E820_DATA_OFFSET);
389         info = (struct e820_info *)(base + E820_INFO_OFFSET);
390
391         memset(info, 0, sizeof(struct e820_info));
392         info->sign = E820_SIGNATURE;
393         info->entries = install_e820_map(E820MAX, data);
394         info->addr = (info->entries - 1) * sizeof(struct e820_entry) +
395                      E820_DATA_OFFSET;
396
397         /*
398          * Explicitly clear the bootloader image size otherwise if memory
399          * at this offset happens to contain some garbage data, the final
400          * available memory size for the kernel is insane.
401          */
402         *(u32 *)(base + BOOT_IMAGE_SIZE_OFFSET) = 0;
403
404         /*
405          * Prepare compatible framebuffer information block.
406          * The VESA mode has to be 32-bit RGBA.
407          */
408         if (vesa->x_resolution && vesa->y_resolution) {
409                 gop = (struct efi_gop_info *)(base + EFI_GOP_INFO_OFFSET);
410                 gop->magic = EFI_GOP_INFO_MAGIC;
411                 gop->info.version = 0;
412                 gop->info.width = vesa->x_resolution;
413                 gop->info.height = vesa->y_resolution;
414                 gop->info.pixel_format = EFI_GOT_RGBA8;
415                 gop->info.pixels_per_scanline = vesa->bytes_per_scanline / 4;
416                 gop->fb_base = vesa->phys_base_ptr;
417                 gop->fb_size = vesa->bytes_per_scanline * vesa->y_resolution;
418         }
419 #endif
420
421         /*
422          * Use bootaddr to find the location in memory that VxWorks
423          * will look for the bootline string. The default value is
424          * (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by
425          * VxWorks BSP. For example, on PowerPC it defaults to 0x4200.
426          */
427         tmp = env_get("bootaddr");
428         if (!tmp) {
429 #ifdef CONFIG_X86
430                 bootaddr = base + X86_BOOT_LINE_OFFSET;
431 #else
432                 printf("## VxWorks bootline address not specified\n");
433                 return 1;
434 #endif
435         }
436
437         if (!bootaddr)
438                 bootaddr = simple_strtoul(tmp, NULL, 16);
439
440         /*
441          * Check to see if the bootline is defined in the 'bootargs' parameter.
442          * If it is not defined, we may be able to construct the info.
443          */
444         bootline = env_get("bootargs");
445         if (!bootline) {
446                 tmp = env_get("bootdev");
447                 if (tmp) {
448                         strcpy(build_buf, tmp);
449                         ptr = strlen(tmp);
450                 } else {
451                         printf("## VxWorks boot device not specified\n");
452                 }
453
454                 tmp = env_get("bootfile");
455                 if (tmp)
456                         ptr += sprintf(build_buf + ptr, "host:%s ", tmp);
457                 else
458                         ptr += sprintf(build_buf + ptr, "host:vxWorks ");
459
460                 /*
461                  * The following parameters are only needed if 'bootdev'
462                  * is an ethernet device, otherwise they are optional.
463                  */
464                 tmp = env_get("ipaddr");
465                 if (tmp) {
466                         ptr += sprintf(build_buf + ptr, "e=%s", tmp);
467                         tmp = env_get("netmask");
468                         if (tmp) {
469                                 u32 mask = env_get_ip("netmask").s_addr;
470                                 ptr += sprintf(build_buf + ptr,
471                                                ":%08x ", ntohl(mask));
472                         } else {
473                                 ptr += sprintf(build_buf + ptr, " ");
474                         }
475                 }
476
477                 tmp = env_get("serverip");
478                 if (tmp)
479                         ptr += sprintf(build_buf + ptr, "h=%s ", tmp);
480
481                 tmp = env_get("gatewayip");
482                 if (tmp)
483                         ptr += sprintf(build_buf + ptr, "g=%s ", tmp);
484
485                 tmp = env_get("hostname");
486                 if (tmp)
487                         ptr += sprintf(build_buf + ptr, "tn=%s ", tmp);
488
489                 tmp = env_get("othbootargs");
490                 if (tmp) {
491                         strcpy(build_buf + ptr, tmp);
492                         ptr += strlen(tmp);
493                 }
494
495                 bootline = build_buf;
496         }
497
498         memcpy((void *)bootaddr, bootline, max(strlen(bootline), (size_t)255));
499         flush_cache(bootaddr, max(strlen(bootline), (size_t)255));
500         printf("## Using bootline (@ 0x%lx): %s\n", bootaddr, (char *)bootaddr);
501
502         /*
503          * If the data at the load address is an elf image, then
504          * treat it like an elf image. Otherwise, assume that it is a
505          * binary image.
506          */
507         if (valid_elf_image(addr))
508                 addr = load_elf_image_phdr(addr);
509         else
510                 puts("## Not an ELF image, assuming binary\n");
511
512         printf("## Starting vxWorks at 0x%08lx ...\n", addr);
513
514         dcache_disable();
515 #if defined(CONFIG_ARM64) && defined(CONFIG_ARMV8_PSCI)
516         armv8_setup_psci();
517         smp_kick_all_cpus();
518 #endif
519
520 #ifdef CONFIG_X86
521         /* VxWorks on x86 uses stack to pass parameters */
522         ((asmlinkage void (*)(int))addr)(0);
523 #else
524         ((void (*)(int))addr)(0);
525 #endif
526
527         puts("## vxWorks terminated\n");
528
529         return 1;
530 }
531
532 U_BOOT_CMD(
533         bootelf, CONFIG_SYS_MAXARGS, 0, do_bootelf,
534         "Boot from an ELF image in memory",
535         "[-p|-s] [address]\n"
536         "\t- load ELF image at [address] via program headers (-p)\n"
537         "\t  or via section headers (-s)"
538 );
539
540 U_BOOT_CMD(
541         bootvx, 2, 0, do_bootvx,
542         "Boot vxWorks from an ELF image",
543         " [address] - load address of vxWorks ELF image."
544 );