1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2 /*
3  * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
4  */
5 #include <common.h>
6 #include <cpu_func.h>
7 #include <dm.h>
8 #include <elf.h>
9 #include <log.h>
10 #include <remoteproc.h>
11 #include <asm/cache.h>
12 #include <dm/device_compat.h>
13 #include <linux/compat.h>
14 
15 /**
16  * struct resource_table - firmware resource table header
17  * @ver: version number
18  * @num: number of resource entries
19  * @reserved: reserved (must be zero)
20  * @offset: array of offsets pointing at the various resource entries
21  *
22  * A resource table is essentially a list of system resources required
23  * by the remote processor. It may also include configuration entries.
24  * If needed, the remote processor firmware should contain this table
25  * as a dedicated ".resource_table" ELF section.
26  *
27  * Some resources entries are mere announcements, where the host is informed
28  * of specific remoteproc configuration. Other entries require the host to
29  * do something (e.g. allocate a system resource). Sometimes a negotiation
30  * is expected, where the firmware requests a resource, and once allocated,
31  * the host should provide back its details (e.g. address of an allocated
32  * memory region).
33  *
34  * The header of the resource table, as expressed by this structure,
35  * contains a version number (should we need to change this format in the
36  * future), the number of available resource entries, and their offsets
37  * in the table.
38  *
39  * Immediately following this header are the resource entries themselves.
40  */
41 struct resource_table {
42 	u32 ver;
43 	u32 num;
44 	u32 reserved[2];
45 	u32 offset[0];
46 } __packed;
47 
48 /* Basic function to verify ELF32 image format */
rproc_elf32_sanity_check(ulong addr,ulong size)49 int rproc_elf32_sanity_check(ulong addr, ulong size)
50 {
51 	Elf32_Ehdr *ehdr;
52 	char class;
53 
54 	if (!addr) {
55 		pr_debug("Invalid fw address?\n");
56 		return -EFAULT;
57 	}
58 
59 	if (size < sizeof(Elf32_Ehdr)) {
60 		pr_debug("Image is too small\n");
61 		return -ENOSPC;
62 	}
63 
64 	ehdr = (Elf32_Ehdr *)addr;
65 	class = ehdr->e_ident[EI_CLASS];
66 
67 	if (!IS_ELF(*ehdr) || ehdr->e_type != ET_EXEC || class != ELFCLASS32) {
68 		pr_debug("Not an executable ELF32 image\n");
69 		return -EPROTONOSUPPORT;
70 	}
71 
72 	/* We assume the firmware has the same endianness as the host */
73 # ifdef __LITTLE_ENDIAN
74 	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
75 # else /* BIG ENDIAN */
76 	if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
77 # endif
78 		pr_debug("Unsupported firmware endianness\n");
79 		return -EILSEQ;
80 	}
81 
82 	if (size < ehdr->e_shoff + sizeof(Elf32_Shdr)) {
83 		pr_debug("Image is too small\n");
84 		return -ENOSPC;
85 	}
86 
87 	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
88 		pr_debug("Image is corrupted (bad magic)\n");
89 		return -EBADF;
90 	}
91 
92 	if (ehdr->e_phnum == 0) {
93 		pr_debug("No loadable segments\n");
94 		return -ENOEXEC;
95 	}
96 
97 	if (ehdr->e_phoff > size) {
98 		pr_debug("Firmware size is too small\n");
99 		return -ENOSPC;
100 	}
101 
102 	return 0;
103 }
104 
105 /* Basic function to verify ELF64 image format */
106 int rproc_elf64_sanity_check(ulong addr, ulong size)
107 {
108 	Elf64_Ehdr *ehdr = (Elf64_Ehdr *)addr;
109 	char class;
110 
111 	if (!addr) {
112 		pr_debug("Invalid fw address?\n");
113 		return -EFAULT;
114 	}
115 
116 	if (size < sizeof(Elf64_Ehdr)) {
117 		pr_debug("Image is too small\n");
118 		return -ENOSPC;
119 	}
120 
121 	class = ehdr->e_ident[EI_CLASS];
122 
123 	if (!IS_ELF(*ehdr) || ehdr->e_type != ET_EXEC || class != ELFCLASS64) {
124 		pr_debug("Not an executable ELF64 image\n");
125 		return -EPROTONOSUPPORT;
126 	}
127 
128 	/* We assume the firmware has the same endianness as the host */
129 # ifdef __LITTLE_ENDIAN
130 	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
131 # else /* BIG ENDIAN */
132 	if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
133 # endif
134 		pr_debug("Unsupported firmware endianness\n");
135 		return -EILSEQ;
136 	}
137 
138 	if (size < ehdr->e_shoff + sizeof(Elf64_Shdr)) {
139 		pr_debug("Image is too small\n");
140 		return -ENOSPC;
141 	}
142 
143 	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
144 		pr_debug("Image is corrupted (bad magic)\n");
145 		return -EBADF;
146 	}
147 
148 	if (ehdr->e_phnum == 0) {
149 		pr_debug("No loadable segments\n");
150 		return -ENOEXEC;
151 	}
152 
153 	if (ehdr->e_phoff > size) {
154 		pr_debug("Firmware size is too small\n");
155 		return -ENOSPC;
156 	}
157 
158 	return 0;
159 }
160 
161 int rproc_elf32_load_image(struct udevice *dev, unsigned long addr, ulong size)
162 {
163 	Elf32_Ehdr *ehdr; /* Elf header structure pointer */
164 	Elf32_Phdr *phdr; /* Program header structure pointer */
165 	const struct dm_rproc_ops *ops;
166 	unsigned int i, ret;
167 
168 	ret =  rproc_elf32_sanity_check(addr, size);
169 	if (ret) {
170 		dev_err(dev, "Invalid ELF32 Image %d\n", ret);
171 		return ret;
172 	}
173 
174 	ehdr = (Elf32_Ehdr *)addr;
175 	phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
176 
177 	ops = rproc_get_ops(dev);
178 
179 	/* Load each program header */
180 	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
181 		void *dst = (void *)(uintptr_t)phdr->p_paddr;
182 		void *src = (void *)addr + phdr->p_offset;
183 
184 		if (phdr->p_type != PT_LOAD)
185 			continue;
186 
187 		if (ops->device_to_virt)
188 			dst = ops->device_to_virt(dev, (ulong)dst,
189 						  phdr->p_memsz);
190 
191 		dev_dbg(dev, "Loading phdr %i to 0x%p (%i bytes)\n",
192 			i, dst, phdr->p_filesz);
193 		if (phdr->p_filesz)
194 			memcpy(dst, src, phdr->p_filesz);
195 		if (phdr->p_filesz != phdr->p_memsz)
196 			memset(dst + phdr->p_filesz, 0x00,
197 			       phdr->p_memsz - phdr->p_filesz);
198 		flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
199 			    roundup((unsigned long)dst + phdr->p_filesz,
200 				    ARCH_DMA_MINALIGN) -
201 			    rounddown((unsigned long)dst, ARCH_DMA_MINALIGN));
202 	}
203 
204 	return 0;
205 }
206 
207 int rproc_elf64_load_image(struct udevice *dev, ulong addr, ulong size)
208 {
209 	const struct dm_rproc_ops *ops = rproc_get_ops(dev);
210 	u64 da, memsz, filesz, offset;
211 	Elf64_Ehdr *ehdr;
212 	Elf64_Phdr *phdr;
213 	int i, ret = 0;
214 	void *ptr;
215 
216 	dev_dbg(dev, "%s: addr = 0x%lx size = 0x%lx\n", __func__, addr, size);
217 
218 	if (rproc_elf64_sanity_check(addr, size))
219 		return -EINVAL;
220 
221 	ehdr = (Elf64_Ehdr *)addr;
222 	phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff);
223 
224 	/* go through the available ELF segments */
225 	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
226 		da = phdr->p_paddr;
227 		memsz = phdr->p_memsz;
228 		filesz = phdr->p_filesz;
229 		offset = phdr->p_offset;
230 
231 		if (phdr->p_type != PT_LOAD)
232 			continue;
233 
234 		dev_dbg(dev, "%s:phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
235 			__func__, phdr->p_type, da, memsz, filesz);
236 
237 		ptr = (void *)(uintptr_t)da;
238 		if (ops->device_to_virt) {
239 			ptr = ops->device_to_virt(dev, da, phdr->p_memsz);
240 			if (!ptr) {
241 				dev_err(dev, "bad da 0x%llx mem 0x%llx\n", da,
242 					memsz);
243 				ret = -EINVAL;
244 				break;
245 			}
246 		}
247 
248 		if (filesz)
249 			memcpy(ptr, (void *)addr + offset, filesz);
250 		if (filesz != memsz)
251 			memset(ptr + filesz, 0x00, memsz - filesz);
252 
253 		flush_cache(rounddown((ulong)ptr, ARCH_DMA_MINALIGN),
254 			    roundup((ulong)ptr + filesz, ARCH_DMA_MINALIGN) -
255 			    rounddown((ulong)ptr, ARCH_DMA_MINALIGN));
256 	}
257 
258 	return ret;
259 }
260 
261 int rproc_elf_load_image(struct udevice *dev, ulong addr, ulong size)
262 {
263 	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr;
264 
265 	if (!addr) {
266 		dev_err(dev, "Invalid firmware address\n");
267 		return -EFAULT;
268 	}
269 
270 	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
271 		return rproc_elf64_load_image(dev, addr, size);
272 	else
273 		return rproc_elf32_load_image(dev, addr, size);
274 }
275 
276 static ulong rproc_elf32_get_boot_addr(ulong addr)
277 {
278 	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr;
279 
280 	return ehdr->e_entry;
281 }
282 
283 static ulong rproc_elf64_get_boot_addr(ulong addr)
284 {
285 	Elf64_Ehdr *ehdr = (Elf64_Ehdr *)addr;
286 
287 	return ehdr->e_entry;
288 }
289 
290 ulong rproc_elf_get_boot_addr(struct udevice *dev, ulong addr)
291 {
292 	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)addr;
293 
294 	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
295 		return rproc_elf64_get_boot_addr(addr);
296 	else
297 		return rproc_elf32_get_boot_addr(addr);
298 }
299 
300 /*
301  * Search for the resource table in an ELF32 image.
302  * Returns the address of the resource table section if found, NULL if there is
303  * no resource table section, or error pointer.
304  */
305 static Elf32_Shdr *rproc_elf32_find_rsc_table(struct udevice *dev,
306 					      ulong fw_addr, ulong fw_size)
307 {
308 	int ret;
309 	unsigned int i;
310 	const char *name_table;
311 	struct resource_table *table;
312 	const u8 *elf_data = (void *)fw_addr;
313 	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)fw_addr;
314 	Elf32_Shdr *shdr;
315 
316 	ret = rproc_elf32_sanity_check(fw_addr, fw_size);
317 	if (ret) {
318 		pr_debug("Invalid ELF32 Image %d\n", ret);
319 		return ERR_PTR(ret);
320 	}
321 
322 	/* look for the resource table and handle it */
323 	shdr = (Elf32_Shdr *)(elf_data + ehdr->e_shoff);
324 	name_table = (const char *)(elf_data +
325 				    shdr[ehdr->e_shstrndx].sh_offset);
326 
327 	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
328 		u32 size = shdr->sh_size;
329 		u32 offset = shdr->sh_offset;
330 
331 		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
332 			continue;
333 
334 		table = (struct resource_table *)(elf_data + offset);
335 
336 		/* make sure we have the entire table */
337 		if (offset + size > fw_size) {
338 			pr_debug("resource table truncated\n");
339 			return ERR_PTR(-ENOSPC);
340 		}
341 
342 		/* make sure table has at least the header */
343 		if (sizeof(*table) > size) {
344 			pr_debug("header-less resource table\n");
345 			return ERR_PTR(-ENOSPC);
346 		}
347 
348 		/* we don't support any version beyond the first */
349 		if (table->ver != 1) {
350 			pr_debug("unsupported fw ver: %d\n", table->ver);
351 			return ERR_PTR(-EPROTONOSUPPORT);
352 		}
353 
354 		/* make sure reserved bytes are zeroes */
355 		if (table->reserved[0] || table->reserved[1]) {
356 			pr_debug("non zero reserved bytes\n");
357 			return ERR_PTR(-EBADF);
358 		}
359 
360 		/* make sure the offsets array isn't truncated */
361 		if (table->num * sizeof(table->offset[0]) +
362 				 sizeof(*table) > size) {
363 			pr_debug("resource table incomplete\n");
364 			return ERR_PTR(-ENOSPC);
365 		}
366 
367 		return shdr;
368 	}
369 
370 	return NULL;
371 }
372 
373 /* Load the resource table from an ELF32 image */
374 int rproc_elf32_load_rsc_table(struct udevice *dev, ulong fw_addr,
375 			       ulong fw_size, ulong *rsc_addr, ulong *rsc_size)
376 {
377 	const struct dm_rproc_ops *ops;
378 	Elf32_Shdr *shdr;
379 	void *src, *dst;
380 
381 	shdr = rproc_elf32_find_rsc_table(dev, fw_addr, fw_size);
382 	if (!shdr)
383 		return -ENODATA;
384 	if (IS_ERR(shdr))
385 		return PTR_ERR(shdr);
386 
387 	ops = rproc_get_ops(dev);
388 	*rsc_addr = (ulong)shdr->sh_addr;
389 	*rsc_size = (ulong)shdr->sh_size;
390 
391 	src = (void *)fw_addr + shdr->sh_offset;
392 	if (ops->device_to_virt)
393 		dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size);
394 	else
395 		dst = (void *)rsc_addr;
396 
397 	dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n",
398 		(ulong)dst, *rsc_size);
399 
400 	memcpy(dst, src, *rsc_size);
401 	flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
402 		    roundup((unsigned long)dst + *rsc_size,
403 			    ARCH_DMA_MINALIGN) -
404 		    rounddown((unsigned long)dst, ARCH_DMA_MINALIGN));
405 
406 	return 0;
407 }
408 
409 /*
410  * Search for the resource table in an ELF64 image.
411  * Returns the address of the resource table section if found, NULL if there is
412  * no resource table section, or error pointer.
413  */
414 static Elf64_Shdr *rproc_elf64_find_rsc_table(struct udevice *dev,
415 					      ulong fw_addr, ulong fw_size)
416 {
417 	int ret;
418 	unsigned int i;
419 	const char *name_table;
420 	struct resource_table *table;
421 	const u8 *elf_data = (void *)fw_addr;
422 	Elf64_Ehdr *ehdr = (Elf64_Ehdr *)fw_addr;
423 	Elf64_Shdr *shdr;
424 
425 	ret = rproc_elf64_sanity_check(fw_addr, fw_size);
426 	if (ret) {
427 		pr_debug("Invalid ELF64 Image %d\n", ret);
428 		return ERR_PTR(ret);
429 	}
430 
431 	/* look for the resource table and handle it */
432 	shdr = (Elf64_Shdr *)(elf_data + ehdr->e_shoff);
433 	name_table = (const char *)(elf_data +
434 				    shdr[ehdr->e_shstrndx].sh_offset);
435 
436 	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
437 		u64 size = shdr->sh_size;
438 		u64 offset = shdr->sh_offset;
439 
440 		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
441 			continue;
442 
443 		table = (struct resource_table *)(elf_data + offset);
444 
445 		/* make sure we have the entire table */
446 		if (offset + size > fw_size) {
447 			pr_debug("resource table truncated\n");
448 			return ERR_PTR(-ENOSPC);
449 		}
450 
451 		/* make sure table has at least the header */
452 		if (sizeof(*table) > size) {
453 			pr_debug("header-less resource table\n");
454 			return ERR_PTR(-ENOSPC);
455 		}
456 
457 		/* we don't support any version beyond the first */
458 		if (table->ver != 1) {
459 			pr_debug("unsupported fw ver: %d\n", table->ver);
460 			return ERR_PTR(-EPROTONOSUPPORT);
461 		}
462 
463 		/* make sure reserved bytes are zeroes */
464 		if (table->reserved[0] || table->reserved[1]) {
465 			pr_debug("non zero reserved bytes\n");
466 			return ERR_PTR(-EBADF);
467 		}
468 
469 		/* make sure the offsets array isn't truncated */
470 		if (table->num * sizeof(table->offset[0]) +
471 				 sizeof(*table) > size) {
472 			pr_debug("resource table incomplete\n");
473 			return ERR_PTR(-ENOSPC);
474 		}
475 
476 		return shdr;
477 	}
478 
479 	return NULL;
480 }
481 
482 /* Load the resource table from an ELF64 image */
483 int rproc_elf64_load_rsc_table(struct udevice *dev, ulong fw_addr,
484 			       ulong fw_size, ulong *rsc_addr, ulong *rsc_size)
485 {
486 	const struct dm_rproc_ops *ops;
487 	Elf64_Shdr *shdr;
488 	void *src, *dst;
489 
490 	shdr = rproc_elf64_find_rsc_table(dev, fw_addr, fw_size);
491 	if (!shdr)
492 		return -ENODATA;
493 	if (IS_ERR(shdr))
494 		return PTR_ERR(shdr);
495 
496 	ops = rproc_get_ops(dev);
497 	*rsc_addr = (ulong)shdr->sh_addr;
498 	*rsc_size = (ulong)shdr->sh_size;
499 
500 	src = (void *)fw_addr + shdr->sh_offset;
501 	if (ops->device_to_virt)
502 		dst = (void *)ops->device_to_virt(dev, *rsc_addr, *rsc_size);
503 	else
504 		dst = (void *)rsc_addr;
505 
506 	dev_dbg(dev, "Loading resource table to 0x%8lx (%ld bytes)\n",
507 		(ulong)dst, *rsc_size);
508 
509 	memcpy(dst, src, *rsc_size);
510 	flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN),
511 		    roundup((unsigned long)dst + *rsc_size,
512 			    ARCH_DMA_MINALIGN) -
513 		    rounddown((unsigned long)dst, ARCH_DMA_MINALIGN));
514 
515 	return 0;
516 }
517 
518 /* Load the resource table from an ELF32 or ELF64 image */
519 int rproc_elf_load_rsc_table(struct udevice *dev, ulong fw_addr,
520 			     ulong fw_size, ulong *rsc_addr, ulong *rsc_size)
521 
522 {
523 	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)fw_addr;
524 
525 	if (!fw_addr)
526 		return -EFAULT;
527 
528 	if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
529 		return rproc_elf64_load_rsc_table(dev, fw_addr, fw_size,
530 						  rsc_addr, rsc_size);
531 	else
532 		return rproc_elf32_load_rsc_table(dev, fw_addr, fw_size,
533 						  rsc_addr, rsc_size);
534 }
535