CS350 COS
COS
Loading...
Searching...
No Matches
loader.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006-2023 Ali Mashtizadeh
3 * All rights reserved.
4 */
5
6#include <stdbool.h>
7#include <stdint.h>
8#include <string.h>
9
10#include <sys/kassert.h>
11#include <sys/sysctl.h>
12#include <sys/kmem.h>
13#include <sys/queue.h>
14#include <sys/disk.h>
15#include <sys/elf64.h>
16
17#include <machine/amd64.h>
18#include <machine/trap.h>
19#include <machine/pmap.h>
20#include <sys/thread.h>
21#include <sys/spinlock.h>
22#include <sys/loader.h>
23
24#include <sys/vfs.h>
25
27
33bool
35{
36 if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
37 ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
38 ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
39 ehdr->e_ident[EI_MAG3] != ELFMAG3)
40 return false;
41
42 if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) {
43 return false;
44 }
45
46 if (ehdr->e_machine != EM_AMD64) {
47 return false;
48 }
49
50 return true;
51}
52
60static void
62 uintptr_t offset, uintptr_t len)
63{
64 void *raddr;
65
66 if ((vaddr % PGSIZE) != 0) {
67 uintptr_t maxlen = PGSIZE - (vaddr % PGSIZE);
68 uintptr_t rlen = maxlen < len ? maxlen : len;
69
70 raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
71 VFS_Read(vn, raddr, offset, rlen);
72 vaddr += rlen;
73 offset += rlen;
74 len -= rlen;
75 }
76
77 while (len > PGSIZE) {
78 raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
79 VFS_Read(vn, raddr, offset, PGSIZE);
80 vaddr += PGSIZE;
81 offset += PGSIZE;
82 len -= PGSIZE;
83 }
84
85 if (len > 0) {
86 raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
87 VFS_Read(vn, raddr, offset, len);
88 }
89}
90
97static void
99{
100 void *raddr;
101
102 if ((vaddr % PGSIZE) != 0) {
103 uintptr_t maxlen = PGSIZE - (vaddr % PGSIZE);
104 uintptr_t rlen = maxlen < len ? maxlen : len;
105
106 raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
107 memset(raddr, 0, rlen);
108 vaddr += rlen;
109 len -= rlen;
110 }
111
112 while (len > PGSIZE) {
113 raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
114 memset(raddr, 0, PGSIZE);
115 vaddr += PGSIZE;
116 len -= PGSIZE;
117 }
118
119 if (len > 0) {
120 raddr = (void *)DMPA2VA(PMap_Translate(as, vaddr));
121 memset(raddr, 0, len);
122 }
123}
124
130bool
132{
133 int i;
134 const Elf64_Ehdr *ehdr;
135 const Elf64_Phdr *phdr;
136 AS *as = thr->space;
137
138 ehdr = (const Elf64_Ehdr *)(buf);
139 phdr = (const Elf64_Phdr *)(buf + ehdr->e_phoff);
140
141 if (!Loader_CheckHeader(ehdr)) {
142 Log(loader, "Not a valid executable!\n");
143 return false;
144 }
145
146 Log(loader, "%8s %16s %8s %8s\n", "Offset", "VAddr", "FileSize", "MemSize");
147 for (i = 0; i < ehdr->e_phnum; i++)
148 {
149 ASSERT(phdr[i].p_type != PT_DYNAMIC);
150 if (phdr[i].p_type == PT_LOAD) {
151 uint64_t va = phdr[i].p_vaddr;
152 uint64_t memsz = phdr[i].p_memsz;
153 Log(loader, "%08llx %016llx %08llx %08llx\n", phdr[i].p_offset,
154 phdr[i].p_vaddr, phdr[i].p_filesz, phdr[i].p_memsz);
155
156 // Make sure it is page aligned
157 va = va & ~(uint64_t)PGMASK;
158 memsz += phdr[i].p_vaddr - va;
159
160 Log(loader, "AllocMap %016llx %08llx\n", va, memsz);
161 if (!PMap_AllocMap(as, va, memsz, PTE_W)) {
162 // XXX: Cleanup!
163 ASSERT(false);
164 return false;
165 }
166 }
167 }
168
170
171 /* XXXFILLMEIN: Load the ELF segments. */
172
173 /* Save the process entry point (i.e., _start) */
174 thr->proc->entrypoint = ehdr->e_entry;
175
176 return true;
177}
178
186void
188{
189 int status;
190 void *pg;
191 VNode *initvn;
192
193 pg = PAlloc_AllocPage();
194 if (!pg)
195 Panic("Not enough memory!");
196
197 initvn = VFS_Lookup("/sbin/init");
198 status = VFS_Open(initvn);
199 if (status < 0)
200 Panic("Loading init process failed!");
201 status = VFS_Read(initvn, pg, 0, 1024);
202 if (status < 0)
203 Panic("Reading init process failed!");
204
205 Thread *thr = Sched_Current();
206
207 // Open stdin/out/err
208 Handle *handle = Console_OpenHandle();
209 Handle_Add(thr->proc, handle);
210 handle = Console_OpenHandle();
211 Handle_Add(thr->proc, handle);
212 handle = Console_OpenHandle();
213 Handle_Add(thr->proc, handle);
214
215 /*
216 * Load init binary
217 */
218 Loader_Load(thr, initvn, pg, 1024);
219
220 VFS_Close(initvn);
221
222 Log(loader, "Jumping to userspace\n");
223
224 /*
225 * Reload the page tables for the current process
226 */
227 PMap_LoadAS(thr->space); // Reload CR3
228
229 /*
230 * Pass in zero arguments with null pointers to init
231 */
232 uintptr_t ap[3];
233 ap[0] = 0;
234 ap[1] = 0;
235 ap[2] = 0xDEADBEEF;
237
238 Copy_Out(&ap[0], rsp, sizeof(uintptr_t)*3);
239
240 /*
241 * The last step is to return into userspace handing control to init. We
242 * create a valid trap frame and return into userspace using Trap_Pop().
243 */
244 TrapFrame tf;
245 memset(&tf, 0, sizeof(tf));
246 tf.ds = SEL_UDS | 3;
247 tf.rip = thr->proc->entrypoint;
248 tf.cs = SEL_UCS | 3;
249 tf.rsp = rsp;
250 tf.ss = SEL_UDS | 3;
251 tf.rflags = RFLAGS_IF;
252 tf.rdi = rsp;
253 Trap_Pop(&tf);
254
255 /*
256 * We should never reach this point!
257 */
258 Panic("Unreachable: Trap_Pop() returned!\n");
259}
260
261
#define PTE_W
Definition: amd64.h:36
#define RFLAGS_IF
Definition: amd64.h:180
#define SEL_UDS
Definition: amd64.h:84
#define SEL_UCS
Definition: amd64.h:83
#define PGMASK
Definition: amd64.h:22
Elf64_Xword p_memsz
Definition: elf64.h:110
Elf64_Addr p_vaddr
Definition: elf64.h:107
Elf64_Addr e_entry
Definition: elf64.h:69
unsigned char e_ident[EI_NIDENT]
Definition: elf64.h:65
Elf64_Off e_phoff
Definition: elf64.h:70
Elf64_Half e_machine
Definition: elf64.h:67
Elf64_Half e_phnum
Definition: elf64.h:75
#define PT_DYNAMIC
Definition: elf_common.h:319
#define EI_MAG2
Definition: elf_common.h:67
#define ELFMAG0
Definition: elf_common.h:79
#define ELFMAG3
Definition: elf_common.h:82
#define EI_MAG1
Definition: elf_common.h:66
#define EI_CLASS
Definition: elf_common.h:69
#define ELFMAG1
Definition: elf_common.h:80
#define EM_AMD64
Definition: elf_common.h:184
#define PT_LOAD
Definition: elf_common.h:318
#define ELFMAG2
Definition: elf_common.h:81
#define ELFCLASS64
Definition: elf_common.h:93
#define EI_MAG0
Definition: elf_common.h:65
#define EI_MAG3
Definition: elf_common.h:68
static char buf[4096]
Definition: ethdump.c:10
int Copy_Out(void *fromkernel, uintptr_t touser, uintptr_t len)
Definition: copy.c:70
uint64_t Handle_Add(Process *proc, Handle *handle)
Definition: handle.c:47
Thread * Sched_Current()
Definition: sched.c:56
#define Log(_module, _format,...)
Definition: kassert.h:32
#define ASSERT(_x)
Definition: kassert.h:8
void * PAlloc_AllocPage()
Definition: palloc.c:188
#define PGSIZE
Definition: malloc.c:21
bool Loader_Load(Thread *thr, VNode *vn, void *buf, uint64_t len)
Definition: loader.c:131
void Loader_LoadInit()
Definition: loader.c:187
bool Loader_CheckHeader(const Elf64_Ehdr *ehdr)
Definition: loader.c:34
static void LoaderLoadSegment(AS *as, VNode *vn, uintptr_t vaddr, uintptr_t offset, uintptr_t len)
Definition: loader.c:61
static void LoaderZeroSegment(AS *as, uintptr_t vaddr, uintptr_t len)
Definition: loader.c:98
Handle * Console_OpenHandle()
Definition: console.c:200
uint64_t len
Definition: multiboot.h:2
#define MEM_USERSPACE_STKTOP
Definition: pmap.h:38
#define MEM_USERSPACE_STKLEN
Definition: pmap.h:37
void PMap_LoadAS(AS *space)
Definition: pmap.c:182
uintptr_t PMap_Translate(AS *space, uintptr_t va)
Definition: pmap.c:220
#define DMPA2VA(pa)
Definition: pmap.h:48
#define MEM_USERSPACE_STKBASE
Definition: pmap.h:36
bool PMap_AllocMap(AS *as, uint64_t virt, uint64_t len, uint64_t flags)
Definition: pmap.c:423
Definition: pmap.h:52
void * memset(void *dst, int c, size_t len)
Definition: string.c:164
Definition: handle.h:17
uintptr_t entrypoint
Definition: thread.h:69
Definition: thread.h:31
struct Process * proc
Definition: thread.h:39
AS * space
Definition: thread.h:33
uint16_t cs
Definition: trap.h:73
uint16_t ss
Definition: trap.h:79
uint64_t rsp
Definition: trap.h:78
uint64_t rip
Definition: trap.h:72
uint64_t rdi
Definition: trap.h:61
void Trap_Pop(TrapFrame *tf)
uint64_t rflags
Definition: trap.h:77
uint64_t ds
Definition: trap.h:66
Definition: trap.h:51
uint64_t uintptr_t
Definition: types.h:16
unsigned long uint64_t
Definition: types.h:13
int VFS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len)
Definition: vfs.c:180
VNode * VFS_Lookup(const char *path)
Definition: vfs.c:63
int VFS_Open(VNode *fn)
Definition: vfs.c:147
int VFS_Close(VNode *fn)
Definition: vfs.c:162
Definition: vfs.h:24
void Panic(const char *str)
Definition: vgacons.c:164