#include <arch.h>
#include <process.h>
#include <debug.h>
+#include <string.h>
int sys_exit(int status)
{
ct = task_get_current();
stk->cr3 = ct->t_pgdir;
+ dbg_printf("[0x%08x] sys_fork()\n", stk->cr3);
+
+ return(ret_val);
+}
+
+#if FEATURE(ELF)
+int sys_execelf(stack_frame_t *stk)
+{
+ int ret_val;
+ void *elfdata;
+ u32_t elfsize;
+ pg_dir_t *pd;
+ pg_dir_t *oldpd;
+ process_t *cproc;
+ void *ostack;
+ void *nstack;
+
+ /*
+ * sys_execelf() - Replace the process image with the provided ELF file
+ *
+ * This function will:
+ * [ 0. Validate the provided ELF file ]
+ * 1. Create a new address space (page directory)
+ * 2. Copy the ELF data into the new address space
+ * 3. Initialize the initial stack frame for the new image
+ *
+ * The new process will start execution in the ELF parser, preparing
+ * its own environment.
+ */
+
+ ret_val = -EINVAL;
+ elfdata = (void*)stk->ebx;
+ elfsize = (u32_t)stk->ecx;
+ cproc = process_get_current();
+
+ /* FIXME: Verify ELF file integrity before doing the heavy lifting */
+
+ /* FIXME: Destroy all but one task in the process */
+
+ ret_val = pg_dir_create(&pd);
+
+ if(ret_val < 0) {
+ goto cleanup;
+ }
+
+ /* FIXME: Copy the elf image into the new address space */
+
+
+ /* make the process and its tasks refer to the new page directory */
+ process_get_pagedir(cproc, &oldpd);
+ process_set_pagedir(cproc, pd);
+
+ /* update the stack frame of the executing task */
+ stk->cr3 = (u32_t)pg_dir_get_pdbr(pd);
+
+ /*
+ * The kernel is currently executing on the kernel stack inside the
+ * page directory that we're about to free. We have to copy the old
+ * stack to the new one and update ESP, EBP.
+ */
+ ostack = cproc->p_tasks->t_kstack;
+ nstack = pg_dir_get_kstack(pd);
+
+ /*
+ * task_move_stack() will move the current stack and update the
+ * stack pointers. When this function returns, we will be executing
+ * on the kernel-mode stack from the new page directory.
+ */
+ task_move_stack(nstack, ostack, CONFIG_KERNEL_STACK_SIZE);
+
+#if 0
+ /* values on the stack should also have been adjusted by task_move_stack() */
+ stk = (stack_frame_t*)((u32_t)stk - (u32_t)ostack + (u32_t)nstack);
+#endif /* 0 */
+
+ /* FIXME: destroy the previous address space, if not used anymore */
+
+
+ ret_val = 0;
+
+cleanup:
+ return(ret_val);
+}
+#endif /* FEATURE(ELF) */
+
+void* setstackvfe(void *ustack, char **argv, char **envp)
+{
+ int nstrs;
+ int i;
+
+ if(ustack) {
+ char **nargv;
+ char **nenvp;
+ int nargc;
+
+ nargv = NULL;
+ nenvp = NULL;
+ nargc = 0;
+
+ /* copy the environment string, if it was provided */
+ if(envp) {
+ char *nextstr;
+
+ /* count the strings in envp */
+ for(nstrs = 0; envp[nstrs]; nstrs++);
+
+ /* copy the environment variable to the destination stack */
+ for(i = 0; i < nstrs; i++) {
+ int idx;
+ int len;
+
+ idx = nstrs - i - 1;
+ len = strlen(envp[idx]) + 1;
+
+ ustack -= len;
+ memcpy(ustack, envp[idx], len);
+ }
+
+ nextstr = (char*)ustack;
+ /* make space for the new envp */
+ ustack -= sizeof(char*) * (nstrs + 1);
+ nenvp = (char**)ustack;
+
+ for(i = 0; i < nstrs; i++) {
+ nenvp[i] = nextstr;
+ nextstr += strlen(nextstr);
+ }
+ nenvp[nstrs] = NULL;
+ }
+
+ /* copy arguments, if they were provided */
+ if(argv) {
+ char *nextstr;
+
+ /* count the arguments */
+ for(nstrs = 0; argv[nstrs]; nstrs++);
+
+ /* copy the arguments to the destination stack */
+ for(i = 0; i < nstrs; i++) {
+ int idx;
+ int len;
+
+ idx = nstrs - i - 1;
+ len = strlen(argv[idx]) * 1;
+
+ ustack -= len;
+ memcpy(ustack, argv[idx], len);
+ }
+
+ nextstr = (char*)ustack;
+ /* make space for the new argv */
+ ustack -= sizeof(char*) * (nstrs + 1);
+ nargv = (char**)ustack;
+
+ for(i = 0; i < nstrs; i++) {
+ nargv[i] = nextstr;
+ nextstr += strlen(nextstr);
+ }
+ nargv[nstrs] = NULL;
+ nargc = nstrs;
+ }
+
+ /* finally, prepare the stack frame for the function call */
+ ustack -= sizeof(char**);
+ *(char***)ustack = envp;
+ ustack -= sizeof(char**);
+ *(char***)ustack = argv;
+ ustack -= sizeof(int);
+ *(int*)ustack = nargc;
+ }
+
+ return(ustack);
+}
+
+int sys_execfve(stack_frame_t *stk)
+{
+ process_t *proc;
+ pg_dir_t *pgdir;
+ void *ustack;
+ void *entry;
+ char **argv;
+ char **envp;
+ int ret_val;
+
+ entry = (void*)stk->ebx;
+ argv = (char**)stk->ecx;
+ envp = (char**)stk->edx;
+ ret_val = 0;
+
+ proc = process_get_current();
+ process_get_pagedir(proc, &pgdir);
+
+ /* FIXME: Stack size may not be static */
+ ustack = (void*)((u32_t)pg_dir_get_ustack(pgdir) +
+ CONFIG_USER_STACK_SIZE);
+
+ /* FIXME: We also need to duplicate the .data and .bss sections */
+
+ /* prepare the stack frame for the function */
+ ustack = setstackvfe(ustack, argv, envp);
+
+ /* FIXME: This will not work on any architecture but IA-32 */
+
+ /* make the task execute the new function upon return from the interrupt */
+ stk->eip = (u32_t)entry;
+ stk->ebp = (u32_t)ustack;
+ stk->esp = (u32_t)ustack;
+ stk->prevesp = (u32_t)ustack;
+
+ /* TODO: Stop remaining tasks that may be executing in the process */
+ /* FIXME: Shouldn't we also wipe the heap? */
return(ret_val);
}
return(process_fork(1));
}
-int sys_wait(int *status)
+int sys_sleep(unsigned int seconds)
{
return(-ENOSYS);
}
+int sys_wait(int *status)
+{
+ pid_t self;
+ int ret_val;
+
+ self = process_get_id(process_get_current());
+
+ /* wait for a signal from any process */
+ dbg_printf("[%u] going to wait\n", self);
+
+ ret_val = process_wait(-1);
+
+ /* TODO: Handle the signal */
+
+ return(ret_val);
+}
+
int sys_waitpid(pid_t pid, int *status, int options)
{
return(-ENOSYS);
if(cproc) {
/*
* At this point there is nothing that needs to be done here. Maybe
- * in the future there will be more that needs to be done.
+ * in the future there will be lists that the child needs to be removed
+ * from, or things like that.
*/
-
#if 0
process_t *pproc;
ret_val = sys_setsid();
break;
+ case SYS_SLEEP:
+ ret_val = sys_sleep((unsigned int)stk->ebx);
+ break;
+
+ case SYS_EXECFVE:
+ ret_val = sys_execfve(stk);
+ break;
+
default:
ret_val = -EOPNOTSUPP;
break;