]> Git Repo - u-boot.git/blob - lib/elf.c
lmb: allow for resizing lmb regions
[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 <command.h>
7 #include <cpu_func.h>
8 #include <elf.h>
9 #include <env.h>
10 #include <errno.h>
11 #include <net.h>
12 #include <vxworks.h>
13 #ifdef CONFIG_X86
14 #include <vesa.h>
15 #include <asm/e820.h>
16 #include <linux/linkage.h>
17 #endif
18
19 /**
20  * bootelf_exec() - start the ELF image execution.
21  *
22  * @entry: address of entry point of ELF.
23  *
24  * May by used to allow ports to override the default behavior.
25  */
26 unsigned long bootelf_exec(ulong (*entry)(int, char * const[]),
27                            int argc, char *const argv[])
28 {
29         return entry(argc, argv);
30 }
31
32 /**
33  * bootelf() - Boot ELF from memory.
34  *
35  * @addr:  Loading address of ELF in memory.
36  * @flags: Bits like ELF_PHDR to control boot details.
37  * @argc: May be used to pass command line arguments (maybe unused).
38  *        Necessary for backward compatibility with the CLI command.
39  *        If unused, must be 0.
40  * @argv: see @argc. If unused, must be NULL.
41  * Return: Number returned by ELF application.
42  *
43  * Sets errno = ENOEXEC if the ELF image is not valid.
44  */
45 unsigned long bootelf(unsigned long addr, Bootelf_flags flags,
46                       int argc, char *const argv[])
47 {
48         unsigned long entry_addr;
49         char *args[] = {"", NULL};
50
51         errno = 0;
52
53         if (!valid_elf_image(addr)) {
54                 errno = ENOEXEC;
55                 return 1;
56         }
57
58         entry_addr = flags.phdr ? load_elf_image_phdr(addr)
59                                             : load_elf_image_shdr(addr);
60
61         if (!flags.autostart)
62                 return 0;
63
64         if (!argc && !argv) {
65                 argc = 1;
66                 argv = args;
67         }
68
69         return bootelf_exec((void *)entry_addr, argc, argv);
70 }
71
72 /*
73  * A very simple ELF64 loader, assumes the image is valid, returns the
74  * entry point address.
75  *
76  * Note if U-Boot is 32-bit, the loader assumes the to segment's
77  * physical address and size is within the lower 32-bit address space.
78  */
79 unsigned long load_elf64_image_phdr(unsigned long addr)
80 {
81         Elf64_Ehdr *ehdr; /* Elf header structure pointer */
82         Elf64_Phdr *phdr; /* Program header structure pointer */
83         int i;
84
85         ehdr = (Elf64_Ehdr *)addr;
86         phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
87
88         /* Load each program header */
89         for (i = 0; i < ehdr->e_phnum; ++i) {
90                 void *dst = (void *)(ulong)phdr->p_paddr;
91                 void *src = (void *)addr + phdr->p_offset;
92
93                 /* Only load PT_LOAD program header */
94                 if (phdr->p_type != PT_LOAD)
95                         continue;
96
97                 debug("Loading phdr %i to 0x%p (%lu bytes)\n",
98                       i, dst, (ulong)phdr->p_filesz);
99                 if (phdr->p_filesz)
100                         memcpy(dst, src, phdr->p_filesz);
101                 if (phdr->p_filesz != phdr->p_memsz)
102                         memset(dst + phdr->p_filesz, 0x00,
103                                phdr->p_memsz - phdr->p_filesz);
104                 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
105                             roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
106                 ++phdr;
107         }
108
109         if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
110                                             EF_PPC64_ELFV1_ABI)) {
111                 /*
112                  * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
113                  * descriptor pointer with the first double word being the
114                  * address of the entry point of the function.
115                  */
116                 uintptr_t addr = ehdr->e_entry;
117
118                 return *(Elf64_Addr *)addr;
119         }
120
121         return ehdr->e_entry;
122 }
123
124 unsigned long load_elf64_image_shdr(unsigned long addr)
125 {
126         Elf64_Ehdr *ehdr; /* Elf header structure pointer */
127         Elf64_Shdr *shdr; /* Section header structure pointer */
128         unsigned char *strtab = 0; /* String table pointer */
129         unsigned char *image; /* Binary image pointer */
130         int i; /* Loop counter */
131
132         ehdr = (Elf64_Ehdr *)addr;
133
134         /* Find the section header string table for output info */
135         shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
136                              (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
137
138         if (shdr->sh_type == SHT_STRTAB)
139                 strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
140
141         /* Load each appropriate section */
142         for (i = 0; i < ehdr->e_shnum; ++i) {
143                 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
144                                      (i * sizeof(Elf64_Shdr)));
145
146                 if (!(shdr->sh_flags & SHF_ALLOC) ||
147                     shdr->sh_addr == 0 || shdr->sh_size == 0) {
148                         continue;
149                 }
150
151                 if (strtab) {
152                         debug("%sing %s @ 0x%08lx (%ld bytes)\n",
153                               (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
154                                &strtab[shdr->sh_name],
155                                (unsigned long)shdr->sh_addr,
156                                (long)shdr->sh_size);
157                 }
158
159                 if (shdr->sh_type == SHT_NOBITS) {
160                         memset((void *)(uintptr_t)shdr->sh_addr, 0,
161                                shdr->sh_size);
162                 } else {
163                         image = (unsigned char *)addr + (ulong)shdr->sh_offset;
164                         memcpy((void *)(uintptr_t)shdr->sh_addr,
165                                (const void *)image, shdr->sh_size);
166                 }
167                 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
168                             roundup((shdr->sh_addr + shdr->sh_size),
169                                      ARCH_DMA_MINALIGN) -
170                                 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
171         }
172
173         if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
174                                             EF_PPC64_ELFV1_ABI)) {
175                 /*
176                  * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
177                  * descriptor pointer with the first double word being the
178                  * address of the entry point of the function.
179                  */
180                 uintptr_t addr = ehdr->e_entry;
181
182                 return *(Elf64_Addr *)addr;
183         }
184
185         return ehdr->e_entry;
186 }
187
188 /*
189  * A very simple ELF loader, assumes the image is valid, returns the
190  * entry point address.
191  *
192  * The loader firstly reads the EFI class to see if it's a 64-bit image.
193  * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
194  */
195 unsigned long load_elf_image_phdr(unsigned long addr)
196 {
197         Elf32_Ehdr *ehdr; /* Elf header structure pointer */
198         Elf32_Phdr *phdr; /* Program header structure pointer */
199         int i;
200
201         ehdr = (Elf32_Ehdr *)addr;
202         if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
203                 return load_elf64_image_phdr(addr);
204
205         phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
206
207         /* Load each program header */
208         for (i = 0; i < ehdr->e_phnum; ++i) {
209                 void *dst = (void *)(uintptr_t)phdr->p_paddr;
210                 void *src = (void *)addr + phdr->p_offset;
211
212                 /* Only load PT_LOAD program header */
213                 if (phdr->p_type != PT_LOAD)
214                         continue;
215
216                 debug("Loading phdr %i to 0x%p (%i bytes)\n",
217                       i, dst, phdr->p_filesz);
218                 if (phdr->p_filesz)
219                         memcpy(dst, src, phdr->p_filesz);
220                 if (phdr->p_filesz != phdr->p_memsz)
221                         memset(dst + phdr->p_filesz, 0x00,
222                                phdr->p_memsz - phdr->p_filesz);
223                 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
224                             roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
225                 ++phdr;
226         }
227
228         return ehdr->e_entry;
229 }
230
231 unsigned long load_elf_image_shdr(unsigned long addr)
232 {
233         Elf32_Ehdr *ehdr; /* Elf header structure pointer */
234         Elf32_Shdr *shdr; /* Section header structure pointer */
235         unsigned char *strtab = 0; /* String table pointer */
236         unsigned char *image; /* Binary image pointer */
237         int i; /* Loop counter */
238
239         ehdr = (Elf32_Ehdr *)addr;
240         if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
241                 return load_elf64_image_shdr(addr);
242
243         /* Find the section header string table for output info */
244         shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
245                              (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
246
247         if (shdr->sh_type == SHT_STRTAB)
248                 strtab = (unsigned char *)(addr + shdr->sh_offset);
249
250         /* Load each appropriate section */
251         for (i = 0; i < ehdr->e_shnum; ++i) {
252                 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
253                                      (i * sizeof(Elf32_Shdr)));
254
255                 if (!(shdr->sh_flags & SHF_ALLOC) ||
256                     shdr->sh_addr == 0 || shdr->sh_size == 0) {
257                         continue;
258                 }
259
260                 if (strtab) {
261                         debug("%sing %s @ 0x%08lx (%ld bytes)\n",
262                               (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
263                                &strtab[shdr->sh_name],
264                                (unsigned long)shdr->sh_addr,
265                                (long)shdr->sh_size);
266                 }
267
268                 if (shdr->sh_type == SHT_NOBITS) {
269                         memset((void *)(uintptr_t)shdr->sh_addr, 0,
270                                shdr->sh_size);
271                 } else {
272                         image = (unsigned char *)addr + shdr->sh_offset;
273                         memcpy((void *)(uintptr_t)shdr->sh_addr,
274                                (const void *)image, shdr->sh_size);
275                 }
276                 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
277                             roundup((shdr->sh_addr + shdr->sh_size),
278                                     ARCH_DMA_MINALIGN) -
279                             rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
280         }
281
282         return ehdr->e_entry;
283 }
284
285 /*
286  * Determine if a valid ELF image exists at the given memory location.
287  * First look at the ELF header magic field, then make sure that it is
288  * executable.
289  */
290 int valid_elf_image(unsigned long addr)
291 {
292         Elf32_Ehdr *ehdr; /* Elf header structure pointer */
293
294         ehdr = (Elf32_Ehdr *)addr;
295
296         if (!IS_ELF(*ehdr)) {
297                 printf("## No elf image at address 0x%08lx\n", addr);
298                 return 0;
299         }
300
301         if (ehdr->e_type != ET_EXEC) {
302                 printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
303                 return 0;
304         }
305
306         return 1;
307 }
This page took 0.07302 seconds and 4 git commands to generate.