root/ar5315_microredboot/microredboot/boot/src/lib/elf.c

Revision 12429, 2.6 kB (checked in by BrainSlayer, 5 months ago)

compressed ELF support is required for ubnt images

Line 
1 #include "elf.h"
2
3 static unsigned long fis_load_elf_image(unsigned long flash, unsigned long base,
4                                         unsigned long length,
5                                         unsigned long *entry_address,
6                                         unsigned long *load_address,
7                                         unsigned long *load_address_end)
8 {
9         Elf32_Ehdr ehdr;
10 #define MAX_PHDR 8
11         Elf32_Phdr phdr[MAX_PHDR];
12         unsigned long offset = 0;
13         int phx, len;
14         unsigned char *addr;
15         unsigned long addr_offset = 0;
16         unsigned long highest_address = 0;
17         unsigned long lowest_address = 0xFFFFFFFF;
18
19         memmove(&ehdr, (char *)flash, sizeof(Elf32_Ehdr));
20
21         offset += sizeof(Elf32_Ehdr);
22
23         if (ehdr.e_type != ET_EXEC) {
24                 printf("Only absolute ELF images supported\n");
25                 return 0;
26         }
27         if (ehdr.e_phnum > MAX_PHDR) {
28                 printf("Too many program headers\n");
29                 return 0;
30         }
31
32         offset = ehdr.e_phoff;  /* =, not += !!! */
33
34         for (phx = 0; phx < ehdr.e_phnum; phx++) {
35
36                 memmove(&phdr[phx], (char *)(flash + offset),
37                         sizeof(Elf32_Phdr));
38
39                 offset += sizeof(Elf32_Phdr);
40         }
41         if (base) {
42                 // Set address offset based on lowest address in file.
43                 addr_offset = 0xFFFFFFFF;
44                 for (phx = 0; phx < ehdr.e_phnum; phx++) {
45                         if (phdr[phx].p_vaddr < addr_offset) {
46                                 addr_offset = phdr[phx].p_vaddr;
47                         }
48                 }
49                 addr_offset = (unsigned long)base - addr_offset;
50         } else {
51                 addr_offset = 0;
52         }
53
54         for (phx = 0; phx < ehdr.e_phnum; phx++) {
55                 if (phdr[phx].p_type == PT_LOAD) {
56                         // Loadable segment
57                         addr = (unsigned char *)phdr[phx].p_vaddr;
58                         len = phdr[phx].p_filesz;
59                         if ((unsigned long)addr < lowest_address) {
60                                 lowest_address = (unsigned long)addr;
61                         }
62                         addr += addr_offset;
63                         if (offset > phdr[phx].p_offset) {
64                                 if ((phdr[phx].p_offset + len) < offset) {
65                                         printf
66                                             ("Can't load ELF file - program headers out of order\n");
67                                         return 0;
68                                 }
69                                 addr += offset - phdr[phx].p_offset;
70                         } else {
71                                 offset = phdr[phx].p_offset;    /* _=_ */
72                         }
73
74                         memmove((char *)addr, (char *)(flash + offset), len);
75                         offset += len;
76                         len = 0;
77
78                         if ((unsigned long)(addr - addr_offset) >
79                             highest_address) {
80                                 highest_address =
81                                     (unsigned long)(addr - addr_offset);
82                         }
83                 }
84         }                       /* for (phx... */
85         // Save load base/top and entry
86         if (base) {
87                 *load_address = base;
88                 *load_address_end = base + (highest_address - lowest_address);
89                 *entry_address = base + (ehdr.e_entry - lowest_address);
90         } else {
91                 *load_address = lowest_address;
92                 *load_address_end = highest_address;
93                 *entry_address = ehdr.e_entry;
94         }
95
96         // redboot_getc_terminate(false);
97         if (addr_offset)
98                 printf("\nAddress offset = 0x%08X\n", (void *)addr_offset);
99         printf("Entry point: 0x%08X, address range: 0x%08X-0x%08X\n",
100                     (void *)*entry_address, (void *)*load_address,
101                     (void *)*load_address_end);
102         return 1;
103 }
Note: See TracBrowser for help on using the browser.