Tried to fix whole execution system (Shell, Unnamed Pipes)
[meinos.git] / apps / init / exe_elf.c
blob65c81902361d6051a811320242c68e47cf1b0d03
1 /*
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>
20 #include <stdlib.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <misc.h>
24 #include <proc.h>
25 #include <limits.h>
27 #include "exe_elf.h"
29 /**
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;
40 return 1;
42 #include <stdio.h>
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;
45 size_t i;
46 int ret = 0;
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);
57 else {
58 proc_memfree(own_pid,buf);
59 ret = -1;
60 break;
63 return ret;
66 void *elf_load(pid_t pid,const char *file) {
67 int fh = open(file,O_RDONLY);
68 if (fh!=-1) {
69 size_t i;
70 void *entrypoint;
71 elf_header_t header;
72 elf_progheader_t *progheader;
74 // Header
75 read(fh,&header,sizeof(header));
76 if (!elf_validate(&header)) return NULL;
77 entrypoint = (void*)(header.entry);
79 // Program Headers
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) {
86 entrypoint = NULL;
87 break;
92 free(progheader);
93 close(fh);
94 return entrypoint;
96 else return NULL;