]> git.ipfire.org Git - thirdparty/u-boot.git/blame - lib/elf.c
net: hifemac_mdio: use log_msg_ret() correctly, report error by dev_err()
[thirdparty/u-boot.git] / lib / elf.c
CommitLineData
805b3cac
K
1// SPDX-License-Identifier: BSD-2-Clause
2/*
3 Copyright (c) 2001 William L. Pitts
4*/
5
805b3cac
K
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
cafe8712 13#include <vesa.h>
805b3cac
K
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 */
25unsigned 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
66unsigned 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 */
137unsigned 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
169unsigned 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 */
228int 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}