1 /*
2 * Copyright (c) 2014, Mentor Graphics Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. Neither the name of Mentor Graphics Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
30 #include <string.h>
31 #include "metal/alloc.h"
32 #include "openamp/elf_loader.h"
34 /* Local functions. */
36 static int elf_loader_get_needed_sections(struct elf_decode_info *elf_info);
37 static int elf_loader_relocs_specific(struct elf_decode_info *elf_info,
38 Elf32_Shdr * section);
39 static void *elf_loader_get_entry_point_address(struct elf_decode_info
40 *elf_info);
41 static int elf_loader_relocate_link(struct elf_decode_info *elf_info);
42 static int elf_loader_seek_and_read(void *firmware, void *destination,
43 Elf32_Off offset, Elf32_Word size);
44 static int elf_loader_read_headers(void *firmware,
45 struct elf_decode_info *elf_info);
46 static int elf_loader_load_sections(void *firmware,
47 struct elf_decode_info *elf_info);
48 static int elf_loader_get_decode_info(void *firmware,
49 struct elf_decode_info *elf_info);
50 static int elf_loader_reloc_entry(struct elf_decode_info *elf_info,
51 Elf32_Rel * rel_entry);
52 static Elf32_Addr elf_loader_get_dynamic_symbol_addr(struct elf_decode_info
53 *elf_info, int index);
55 /**
56 * elf_loader_init
57 *
58 * Initializes ELF loader.
59 *
60 * @param loader - pointer to remoteproc loader
61 *
62 * @return - 0 if success, error otherwise
63 */
64 int elf_loader_init(struct remoteproc_loader *loader)
65 {
67 /* Initialize loader function table */
68 loader->load_firmware = elf_loader_load_remote_firmware;
69 loader->retrieve_entry = elf_loader_retrieve_entry_point;
70 loader->retrieve_rsc = elf_loader_retrieve_resource_section;
71 loader->attach_firmware = elf_loader_attach_firmware;
72 loader->detach_firmware = elf_loader_detach_firmware;
73 loader->retrieve_load_addr = elf_get_load_address;
75 return RPROC_SUCCESS;
76 }
78 /**
79 * elf_loader_attach_firmware
80 *
81 * Attaches an ELF firmware to the loader
82 *
83 * @param loader - pointer to remoteproc loader
84 * @param firmware - pointer to the firmware start location
85 *
86 * @return - 0 if success, error otherwise
87 */
88 int elf_loader_attach_firmware(struct remoteproc_loader *loader, void *firmware)
89 {
91 struct elf_decode_info *elf_info;
92 int status;
94 /* Allocate memory for decode info structure. */
95 elf_info = metal_allocate_memory(sizeof(struct elf_decode_info));
97 if (!elf_info) {
98 return RPROC_ERR_NO_MEM;
99 }
101 /* Clear the ELF decode struct. */
102 memset(elf_info, 0, sizeof(struct elf_decode_info));
104 /* Get the essential information to decode the ELF. */
105 status = elf_loader_get_decode_info(firmware, elf_info);
107 if (status) {
108 /* Free memory. */
109 metal_free_memory(elf_info);
110 return status;
111 }
113 elf_info->firmware = firmware;
114 loader->fw_decode_info = elf_info;
116 return status;
117 }
119 /**
120 * elf_loader_detach_firmware
121 *
122 * Detaches ELF firmware from the loader
123 *
124 * @param loader - pointer to remoteproc loader
125 *
126 * @return - 0 if success, error otherwise
127 */
128 int elf_loader_detach_firmware(struct remoteproc_loader *loader)
129 {
131 struct elf_decode_info *elf_info =
132 (struct elf_decode_info *)loader->fw_decode_info;
133 if (elf_info) {
134 /* Free memory. */
135 metal_free_memory(elf_info->shstrtab);
136 metal_free_memory(elf_info->section_headers_start);
137 metal_free_memory(elf_info);
138 }
140 return RPROC_SUCCESS;
141 }
143 /**
144 * elf_loader_retrieve_entry_point
145 *
146 * Retrieves the ELF entrypoint.
147 *
148 * @param loader - pointer to remoteproc loader
149 *
150 * @return - entrypoint
151 */
152 void *elf_loader_retrieve_entry_point(struct remoteproc_loader *loader)
153 {
155 return elf_loader_get_entry_point_address((struct elf_decode_info *)
156 loader->fw_decode_info);
157 }
159 /**
160 * elf_loader_retrieve_resource_section
161 *
162 * Retrieves the resource section.
163 *
164 * @param loader - pointer to remoteproc loader
165 * @param size - pointer to contain the size of the section
166 *
167 * @return - pointer to resource section
168 */
169 void *elf_loader_retrieve_resource_section(struct remoteproc_loader *loader,
170 unsigned int *size)
171 {
173 Elf32_Shdr *rsc_header;
174 void *resource_section = NULL;
175 struct elf_decode_info *elf_info =
176 (struct elf_decode_info *)loader->fw_decode_info;
178 if (elf_info->rsc) {
179 /* Retrieve resource section header. */
180 rsc_header = elf_info->rsc;
181 /* Retrieve resource section size. */
182 *size = rsc_header->sh_size;
184 /* Locate the start of resource section. */
185 resource_section = (void *)((uintptr_t)elf_info->firmware
186 + rsc_header->sh_offset);
187 }
189 /* Return the address of resource section. */
190 return resource_section;
191 }
193 /**
194 * elf_loader_load_remote_firmware
195 *
196 * Loads the ELF firmware.
197 *
198 * @param loader - pointer to remoteproc loader
199 *
200 * @return - 0 if success, error otherwise
201 */
202 int elf_loader_load_remote_firmware(struct remoteproc_loader *loader)
203 {
205 struct elf_decode_info *elf_info =
206 (struct elf_decode_info *)loader->fw_decode_info;
207 int status;
209 /* Load ELF sections. */
210 status = elf_loader_load_sections(elf_info->firmware, elf_info);
212 if (!status) {
214 /* Perform dynamic relocations if needed. */
215 status = elf_loader_relocate_link(elf_info);
216 }
218 return status;
219 }
221 /**
222 * elf_get_load_address
223 *
224 * Provides firmware load address.
225 *
226 * @param loader - pointer to remoteproc loader
227 *
228 * @return - load address pointer
229 */
230 void *elf_get_load_address(struct remoteproc_loader *loader)
231 {
233 struct elf_decode_info *elf_info =
234 (struct elf_decode_info *)loader->fw_decode_info;
235 int status = 0;
236 Elf32_Shdr *current = (Elf32_Shdr *) (elf_info->section_headers_start);
238 /* Traverse all sections except the reserved null section. */
239 int section_count = elf_info->elf_header.e_shnum - 1;
240 while ((section_count > 0) && (status == 0)) {
241 /* Compute the pointer to section header. */
242 current = (Elf32_Shdr *) (((unsigned char *)current)
243 + elf_info->elf_header.e_shentsize);
244 /* Get the name of current section. */
245 char *current_name = elf_info->shstrtab + current->sh_name;
246 if (!strcmp(current_name, ".text")) {
247 return ((void *)(current->sh_addr));
248 }
249 /* Move to the next section. */
250 section_count--;
251 }
253 return (RPROC_ERR_PTR);
254 }
256 /**
257 * elf_loader_get_needed_sections
258 *
259 * Retrieves the sections we need during the load and link from the
260 * section headers list.
261 *
262 * @param elf_info - ELF object decode info container.
263 *
264 * @return- Pointer to the ELF section header.
265 */
267 static int elf_loader_get_needed_sections(struct elf_decode_info *elf_info)
268 {
269 Elf32_Shdr *current = (Elf32_Shdr *) (elf_info->section_headers_start);
271 /* We are interested in the following sections:
272 .dynsym
273 .dynstr
274 .rel.plt
275 .rel.dyn
276 */
277 int sections_to_find = 5;
279 /* Search for sections but skip the reserved null section. */
281 int section_count = elf_info->elf_header.e_shnum - 1;
282 while ((section_count > 0) && (sections_to_find > 0)) {
283 /* Compute the section header pointer. */
284 current = (Elf32_Shdr *) (((unsigned char *)current)
285 + elf_info->elf_header.e_shentsize);
287 /* Get the name of current section. */
288 char *current_name = elf_info->shstrtab + current->sh_name;
290 /* Proceed if the section is allocatable and is not executable. */
291 if ((current->sh_flags & SHF_ALLOC)
292 && !(current->sh_flags & SHF_EXECINSTR)) {
293 /* Check for '.dynsym' or '.dynstr' or '.rel.plt' or '.rel.dyn'. */
294 if (*current_name == '.') {
295 current_name++;
297 /* Check for '.dynsym' or 'dynstr'. */
298 if (*current_name == 'd') {
299 current_name++;
301 /* Check for '.dynsym'. */
302 if (strncmp(current_name, "ynsym", 5) == 0) {
303 elf_info->dynsym = current;
304 sections_to_find--;
305 }
307 /* Check for '.dynstr'. */
308 else if (strncmp(current_name, "ynstr", 5) == 0) {
309 elf_info->dynstr = current;
310 sections_to_find--;
311 }
312 }
314 /* Check for '.rel.plt' or '.rel.dyn'. */
315 else if (*current_name == 'r') {
316 current_name++;
318 /* Check for '.rel.plt'. */
319 if (strncmp(current_name, "el.plt", 6) == 0) {
320 elf_info->rel_plt = current;
321 sections_to_find--;
322 }
324 /* Check for '.rel.dyn'. */
325 else if (strncmp(current_name, "el.dyn", 6) == 0) {
326 elf_info->rel_dyn = current;
327 sections_to_find--;
328 }
330 /* Check for '.resource_table'. */
331 else if (strncmp(current_name, "esource_table", 13)
332 == 0) {
333 elf_info->rsc = current;
334 sections_to_find--;
335 }
336 }
337 }
338 }
340 /* Move to the next section. */
341 section_count--;
342 }
344 /* Return remaining sections section. */
345 return (sections_to_find);
346 }
348 /**
349 * elf_loader_relocs_specific
350 *
351 * Processes the relocations contained in the specified section.
352 *
353 * @param elf_info - elf decoding information.
354 * @param section - header of the specified relocation section.
355 *
356 * @return - 0 if success, error otherwise
357 */
358 static int elf_loader_relocs_specific(struct elf_decode_info *elf_info,
359 Elf32_Shdr * section)
360 {
362 unsigned char *section_load_addr = (unsigned char *)section->sh_addr;
363 int status = 0;
364 unsigned int i;
366 /* Check the section type. */
367 if (section->sh_type == SHT_REL) {
368 /* Traverse the list of relocation entries contained in the section. */
369 for (i = 0; (i < section->sh_size) && (status == 0);
370 i += section->sh_entsize) {
371 /* Compute the relocation entry address. */
372 Elf32_Rel *rel_entry =
373 (Elf32_Rel *) (section_load_addr + i);
375 /* Process the relocation entry. */
376 status = elf_loader_reloc_entry(elf_info, rel_entry);
377 }
378 }
380 /* Return status to caller. */
381 return (status);
382 }
384 /**
385 * elf_loader_get_entry_point_address
386 *
387 * Retrieves the entry point address from the specified ELF object.
388 *
389 * @param elf_info - elf object decode info container.
390 * @param runtime_buffer - buffer containing ELF sections which are
391 * part of runtime.
392 *
393 * @return - entry point address of the specified ELF object.
394 */
395 static void *elf_loader_get_entry_point_address(struct elf_decode_info
396 *elf_info)
397 {
398 return ((void *)elf_info->elf_header.e_entry);
399 }
401 /**
402 * elf_loader_relocate_link
403 *
404 * Relocates and links the given ELF object.
405 *
406 * @param elf_info - elf object decode info container.
408 *
409 * @return - 0 if success, error otherwise
410 */
412 static int elf_loader_relocate_link(struct elf_decode_info *elf_info)
413 {
414 int status = 0;
416 /* Check of .rel.dyn section exists in the ELF. */
417 if (elf_info->rel_dyn) {
418 /* Relocate and link .rel.dyn section. */
419 status =
420 elf_loader_relocs_specific(elf_info, elf_info->rel_dyn);
421 }
423 /* Proceed to check if .rel.plt section exists, if no error encountered yet. */
424 if (status == 0 && elf_info->rel_plt) {
425 /* Relocate and link .rel.plt section. */
426 status =
427 elf_loader_relocs_specific(elf_info, elf_info->rel_plt);
428 }
430 /* Return status to caller */
431 return (status);
432 }
434 /**
435 * elf_loader_seek_and_read
436 *
437 * Seeks to the specified offset in the given file and reads the data
438 * into the specified destination location.
439 *
440 * @param firmware - firmware to read from.
441 * @param destination - Location into which the data should be read.
442 * @param offset - Offset to seek in the file.
443 * @param size - Size of the data to read.
445 *
446 * @return - 0 if success, error otherwise
447 */
449 static int elf_loader_seek_and_read(void *firmware, void *destination,
450 Elf32_Off offset, Elf32_Word size)
451 {
452 char *src = (char *)firmware;
454 /* Seek to the specified offset. */
455 src = src + offset;
457 /* Read the data. */
458 memcpy((char *)destination, src, size);
460 /* Return status to caller. */
461 return (0);
462 }
464 /**
465 * elf_loader_read_headers
466 *
467 * Reads the ELF headers (ELF header, section headers and the section
468 * headers string table) essential to access further information from
469 * the file containing the ELF object.
470 *
471 * @param firmware - firmware to read from.
472 * @param elf_info - ELF object decode info container.
473 *
474 * @return - 0 if success, error otherwise
475 */
476 static int elf_loader_read_headers(void *firmware,
477 struct elf_decode_info *elf_info)
478 {
479 int status = 0;
480 unsigned int section_count;
482 /* Read the ELF header. */
483 status = elf_loader_seek_and_read(firmware, &(elf_info->elf_header), 0,
484 sizeof(Elf32_Ehdr));
486 /* Ensure the read was successful. */
487 if (!status) {
488 /* Get section count from the ELF header. */
489 section_count = elf_info->elf_header.e_shnum;
491 /* Allocate memory to read in the section headers. */
492 elf_info->section_headers_start = metal_allocate_memory(section_count * elf_info->elf_header.e_shentsize);
494 /* Check if the allocation was successful. */
495 if (elf_info->section_headers_start) {
496 /* Read the section headers list. */
497 status = elf_loader_seek_and_read(firmware,
498 elf_info->
499 section_headers_start,
500 elf_info->elf_header.
501 e_shoff,
502 section_count *
503 elf_info->elf_header.
504 e_shentsize);
506 /* Ensure the read was successful. */
507 if (!status) {
508 /* Compute the pointer to section header string table section. */
509 Elf32_Shdr *section_header_string_table =
510 (Elf32_Shdr *) (elf_info->
511 section_headers_start +
512 elf_info->elf_header.
513 e_shstrndx *
514 elf_info->elf_header.
515 e_shentsize);
517 /* Allocate the memory for section header string table. */
518 elf_info->shstrtab = metal_allocate_memory(section_header_string_table->sh_size);
520 /* Ensure the allocation was successful. */
521 if (elf_info->shstrtab) {
522 /* Read the section headers string table. */
523 status =
524 elf_loader_seek_and_read(firmware,
525 elf_info->
526 shstrtab,
527 section_header_string_table->
528 sh_offset,
529 section_header_string_table->
530 sh_size);
531 }
532 }
533 }
534 }
536 /* Return status to caller. */
537 return (status);
538 }
540 /**
541 * elf_loader_file_read_sections
542 *
543 * Reads the ELF section contents from the specified file containing
544 * the ELF object.
545 *
546 * @param firmware - firmware to read from.
547 * @param elf_info - ELF object decode info container.
548 *
549 * @return - 0 if success, error otherwise
550 */
551 static int elf_loader_load_sections(void *firmware,
552 struct elf_decode_info *elf_info)
553 {
554 int status = 0;
555 Elf32_Shdr *current = (Elf32_Shdr *) (elf_info->section_headers_start);
557 /* Traverse all sections except the reserved null section. */
558 int section_count = elf_info->elf_header.e_shnum - 1;
559 while ((section_count > 0) && (status == 0)) {
560 /* Compute the pointer to section header. */
561 current = (Elf32_Shdr *) (((unsigned char *)current)
562 + elf_info->elf_header.e_shentsize);
564 /* Make sure the section can be allocated and is not empty. */
565 if ((current->sh_flags & SHF_ALLOC) && (current->sh_size)) {
566 char *destination = NULL;
568 /* Check if the section is part of runtime and is not section with
569 * no-load attributes such as BSS or heap. */
570 if ((current->sh_type & SHT_NOBITS) == 0) {
571 /* Compute the destination address where the section should
572 * be copied. */
573 destination = (char *)(current->sh_addr);
574 status =
575 elf_loader_seek_and_read(firmware,
576 destination,
577 current->sh_offset,
578 current->sh_size);
579 }
580 }
582 /* Move to the next section. */
583 section_count--;
584 }
586 /* Return status to caller. */
587 return (status);
588 }
590 /**
591 * elf_loader_get_decode_info
592 *
593 * Retrieves the information necessary to decode the ELF object for
594 * loading, relocating and linking.
595 *
596 * @param firmware - firmware to read from.
597 * @param elf_info - ELF object decode info container.
598 *
599 * @return - 0 if success, error otherwise
600 */
601 static int elf_loader_get_decode_info(void *firmware,
602 struct elf_decode_info *elf_info)
603 {
604 int status;
606 /* Read the ELF headers (ELF header and section headers including
607 * the section header string table). */
608 status = elf_loader_read_headers(firmware, elf_info);
610 /* Ensure that ELF headers were read successfully. */
611 if (!status) {
612 /* Retrieve the sections required for load. */
613 elf_loader_get_needed_sections(elf_info);
615 }
617 /* Return status to caller. */
618 return (status);
619 }
621 /**
622 * elf_loader_get_dynamic_symbol_addr
623 *
624 * Retrieves the (relocatable) address of the symbol specified as
625 * index from the given ELF object.
626 *
627 * @param elf_info - ELF object decode info container.
628 * @param index - Index of the desired symbol in the dynamic symbol table.
629 *
630 * @return - Address of the specified symbol.
631 */
632 static Elf32_Addr elf_loader_get_dynamic_symbol_addr(struct elf_decode_info
633 *elf_info, int index)
634 {
635 Elf32_Sym *symbol_entry = (Elf32_Sym *) (elf_info->dynsym_addr
636 +
637 index *
638 elf_info->dynsym->sh_entsize);
640 /* Return the symbol address. */
641 return (symbol_entry->st_value);
642 }
644 /**
645 * elf_loader_reloc_entry
646 *
647 * Processes the specified relocation entry. It handles the relocation
648 * and linking both cases.
649 *
650 *
651 * @param elf_info - ELF object decode info container.
652 *
653 * @return - 0 if success, error otherwise
654 */
655 static int elf_loader_reloc_entry(struct elf_decode_info *elf_info,
656 Elf32_Rel * rel_entry)
657 {
658 unsigned char rel_type = ELF32_R_TYPE(rel_entry->r_info);
659 int status = 0;
661 switch (rel_type) {
662 case R_ARM_ABS32: /* 0x02 */
663 {
664 Elf32_Addr sym_addr =
665 elf_loader_get_dynamic_symbol_addr(elf_info,
666 ELF32_R_SYM
667 (rel_entry->
668 r_info));
670 if (sym_addr) {
671 *((unsigned int *)(rel_entry->r_offset)) =
672 (unsigned int)sym_addr;
673 break;
674 }
675 }
677 break;
679 default:
680 break;
681 }
683 return status;
684 }