xref: /linux/drivers/remoteproc/remoteproc_elf_loader.c (revision 18f90d372cf35b387663f1567de701e5393f6eb5)
1 /*
2  * Remote Processor Framework Elf loader
3  *
4  * Copyright (C) 2011 Texas Instruments, Inc.
5  * Copyright (C) 2011 Google, Inc.
6  *
7  * Ohad Ben-Cohen <ohad@wizery.com>
8  * Brian Swetland <swetland@google.com>
9  * Mark Grosen <mgrosen@ti.com>
10  * Fernando Guzman Lugo <fernando.lugo@ti.com>
11  * Suman Anna <s-anna@ti.com>
12  * Robert Tivy <rtivy@ti.com>
13  * Armando Uribe De Leon <x0095078@ti.com>
14  * Sjur Brændeland <sjur.brandeland@stericsson.com>
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * version 2 as published by the Free Software Foundation.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  */
25 
26 #define pr_fmt(fmt)    "%s: " fmt, __func__
27 
28 #include <linux/module.h>
29 #include <linux/firmware.h>
30 #include <linux/remoteproc.h>
31 #include <linux/elf.h>
32 
33 #include "remoteproc_internal.h"
34 
35 /**
36  * rproc_elf_sanity_check() - Sanity Check ELF firmware image
37  * @rproc: the remote processor handle
38  * @fw: the ELF firmware image
39  *
40  * Make sure this fw image is sane.
41  */
42 int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
43 {
44 	const char *name = rproc->firmware;
45 	struct device *dev = &rproc->dev;
46 	struct elf32_hdr *ehdr;
47 	char class;
48 
49 	if (!fw) {
50 		dev_err(dev, "failed to load %s\n", name);
51 		return -EINVAL;
52 	}
53 
54 	if (fw->size < sizeof(struct elf32_hdr)) {
55 		dev_err(dev, "Image is too small\n");
56 		return -EINVAL;
57 	}
58 
59 	ehdr = (struct elf32_hdr *)fw->data;
60 
61 	/* We only support ELF32 at this point */
62 	class = ehdr->e_ident[EI_CLASS];
63 	if (class != ELFCLASS32) {
64 		dev_err(dev, "Unsupported class: %d\n", class);
65 		return -EINVAL;
66 	}
67 
68 	/* We assume the firmware has the same endianness as the host */
69 # ifdef __LITTLE_ENDIAN
70 	if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
71 # else /* BIG ENDIAN */
72 	if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
73 # endif
74 		dev_err(dev, "Unsupported firmware endianness\n");
75 		return -EINVAL;
76 	}
77 
78 	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
79 		dev_err(dev, "Image is too small\n");
80 		return -EINVAL;
81 	}
82 
83 	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
84 		dev_err(dev, "Image is corrupted (bad magic)\n");
85 		return -EINVAL;
86 	}
87 
88 	if (ehdr->e_phnum == 0) {
89 		dev_err(dev, "No loadable segments\n");
90 		return -EINVAL;
91 	}
92 
93 	if (ehdr->e_phoff > fw->size) {
94 		dev_err(dev, "Firmware size is too small\n");
95 		return -EINVAL;
96 	}
97 
98 	return 0;
99 }
100 EXPORT_SYMBOL(rproc_elf_sanity_check);
101 
102 /**
103  * rproc_elf_get_boot_addr() - Get rproc's boot address.
104  * @rproc: the remote processor handle
105  * @fw: the ELF firmware image
106  *
107  * This function returns the entry point address of the ELF
108  * image.
109  *
110  * Note that the boot address is not a configurable property of all remote
111  * processors. Some will always boot at a specific hard-coded address.
112  */
113 u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)
114 {
115 	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;
116 
117 	return ehdr->e_entry;
118 }
119 EXPORT_SYMBOL(rproc_elf_get_boot_addr);
120 
121 /**
122  * rproc_elf_load_segments() - load firmware segments to memory
123  * @rproc: remote processor which will be booted using these fw segments
124  * @fw: the ELF firmware image
125  *
126  * This function loads the firmware segments to memory, where the remote
127  * processor expects them.
128  *
129  * Some remote processors will expect their code and data to be placed
130  * in specific device addresses, and can't have them dynamically assigned.
131  *
132  * We currently support only those kind of remote processors, and expect
133  * the program header's paddr member to contain those addresses. We then go
134  * through the physically contiguous "carveout" memory regions which we
135  * allocated (and mapped) earlier on behalf of the remote processor,
136  * and "translate" device address to kernel addresses, so we can copy the
137  * segments where they are expected.
138  *
139  * Currently we only support remote processors that required carveout
140  * allocations and got them mapped onto their iommus. Some processors
141  * might be different: they might not have iommus, and would prefer to
142  * directly allocate memory for every segment/resource. This is not yet
143  * supported, though.
144  */
145 int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
146 {
147 	struct device *dev = &rproc->dev;
148 	struct elf32_hdr *ehdr;
149 	struct elf32_phdr *phdr;
150 	int i, ret = 0;
151 	const u8 *elf_data = fw->data;
152 
153 	ehdr = (struct elf32_hdr *)elf_data;
154 	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
155 
156 	/* go through the available ELF segments */
157 	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
158 		u32 da = phdr->p_paddr;
159 		u32 memsz = phdr->p_memsz;
160 		u32 filesz = phdr->p_filesz;
161 		u32 offset = phdr->p_offset;
162 		void *ptr;
163 
164 		if (phdr->p_type != PT_LOAD)
165 			continue;
166 
167 		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
168 			phdr->p_type, da, memsz, filesz);
169 
170 		if (filesz > memsz) {
171 			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
172 				filesz, memsz);
173 			ret = -EINVAL;
174 			break;
175 		}
176 
177 		if (offset + filesz > fw->size) {
178 			dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n",
179 				offset + filesz, fw->size);
180 			ret = -EINVAL;
181 			break;
182 		}
183 
184 		/* grab the kernel address for this device address */
185 		ptr = rproc_da_to_va(rproc, da, memsz);
186 		if (!ptr) {
187 			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
188 			ret = -EINVAL;
189 			break;
190 		}
191 
192 		/* put the segment where the remote processor expects it */
193 		if (phdr->p_filesz)
194 			memcpy(ptr, elf_data + phdr->p_offset, filesz);
195 
196 		/*
197 		 * Zero out remaining memory for this segment.
198 		 *
199 		 * This isn't strictly required since dma_alloc_coherent already
200 		 * did this for us. albeit harmless, we may consider removing
201 		 * this.
202 		 */
203 		if (memsz > filesz)
204 			memset(ptr + filesz, 0, memsz - filesz);
205 	}
206 
207 	return ret;
208 }
209 EXPORT_SYMBOL(rproc_elf_load_segments);
210 
211 static struct elf32_shdr *
212 find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
213 {
214 	struct elf32_shdr *shdr;
215 	int i;
216 	const char *name_table;
217 	struct resource_table *table = NULL;
218 	const u8 *elf_data = (void *)ehdr;
219 
220 	/* look for the resource table and handle it */
221 	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
222 	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
223 
224 	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
225 		u32 size = shdr->sh_size;
226 		u32 offset = shdr->sh_offset;
227 
228 		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
229 			continue;
230 
231 		table = (struct resource_table *)(elf_data + offset);
232 
233 		/* make sure we have the entire table */
234 		if (offset + size > fw_size || offset + size < size) {
235 			dev_err(dev, "resource table truncated\n");
236 			return NULL;
237 		}
238 
239 		/* make sure table has at least the header */
240 		if (sizeof(struct resource_table) > size) {
241 			dev_err(dev, "header-less resource table\n");
242 			return NULL;
243 		}
244 
245 		/* we don't support any version beyond the first */
246 		if (table->ver != 1) {
247 			dev_err(dev, "unsupported fw ver: %d\n", table->ver);
248 			return NULL;
249 		}
250 
251 		/* make sure reserved bytes are zeroes */
252 		if (table->reserved[0] || table->reserved[1]) {
253 			dev_err(dev, "non zero reserved bytes\n");
254 			return NULL;
255 		}
256 
257 		/* make sure the offsets array isn't truncated */
258 		if (table->num * sizeof(table->offset[0]) +
259 				sizeof(struct resource_table) > size) {
260 			dev_err(dev, "resource table incomplete\n");
261 			return NULL;
262 		}
263 
264 		return shdr;
265 	}
266 
267 	return NULL;
268 }
269 
270 /**
271  * rproc_elf_load_rsc_table() - load the resource table
272  * @rproc: the rproc handle
273  * @fw: the ELF firmware image
274  *
275  * This function finds the resource table inside the remote processor's
276  * firmware, load it into the @cached_table and update @table_ptr.
277  *
278  * Return: 0 on success, negative errno on failure.
279  */
280 int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)
281 {
282 	struct elf32_hdr *ehdr;
283 	struct elf32_shdr *shdr;
284 	struct device *dev = &rproc->dev;
285 	struct resource_table *table = NULL;
286 	const u8 *elf_data = fw->data;
287 	size_t tablesz;
288 
289 	ehdr = (struct elf32_hdr *)elf_data;
290 
291 	shdr = find_table(dev, ehdr, fw->size);
292 	if (!shdr)
293 		return -EINVAL;
294 
295 	table = (struct resource_table *)(elf_data + shdr->sh_offset);
296 	tablesz = shdr->sh_size;
297 
298 	/*
299 	 * Create a copy of the resource table. When a virtio device starts
300 	 * and calls vring_new_virtqueue() the address of the allocated vring
301 	 * will be stored in the cached_table. Before the device is started,
302 	 * cached_table will be copied into device memory.
303 	 */
304 	rproc->cached_table = kmemdup(table, tablesz, GFP_KERNEL);
305 	if (!rproc->cached_table)
306 		return -ENOMEM;
307 
308 	rproc->table_ptr = rproc->cached_table;
309 	rproc->table_sz = tablesz;
310 
311 	return 0;
312 }
313 EXPORT_SYMBOL(rproc_elf_load_rsc_table);
314 
315 /**
316  * rproc_elf_find_loaded_rsc_table() - find the loaded resource table
317  * @rproc: the rproc handle
318  * @fw: the ELF firmware image
319  *
320  * This function finds the location of the loaded resource table. Don't
321  * call this function if the table wasn't loaded yet - it's a bug if you do.
322  *
323  * Returns the pointer to the resource table if it is found or NULL otherwise.
324  * If the table wasn't loaded yet the result is unspecified.
325  */
326 struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
327 						       const struct firmware *fw)
328 {
329 	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
330 	struct elf32_shdr *shdr;
331 
332 	shdr = find_table(&rproc->dev, ehdr, fw->size);
333 	if (!shdr)
334 		return NULL;
335 
336 	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
337 }
338 EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
339