1 /*
2  * Copyright (c) 2014, Mentor Graphics Corporation
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #ifndef ELF_LOADER_H_
9 #define ELF_LOADER_H_
10 
11 #include <openamp/remoteproc.h>
12 #include <openamp/remoteproc_loader.h>
13 
14 #if defined __cplusplus
15 extern "C" {
16 #endif
17 
18 /* ELF32 base types - 32-bit. */
19 typedef uint32_t Elf32_Addr;
20 typedef uint16_t Elf32_Half;
21 typedef uint32_t Elf32_Off;
22 typedef int32_t Elf32_Sword;
23 typedef uint32_t Elf32_Word;
24 
25 /* ELF64 base types - 64-bit. */
26 typedef uint64_t Elf64_Addr;
27 typedef uint16_t Elf64_Half;
28 typedef uint64_t Elf64_Off;
29 typedef int32_t Elf64_Sword;
30 typedef uint32_t Elf64_Word;
31 typedef uint64_t Elf64_Xword;
32 typedef int64_t Elf64_Sxword;
33 
34 /* Size of ELF identifier field in the ELF file header. */
35 #define     EI_NIDENT       16
36 
37 /* ELF32 file header */
38 typedef struct {
39 	unsigned char e_ident[EI_NIDENT];
40 	Elf32_Half e_type;
41 	Elf32_Half e_machine;
42 	Elf32_Word e_version;
43 	Elf32_Addr e_entry;
44 	Elf32_Off e_phoff;
45 	Elf32_Off e_shoff;
46 	Elf32_Word e_flags;
47 	Elf32_Half e_ehsize;
48 	Elf32_Half e_phentsize;
49 	Elf32_Half e_phnum;
50 	Elf32_Half e_shentsize;
51 	Elf32_Half e_shnum;
52 	Elf32_Half e_shstrndx;
53 } Elf32_Ehdr;
54 
55 /* ELF64 file header */
56 typedef struct {
57 	unsigned char e_ident[EI_NIDENT];
58 	Elf64_Half e_type;
59 	Elf64_Half e_machine;
60 	Elf64_Word e_version;
61 	Elf64_Addr e_entry;
62 	Elf64_Off e_phoff;
63 	Elf64_Off e_shoff;
64 	Elf64_Word e_flags;
65 	Elf64_Half e_ehsize;
66 	Elf64_Half e_phentsize;
67 	Elf64_Half e_phnum;
68 	Elf64_Half e_shentsize;
69 	Elf64_Half e_shnum;
70 	Elf64_Half e_shstrndx;
71 } Elf64_Ehdr;
72 
73 /* e_ident */
74 #define     ET_NONE         0
75 #define     ET_REL          1	/* Re-locatable file         */
76 #define     ET_EXEC         2	/* Executable file           */
77 #define     ET_DYN          3	/* Shared object file        */
78 #define     ET_CORE         4	/* Core file                 */
79 #define     ET_LOOS         0xfe00	/* Operating system-specific */
80 #define     ET_HIOS         0xfeff	/* Operating system-specific */
81 #define     ET_LOPROC       0xff00	/* remote_proc-specific        */
82 #define     ET_HIPROC       0xffff	/* remote_proc-specific        */
83 
84 /* e_machine */
85 #define     EM_ARM          40	/* ARM/Thumb Architecture    */
86 
87 /* e_version */
88 #define     EV_CURRENT      1	/* Current version           */
89 
90 /* e_ident[] Identification Indexes */
91 #define     EI_MAG0         0	/* File identification       */
92 #define     EI_MAG1         1	/* File identification       */
93 #define     EI_MAG2         2	/* File identification       */
94 #define     EI_MAG3         3	/* File identification       */
95 #define     EI_CLASS        4	/* File class                */
96 #define     EI_DATA         5	/* Data encoding             */
97 #define     EI_VERSION      6	/* File version              */
98 #define     EI_OSABI        7	/* Operating system/ABI identification */
99 #define     EI_ABIVERSION   8	/* ABI version               */
100 #define     EI_PAD          9	/* Start of padding bytes    */
101 #define     EI_NIDENT       16	/* Size of e_ident[]         */
102 
103 /*
104  * EI_MAG0 to EI_MAG3 - A file's first 4 bytes hold amagic number, identifying
105  * the file as an ELF object file
106  */
107 #define     ELFMAG0         0x7f /* e_ident[EI_MAG0]          */
108 #define     ELFMAG1         'E'	/* e_ident[EI_MAG1]          */
109 #define     ELFMAG2         'L'	/* e_ident[EI_MAG2]          */
110 #define     ELFMAG3         'F'	/* e_ident[EI_MAG3]          */
111 #define     ELFMAG          "\177ELF"
112 #define     SELFMAG         4
113 
114 /*
115  * EI_CLASS - The next byte, e_ident[EI_CLASS], identifies the file's class, or
116  * capacity.
117  */
118 #define     ELFCLASSNONE    0	/* Invalid class             */
119 #define     ELFCLASS32      1	/* 32-bit objects            */
120 #define     ELFCLASS64      2	/* 64-bit objects            */
121 
122 /*
123  * EI_DATA - Byte e_ident[EI_DATA] specifies the data encoding of the
124  * remote_proc-specific data in the object file. The following encodings are
125  * currently defined.
126  */
127 #define     ELFDATANONE     0	/* Invalid data encoding     */
128 #define     ELFDATA2LSB     1	/* See Data encodings, below */
129 #define     ELFDATA2MSB     2	/* See Data encodings, below */
130 
131 /* EI_OSABI - We do not define an OS specific ABI */
132 #define     ELFOSABI_NONE   0
133 
134 /* ELF32 program header */
135 typedef struct elf32_phdr {
136 	Elf32_Word p_type;
137 	Elf32_Off p_offset;
138 	Elf32_Addr p_vaddr;
139 	Elf32_Addr p_paddr;
140 	Elf32_Word p_filesz;
141 	Elf32_Word p_memsz;
142 	Elf32_Word p_flags;
143 	Elf32_Word p_align;
144 } Elf32_Phdr;
145 
146 /* ELF64 program header */
147 typedef struct elf64_phdr {
148 	Elf64_Word p_type;
149 	Elf64_Word p_flags;
150 	Elf64_Off p_offset;
151 	Elf64_Addr p_vaddr;
152 	Elf64_Addr p_paddr;
153 	Elf64_Xword p_filesz;
154 	Elf64_Xword p_memsz;
155 	Elf64_Xword p_align;
156 } Elf64_Phdr;
157 
158 /* segment types */
159 #define PT_NULL    0
160 #define PT_LOAD    1
161 #define PT_DYNAMIC 2
162 #define PT_INTERP  3
163 #define PT_NOTE    4
164 #define PT_SHLIB   5
165 #define PT_PHDR    6
166 #define PT_TLS     7               /* Thread local storage segment */
167 #define PT_LOOS    0x60000000      /* OS-specific */
168 #define PT_HIOS    0x6fffffff      /* OS-specific */
169 #define PT_LOPROC  0x70000000
170 #define PT_HIPROC  0x7fffffff
171 
172 /* ELF32 section header. */
173 typedef struct {
174 	Elf32_Word sh_name;
175 	Elf32_Word sh_type;
176 	Elf32_Word sh_flags;
177 	Elf32_Addr sh_addr;
178 	Elf32_Off sh_offset;
179 	Elf32_Word sh_size;
180 	Elf32_Word sh_link;
181 	Elf32_Word sh_info;
182 	Elf32_Word sh_addralign;
183 	Elf32_Word sh_entsize;
184 } Elf32_Shdr;
185 
186 /* ELF64 section header. */
187 typedef struct {
188 	Elf64_Word sh_name;
189 	Elf64_Word sh_type;
190 	Elf64_Xword sh_flags;
191 	Elf64_Addr sh_addr;
192 	Elf64_Off sh_offset;
193 	Elf64_Xword sh_size;
194 	Elf64_Word sh_link;
195 	Elf64_Word sh_info;
196 	Elf64_Xword sh_addralign;
197 	Elf64_Xword sh_entsize;
198 } Elf64_Shdr;
199 
200 /* sh_type */
201 #define     SHT_NULL                0
202 #define     SHT_PROGBITS            1
203 #define     SHT_SYMTAB              2
204 #define     SHT_STRTAB              3
205 #define     SHT_RELA                4
206 #define     SHT_HASH                5
207 #define     SHT_DYNAMIC             6
208 #define     SHT_NOTE                7
209 #define     SHT_NOBITS              8
210 #define     SHT_REL                 9
211 #define     SHT_SHLIB               10
212 #define     SHT_DYNSYM              11
213 #define     SHT_INIT_ARRAY          14
214 #define     SHT_FINI_ARRAY          15
215 #define     SHT_PREINIT_ARRAY       16
216 #define     SHT_GROUP               17
217 #define     SHT_SYMTAB_SHNDX        18
218 #define     SHT_LOOS                0x60000000
219 #define     SHT_HIOS                0x6fffffff
220 #define     SHT_LOPROC              0x70000000
221 #define     SHT_HIPROC              0x7fffffff
222 #define     SHT_LOUSER              0x80000000
223 #define     SHT_HIUSER              0xffffffff
224 
225 /* sh_flags */
226 #define     SHF_WRITE       0x1
227 #define     SHF_ALLOC       0x2
228 #define     SHF_EXECINSTR   0x4
229 #define     SHF_MASKPROC    0xf0000000
230 
231 /* Relocation entry (without addend) */
232 typedef struct {
233 	Elf32_Addr r_offset;
234 	Elf32_Word r_info;
235 } Elf32_Rel;
236 
237 typedef struct {
238 	Elf64_Addr r_offset;
239 	Elf64_Xword r_info;
240 } Elf64_Rel;
241 
242 /* Relocation entry with addend */
243 typedef struct {
244 	Elf32_Addr r_offset;
245 	Elf32_Word r_info;
246 	Elf32_Sword r_addend;
247 } Elf32_Rela;
248 
249 typedef struct elf64_rela {
250 	Elf64_Addr r_offset;
251 	Elf64_Xword r_info;
252 	Elf64_Sxword r_addend;
253 } Elf64_Rela;
254 
255 /* Macros to extract information from 'r_info' field of relocation entries */
256 #define ELF32_R_SYM(i)  ((i) >> 8)
257 #define ELF32_R_TYPE(i) ((unsigned char)(i))
258 #define ELF64_R_SYM(i)  ((i) >> 32)
259 #define ELF64_R_TYPE(i) ((i) & 0xffffffff)
260 
261 /* Symbol table entry */
262 typedef struct {
263 	Elf32_Word st_name;
264 	Elf32_Addr st_value;
265 	Elf32_Word st_size;
266 	unsigned char st_info;
267 	unsigned char st_other;
268 	Elf32_Half st_shndx;
269 } Elf32_Sym;
270 
271 typedef struct elf64_sym {
272 	Elf64_Word st_name;
273 	unsigned char st_info;
274 	unsigned char st_other;
275 	Elf64_Half st_shndx;
276 	Elf64_Addr st_value;
277 	Elf64_Xword st_size;
278 } Elf64_Sym;
279 
280 /* ARM specific dynamic relocation codes */
281 #define     R_ARM_GLOB_DAT	21	/* 0x15 */
282 #define     R_ARM_JUMP_SLOT	22	/* 0x16 */
283 #define     R_ARM_RELATIVE	23	/* 0x17 */
284 #define     R_ARM_ABS32		2	/* 0x02 */
285 
286 /* ELF decoding information */
287 struct elf32_info {
288 	Elf32_Ehdr ehdr;
289 	int load_state;
290 	Elf32_Phdr *phdrs;
291 	Elf32_Shdr *shdrs;
292 	void *shstrtab;
293 };
294 
295 struct elf64_info {
296 	Elf64_Ehdr ehdr;
297 	int load_state;
298 	Elf64_Phdr *phdrs;
299 	Elf64_Shdr *shdrs;
300 	void *shstrtab;
301 };
302 
303 #define ELF_STATE_INIT              0x0L
304 #define ELF_STATE_WAIT_FOR_PHDRS    0x100L
305 #define ELF_STATE_WAIT_FOR_SHDRS    0x200L
306 #define ELF_STATE_WAIT_FOR_SHSTRTAB 0x400L
307 #define ELF_STATE_HDRS_COMPLETE     0x800L
308 #define ELF_STATE_MASK              0xFF00L
309 #define ELF_NEXT_SEGMENT_MASK       0x00FFL
310 
311 extern const struct loader_ops elf_ops;
312 
313 /**
314  * @internal
315  *
316  * @brief Check if it is an ELF file
317  *
318  * It will check if the input image header is an ELF header.
319  *
320  * @param img_data	Firmware private data which will be passed to user
321  *			defined loader operations
322  * @param len		Firmware header length
323  *
324  * @return 0 for success or negative value for failure.
325  */
326 int elf_identify(const void *img_data, size_t len);
327 
328 /**
329  * @internal
330  *
331  * @brief Load ELF headers
332  *
333  * It will get the ELF header, the program header, and the section header.
334  *
335  * @param img_data		Image data
336  * @param offset		Input image data offset to the start of image
337  *				file
338  * @param len			Input image data length
339  * @param img_info		Pointer to store image information data
340  * @param last_load_state	Last state return by this function
341  * @param noffset		Pointer to next offset required by loading ELF
342  *				header
343  * @param nlen			Pointer to next data length required by loading
344  *				ELF header
345  *
346  * @return ELF loading header state, or negative value for failure
347  */
348 int elf_load_header(const void *img_data, size_t offset, size_t len,
349 		    void **img_info, int last_load_state,
350 		    size_t *noffset, size_t *nlen);
351 
352 /**
353  * @internal
354  *
355  * @brief Load ELF data
356  *
357  * It will parse the ELF image and return the target device address,
358  * offset to the start of the ELF image of the data to load and the
359  * length of the data to load.
360  *
361  * @param rproc			Pointer to remoteproc instance
362  * @param img_data		Image data which will passed to the function.
363  *				it can be NULL, if image data doesn't need to
364  *				be handled by the load function. E.g. binary
365  *				data which was loaded to the target memory.
366  * @param offset		Last loaded image data offset to the start of
367  *				image file
368  * @param len			Last loaded image data length
369  * @param img_info		Pointer to store image information data
370  * @param last_load_state	The returned state of the last function call.
371  * @param da			Target device address, if the data to load is
372  *				not for target memory the da will be set to
373  *				ANY.
374  * @param noffset		Pointer to next offset required by loading ELF
375  *				header
376  * @param nlen			Pointer to next data length required by loading
377  *				ELF header
378  * @param padding		Value to pad it is possible that a size of a
379  *				segment in memory is larger than what it is in
380  *				the ELF image. e.g. a segment can have stack
381  *				section .bss. It doesn't need to copy image
382  *				file space, in this case, it will be packed
383  *				with 0.
384  * @param nmemsize		Pointer to next data target memory size. The
385  *				size of a segment in the target memory can be
386  *				larger than the its size in the image file.
387  *
388  * @return 0 for success, otherwise negative value for failure
389  */
390 int elf_load(struct remoteproc *rproc, const void *img_data,
391 	     size_t offset, size_t len,
392 	     void **img_info, int last_load_state,
393 	     metal_phys_addr_t *da,
394 	     size_t *noffset, size_t *nlen,
395 	     unsigned char *padding, size_t *nmemsize);
396 
397 /**
398  * @internal
399  *
400  * @brief Release ELF image information
401  *
402  * It will release ELF image information data.
403  *
404  * @param img_info	Pointer to ELF image information
405  */
406 void elf_release(void *img_info);
407 
408 /**
409  * @internal
410  *
411  * @brief Get entry point
412  *
413  * It will return entry point specified in the ELF file.
414  *
415  * @param img_info	Pointer to ELF image information
416  *
417  * @return Entry address
418  */
419 metal_phys_addr_t elf_get_entry(void *img_info);
420 
421 /**
422  * @internal
423  *
424  * @brief Locate the resource table information
425  *
426  * It will return the length of the resource table, and the device address of
427  * the resource table.
428  *
429  * @param img_info	Pointer to ELF image information
430  * @param da		Pointer to the device address
431  * @param offset	Pointer to the offset to in the ELF image of the
432  *			resource table section.
433  * @param size		Pointer to the size of the resource table section.
434  *
435  * @return 0 if successfully locate the resource table, negative value for
436  * failure.
437  */
438 int elf_locate_rsc_table(void *img_info, metal_phys_addr_t *da,
439 			 size_t *offset, size_t *size);
440 
441 #if defined __cplusplus
442 }
443 #endif
444 
445 #endif /* ELF_LOADER_H_ */
446