2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
30 * Validates ELF header
31 * @param header Pointer to ELF header
32 * @return Whether header is valid
34 static int elf_validate(elf_header_t
*header
) {
35 if (header
->ident
[EI_MAG0
]!=ELFMAG0
|| header
->ident
[EI_MAG1
]!=ELFMAG1
|| header
->ident
[EI_MAG2
]!=ELFMAG2
|| header
->ident
[EI_MAG3
]!=ELFMAG3
) return 0;
36 if (header
->machine
!=EM_386
) return 0;
37 if (header
->ident
[EI_CLASS
]!=ELFCLASS32
) return 0;
38 if (header
->ident
[EI_DATA
]!=ELFDATA2LSB
) return 0;
39 if (header
->ident
[EI_VERSION
]!=header
->version
) return 0;
43 static int elf_loadseg(pid_t pid
,int fh
,void *mem_addr
,size_t mem_size
,size_t file_addr
,size_t file_size
,int writable
) {
44 if (mem_addr
<(void*)USERSPACE_ADDRESS
) return -1;
47 pid_t own_pid
= getpid();
49 lseek(fh
,file_addr
,SEEK_SET
);
51 for (i
=0;i
<mem_size
;i
+=PAGE_SIZE
) {
52 void *buf
= mem_alloc(PAGE_SIZE
);
53 size_t cur_count
= i
>file_size
?0:(i
+PAGE_SIZE
>file_size
?file_size
%PAGE_SIZE
:PAGE_SIZE
);
54 if (cur_count
>0) read(fh
,buf
,cur_count
);
55 else memset(buf
,0,PAGE_SIZE
);
56 if (proc_memmap(pid
,mem_addr
+i
,mem_getphysaddr(buf
),writable
,1,0)==0) proc_memunmap(own_pid
,buf
);
58 proc_memfree(own_pid
,buf
);
66 void *elf_load(pid_t pid
,const char *file
) {
67 int fh
= open(file
,O_RDONLY
);
72 elf_progheader_t
*progheader
;
75 read(fh
,&header
,sizeof(header
));
76 if (!elf_validate(&header
)) return NULL
;
77 entrypoint
= (void*)(header
.entry
);
80 progheader
= malloc(sizeof(elf_progheader_t
)*header
.phnum
);
81 lseek(fh
,header
.phoff
,SEEK_SET
);
82 read(fh
,progheader
,sizeof(elf_progheader_t
)*header
.phnum
);
83 for (i
=0;i
<header
.phnum
;i
++) {
84 if (progheader
[i
].type
==PT_LOAD
) {
85 if (elf_loadseg(pid
,fh
,(void*)(progheader
[i
].vaddr
),progheader
[i
].memsz
,progheader
[i
].offset
,progheader
[i
].filesz
,(progheader
[i
].flags
&PF_W
)==PF_W
)==-1) {