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