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