Mercurial > hg > Members > mitsuki > xv6_rpi2_port
diff source/exec.c @ 0:ed10291ff195
first commit
author | mir3636 |
---|---|
date | Sun, 06 Jan 2019 19:27:03 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/exec.c Sun Jan 06 19:27:03 2019 +0900 @@ -0,0 +1,104 @@ +#include "types.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "defs.h" +#include "arm.h" +#include "elf.h" + +int +exec(char *path, char **argv) +{ + char *last; + int i, off; + uint argc, sz, sp, ustack[3+MAXARG+1]; + struct elfhdr elf; + struct inode *ip; + struct proghdr ph; + pde_t *pgdir, *oldpgdir; + + if((ip = namei(path)) == 0) + return -1; + ilock(ip); + pgdir = 0; + + // Check ELF header + if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) + goto bad; + if(elf.magic != ELF_MAGIC) + goto bad; + + if((pgdir = setupkvm()) == 0) + goto bad; + // Load program into memory. + sz = 0; + for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ + if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) + goto bad; + if(ph.type != ELF_PROG_LOAD) + continue; + if(ph.memsz < ph.filesz) + goto bad; + if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) + goto bad; + if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) + goto bad; + } + iunlockput(ip); + ip = 0; + + // Allocate two pages at the next page boundary. + // Make the first inaccessible. Use the second as the user stack. + sz = PGROUNDUP(sz); + if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) + goto bad; + clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); + sp = sz; + // Push argument strings, prepare rest of stack in ustack. + for(argc = 0; argv[argc]; argc++) { + if(argc >= MAXARG) + goto bad; + sp = (sp - (strlen(argv[argc]) + 1)) & ~3; + if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) + goto bad; + ustack[3+argc] = sp; + } + ustack[3+argc] = 0; + +//cprintf("Exec is called argc=%d sz=%x\n", argc, sz); + + ustack[0] = 0xffffffff; // fake return PC + ustack[1] = argc; + ustack[2] = sp - (argc+1)*4; // argv pointer + + sp -= (3+argc+1) * 4; + if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) + goto bad; + + // Save program name for debugging. +/* for(last=s=path; *s; s++) + if(*s == '/') + last = s+1;*/ + last = argv[0]; + safestrcpy(curr_proc->name, last, sizeof(curr_proc->name)); + + // Commit to the user image. + oldpgdir = curr_proc->pgdir; + curr_proc->pgdir = pgdir; + curr_proc->sz = sz; + curr_proc->tf->pc = elf.entry; // main + curr_proc->tf->sp = sp; + curr_proc->tf->r0 = ustack[1]; + curr_proc->tf->r1 = ustack[2]; + switchuvm(curr_proc); + freevm(oldpgdir); + return 0; + + bad: + if(pgdir) + freevm(pgdir); + if(ip) + iunlockput(ip); + return -1; +}