colibri_imx6: fix video stdout in default environment
[oweals/u-boot.git] / lib / elf.c
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3    Copyright (c) 2001 William L. Pitts
4 */
5
6 #include <common.h>
7 #include <command.h>
8 #include <cpu_func.h>
9 #include <elf.h>
10 #include <env.h>
11 #include <net.h>
12 #include <vxworks.h>
13 #ifdef CONFIG_X86
14 #include <vbe.h>
15 #include <asm/e820.h>
16 #include <linux/linkage.h>
17 #endif
18
19 /*
20  * A very simple ELF64 loader, assumes the image is valid, returns the
21  * entry point address.
22  *
23  * Note if U-Boot is 32-bit, the loader assumes the to segment's
24  * physical address and size is within the lower 32-bit address space.
25  */
26 unsigned long load_elf64_image_phdr(unsigned long addr)
27 {
28         Elf64_Ehdr *ehdr; /* Elf header structure pointer */
29         Elf64_Phdr *phdr; /* Program header structure pointer */
30         int i;
31
32         ehdr = (Elf64_Ehdr *)addr;
33         phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
34
35         /* Load each program header */
36         for (i = 0; i < ehdr->e_phnum; ++i) {
37                 void *dst = (void *)(ulong)phdr->p_paddr;
38                 void *src = (void *)addr + phdr->p_offset;
39
40                 debug("Loading phdr %i to 0x%p (%lu bytes)\n",
41                       i, dst, (ulong)phdr->p_filesz);
42                 if (phdr->p_filesz)
43                         memcpy(dst, src, phdr->p_filesz);
44                 if (phdr->p_filesz != phdr->p_memsz)
45                         memset(dst + phdr->p_filesz, 0x00,
46                                phdr->p_memsz - phdr->p_filesz);
47                 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
48                             roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
49                 ++phdr;
50         }
51
52         if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
53                                             EF_PPC64_ELFV1_ABI)) {
54                 /*
55                  * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
56                  * descriptor pointer with the first double word being the
57                  * address of the entry point of the function.
58                  */
59                 uintptr_t addr = ehdr->e_entry;
60
61                 return *(Elf64_Addr *)addr;
62         }
63
64         return ehdr->e_entry;
65 }
66
67 unsigned long load_elf64_image_shdr(unsigned long addr)
68 {
69         Elf64_Ehdr *ehdr; /* Elf header structure pointer */
70         Elf64_Shdr *shdr; /* Section header structure pointer */
71         unsigned char *strtab = 0; /* String table pointer */
72         unsigned char *image; /* Binary image pointer */
73         int i; /* Loop counter */
74
75         ehdr = (Elf64_Ehdr *)addr;
76
77         /* Find the section header string table for output info */
78         shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
79                              (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
80
81         if (shdr->sh_type == SHT_STRTAB)
82                 strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
83
84         /* Load each appropriate section */
85         for (i = 0; i < ehdr->e_shnum; ++i) {
86                 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
87                                      (i * sizeof(Elf64_Shdr)));
88
89                 if (!(shdr->sh_flags & SHF_ALLOC) ||
90                     shdr->sh_addr == 0 || shdr->sh_size == 0) {
91                         continue;
92                 }
93
94                 if (strtab) {
95                         debug("%sing %s @ 0x%08lx (%ld bytes)\n",
96                               (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
97                                &strtab[shdr->sh_name],
98                                (unsigned long)shdr->sh_addr,
99                                (long)shdr->sh_size);
100                 }
101
102                 if (shdr->sh_type == SHT_NOBITS) {
103                         memset((void *)(uintptr_t)shdr->sh_addr, 0,
104                                shdr->sh_size);
105                 } else {
106                         image = (unsigned char *)addr + (ulong)shdr->sh_offset;
107                         memcpy((void *)(uintptr_t)shdr->sh_addr,
108                                (const void *)image, shdr->sh_size);
109                 }
110                 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
111                             roundup((shdr->sh_addr + shdr->sh_size),
112                                      ARCH_DMA_MINALIGN) -
113                                 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
114         }
115
116         if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
117                                             EF_PPC64_ELFV1_ABI)) {
118                 /*
119                  * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
120                  * descriptor pointer with the first double word being the
121                  * address of the entry point of the function.
122                  */
123                 uintptr_t addr = ehdr->e_entry;
124
125                 return *(Elf64_Addr *)addr;
126         }
127
128         return ehdr->e_entry;
129 }
130
131 /*
132  * A very simple ELF loader, assumes the image is valid, returns the
133  * entry point address.
134  *
135  * The loader firstly reads the EFI class to see if it's a 64-bit image.
136  * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
137  */
138 unsigned long load_elf_image_phdr(unsigned long addr)
139 {
140         Elf32_Ehdr *ehdr; /* Elf header structure pointer */
141         Elf32_Phdr *phdr; /* Program header structure pointer */
142         int i;
143
144         ehdr = (Elf32_Ehdr *)addr;
145         if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
146                 return load_elf64_image_phdr(addr);
147
148         phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
149
150         /* Load each program header */
151         for (i = 0; i < ehdr->e_phnum; ++i) {
152                 void *dst = (void *)(uintptr_t)phdr->p_paddr;
153                 void *src = (void *)addr + phdr->p_offset;
154
155                 debug("Loading phdr %i to 0x%p (%i bytes)\n",
156                       i, dst, phdr->p_filesz);
157                 if (phdr->p_filesz)
158                         memcpy(dst, src, phdr->p_filesz);
159                 if (phdr->p_filesz != phdr->p_memsz)
160                         memset(dst + phdr->p_filesz, 0x00,
161                                phdr->p_memsz - phdr->p_filesz);
162                 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
163                             roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
164                 ++phdr;
165         }
166
167         return ehdr->e_entry;
168 }
169
170 unsigned long load_elf_image_shdr(unsigned long addr)
171 {
172         Elf32_Ehdr *ehdr; /* Elf header structure pointer */
173         Elf32_Shdr *shdr; /* Section header structure pointer */
174         unsigned char *strtab = 0; /* String table pointer */
175         unsigned char *image; /* Binary image pointer */
176         int i; /* Loop counter */
177
178         ehdr = (Elf32_Ehdr *)addr;
179         if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
180                 return load_elf64_image_shdr(addr);
181
182         /* Find the section header string table for output info */
183         shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
184                              (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
185
186         if (shdr->sh_type == SHT_STRTAB)
187                 strtab = (unsigned char *)(addr + shdr->sh_offset);
188
189         /* Load each appropriate section */
190         for (i = 0; i < ehdr->e_shnum; ++i) {
191                 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
192                                      (i * sizeof(Elf32_Shdr)));
193
194                 if (!(shdr->sh_flags & SHF_ALLOC) ||
195                     shdr->sh_addr == 0 || shdr->sh_size == 0) {
196                         continue;
197                 }
198
199                 if (strtab) {
200                         debug("%sing %s @ 0x%08lx (%ld bytes)\n",
201                               (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
202                                &strtab[shdr->sh_name],
203                                (unsigned long)shdr->sh_addr,
204                                (long)shdr->sh_size);
205                 }
206
207                 if (shdr->sh_type == SHT_NOBITS) {
208                         memset((void *)(uintptr_t)shdr->sh_addr, 0,
209                                shdr->sh_size);
210                 } else {
211                         image = (unsigned char *)addr + shdr->sh_offset;
212                         memcpy((void *)(uintptr_t)shdr->sh_addr,
213                                (const void *)image, shdr->sh_size);
214                 }
215                 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
216                             roundup((shdr->sh_addr + shdr->sh_size),
217                                     ARCH_DMA_MINALIGN) -
218                             rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
219         }
220
221         return ehdr->e_entry;
222 }
223
224 /*
225  * Determine if a valid ELF image exists at the given memory location.
226  * First look at the ELF header magic field, then make sure that it is
227  * executable.
228  */
229 int valid_elf_image(unsigned long addr)
230 {
231         Elf32_Ehdr *ehdr; /* Elf header structure pointer */
232
233         ehdr = (Elf32_Ehdr *)addr;
234
235         if (!IS_ELF(*ehdr)) {
236                 printf("## No elf image at address 0x%08lx\n", addr);
237                 return 0;
238         }
239
240         if (ehdr->e_type != ET_EXEC) {
241                 printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
242                 return 0;
243         }
244
245         return 1;
246 }