-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmpos-loader.c
86 lines (72 loc) · 2.25 KB
/
mpos-loader.c
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "x86.h"
#include "elf.h"
#include "lib.h"
#include "mpos-kern.h"
/*****************************************************************************
* mpos-loader.c
*
* Load a miniprocos application in from a RAM image.
*
* Don't worry about understanding this loader!
*
*****************************************************************************/
#define SECTORSIZE 512
#define PAGESIZE 4096
extern uint8_t _binary_obj_mpos_app_start[];
extern uint8_t _binary_obj_mpos_app_end[];
extern uint8_t _binary_obj_mpos_app2_start[];
extern uint8_t _binary_obj_mpos_app2_end[];
struct ramimage {
void *begin;
void *end;
} ramimages[] = {
{ _binary_obj_mpos_app_start, _binary_obj_mpos_app_end },
{ _binary_obj_mpos_app2_start, _binary_obj_mpos_app2_end }
};
static void copyseg(void *dst, const uint8_t *src,
uint32_t filesz, uint32_t memsz);
static void loader_panic(void);
void
program_loader(int program_id, uint32_t *entry_point)
{
struct Proghdr *ph, *eph;
struct Elf *elf_header;
int nprograms = sizeof(ramimages) / sizeof(ramimages[0]);
if (program_id < 0 || program_id >= nprograms)
loader_panic();
// is this a valid ELF?
elf_header = (struct Elf *) ramimages[program_id].begin;
if (elf_header->e_magic != ELF_MAGIC)
loader_panic();
// load each program segment (ignores ph flags)
ph = (struct Proghdr*) ((const uint8_t *) elf_header + elf_header->e_phoff);
eph = ph + elf_header->e_phnum;
for (; ph < eph; ph++)
if (ph->p_type == ELF_PROG_LOAD)
copyseg((void *) ph->p_va,
(const uint8_t *) elf_header + ph->p_offset,
ph->p_filesz, ph->p_memsz);
// store the entry point from the ELF header
*entry_point = elf_header->e_entry;
}
// Copy 'filesz' bytes starting at address 'data' into virtual address 'dst',
// then clear the memory from 'va+filesz' up to 'va+memsz' (set it to 0).
static void
copyseg(void *dst, const uint8_t *src, uint32_t filesz, uint32_t memsz)
{
uint32_t va = (uint32_t) dst;
uint32_t end_va = va + filesz;
memsz += va;
va &= ~(PAGESIZE - 1); // round to page boundary
// copy data
memcpy((uint8_t *) va, src, end_va - va);
// clear bss segment
while (end_va < memsz)
*((uint8_t *) end_va++) = 0;
}
static void
loader_panic(void)
{
*((uint16_t *) 0xB8000) = '!' | 0x700;
loop: goto loop;
}