2 * Remote Processor Framework Elf loader
4 * Copyright (C) 2011 Texas Instruments, Inc.
5 * Copyright (C) 2011 Google, Inc.
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>
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.
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.
26 #define pr_fmt(fmt) "%s: " fmt, __func__
28 #include <linux/module.h>
29 #include <linux/firmware.h>
30 #include <linux/remoteproc.h>
31 #include <linux/elf.h>
33 #include "remoteproc_internal.h"
36 * rproc_elf_sanity_check() - Sanity Check ELF firmware image
37 * @rproc: the remote processor handle
38 * @fw: the ELF firmware image
40 * Make sure this fw image is sane.
43 rproc_elf_sanity_check(struct rproc
*rproc
, const struct firmware
*fw
)
45 const char *name
= rproc
->firmware
;
46 struct device
*dev
= &rproc
->dev
;
47 struct elf32_hdr
*ehdr
;
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 /* We only support ELF32 at this point */
63 class = ehdr
->e_ident
[EI_CLASS
];
64 if (class != ELFCLASS32
) {
65 dev_err(dev
, "Unsupported class: %d\n", class);
69 /* We assume the firmware has the same endianness as the host */
70 # ifdef __LITTLE_ENDIAN
71 if (ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
) {
72 # else /* BIG ENDIAN */
73 if (ehdr
->e_ident
[EI_DATA
] != ELFDATA2MSB
) {
75 dev_err(dev
, "Unsupported firmware endianness\n");
79 if (fw
->size
< ehdr
->e_shoff
+ sizeof(struct elf32_shdr
)) {
80 dev_err(dev
, "Image is too small\n");
84 if (memcmp(ehdr
->e_ident
, ELFMAG
, SELFMAG
)) {
85 dev_err(dev
, "Image is corrupted (bad magic)\n");
89 if (ehdr
->e_phnum
== 0) {
90 dev_err(dev
, "No loadable segments\n");
94 if (ehdr
->e_phoff
> fw
->size
) {
95 dev_err(dev
, "Firmware size is too small\n");
103 * rproc_elf_get_boot_addr() - Get rproc's boot address.
104 * @rproc: the remote processor handle
105 * @fw: the ELF firmware image
107 * This function returns the entry point address of the ELF
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.
114 u32
rproc_elf_get_boot_addr(struct rproc
*rproc
, const struct firmware
*fw
)
116 struct elf32_hdr
*ehdr
= (struct elf32_hdr
*)fw
->data
;
118 return ehdr
->e_entry
;
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
126 * This function loads the firmware segments to memory, where the remote
127 * processor expects them.
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.
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.
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
146 rproc_elf_load_segments(struct rproc
*rproc
, const struct firmware
*fw
)
148 struct device
*dev
= &rproc
->dev
;
149 struct elf32_hdr
*ehdr
;
150 struct elf32_phdr
*phdr
;
152 const u8
*elf_data
= fw
->data
;
154 ehdr
= (struct elf32_hdr
*)elf_data
;
155 phdr
= (struct elf32_phdr
*)(elf_data
+ ehdr
->e_phoff
);
157 /* go through the available ELF segments */
158 for (i
= 0; i
< ehdr
->e_phnum
; i
++, phdr
++) {
159 u32 da
= phdr
->p_paddr
;
160 u32 memsz
= phdr
->p_memsz
;
161 u32 filesz
= phdr
->p_filesz
;
162 u32 offset
= phdr
->p_offset
;
165 if (phdr
->p_type
!= PT_LOAD
)
168 dev_dbg(dev
, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
169 phdr
->p_type
, da
, memsz
, filesz
);
171 if (filesz
> memsz
) {
172 dev_err(dev
, "bad phdr filesz 0x%x memsz 0x%x\n",
178 if (offset
+ filesz
> fw
->size
) {
179 dev_err(dev
, "truncated fw: need 0x%x avail 0x%zx\n",
180 offset
+ filesz
, fw
->size
);
185 /* grab the kernel address for this device address */
186 ptr
= rproc_da_to_va(rproc
, da
, memsz
);
188 dev_err(dev
, "bad phdr da 0x%x mem 0x%x\n", da
, memsz
);
193 /* put the segment where the remote processor expects it */
195 memcpy(ptr
, elf_data
+ phdr
->p_offset
, filesz
);
198 * Zero out remaining memory for this segment.
200 * This isn't strictly required since dma_alloc_coherent already
201 * did this for us. albeit harmless, we may consider removing
205 memset(ptr
+ filesz
, 0, memsz
- filesz
);
211 static struct elf32_shdr
*
212 find_table(struct device
*dev
, struct elf32_hdr
*ehdr
, size_t fw_size
)
214 struct elf32_shdr
*shdr
;
216 const char *name_table
;
217 struct resource_table
*table
= NULL
;
218 const u8
*elf_data
= (void *)ehdr
;
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
;
224 for (i
= 0; i
< ehdr
->e_shnum
; i
++, shdr
++) {
225 u32 size
= shdr
->sh_size
;
226 u32 offset
= shdr
->sh_offset
;
228 if (strcmp(name_table
+ shdr
->sh_name
, ".resource_table"))
231 table
= (struct resource_table
*)(elf_data
+ offset
);
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");
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");
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
);
251 /* make sure reserved bytes are zeroes */
252 if (table
->reserved
[0] || table
->reserved
[1]) {
253 dev_err(dev
, "non zero reserved bytes\n");
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");
271 * rproc_elf_find_rsc_table() - find the resource table
272 * @rproc: the rproc handle
273 * @fw: the ELF firmware image
274 * @tablesz: place holder for providing back the table size
276 * This function finds the resource table inside the remote processor's
277 * firmware. It is used both upon the registration of @rproc (in order
278 * to look for and register the supported virito devices), and when the
281 * Returns the pointer to the resource table if it is found, and write its
282 * size into @tablesz. If a valid table isn't found, NULL is returned
283 * (and @tablesz isn't set).
285 static struct resource_table
*
286 rproc_elf_find_rsc_table(struct rproc
*rproc
, const struct firmware
*fw
,
289 struct elf32_hdr
*ehdr
;
290 struct elf32_shdr
*shdr
;
291 struct device
*dev
= &rproc
->dev
;
292 struct resource_table
*table
= NULL
;
293 const u8
*elf_data
= fw
->data
;
295 ehdr
= (struct elf32_hdr
*)elf_data
;
297 shdr
= find_table(dev
, ehdr
, fw
->size
);
301 table
= (struct resource_table
*)(elf_data
+ shdr
->sh_offset
);
302 *tablesz
= shdr
->sh_size
;
308 * rproc_elf_find_loaded_rsc_table() - find the loaded resource table
309 * @rproc: the rproc handle
310 * @fw: the ELF firmware image
312 * This function finds the location of the loaded resource table. Don't
313 * call this function if the table wasn't loaded yet - it's a bug if you do.
315 * Returns the pointer to the resource table if it is found or NULL otherwise.
316 * If the table wasn't loaded yet the result is unspecified.
318 static struct resource_table
*
319 rproc_elf_find_loaded_rsc_table(struct rproc
*rproc
, const struct firmware
*fw
)
321 struct elf32_hdr
*ehdr
= (struct elf32_hdr
*)fw
->data
;
322 struct elf32_shdr
*shdr
;
324 shdr
= find_table(&rproc
->dev
, ehdr
, fw
->size
);
328 return rproc_da_to_va(rproc
, shdr
->sh_addr
, shdr
->sh_size
);
331 const struct rproc_fw_ops rproc_elf_fw_ops
= {
332 .load
= rproc_elf_load_segments
,
333 .find_rsc_table
= rproc_elf_find_rsc_table
,
334 .find_loaded_rsc_table
= rproc_elf_find_loaded_rsc_table
,
335 .sanity_check
= rproc_elf_sanity_check
,
336 .get_boot_addr
= rproc_elf_get_boot_addr