blob: dc13935e1035107630e800fa15be46e8f49edc61 [file] [log] [blame]
Keerthy805b3ca2020-02-12 13:55:03 +05301// SPDX-License-Identifier: BSD-2-Clause
2/*
3 Copyright (c) 2001 William L. Pitts
4*/
5
Keerthy805b3ca2020-02-12 13:55:03 +05306#include <command.h>
7#include <cpu_func.h>
8#include <elf.h>
9#include <env.h>
Maxim Moskalets46b6a3e2024-06-05 21:43:34 +030010#include <errno.h>
Keerthy805b3ca2020-02-12 13:55:03 +053011#include <net.h>
12#include <vxworks.h>
13#ifdef CONFIG_X86
Simon Glasscafe8712022-07-30 15:52:04 -060014#include <vesa.h>
Keerthy805b3ca2020-02-12 13:55:03 +053015#include <asm/e820.h>
16#include <linux/linkage.h>
17#endif
18
Maxim Moskalets46b6a3e2024-06-05 21:43:34 +030019/**
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 */
26unsigned 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 */
45unsigned 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
Keerthy805b3ca2020-02-12 13:55:03 +053072/*
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 */
79unsigned 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 debug("Loading phdr %i to 0x%p (%lu bytes)\n",
94 i, dst, (ulong)phdr->p_filesz);
95 if (phdr->p_filesz)
96 memcpy(dst, src, phdr->p_filesz);
97 if (phdr->p_filesz != phdr->p_memsz)
98 memset(dst + phdr->p_filesz, 0x00,
99 phdr->p_memsz - phdr->p_filesz);
100 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
101 roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
102 ++phdr;
103 }
104
105 if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
106 EF_PPC64_ELFV1_ABI)) {
107 /*
108 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
109 * descriptor pointer with the first double word being the
110 * address of the entry point of the function.
111 */
112 uintptr_t addr = ehdr->e_entry;
113
114 return *(Elf64_Addr *)addr;
115 }
116
117 return ehdr->e_entry;
118}
119
120unsigned long load_elf64_image_shdr(unsigned long addr)
121{
122 Elf64_Ehdr *ehdr; /* Elf header structure pointer */
123 Elf64_Shdr *shdr; /* Section header structure pointer */
124 unsigned char *strtab = 0; /* String table pointer */
125 unsigned char *image; /* Binary image pointer */
126 int i; /* Loop counter */
127
128 ehdr = (Elf64_Ehdr *)addr;
129
130 /* Find the section header string table for output info */
131 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
132 (ehdr->e_shstrndx * sizeof(Elf64_Shdr)));
133
134 if (shdr->sh_type == SHT_STRTAB)
135 strtab = (unsigned char *)(addr + (ulong)shdr->sh_offset);
136
137 /* Load each appropriate section */
138 for (i = 0; i < ehdr->e_shnum; ++i) {
139 shdr = (Elf64_Shdr *)(addr + (ulong)ehdr->e_shoff +
140 (i * sizeof(Elf64_Shdr)));
141
142 if (!(shdr->sh_flags & SHF_ALLOC) ||
143 shdr->sh_addr == 0 || shdr->sh_size == 0) {
144 continue;
145 }
146
147 if (strtab) {
148 debug("%sing %s @ 0x%08lx (%ld bytes)\n",
149 (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
150 &strtab[shdr->sh_name],
151 (unsigned long)shdr->sh_addr,
152 (long)shdr->sh_size);
153 }
154
155 if (shdr->sh_type == SHT_NOBITS) {
156 memset((void *)(uintptr_t)shdr->sh_addr, 0,
157 shdr->sh_size);
158 } else {
159 image = (unsigned char *)addr + (ulong)shdr->sh_offset;
160 memcpy((void *)(uintptr_t)shdr->sh_addr,
161 (const void *)image, shdr->sh_size);
162 }
163 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
164 roundup((shdr->sh_addr + shdr->sh_size),
165 ARCH_DMA_MINALIGN) -
166 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
167 }
168
169 if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags &
170 EF_PPC64_ELFV1_ABI)) {
171 /*
172 * For the 64-bit PowerPC ELF V1 ABI, e_entry is a function
173 * descriptor pointer with the first double word being the
174 * address of the entry point of the function.
175 */
176 uintptr_t addr = ehdr->e_entry;
177
178 return *(Elf64_Addr *)addr;
179 }
180
181 return ehdr->e_entry;
182}
183
184/*
185 * A very simple ELF loader, assumes the image is valid, returns the
186 * entry point address.
187 *
188 * The loader firstly reads the EFI class to see if it's a 64-bit image.
189 * If yes, call the ELF64 loader. Otherwise continue with the ELF32 loader.
190 */
191unsigned long load_elf_image_phdr(unsigned long addr)
192{
193 Elf32_Ehdr *ehdr; /* Elf header structure pointer */
194 Elf32_Phdr *phdr; /* Program header structure pointer */
195 int i;
196
197 ehdr = (Elf32_Ehdr *)addr;
198 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
199 return load_elf64_image_phdr(addr);
200
201 phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
202
203 /* Load each program header */
204 for (i = 0; i < ehdr->e_phnum; ++i) {
205 void *dst = (void *)(uintptr_t)phdr->p_paddr;
206 void *src = (void *)addr + phdr->p_offset;
207
208 debug("Loading phdr %i to 0x%p (%i bytes)\n",
209 i, dst, phdr->p_filesz);
210 if (phdr->p_filesz)
211 memcpy(dst, src, phdr->p_filesz);
212 if (phdr->p_filesz != phdr->p_memsz)
213 memset(dst + phdr->p_filesz, 0x00,
214 phdr->p_memsz - phdr->p_filesz);
215 flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
216 roundup(phdr->p_memsz, ARCH_DMA_MINALIGN));
217 ++phdr;
218 }
219
220 return ehdr->e_entry;
221}
222
223unsigned long load_elf_image_shdr(unsigned long addr)
224{
225 Elf32_Ehdr *ehdr; /* Elf header structure pointer */
226 Elf32_Shdr *shdr; /* Section header structure pointer */
227 unsigned char *strtab = 0; /* String table pointer */
228 unsigned char *image; /* Binary image pointer */
229 int i; /* Loop counter */
230
231 ehdr = (Elf32_Ehdr *)addr;
232 if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
233 return load_elf64_image_shdr(addr);
234
235 /* Find the section header string table for output info */
236 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
237 (ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
238
239 if (shdr->sh_type == SHT_STRTAB)
240 strtab = (unsigned char *)(addr + shdr->sh_offset);
241
242 /* Load each appropriate section */
243 for (i = 0; i < ehdr->e_shnum; ++i) {
244 shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
245 (i * sizeof(Elf32_Shdr)));
246
247 if (!(shdr->sh_flags & SHF_ALLOC) ||
248 shdr->sh_addr == 0 || shdr->sh_size == 0) {
249 continue;
250 }
251
252 if (strtab) {
253 debug("%sing %s @ 0x%08lx (%ld bytes)\n",
254 (shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
255 &strtab[shdr->sh_name],
256 (unsigned long)shdr->sh_addr,
257 (long)shdr->sh_size);
258 }
259
260 if (shdr->sh_type == SHT_NOBITS) {
261 memset((void *)(uintptr_t)shdr->sh_addr, 0,
262 shdr->sh_size);
263 } else {
264 image = (unsigned char *)addr + shdr->sh_offset;
265 memcpy((void *)(uintptr_t)shdr->sh_addr,
266 (const void *)image, shdr->sh_size);
267 }
268 flush_cache(rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN),
269 roundup((shdr->sh_addr + shdr->sh_size),
270 ARCH_DMA_MINALIGN) -
271 rounddown(shdr->sh_addr, ARCH_DMA_MINALIGN));
272 }
273
274 return ehdr->e_entry;
275}
276
277/*
278 * Determine if a valid ELF image exists at the given memory location.
279 * First look at the ELF header magic field, then make sure that it is
280 * executable.
281 */
282int valid_elf_image(unsigned long addr)
283{
284 Elf32_Ehdr *ehdr; /* Elf header structure pointer */
285
286 ehdr = (Elf32_Ehdr *)addr;
287
288 if (!IS_ELF(*ehdr)) {
289 printf("## No elf image at address 0x%08lx\n", addr);
290 return 0;
291 }
292
293 if (ehdr->e_type != ET_EXEC) {
294 printf("## Not a 32-bit elf image at address 0x%08lx\n", addr);
295 return 0;
296 }
297
298 return 1;
299}