23 |
#endif |
#endif |
24 |
|
|
25 |
#include <string.h> |
#include <string.h> |
26 |
|
#include <l4/kip.h> |
27 |
|
|
28 |
#include "loader.h" |
#include "loader.h" |
29 |
#include "output.h" |
#include "output.h" |
35 |
|
|
36 |
/* Verify that the memory region START to END (exclusive) is valid. */ |
/* Verify that the memory region START to END (exclusive) is valid. */ |
37 |
static void |
static void |
38 |
mem_check (const char *name, unsigned long start, unsigned long end) |
mem_check (const char *name, l4_word_t start, l4_word_t end) |
39 |
{ |
{ |
40 |
l4_memory_desc_t memdesc; |
l4_memory_desc_t memdesc; |
41 |
int nr; |
int nr; |
45 |
if (!loader_get_num_memory_desc ()) |
if (!loader_get_num_memory_desc ()) |
46 |
return; |
return; |
47 |
|
|
48 |
|
end--; |
49 |
|
|
50 |
/* FIXME: This implementation does not account for conventional |
/* FIXME: This implementation does not account for conventional |
51 |
memory overriding non-conventional memory in the descriptor |
memory overriding non-conventional memory in the descriptor |
52 |
list. */ |
list. */ |
57 |
if (memdesc->type == L4_MEMDESC_CONVENTIONAL) |
if (memdesc->type == L4_MEMDESC_CONVENTIONAL) |
58 |
{ |
{ |
59 |
/* Check if the region fits into conventional memory. */ |
/* Check if the region fits into conventional memory. */ |
60 |
if (start >= (memdesc->low << 10) && start < (memdesc->high << 10) |
if (start >= l4_memory_desc_low (memdesc) |
61 |
&& end > (memdesc->low << 10) && end <= (memdesc->high << 10)) |
&& start <= l4_memory_desc_high (memdesc) |
62 |
|
&& end >= l4_memory_desc_low (memdesc) |
63 |
|
&& end <= l4_memory_desc_high (memdesc)) |
64 |
fits = 1; |
fits = 1; |
65 |
} |
} |
66 |
else |
else |
67 |
{ |
{ |
68 |
/* Check if the region overlaps with non-conventional |
/* Check if the region overlaps with non-conventional |
69 |
memory. */ |
memory. */ |
70 |
if ((start >= (memdesc->low << 10) && start < (memdesc->high << 10)) |
if ((start >= l4_memory_desc_low (memdesc) |
71 |
|| (end > (memdesc->low << 10) && end <= (memdesc->high << 10)) |
&& start <= l4_memory_desc_high (memdesc)) |
72 |
|| (start < (memdesc->low << 10) && end > (memdesc->high << 10))) |
|| (end >= l4_memory_desc_low (memdesc) |
73 |
|
&& end <= l4_memory_desc_high (memdesc)) |
74 |
|
|| (start < l4_memory_desc_low (memdesc) |
75 |
|
&& end > l4_memory_desc_high (memdesc))) |
76 |
{ |
{ |
77 |
conflicts = 1; |
fits = 0; |
78 |
break; |
conflicts = 1 + nr; |
79 |
} |
} |
80 |
} |
} |
81 |
} |
} |
82 |
if (conflicts) |
|
|
panic ("%s (0x%x - 0x%x) conflicts with memory of " |
|
|
"type %i/%i (0x%x - 0x%x)", name, start, end, |
|
|
memdesc->type, memdesc->subtype, |
|
|
memdesc->low << 10, memdesc->high << 10); |
|
83 |
if (!fits) |
if (!fits) |
84 |
panic ("%s (0x%x - 0x%x) does not fit into memory", |
{ |
85 |
name, start, end); |
if (conflicts) |
86 |
|
{ |
87 |
|
memdesc = loader_get_memory_desc (conflicts - 1); |
88 |
|
panic ("%s (0x%" L4_PRIxWORD " - 0x%" L4_PRIxWORD ") conflicts " |
89 |
|
"with memory of type %i/%i (0x%" L4_PRIxWORD " - 0x%" |
90 |
|
L4_PRIxWORD ")", name, start, end + 1, |
91 |
|
memdesc->type, memdesc->subtype, |
92 |
|
l4_memory_desc_low (memdesc), l4_memory_desc_high (memdesc)); |
93 |
|
} |
94 |
|
else |
95 |
|
panic ("%s (0x%" L4_PRIxWORD " - 0x%" L4_PRIxWORD ") does not fit " |
96 |
|
"into memory", name, start, end + 1); |
97 |
|
} |
98 |
} |
} |
99 |
|
|
100 |
|
|
144 |
if (nr_regions == MAX_REGIONS) |
if (nr_regions == MAX_REGIONS) |
145 |
panic ("Too many memory regions, region %s doesn't fit", name); |
panic ("Too many memory regions, region %s doesn't fit", name); |
146 |
|
|
147 |
|
if (start >= end) |
148 |
|
panic ("Region %s has a start address following the end address", name); |
149 |
|
|
150 |
check_region (name, start, end); |
check_region (name, start, end); |
151 |
|
|
152 |
used_regions[nr_regions].name = name; |
used_regions[nr_regions].name = name; |
178 |
} |
} |
179 |
|
|
180 |
|
|
181 |
|
/* Get the memory range to which the ELF image from START to END |
182 |
|
(exclusive) will be loaded. NAME is used for panic messages. */ |
183 |
|
void |
184 |
|
loader_elf_dest (const char *name, l4_word_t start, l4_word_t end, |
185 |
|
l4_word_t *new_start_p, l4_word_t *new_end_p) |
186 |
|
{ |
187 |
|
l4_word_t new_start = -1; |
188 |
|
l4_word_t new_end = 0; |
189 |
|
int i; |
190 |
|
|
191 |
|
Elf32_Ehdr *elf = (Elf32_Ehdr *) start; |
192 |
|
|
193 |
|
if (elf->e_ident[EI_MAG0] != ELFMAG0 |
194 |
|
|| elf->e_ident[EI_MAG1] != ELFMAG1 |
195 |
|
|| elf->e_ident[EI_MAG2] != ELFMAG2 |
196 |
|
|| elf->e_ident[EI_MAG3] != ELFMAG3) |
197 |
|
panic ("%s is not an ELF file", name); |
198 |
|
|
199 |
|
if (elf->e_type != ET_EXEC) |
200 |
|
panic ("%s is not an executable file", name); |
201 |
|
|
202 |
|
if (!elf->e_phoff) |
203 |
|
panic ("%s has no valid program header offset", name); |
204 |
|
|
205 |
|
/* FIXME: Some architectures support both word sizes. */ |
206 |
|
if (!((elf->e_ident[EI_CLASS] == ELFCLASS32 |
207 |
|
&& L4_WORDSIZE == L4_WORDSIZE_32) |
208 |
|
|| (elf->e_ident[EI_CLASS] == ELFCLASS64 |
209 |
|
&& L4_WORDSIZE == L4_WORDSIZE_64))) |
210 |
|
panic ("%s has invalid word size", name); |
211 |
|
if (!((elf->e_ident[EI_DATA] == ELFDATA2LSB |
212 |
|
&& L4_BYTE_ORDER == L4_LITTLE_ENDIAN) |
213 |
|
|| (elf->e_ident[EI_DATA] == ELFDATA2MSB |
214 |
|
&& L4_BYTE_ORDER == L4_BIG_ENDIAN))) |
215 |
|
panic ("%s has invalid byte order", name); |
216 |
|
|
217 |
|
#if i386 |
218 |
|
# define elf_machine EM_386 |
219 |
|
#elif PPC |
220 |
|
# define elf_machine EM_PPC |
221 |
|
#else |
222 |
|
# error Not ported to this architecture! |
223 |
|
#endif |
224 |
|
|
225 |
|
if (elf->e_machine != elf_machine) |
226 |
|
panic ("%s is not for this architecture", name); |
227 |
|
|
228 |
|
for (i = 0; i < elf->e_phnum; i++) |
229 |
|
{ |
230 |
|
Elf32_Phdr *ph = (Elf32_Phdr *) (start + elf->e_phoff |
231 |
|
+ i * elf->e_phentsize); |
232 |
|
if (ph->p_type == PT_LOAD) |
233 |
|
{ |
234 |
|
if (ph->p_paddr < new_start) |
235 |
|
new_start = ph->p_paddr; |
236 |
|
if (ph->p_memsz + ph->p_paddr > new_end) |
237 |
|
new_end = ph->p_memsz + ph->p_paddr; |
238 |
|
} |
239 |
|
} |
240 |
|
|
241 |
|
if (new_start_p) |
242 |
|
*new_start_p = new_start; |
243 |
|
if (new_end_p) |
244 |
|
*new_end_p = new_end; |
245 |
|
} |
246 |
|
|
247 |
|
|
248 |
/* Load the ELF image from START to END (exclusive) into memory under |
/* Load the ELF image from START to END (exclusive) into memory under |
249 |
the name NAME (also used as the name for the region of the |
the name NAME (also used as the name for the region of the |
250 |
resulting ELF program). Return the lowest and highest address used |
resulting ELF program). Return the lowest and highest address used |