001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019 #include <sos/kmalloc.h>
020 #include <sos/assert.h>
021 #include <sos/physmem.h>
022 #include <drivers/bochs.h>
023 #include <hwcore/paging.h>
024 #include <drivers/zero.h>
025
026 #include "binfmt_elf32.h"
027
028
029
030
031
032
033 struct userprog_entry
034 {
035 const char *name;
036 sos_vaddr_t bottom_vaddr;
037 sos_vaddr_t top_vaddr;
038 };
039
040
041
042
043
044
045 extern char _userprogs_table;
046
047
048
049
050
051
052 struct elf32_mapped_program
053 {
054 sos_vaddr_t vaddr;
055 sos_size_t size;
056 int ref_cnt;
057
058 struct sos_umem_vmm_mapped_resource mr;
059 };
060
061
062
063
064 static void elf32prog_ref(struct sos_umem_vmm_vr * vr)
065 {
066 struct elf32_mapped_program * elf32prog_resource;
067 elf32prog_resource = (struct elf32_mapped_program*) sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
068
069 elf32prog_resource->ref_cnt ++;
070 }
071
072
073
074
075 static void elf32prog_unref(struct sos_umem_vmm_vr * vr)
076 {
077 struct elf32_mapped_program * elf32prog_resource;
078 elf32prog_resource
079 = (struct elf32_mapped_program*)
080 sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
081
082 elf32prog_resource->ref_cnt --;
083 SOS_ASSERT_FATAL(elf32prog_resource->ref_cnt >= 0);
084
085
086 if (elf32prog_resource->ref_cnt == 0)
087 sos_kfree((sos_vaddr_t)elf32prog_resource);
088 }
089
090
091
092 static sos_ret_t elf32prog_page_in(struct sos_umem_vmm_vr * vr,
093 sos_uaddr_t uaddr,
094 sos_bool_t write_access)
095 {
096 struct elf32_mapped_program * elf32prog_resource;
097 sos_ret_t retval = SOS_OK;
098 sos_paddr_t ppage_paddr;
099 sos_uaddr_t upage_uaddr = SOS_PAGE_ALIGN_INF(uaddr);
100 sos_uoffset_t offset_in_prog;
101 sos_size_t size_to_copy;
102 sos_ui32_t access_rights = sos_umem_vmm_get_prot_of_vr(vr);
103
104 elf32prog_resource
105 = (struct elf32_mapped_program*)
106 sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
107
108
109
110 offset_in_prog = upage_uaddr - sos_umem_vmm_get_start_of_vr(vr)
111 + sos_umem_vmm_get_offset_in_resource(vr);
112 size_to_copy = SOS_PAGE_SIZE;
113 if (offset_in_prog + size_to_copy > elf32prog_resource->size)
114 size_to_copy = elf32prog_resource->size - offset_in_prog;
115
116
117
118 if (SOS_IS_PAGE_ALIGNED(elf32prog_resource->vaddr + offset_in_prog))
119 {
120 sos_vaddr_t kern_vaddr = elf32prog_resource->vaddr + offset_in_prog;
121
122 ppage_paddr = sos_paging_get_paddr(kern_vaddr);
123
124
125 retval = sos_paging_map(ppage_paddr,
126 upage_uaddr,
127 TRUE,
128 access_rights & ~SOS_VM_MAP_PROT_WRITE);
129 SOS_ASSERT_FATAL(SOS_OK == retval);
130 }
131
132
133 else
134 {
135
136
137 ppage_paddr = sos_physmem_ref_physpage_new(FALSE);
138 if (! ppage_paddr)
139 return -SOS_ENOMEM;
140
141
142
143 retval = sos_paging_map(ppage_paddr,
144 upage_uaddr,
145 TRUE,
146 access_rights | SOS_VM_MAP_PROT_WRITE);
147 SOS_ASSERT_FATAL(SOS_OK == retval);
148 sos_physmem_unref_physpage(ppage_paddr);
149
150
151 memcpy((void*)upage_uaddr,
152 (void*)(elf32prog_resource->vaddr + offset_in_prog),
153 size_to_copy);
154 if (size_to_copy < SOS_PAGE_SIZE)
155 memset((void*)(upage_uaddr + size_to_copy), 0x0,
156 SOS_PAGE_SIZE - size_to_copy);
157
158
159 if (! (access_rights & SOS_VM_MAP_PROT_WRITE))
160 return sos_paging_set_prot(upage_uaddr,
161 access_rights & ~SOS_VM_MAP_PROT_WRITE);
162 }
163
164 return retval;
165 }
166
167
168 static struct sos_umem_vmm_vr_ops elf32prog_ops = (struct sos_umem_vmm_vr_ops)
169 {
170 .ref = elf32prog_ref,
171 .unref = elf32prog_unref,
172 .page_in = elf32prog_page_in,
173 .unmap = NULL
174 };
175
176
177 static sos_ret_t elf32prog_mmap(struct sos_umem_vmm_vr *vr)
178 {
179 return sos_umem_vmm_set_ops_of_vr(vr, &elf32prog_ops);
180 }
181
182
183
184
185
186
187
188
189
190
191 static struct userprog_entry * lookup_userprog(const char *name);
192
193
194 sos_uaddr_t sos_binfmt_elf32_map(struct sos_umem_vmm_as * dest_as,
195 const char * progname)
196 {
197 int i;
198
199
200
201
202
203 typedef unsigned long Elf32_Addr;
204 typedef unsigned long Elf32_Word;
205 typedef unsigned short Elf32_Half;
206 typedef unsigned long Elf32_Off;
207 typedef signed long Elf32_Sword;
208
209
210
211 #define EI_NIDENT 16
212 typedef struct {
213 unsigned char e_ident[EI_NIDENT];
214 Elf32_Half e_type;
215 Elf32_Half e_machine;
216 Elf32_Word e_version;
217 Elf32_Addr e_entry;
218 Elf32_Off e_phoff;
219 Elf32_Off e_shoff;
220 Elf32_Word e_flags;
221 Elf32_Half e_ehsize;
222 Elf32_Half e_phentsize;
223 Elf32_Half e_phnum;
224 Elf32_Half e_shentsize;
225 Elf32_Half e_shnum;
226 Elf32_Half e_shstrndx;
227 } __attribute__((packed)) Elf32_Ehdr_t;
228
229
230 #define ELFMAG0 0x7f
231 #define ELFMAG1 'E'
232 #define ELFMAG2 'L'
233 #define ELFMAG3 'F'
234
235
236 #define EI_MAG0 0
237 #define EI_MAG1 1
238 #define EI_MAG2 2
239 #define EI_MAG3 3
240 #define EI_CLASS 4
241 #define EI_DATA 5
242 #define EI_VERSION 6
243 #define EI_PAD 7
244
245
246 #define ELFCLASSNONE 0
247 #define ELFCLASS32 1
248 #define ELFCLASS64 2
249
250
251 #define ELFDATANONE 0
252 #define ELFDATA2LSB 1
253 #define ELFDATA2MSB 2
254
255
256 #define ET_NONE 0
257 #define ET_REL 1
258 #define ET_EXEC 2
259 #define ET_DYN 3
260 #define ET_CORE 4
261 #define ET_LOPROC 0xff00
262 #define ET_HIPROC 0xffff
263
264
265 #define EM_NONE 0
266 #define EM_M32 1
267 #define EM_SPARC 2
268 #define EM_386 3
269 #define EM_68K 4
270 #define EM_88K 5
271 #define EM_860 7
272 #define EM_MIPS 8
273
274
275 #define EV_NONE 0
276 #define EV_CURRENT 1
277
278 typedef struct {
279 Elf32_Word p_type;
280 Elf32_Off p_offset;
281 Elf32_Addr p_vaddr;
282 Elf32_Addr p_paddr;
283 Elf32_Word p_filesz;
284 Elf32_Word p_memsz;
285 Elf32_Word p_flags;
286 Elf32_Word p_align;
287 } __attribute__((packed)) Elf32_Phdr_t;
288
289
290 #define PT_NULL 0
291 #define PT_LOAD 1
292 #define PT_DYNAMIC 2
293 #define PT_INTERP 3
294 #define PT_NOTE 4
295 #define PT_SHLIB 5
296 #define PT_PHDR 6
297 #define PT_LOPROC 0x70000000
298 #define PT_HIPROC 0x7fffffff
299
300
301 #define PF_X 1
302 #define PF_W 2
303 #define PF_R 4
304
305
306 Elf32_Ehdr_t *elf_hdr;
307 Elf32_Phdr_t *elf_phdrs;
308
309 struct elf32_mapped_program * mapped_prog;
310 struct userprog_entry * prog;
311 sos_uaddr_t prog_top_user_address = 0;
312
313 mapped_prog
314 = (struct elf32_mapped_program*)
315 sos_kmalloc(sizeof(struct elf32_mapped_program), 0);
316 if (! mapped_prog)
317 return -SOS_ENOMEM;
318
319 prog = lookup_userprog(progname);
320 if (! prog)
321 {
322 sos_kfree((sos_vaddr_t)mapped_prog);
323 return 0;
324 }
325
326
327 memset(mapped_prog, 0x0, sizeof(*mapped_prog));
328 mapped_prog->mr.custom_data = mapped_prog;
329 mapped_prog->mr.mmap = elf32prog_mmap;
330 mapped_prog->mr.allowed_access_rights
331 = SOS_VM_MAP_PROT_READ
332 | SOS_VM_MAP_PROT_WRITE
333 | SOS_VM_MAP_PROT_EXEC;
334 mapped_prog->vaddr = prog->bottom_vaddr;
335 mapped_prog->size = prog->top_vaddr - prog->bottom_vaddr;
336
337 elf_hdr = (Elf32_Ehdr_t*) prog->bottom_vaddr;
338
339
340
341 if (prog->bottom_vaddr + sizeof(Elf32_Ehdr_t) > prog->top_vaddr)
342 {
343 sos_bochs_printf("ELF prog %s: incorrect header\n", prog->name);
344 return 0;
345 }
346
347
348 #define ELF_CHECK(hdr,field,expected_value) \
349 ({ if ((hdr)->field != (expected_value)) \
350 { \
351 sos_bochs_printf("ELF prog %s: for %s, expected %x, got %x\n", \
352 prog->name, \
353 #field, \
354 (unsigned)(expected_value), \
355 (unsigned)(hdr)->field); \
356 return 0; \
357 } \
358 })
359
360 ELF_CHECK(elf_hdr, e_ident[EI_MAG0], ELFMAG0);
361 ELF_CHECK(elf_hdr, e_ident[EI_MAG1], ELFMAG1);
362 ELF_CHECK(elf_hdr, e_ident[EI_MAG2], ELFMAG2);
363 ELF_CHECK(elf_hdr, e_ident[EI_MAG3], ELFMAG3);
364 ELF_CHECK(elf_hdr, e_ident[EI_CLASS], ELFCLASS32);
365 ELF_CHECK(elf_hdr, e_ident[EI_DATA], ELFDATA2LSB);
366 ELF_CHECK(elf_hdr, e_type, ET_EXEC);
367 ELF_CHECK(elf_hdr, e_version, EV_CURRENT);
368
369
370 elf_phdrs = (Elf32_Phdr_t*) (prog->bottom_vaddr + elf_hdr->e_phoff);
371
372
373
374 for (i = 0 ; i < elf_hdr->e_phnum ; i++)
375 {
376 sos_ui32_t prot_flags;
377 sos_uaddr_t uaddr;
378
379
380 if (elf_phdrs[i].p_type != PT_LOAD)
381 {
382 if (elf_phdrs[i].p_memsz != 0)
383 {
384 sos_display_fatal_error("ELF: non-empty non-LOAD segments not supported yet");
385 }
386 continue;
387 }
388
389 if (elf_phdrs[i].p_vaddr < SOS_PAGING_BASE_USER_ADDRESS)
390 {
391 sos_display_fatal_error("User program has an incorrect address");
392 }
393
394 prot_flags = 0;
395 if (elf_phdrs[i].p_flags & SOS_VM_MAP_PROT_READ)
396 prot_flags |= SOS_VM_MAP_PROT_READ;
397 if (elf_phdrs[i].p_flags & SOS_VM_MAP_PROT_WRITE)
398 prot_flags |= SOS_VM_MAP_PROT_WRITE;
399 if (elf_phdrs[i].p_flags & SOS_VM_MAP_PROT_EXEC)
400 prot_flags |= SOS_VM_MAP_PROT_EXEC;
401
402 uaddr = elf_phdrs[i].p_vaddr;
403 SOS_ASSERT_FATAL(SOS_IS_PAGE_ALIGNED(uaddr));
404
405
406
407 SOS_ASSERT_FATAL(SOS_OK
408 == sos_umem_vmm_map(dest_as, &uaddr,
409 SOS_PAGE_ALIGN_SUP(elf_phdrs[i].p_filesz),
410 prot_flags,
411 SOS_VR_MAP_FIXED,
412 & mapped_prog->mr,
413 elf_phdrs[i].p_offset));
414
415
416 uaddr += SOS_PAGE_ALIGN_SUP(elf_phdrs[i].p_filesz);
417 if (SOS_PAGE_ALIGN_SUP(elf_phdrs[i].p_filesz)
418 < SOS_PAGE_ALIGN_SUP(elf_phdrs[i].p_memsz))
419 SOS_ASSERT_FATAL(SOS_OK
420 == sos_dev_zero_map(dest_as, &uaddr,
421 SOS_PAGE_ALIGN_SUP(elf_phdrs[i].p_memsz)
422 - SOS_PAGE_ALIGN_SUP(elf_phdrs[i].p_filesz),
423 prot_flags,
424 SOS_VR_MAP_FIXED));
425
426 if (prog_top_user_address
427 < uaddr + SOS_PAGE_ALIGN_SUP(elf_phdrs[i].p_memsz))
428 prog_top_user_address
429 = uaddr + SOS_PAGE_ALIGN_SUP(elf_phdrs[i].p_memsz);
430 }
431
432
433 sos_umem_vmm_init_heap(dest_as, prog_top_user_address);
434
435 return elf_hdr->e_entry;
436 }
437
438
439
440
441
442 static struct userprog_entry * lookup_userprog(const char *name)
443 {
444 struct userprog_entry *prog;
445
446 if (! name)
447 return NULL;
448
449
450
451 for (prog = (struct userprog_entry*) & _userprogs_table ;
452 prog && (prog->name != NULL) ;
453 prog++)
454 {
455 if (0 == strcmp(name, prog->name))
456
457 return prog;
458 }
459
460 return NULL;
461 }