예제 #1
0
파일: syscall_fs.c 프로젝트: 8l/FUZIX
arg_t _pipe(void)
{
	int8_t u1, u2, oft1, oft2;
	inoptr ino;

/* bug fix SN */
	if ((u1 = uf_alloc()) == -1)
		goto nogood;
	if ((oft1 = oft_alloc()) == -1)
		goto nogood;
	udata.u_files[u1] = oft1;

	if ((u2 = uf_alloc()) == -1)
		goto nogood2;
	if ((oft2 = oft_alloc()) == -1)
		goto nogood2;

	if (!(ino = i_open(root_dev, 0))) {
		oft_deref(oft2);
		goto nogood2;
	}

	udata.u_files[u2] = oft2;

	of_tab[oft1].o_ptr = 0;
	of_tab[oft1].o_inode = ino;
	of_tab[oft1].o_access = O_RDONLY;

	of_tab[oft2].o_ptr = 0;
	of_tab[oft2].o_inode = ino;
	of_tab[oft2].o_access = O_WRONLY;

	++ino->c_refs;
	ino->c_node.i_mode = F_PIPE | 0777;	/* No permissions necessary on pipes */
	ino->c_node.i_nlink = 0;	/* a pipe is not in any directory */

	// write results to userspace
	uputw(u1, fildes);
	uputw(u2, fildes + 1);
	return (0);

      nogood2:
	oft_deref(oft1);
	udata.u_files[u1] = NO_FILE;
      nogood:
	return (-1);
}
예제 #2
0
arg_t _waitpid(void)
{
	ptptr p;
	int retval;

	if (statloc && !valaddr((char *) statloc, sizeof(int))) {
		udata.u_error = EFAULT;
		return (-1);
	}

	/* FIXME: move this scan into the main loop and also error
	   on a complete loop finding no matchi for pid */
	/* See if we have any children. */
	for (p = ptab; p < ptab_end; ++p) {
		if (p->p_status && p->p_pptr == udata.u_ptab
		    && p != udata.u_ptab)
			goto ok;
	}
	udata.u_error = ECHILD;
	return (-1);
      ok:
	if (pid == 0)
		pid = -udata.u_ptab->p_pgrp;
	/* Search for an exited child; */
	for (;;) {
		chksigs();
		if (udata.u_cursig) {
			udata.u_error = EINTR;
			return -1;
		}
		for (p = ptab; p < ptab_end; ++p) {
			if (p->p_status == P_ZOMBIE
			    && p->p_pptr == udata.u_ptab) {
				if (pid == -1 || p->p_pid == pid
				    || p->p_pgrp == -pid) {
					if (statloc)
						uputw(p->p_exitval,
						      statloc);

					retval = p->p_pid;
					p->p_status = P_EMPTY;

					/* Add in child's time info.  It was stored on top */
					/* of p_priority in the childs process table entry. */
					udata.u_cutime += ((clock_t *)p->p_priority)[0];
					udata.u_cstime += ((clock_t *)p->p_priority)[1];
					return retval;
				}
			}
		}
		/* Nothing yet, so wait */
		if (options & WNOHANG)
			break;
		psleep(udata.u_ptab);
	}
	udata.u_error = EINTR;
	return -1;
}
예제 #3
0
파일: devsys.c 프로젝트: Abioy/FUZIX
int sys_ioctl(uint8_t minor, uint16_t request, char *data)
{
	if (minor != 3) {
          udata.u_error = ENOTTY;
	  return -1;
        }

	switch (request) {
	case PIO_TABSIZE:
		uputw(maxproc, data);
		break;

	case PIO_ENTRYSIZE:
		uputw(sizeof(struct p_tab), data);
		break;

	default:
		udata.u_error = EINVAL;
		return (-1);
	}
	return 0;
}
예제 #4
0
파일: main.c 프로젝트: davidgiven/FUZIX
void signal_frame(uint8_t *trapframe, uint32_t d0, uint32_t d1, uint32_t a0,
	uint32_t a1)
{
	extern void *udata_shadow;
	uint8_t *usp = get_usp();
	udata_ptr = udata_shadow;
	uint16_t ccr = *(uint16_t *)trapframe;
	uint32_t addr = *(uint32_t *)(trapframe + 2);
	int err = 0;

	/* Build the user stack frame */

	/* FIXME: eventually we should put the trap frame details and trap
	   info into the frame */
	usp -= 4;
	err |= uputl(addr, usp);
	usp -= 4;
	err |= uputw(ccr, usp);
	usp -= 2;
	err |=uputl(a1, usp);
	usp -= 4;
	err |= uputl(a0, usp);
	usp -= 4;
	err |= uputl(d1, usp);
	usp -= 4;
	err |= uputl(d0, usp);
	usp -= 4;
	err |= uputl(udata.u_codebase + 4, usp);
	set_usp(usp);

	if (err) {
		kprintf("%d: stack fault\n", udata.u_ptab->p_pid);
		doexit(dump_core(SIGKILL));
	}
	/* Now patch up the kernel frame */
	*(uint16_t *)trapframe = 0;
	*(uint32_t *)(trapframe + 2) = (uint32_t)udata.u_sigvec[udata.u_cursig];
	udata.u_sigvec[udata.u_cursig] = SIG_DFL;
	udata.u_cursig = 0;
}
예제 #5
0
arg_t _execve(void)
{
	/* We aren't re-entrant where this matters */
	uint8_t hdr[16];
	staticfast inoptr ino;
	char **nargv;		/* In user space */
	char **nenvp;		/* In user space */
	struct s_argblk *abuf, *ebuf;
	int argc;
	uint16_t progptr;
	uint16_t progload;
	staticfast uint16_t top;
	uint16_t bin_size;	/* Will need to be bigger on some cpus */
	uint16_t bss;

	top = ramtop;

	if (!(ino = n_open_lock(name, NULLINOPTR)))
		return (-1);

	if (!((getperm(ino) & OTH_EX) &&
	      (ino->c_node.i_mode & F_REG) &&
	      (ino->c_node.i_mode & (OWN_EX | OTH_EX | GRP_EX)))) {
		udata.u_error = EACCES;
		goto nogood;
	}

	setftime(ino, A_TIME);

	udata.u_offset = 0;
	udata.u_count = 16;
	udata.u_base = hdr;
	udata.u_sysio = true;

	readi(ino, 0);
	if (udata.u_done != 16) {
		udata.u_error = ENOEXEC;
		goto nogood;
	}

	if (!header_ok(hdr)) {
		udata.u_error = ENOEXEC;
		goto nogood2;
	}

	progload = hdr[7] << 8;
	if (progload == 0)
		progload = PROGLOAD;

	top = *(uint16_t *)(hdr + 8);
	if (top == 0)	/* Legacy 'all space' binary */
		top = ramtop;
	else	/* Requested an amount, so adjust for the base */
		top += progload;

	bss = *(uint16_t *)(hdr + 14);

	/* Binary doesn't fit */
	/* FIXME: review overflows */
	bin_size = ino->c_node.i_size;
	progptr = bin_size + 1024 + bss;
	if (progload < PROGLOAD || top - progload < progptr || progptr < bin_size) {
		udata.u_error = ENOMEM;
		goto nogood2;
	}

	udata.u_ptab->p_status = P_NOSLEEP;

	/* If we made pagemap_realloc keep hold of some defined area we
	   could in theory just move the arguments up or down as part of
	   the process - that would save us all this hassle but replace it
	   with new hassle */

	/* Gather the arguments, and put them in temporary buffers. */
	abuf = (struct s_argblk *) tmpbuf();
	/* Put environment in another buffer. */
	ebuf = (struct s_argblk *) tmpbuf();

	/* Read args and environment from process memory */
	if (rargs(argv, abuf) || rargs(envp, ebuf))
		goto nogood3;	/* SN */

	/* This must be the last test as it makes changes if it works */
	/* FIXME: once we sort out chmem we can make stack and data
	   two elements. We never allocate 'code' as there is no split I/D */
	/* This is only safe from deadlocks providing pagemap_realloc doesn't
	   sleep */
	if (pagemap_realloc(0, top - MAPBASE, 0))
		goto nogood3;

	/* From this point on we are commmited to the exec() completing */

	/* Core dump and ptrace permission logic */
#ifdef CONFIG_LEVEL_2
	/* Q: should uid == 0 mean we always allow core */
	if ((!(getperm(ino) & OTH_RD)) ||
		(ino->c_node.i_mode & (SET_UID | SET_GID)))
		udata.u_flags |= U_FLAG_NOCORE;
	else
		udata.u_flags &= ~U_FLAG_NOCORE;
#endif
	udata.u_top = top;
	udata.u_ptab->p_top = top;

	/* setuid, setgid if executable requires it */
	if (ino->c_node.i_mode & SET_UID)
		udata.u_euid = ino->c_node.i_uid;

	if (ino->c_node.i_mode & SET_GID)
		udata.u_egid = ino->c_node.i_gid;

	/* FIXME: In the execve case we may on some platforms have space
	   below PROGLOAD to clear... */

	/* We are definitely going to succeed with the exec,
	 * so we can start writing over the old program
	 */
	uput(hdr, (uint8_t *)progload, 16);
	/* At this point, we are committed to reading in and
	 * executing the program. This call must not block. */

	close_on_exec();

	/*
	 *  Read in the rest of the program, block by block. We rely upon
	 *  the optimization path in readi to spot this is a big move to user
	 *  space and move it directly.
	 */

	 progptr = progload + 16;
	 if (bin_size > 16) {
		bin_size -= 16;
		udata.u_base = (uint8_t *)progptr;		/* We copied the first block already */
		udata.u_count = bin_size;
		udata.u_sysio = false;
		readi(ino, 0);
		if (udata.u_done != bin_size)
			goto nogood4;
		progptr += bin_size;
	}
	/* Wipe the memory in the BSS. We don't wipe the memory above
	   that on 8bit boxes, but defer it to brk/sbrk() */
	uzero((uint8_t *)progptr, bss);

	/* Set initial break for program */
	udata.u_break = (int)ALIGNUP(progptr + bss);

	/* Turn off caught signals */
	memset(udata.u_sigvec, 0, sizeof(udata.u_sigvec));

	// place the arguments, environment and stack at the top of userspace memory,

	// Write back the arguments and the environment
	nargv = wargs(((char *) top - 2), abuf, &argc);
	nenvp = wargs((char *) (nargv), ebuf, NULL);

	// Fill in udata.u_name with program invocation name
	uget((void *) ugetw(nargv), udata.u_name, 8);
	memcpy(udata.u_ptab->p_name, udata.u_name, 8);

	tmpfree(abuf);
	tmpfree(ebuf);
	i_deref(ino);

	/* Shove argc and the address of argv just below envp
	   FIXME: should flip them in crt0.S of app for R2L setups
	   so we can get rid of the ifdefs */
#ifdef CONFIG_CALL_R2L	/* Arguments are stacked the 'wrong' way around */
	uputw((uint16_t) nargv, nenvp - 2);
	uputw((uint16_t) argc, nenvp - 1);
#else
	uputw((uint16_t) nargv, nenvp - 1);
	uputw((uint16_t) argc, nenvp - 2);
#endif

	/* Set stack pointer for the program */
	udata.u_isp = nenvp - 2;

	/* Start execution (never returns) */
	udata.u_ptab->p_status = P_RUNNING;
	doexec(progload);

	/* tidy up in various failure modes */
nogood4:
	/* Must not run userspace */
	ssig(udata.u_ptab, SIGKILL);
nogood3:
	udata.u_ptab->p_status = P_RUNNING;
	tmpfree(abuf);
	tmpfree(ebuf);
nogood2:
nogood:
	i_unlock_deref(ino);
	return (-1);
}
예제 #6
0
파일: tty.c 프로젝트: aralbrec/FUZIX
int tty_ioctl(uint8_t minor, uarg_t request, char *data)
{				/* Data in User Space */
        struct tty *t;
	if (minor > NUM_DEV_TTY + 1) {
		udata.u_error = ENODEV;
		return -1;
	}
        t = &ttydata[minor];
	if (t->flag & TTYF_DEAD) {
	        udata.u_error = ENXIO;
	        return -1;
        }
        jobcontrol_in(minor, t);
	switch (request) {
	case TCGETS:
		return uput(&t->termios, data, sizeof(struct termios));
		break;
	case TCSETSF:
		clrq(&ttyinq[minor]);
		/* Fall through for now */
	case TCSETSW:
		/* We don't have an output queue really so for now drop
		   through */
	case TCSETS:
		if (uget(data, &t->termios, sizeof(struct termios)) == -1)
		        return -1;
                tty_setup(minor);
		break;
	case TIOCINQ:
		return uput(&ttyinq[minor].q_count, data, 2);
	case TIOCFLUSH:
		clrq(&ttyinq[minor]);
		break;
        case TIOCHANGUP:
                tty_hangup(minor);
                return 0;
	case TIOCOSTOP:
		t->flag |= TTYF_STOP;
		break;
	case TIOCOSTART:
		t->flag &= ~TTYF_STOP;
		break;
        case TIOCGWINSZ:
                return uput(&t->winsize, data, sizeof(struct winsize));
        case TIOCSWINSZ:
                if (uget(&t->winsize, data, sizeof(struct winsize)))
                        return -1;
                sgrpsig(t->pgrp, SIGWINCH);
                return 0;
        case TIOCGPGRP:
                return uputw(t->pgrp, data);
#ifdef CONFIG_LEVEL_2
        case TIOCSPGRP:
                /* Only applicable via controlling terminal */
                if (minor != udata.u_ptab->p_tty) {
                        udata.u_error = ENOTTY;
                        return -1;
                }
                return tcsetpgrp(t, data);
#endif
	default:
		udata.u_error = ENOTTY;
		return -1;
	}
	return 0;
}
예제 #7
0
static uint8_t pushw(uint16_t **usp, uint16_t v)
{
	(*usp)--;
	return uputw(v, *usp);
}