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.
30 #include "mm/region.h"
38 int load_elf_module(void *vaddr
, uintptr_t paddr
, size_t size
)
40 struct Elf32_Ehdr
*ehdr
= vaddr
;
41 struct Elf32_Phdr
*phdr
;
42 struct addr_space
*aspace
;
44 struct vm_region
*vmr
;
45 struct thread
*module_thread
;
48 if (ehdr
->e_ident
[EI_MAG0
] == ELFMAG0
49 && ehdr
->e_ident
[EI_MAG1
] == ELFMAG1
50 && ehdr
->e_ident
[EI_MAG2
] == ELFMAG2
51 && ehdr
->e_ident
[EI_MAG3
] == ELFMAG3
){
54 TRACE("Not an ELF file.");
57 if (ehdr
->e_ident
[EI_CLASS
] != ELFCLASS32
){
58 TRACE("invalid or unsupported ELF class");
61 if (ehdr
->e_ident
[EI_DATA
] != ELFDATA2LSB
){
62 TRACE("invalid or unsupported ELF data encoding");
65 if (ehdr
->e_type
!= ET_EXEC
){
66 TRACE("ELF file is not an executable. I can't, erm, execute it.");
69 if (ehdr
->e_machine
!= EM_386
){
70 TRACE("ELF file is not for a 386. I can't execute it.");
73 // map program segments into the correct places
74 aspace
= addr_space_new();
76 TRACE("Cannot create addr_space for ELF module");
79 phdr
= (struct Elf32_Phdr
*) ((char *) vaddr
+ ehdr
->e_phoff
);
80 for (i
=0; i
<ehdr
->e_phnum
; ++i
){
81 if (phdr
->p_type
== PT_DYNAMIC
){
82 TRACE("ELF file requires dynamic linking, and I haven't written a dynamic linker yet.");
83 addr_space_delete(aspace
);
85 } else if (phdr
->p_type
== PT_PHDR
){
86 TRACE("ELF file has a PT_PHDR segment; not implemented yet.");
87 addr_space_delete(aspace
);
89 } else if (phdr
->p_type
== PT_LOAD
){
90 if (phdr
->p_vaddr
> 0xC0000000){
91 TRACE("ELF file wants to load above 0xC0000000");
92 addr_space_delete(aspace
);
94 } else if (phdr
->p_vaddr
< 0x1000){
95 TRACE("ELF file wants to load in NULL page.");
96 addr_space_delete(aspace
);
99 // TODO: load bss segments: phdr->p_filesz == 0
100 unsigned int map_flags
= 0;
101 if (phdr
->p_flags
& PF_W
){
102 map_flags
|= VM_R_WRITABLE
;
104 vmr
= vm_region_new_physical_fixed(aspace
,
106 uldivru(phdr
->p_memsz
, PAGE_SIZE
),
107 paddr
+ phdr
->p_offset
);
109 TRACE("pagedir_add_region() failed - cannot map ELF segment");
113 TRACE("Unknown segment type: %d!", phdr
->p_type
);
115 phdr
= (struct Elf32_Phdr
*) ((char *) phdr
+ ehdr
->e_phentsize
);
118 // create a task to run the module in
119 module_thread
= thread_new();
120 thread_set_aspace(module_thread
, aspace
);
121 thread_set_eip(module_thread
, ehdr
->e_entry
);
122 // XXX: Guessing stack size, blah blah == bad
123 thread_set_esp(module_thread
, (uint32_t) stack
+ 0x4000);
124 thread_set_userspace(module_thread
, 1);
125 thread_resume(module_thread
);