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