aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/fs/elf.c
blob: f6d7fb8a2568e350afae6800cc8e46cc0a1253e6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <kernel/system.h>
#include <kernel/fs/elf.h>
#include <kernel/lib/stdio.h>
#include <kernel/memory/alloc.h>
#include <kernel/lib/lib.h>
#include <kernel/memory/paging.h>

#define USER_OFFSET 0x40000000
#define USER_STACK 0xF0000000
#define PT_LOAD 0x1

int is_elf(char *elf_data)
{
	elf_header_t *header = (elf_header_t *)elf_data;
	if (header->ident[0] == 0x7f && header->ident[1] == 'E' && header->ident[2] == 'L' &&
	    header->ident[3] == 'F') {
		log("Buffer is valid ELF file!");
		return 1;
	}
	return 0;
}

uint32_t load_elf(char *elf_data)
{
	uint32_t v_begin, v_end;
	elf_header_t *hdr;
	elf_program_header_t *p_entry;
	elf_section_header_t *s_entry;

	hdr = (elf_header_t *)elf_data;
	p_entry = (elf_program_header_t *)(elf_data + hdr->phoff);

	s_entry = (elf_section_header_t *)(elf_data + hdr->shoff);

	if (is_elf(elf_data) == 0)
		return 0;

	for (int pe = 0; pe < hdr->phnum; pe++, p_entry++) {
		if (p_entry->type == PT_LOAD) {
			v_begin = p_entry->vaddr;
			v_end = p_entry->vaddr + p_entry->memsz;
			if (v_begin < USER_OFFSET) {
				warn("load_elf(): can't load executable below %x", USER_OFFSET);
				return 0;
			}

			if (v_end > USER_STACK) {
				warn("load_elf(): can't load executable above %x", USER_STACK);
				return 0;
			}

			log("ELF: entry flags: %x (%d)", p_entry->flags, p_entry->flags);

			memcpy((uint8_t *)v_begin, (uint8_t *)(elf_data + p_entry->offset),
			       p_entry->filesz);
			if (p_entry->memsz > p_entry->filesz) {
				char *p = (char *)p_entry->vaddr;
				for (int i = p_entry->filesz; i < (int)(p_entry->memsz); i++) {
					p[i] = 0;
				}
			}
		}
	}

	return hdr->entry;
}