2 * Copyright (c) 2009 Joshua Phillips. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
15 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "mm/region.h"
39 int load_elf_module(void *vaddr
, uintptr_t paddr
, size_t size
)
41 struct Elf32_Ehdr
*ehdr
= vaddr
;
42 struct Elf32_Phdr
*phdr
;
43 struct addr_space
*aspace
;
45 struct vm_region
*vmr
;
46 struct thread
*module_thread
;
49 if (ehdr
->e_ident
[EI_MAG0
] == ELFMAG0
50 && ehdr
->e_ident
[EI_MAG1
] == ELFMAG1
51 && ehdr
->e_ident
[EI_MAG2
] == ELFMAG2
52 && ehdr
->e_ident
[EI_MAG3
] == ELFMAG3
){
55 TRACE("Not an ELF file.");
58 if (ehdr
->e_ident
[EI_CLASS
] != ELFCLASS32
){
59 TRACE("invalid or unsupported ELF class");
62 if (ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
){
63 TRACE("invalid or unsupported ELF data encoding");
66 if (ehdr
->e_type
!= ET_EXEC
){
67 TRACE("ELF file is not an executable. I can't, erm, execute it.");
70 if (ehdr
->e_machine
!= EM_386
){
71 TRACE("ELF file is not for a 386. I can't execute it.");
74 // map program segments into the correct places
75 aspace
= addr_space_new();
77 TRACE("Cannot create addr_space for ELF module");
80 phdr
= (struct Elf32_Phdr
*) ((char *) vaddr
+ ehdr
->e_phoff
);
81 for (i
=0; i
<ehdr
->e_phnum
; ++i
){
82 if (phdr
->p_type
== PT_DYNAMIC
){
83 TRACE("ELF file requires dynamic linking, and I haven't written a dynamic linker yet.");
84 addr_space_delete(aspace
);
86 } else if (phdr
->p_type
== PT_PHDR
){
87 TRACE("ELF file has a PT_PHDR segment; not implemented yet.");
88 addr_space_delete(aspace
);
90 } else if (phdr
->p_type
== PT_LOAD
){
91 if (phdr
->p_vaddr
> 0xC0000000){
92 TRACE("ELF file wants to load above 0xC0000000");
93 addr_space_delete(aspace
);
95 } else if (phdr
->p_vaddr
< 0x1000){
96 TRACE("ELF file wants to load in NULL page.");
97 addr_space_delete(aspace
);
100 // TODO: load bss segments: phdr->p_filesz == 0
101 unsigned int map_flags
= 0;
102 if (phdr
->p_flags
& PF_W
){
103 map_flags
|= VM_R_WRITABLE
;
105 vmr
= vm_region_new_physical_fixed(aspace
,
107 uldivru(phdr
->p_memsz
, PAGE_SIZE
),
108 paddr
+ phdr
->p_offset
);
110 TRACE("pagedir_add_region() failed - cannot map ELF segment");
114 TRACE("Unknown segment type: %d!", phdr
->p_type
);
116 phdr
= (struct Elf32_Phdr
*) ((char *) phdr
+ ehdr
->e_phentsize
);
119 // create a task to run the module in
120 module_thread
= thread_new();
121 thread_set_aspace(module_thread
, aspace
);
122 thread_set_eip(module_thread
, ehdr
->e_entry
);
123 // XXX: Guessing stack size, blah blah == bad
124 thread_set_esp(module_thread
, (uint32_t) stack
+ 0x4000);
125 thread_set_userspace(module_thread
, 1);
126 thread_resume(module_thread
);