Mercurial > hg > Members > mitsuki > xv6_rpi2_port
comparison source/exec.c @ 0:ed10291ff195
first commit
author | mir3636 |
---|---|
date | Sun, 06 Jan 2019 19:27:03 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:ed10291ff195 |
---|---|
1 #include "types.h" | |
2 #include "param.h" | |
3 #include "memlayout.h" | |
4 #include "mmu.h" | |
5 #include "proc.h" | |
6 #include "defs.h" | |
7 #include "arm.h" | |
8 #include "elf.h" | |
9 | |
10 int | |
11 exec(char *path, char **argv) | |
12 { | |
13 char *last; | |
14 int i, off; | |
15 uint argc, sz, sp, ustack[3+MAXARG+1]; | |
16 struct elfhdr elf; | |
17 struct inode *ip; | |
18 struct proghdr ph; | |
19 pde_t *pgdir, *oldpgdir; | |
20 | |
21 if((ip = namei(path)) == 0) | |
22 return -1; | |
23 ilock(ip); | |
24 pgdir = 0; | |
25 | |
26 // Check ELF header | |
27 if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) | |
28 goto bad; | |
29 if(elf.magic != ELF_MAGIC) | |
30 goto bad; | |
31 | |
32 if((pgdir = setupkvm()) == 0) | |
33 goto bad; | |
34 // Load program into memory. | |
35 sz = 0; | |
36 for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ | |
37 if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) | |
38 goto bad; | |
39 if(ph.type != ELF_PROG_LOAD) | |
40 continue; | |
41 if(ph.memsz < ph.filesz) | |
42 goto bad; | |
43 if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) | |
44 goto bad; | |
45 if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) | |
46 goto bad; | |
47 } | |
48 iunlockput(ip); | |
49 ip = 0; | |
50 | |
51 // Allocate two pages at the next page boundary. | |
52 // Make the first inaccessible. Use the second as the user stack. | |
53 sz = PGROUNDUP(sz); | |
54 if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) | |
55 goto bad; | |
56 clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); | |
57 sp = sz; | |
58 // Push argument strings, prepare rest of stack in ustack. | |
59 for(argc = 0; argv[argc]; argc++) { | |
60 if(argc >= MAXARG) | |
61 goto bad; | |
62 sp = (sp - (strlen(argv[argc]) + 1)) & ~3; | |
63 if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) | |
64 goto bad; | |
65 ustack[3+argc] = sp; | |
66 } | |
67 ustack[3+argc] = 0; | |
68 | |
69 //cprintf("Exec is called argc=%d sz=%x\n", argc, sz); | |
70 | |
71 ustack[0] = 0xffffffff; // fake return PC | |
72 ustack[1] = argc; | |
73 ustack[2] = sp - (argc+1)*4; // argv pointer | |
74 | |
75 sp -= (3+argc+1) * 4; | |
76 if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) | |
77 goto bad; | |
78 | |
79 // Save program name for debugging. | |
80 /* for(last=s=path; *s; s++) | |
81 if(*s == '/') | |
82 last = s+1;*/ | |
83 last = argv[0]; | |
84 safestrcpy(curr_proc->name, last, sizeof(curr_proc->name)); | |
85 | |
86 // Commit to the user image. | |
87 oldpgdir = curr_proc->pgdir; | |
88 curr_proc->pgdir = pgdir; | |
89 curr_proc->sz = sz; | |
90 curr_proc->tf->pc = elf.entry; // main | |
91 curr_proc->tf->sp = sp; | |
92 curr_proc->tf->r0 = ustack[1]; | |
93 curr_proc->tf->r1 = ustack[2]; | |
94 switchuvm(curr_proc); | |
95 freevm(oldpgdir); | |
96 return 0; | |
97 | |
98 bad: | |
99 if(pgdir) | |
100 freevm(pgdir); | |
101 if(ip) | |
102 iunlockput(ip); | |
103 return -1; | |
104 } |