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 */
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}
246