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