1 // SPDX-License-Identifier: GPL-2.0-only
3 * Remote Processor Framework Elf loader
5 * Copyright (C) 2011 Texas Instruments, Inc.
6 * Copyright (C) 2011 Google, Inc.
8 * Ohad Ben-Cohen <ohad@wizery.com>
9 * Brian Swetland <swetland@google.com>
10 * Mark Grosen <mgrosen@ti.com>
11 * Fernando Guzman Lugo <fernando.lugo@ti.com>
12 * Suman Anna <s-anna@ti.com>
13 * Robert Tivy <rtivy@ti.com>
14 * Armando Uribe De Leon <x0095078@ti.com>
15 * Sjur Brændeland <sjur.brandeland@stericsson.com>
18 #define pr_fmt(fmt) "%s: " fmt, __func__
20 #include <linux/module.h>
21 #include <linux/firmware.h>
22 #include <linux/remoteproc.h>
23 #include <linux/elf.h>
25 #include "remoteproc_internal.h"
26 #include "remoteproc_elf_helpers.h"
29 * rproc_elf_sanity_check() - Sanity Check for ELF32/ELF64 firmware image
30 * @rproc: the remote processor handle
31 * @fw: the ELF firmware image
33 * Make sure this fw image is sane (ie a correct ELF32/ELF64 file).
35 int rproc_elf_sanity_check(struct rproc
*rproc
, const struct firmware
*fw
)
37 const char *name
= rproc
->firmware
;
38 struct device
*dev
= &rproc
->dev
;
40 * Elf files are beginning with the same structure. Thus, to simplify
41 * header parsing, we can use the elf32_hdr one for both elf64 and
44 struct elf32_hdr
*ehdr
;
45 u32 elf_shdr_get_size
;
51 dev_err(dev
, "failed to load %s\n", name
);
55 if (fw
->size
< sizeof(struct elf32_hdr
)) {
56 dev_err(dev
, "Image is too small\n");
60 ehdr
= (struct elf32_hdr
*)fw
->data
;
62 if (memcmp(ehdr
->e_ident
, ELFMAG
, SELFMAG
)) {
63 dev_err(dev
, "Image is corrupted (bad magic)\n");
67 class = ehdr
->e_ident
[EI_CLASS
];
68 if (class != ELFCLASS32
&& class != ELFCLASS64
) {
69 dev_err(dev
, "Unsupported class: %d\n", class);
73 if (class == ELFCLASS64
&& fw
->size
< sizeof(struct elf64_hdr
)) {
74 dev_err(dev
, "elf64 header is too small\n");
78 /* We assume the firmware has the same endianness as the host */
79 # ifdef __LITTLE_ENDIAN
80 if (ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
) {
81 # else /* BIG ENDIAN */
82 if (ehdr
->e_ident
[EI_DATA
] != ELFDATA2MSB
) {
84 dev_err(dev
, "Unsupported firmware endianness\n");
88 phoff
= elf_hdr_get_e_phoff(class, fw
->data
);
89 shoff
= elf_hdr_get_e_shoff(class, fw
->data
);
90 phnum
= elf_hdr_get_e_phnum(class, fw
->data
);
91 elf_shdr_get_size
= elf_size_of_shdr(class);
93 if (fw
->size
< shoff
+ elf_shdr_get_size
) {
94 dev_err(dev
, "Image is too small\n");
99 dev_err(dev
, "No loadable segments\n");
103 if (phoff
> fw
->size
) {
104 dev_err(dev
, "Firmware size is too small\n");
108 dev_dbg(dev
, "Firmware is an elf%d file\n",
109 class == ELFCLASS32
? 32 : 64);
113 EXPORT_SYMBOL(rproc_elf_sanity_check
);
116 * rproc_elf_get_boot_addr() - Get rproc's boot address.
117 * @rproc: the remote processor handle
118 * @fw: the ELF firmware image
120 * This function returns the entry point address of the ELF
123 * Note that the boot address is not a configurable property of all remote
124 * processors. Some will always boot at a specific hard-coded address.
126 u64
rproc_elf_get_boot_addr(struct rproc
*rproc
, const struct firmware
*fw
)
128 return elf_hdr_get_e_entry(fw_elf_get_class(fw
), fw
->data
);
130 EXPORT_SYMBOL(rproc_elf_get_boot_addr
);
133 * rproc_elf_load_segments() - load firmware segments to memory
134 * @rproc: remote processor which will be booted using these fw segments
135 * @fw: the ELF firmware image
137 * This function loads the firmware segments to memory, where the remote
138 * processor expects them.
140 * Some remote processors will expect their code and data to be placed
141 * in specific device addresses, and can't have them dynamically assigned.
143 * We currently support only those kind of remote processors, and expect
144 * the program header's paddr member to contain those addresses. We then go
145 * through the physically contiguous "carveout" memory regions which we
146 * allocated (and mapped) earlier on behalf of the remote processor,
147 * and "translate" device address to kernel addresses, so we can copy the
148 * segments where they are expected.
150 * Currently we only support remote processors that required carveout
151 * allocations and got them mapped onto their iommus. Some processors
152 * might be different: they might not have iommus, and would prefer to
153 * directly allocate memory for every segment/resource. This is not yet
156 int rproc_elf_load_segments(struct rproc
*rproc
, const struct firmware
*fw
)
158 struct device
*dev
= &rproc
->dev
;
159 const void *ehdr
, *phdr
;
162 const u8
*elf_data
= fw
->data
;
163 u8
class = fw_elf_get_class(fw
);
164 u32 elf_phdr_get_size
= elf_size_of_phdr(class);
167 phnum
= elf_hdr_get_e_phnum(class, ehdr
);
168 phdr
= elf_data
+ elf_hdr_get_e_phoff(class, ehdr
);
170 /* go through the available ELF segments */
171 for (i
= 0; i
< phnum
; i
++, phdr
+= elf_phdr_get_size
) {
172 u64 da
= elf_phdr_get_p_paddr(class, phdr
);
173 u64 memsz
= elf_phdr_get_p_memsz(class, phdr
);
174 u64 filesz
= elf_phdr_get_p_filesz(class, phdr
);
175 u64 offset
= elf_phdr_get_p_offset(class, phdr
);
176 u32 type
= elf_phdr_get_p_type(class, phdr
);
182 dev_dbg(dev
, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
183 type
, da
, memsz
, filesz
);
185 if (filesz
> memsz
) {
186 dev_err(dev
, "bad phdr filesz 0x%llx memsz 0x%llx\n",
192 if (offset
+ filesz
> fw
->size
) {
193 dev_err(dev
, "truncated fw: need 0x%llx avail 0x%zx\n",
194 offset
+ filesz
, fw
->size
);
199 if (!rproc_u64_fit_in_size_t(memsz
)) {
200 dev_err(dev
, "size (%llx) does not fit in size_t type\n",
206 /* grab the kernel address for this device address */
207 ptr
= rproc_da_to_va(rproc
, da
, memsz
);
209 dev_err(dev
, "bad phdr da 0x%llx mem 0x%llx\n", da
,
215 /* put the segment where the remote processor expects it */
217 memcpy(ptr
, elf_data
+ offset
, filesz
);
220 * Zero out remaining memory for this segment.
222 * This isn't strictly required since dma_alloc_coherent already
223 * did this for us. albeit harmless, we may consider removing
227 memset(ptr
+ filesz
, 0, memsz
- filesz
);
232 EXPORT_SYMBOL(rproc_elf_load_segments
);
235 find_table(struct device
*dev
, const struct firmware
*fw
)
237 const void *shdr
, *name_table_shdr
;
239 const char *name_table
;
240 struct resource_table
*table
= NULL
;
241 const u8
*elf_data
= (void *)fw
->data
;
242 u8
class = fw_elf_get_class(fw
);
243 size_t fw_size
= fw
->size
;
244 const void *ehdr
= elf_data
;
245 u16 shnum
= elf_hdr_get_e_shnum(class, ehdr
);
246 u32 elf_shdr_get_size
= elf_size_of_shdr(class);
247 u16 shstrndx
= elf_hdr_get_e_shstrndx(class, ehdr
);
249 /* look for the resource table and handle it */
250 /* First, get the section header according to the elf class */
251 shdr
= elf_data
+ elf_hdr_get_e_shoff(class, ehdr
);
252 /* Compute name table section header entry in shdr array */
253 name_table_shdr
= shdr
+ (shstrndx
* elf_shdr_get_size
);
254 /* Finally, compute the name table section address in elf */
255 name_table
= elf_data
+ elf_shdr_get_sh_offset(class, name_table_shdr
);
257 for (i
= 0; i
< shnum
; i
++, shdr
+= elf_shdr_get_size
) {
258 u64 size
= elf_shdr_get_sh_size(class, shdr
);
259 u64 offset
= elf_shdr_get_sh_offset(class, shdr
);
260 u32 name
= elf_shdr_get_sh_name(class, shdr
);
262 if (strcmp(name_table
+ name
, ".resource_table"))
265 table
= (struct resource_table
*)(elf_data
+ offset
);
267 /* make sure we have the entire table */
268 if (offset
+ size
> fw_size
|| offset
+ size
< size
) {
269 dev_err(dev
, "resource table truncated\n");
273 /* make sure table has at least the header */
274 if (sizeof(struct resource_table
) > size
) {
275 dev_err(dev
, "header-less resource table\n");
279 /* we don't support any version beyond the first */
280 if (table
->ver
!= 1) {
281 dev_err(dev
, "unsupported fw ver: %d\n", table
->ver
);
285 /* make sure reserved bytes are zeroes */
286 if (table
->reserved
[0] || table
->reserved
[1]) {
287 dev_err(dev
, "non zero reserved bytes\n");
291 /* make sure the offsets array isn't truncated */
292 if (struct_size(table
, offset
, table
->num
) > size
) {
293 dev_err(dev
, "resource table incomplete\n");
304 * rproc_elf_load_rsc_table() - load the resource table
305 * @rproc: the rproc handle
306 * @fw: the ELF firmware image
308 * This function finds the resource table inside the remote processor's
309 * firmware, load it into the @cached_table and update @table_ptr.
311 * Return: 0 on success, negative errno on failure.
313 int rproc_elf_load_rsc_table(struct rproc
*rproc
, const struct firmware
*fw
)
316 struct device
*dev
= &rproc
->dev
;
317 struct resource_table
*table
= NULL
;
318 const u8
*elf_data
= fw
->data
;
320 u8
class = fw_elf_get_class(fw
);
323 shdr
= find_table(dev
, fw
);
327 sh_offset
= elf_shdr_get_sh_offset(class, shdr
);
328 table
= (struct resource_table
*)(elf_data
+ sh_offset
);
329 tablesz
= elf_shdr_get_sh_size(class, shdr
);
332 * Create a copy of the resource table. When a virtio device starts
333 * and calls vring_new_virtqueue() the address of the allocated vring
334 * will be stored in the cached_table. Before the device is started,
335 * cached_table will be copied into device memory.
337 rproc
->cached_table
= kmemdup(table
, tablesz
, GFP_KERNEL
);
338 if (!rproc
->cached_table
)
341 rproc
->table_ptr
= rproc
->cached_table
;
342 rproc
->table_sz
= tablesz
;
346 EXPORT_SYMBOL(rproc_elf_load_rsc_table
);
349 * rproc_elf_find_loaded_rsc_table() - find the loaded resource table
350 * @rproc: the rproc handle
351 * @fw: the ELF firmware image
353 * This function finds the location of the loaded resource table. Don't
354 * call this function if the table wasn't loaded yet - it's a bug if you do.
356 * Returns the pointer to the resource table if it is found or NULL otherwise.
357 * If the table wasn't loaded yet the result is unspecified.
359 struct resource_table
*rproc_elf_find_loaded_rsc_table(struct rproc
*rproc
,
360 const struct firmware
*fw
)
363 u64 sh_addr
, sh_size
;
364 u8
class = fw_elf_get_class(fw
);
365 struct device
*dev
= &rproc
->dev
;
367 shdr
= find_table(&rproc
->dev
, fw
);
371 sh_addr
= elf_shdr_get_sh_addr(class, shdr
);
372 sh_size
= elf_shdr_get_sh_size(class, shdr
);
374 if (!rproc_u64_fit_in_size_t(sh_size
)) {
375 dev_err(dev
, "size (%llx) does not fit in size_t type\n",
380 return rproc_da_to_va(rproc
, sh_addr
, sh_size
);
382 EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table
);