This source file includes following definitions.
- flags2perm
- kexec
- loadseg
1 #include "types.h"
2 #include "param.h"
3 #include "memlayout.h"
4 #include "riscv.h"
5 #include "spinlock.h"
6 #include "proc.h"
7 #include "defs.h"
8 #include "elf.h"
9
10 static int loadseg(pde_t *, uint64, struct inode *, uint, uint);
11
12
13 int
14 flags2perm(int flags)
15 {
16 int perm = 0;
17 if (flags & 0x1)
18 perm = PTE_X;
19 if (flags & 0x2)
20 perm |= PTE_W;
21 return perm;
22 }
23
24
25
26
27 int
28 kexec(char *path, char **argv)
29 {
30 char *s, *last;
31 int i, off;
32 uint64 argc, sz = 0, sp, ustack[MAXARG], stackbase;
33 struct elfhdr elf;
34 struct inode *ip;
35 struct proghdr ph;
36 pagetable_t pagetable = 0, oldpagetable;
37 struct proc *p = myproc();
38
39 begin_op();
40
41
42 if ((ip = namei(path)) == 0) {
43 end_op();
44 return -1;
45 }
46 ilock(ip);
47
48
49 if (readi(ip, 0, (uint64)&elf, 0, sizeof(elf)) != sizeof(elf))
50 goto bad;
51
52
53 if (elf.magic != ELF_MAGIC)
54 goto bad;
55
56 if ((pagetable = proc_pagetable(p)) == 0)
57 goto bad;
58
59
60 for (i = 0, off = elf.phoff; i < elf.phnum; i++, off += sizeof(ph)) {
61 if (readi(ip, 0, (uint64)&ph, off, sizeof(ph)) != sizeof(ph))
62 goto bad;
63 if (ph.type != ELF_PROG_LOAD)
64 continue;
65 if (ph.memsz < ph.filesz)
66 goto bad;
67 if (ph.vaddr + ph.memsz < ph.vaddr)
68 goto bad;
69 if (ph.vaddr % PGSIZE != 0)
70 goto bad;
71 uint64 sz1;
72 if ((sz1 = uvmalloc(pagetable, sz, ph.vaddr + ph.memsz,
73 flags2perm(ph.flags))) == 0)
74 goto bad;
75 sz = sz1;
76 if (loadseg(pagetable, ph.vaddr, ip, ph.off, ph.filesz) < 0)
77 goto bad;
78 }
79 iunlockput(ip);
80 end_op();
81 ip = 0;
82
83 p = myproc();
84 uint64 oldsz = p->sz;
85
86
87
88
89 sz = PGROUNDUP(sz);
90 uint64 sz1;
91 if ((sz1 = uvmalloc(pagetable, sz, sz + (USERSTACK + 1) * PGSIZE, PTE_W)) ==
92 0)
93 goto bad;
94 sz = sz1;
95 uvmclear(pagetable, sz - (USERSTACK + 1) * PGSIZE);
96 sp = sz;
97 stackbase = sp - USERSTACK * PGSIZE;
98
99
100
101 for (argc = 0; argv[argc]; argc++) {
102 sp -= strlen(argv[argc]) + 1;
103 sp -= sp % 16;
104 if (sp < stackbase)
105 goto bad;
106 if (copyout(pagetable, sz, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
107 goto bad;
108 ustack[argc] = sp;
109 }
110 ustack[argc] = 0;
111
112
113 sp -= (argc + 1) * sizeof(uint64);
114 sp -= sp % 16;
115 if (sp < stackbase)
116 goto bad;
117 if (copyout(pagetable, sz, sp, (char *)ustack, (argc + 1) * sizeof(uint64)) <
118 0)
119 goto bad;
120
121
122
123
124 p->trapframe->a1 = sp;
125
126
127 for (last = s = path; *s; s++)
128 if (*s == '/')
129 last = s + 1;
130 safestrcpy(p->name, last, sizeof(p->name));
131
132
133 oldpagetable = p->pagetable;
134 p->pagetable = pagetable;
135 p->sz = sz;
136 p->trapframe->epc = elf.entry;
137 p->trapframe->sp = sp;
138 proc_freepagetable(oldpagetable, oldsz);
139
140 return argc;
141
142 bad:
143 if (pagetable)
144 proc_freepagetable(pagetable, sz);
145 if (ip) {
146 iunlockput(ip);
147 end_op();
148 }
149 return -1;
150 }
151
152
153
154
155
156 static int
157 loadseg(pagetable_t pagetable, uint64 va, struct inode *ip, uint offset,
158 uint sz)
159 {
160 uint i, n;
161 uint64 pa;
162
163 for (i = 0; i < sz; i += PGSIZE) {
164 pa = walkaddr(pagetable, va + i);
165 if (pa == 0)
166 panic("loadseg: address should exist");
167 if (sz - i < PGSIZE)
168 n = sz - i;
169 else
170 n = PGSIZE;
171 if (readi(ip, 0, (uint64)pa, offset + i, n) != n)
172 return -1;
173 }
174
175 return 0;
176 }