Esempio n. 1
0
File: vt.c Progetto: Rappalot/FUZIX
int vt_ioctl(uint8_t minor, uarg_t request, char *data)
{
	/* FIXME: need to address the multiple vt switching case
	   here.. probably need to switch vt */
	if (minor <= MAX_VT) {
		switch(request) {
#ifdef KEY_ROWS
			case KBMAPSIZE:
				return KEY_ROWS << 8 | KEY_COLS;
			case KBMAPGET:
				return uput(keymap, data, sizeof(keymap));
			case KBSETTRANS:
				if (esuper())
					return -1;
				if (uget(keyboard, data, sizeof(keyboard)) == -1)
					return -1;
				return uget(shiftkeyboard,
					data + sizeof(keyboard),
					sizeof(shiftkeyboard));
#endif					
			case VTSIZE:
				return VT_HEIGHT << 8 | VT_WIDTH;
			case VTATTRS:
				return vtattr_cap;
		}
	}
	return tty_ioctl(minor, request, data);
}
Esempio n. 2
0
File: start.c Progetto: Abioy/FUZIX
void create_init(void)
{
	uint8_t *j;
	/* userspace: 0x100+ 0   1   2   3   4   5   6   7   8   9   A   B   C */
	const char arg[] =
	    { '/', 'i', 'n', 'i', 't', 0, 0, 1, 1, 0, 0, 0, 0 };

	init_process = ptab_alloc();
	udata.u_ptab = init_process;
	udata.u_top = 4096;	/* Plenty for the boot */
	map_init();
	newproc(init_process);

	init_process->p_status = P_RUNNING;

	/* wipe file table */
	for (j = udata.u_files; j < (udata.u_files + UFTSIZE); ++j) {
		*j = NO_FILE;
	}
	/* Poke the execve arguments into user data space so _execve() can read them back */
	uput(arg, PROGBASE, sizeof(arg));

	/* Set up things to look like the process is calling _execve() */
	udata.u_argn = (uint16_t) PROGBASE;
	/* FIXME - should be relative to PROGBASE... */
	udata.u_argn1 = 0x107;	/* Arguments (just "/init") */
	udata.u_argn2 = 0x10b;	/* Environment (none) */
}
Esempio n. 3
0
int platform_rtc_read(void)
{
    uint16_t len = sizeof(struct cmos_rtc);
    irqflags_t irqflags;
    struct cmos_rtc cmos;
    uint8_t *p;
    uint_fast8_t r, y;

    if (udata.u_count < len)
        len = udata.u_count;

    irqflags = di();

    p = cmos.data.bytes;
    y  = rtc_get(11);
    if (y >= 0x70)
        *p++ = 0x19;
    else
        *p++ = 0x20;
    *p++ = y;
    *p++ = rtc_get(9) & 0x1F;
    *p++ = rtc_get(7) & 0x3F;
    *p++ = rtc_get(4) & 0x3F;
    *p++ = rtc_get(2) & 0x7F;
    *p++ = rtc_get(0) & 0x7F;
    irqrestore(irqflags);

    cmos.type = CMOS_RTC_BCD;
    if (uput(&cmos, udata.u_base, len) == -1)
        return -1;
    return len;
}
Esempio n. 4
0
void add_argument(const char *s)
{
	int l = strlen(s) + 1;
	uput(s, (void *)progptr, l);
	uputp(progptr, (void *)argptr);
	progptr += ((l + 3) & ~3);
	argptr += sizeof(uptr_t);
}
Esempio n. 5
0
arg_t _time(void)
{
	time_t t;
	switch (type) {
		case 0:
			rdtime(&t);
			uput(&t, tvec, sizeof(t));
			return (0);
		case 1:
			uput(&t.low, &ticks.full, sizeof(ticks));
			uzero(&t.high, sizeof(t.high));
			return 0;
		default:
			udata.u_error = EINVAL;
			return -1;
	}
}
Esempio n. 6
0
File: mm.c Progetto: ljalves/FUZIX
unsigned int uputsys(unsigned char *from, unsigned int size)
{
	if (udata.u_sysio)
		memcpy(udata.u_base, from, size);
	else
		uput(from, udata.u_base, size);
	return size;
}
Esempio n. 7
0
arg_t _getrlimit(void)
{
	if (res < 0 || res >= NRLIMIT) {
		udata.u_error = EINVAL;
		return -1;
	}
	return uput(rlim, udata.u_rlimit + res, sizeof(struct rlimit));
}
Esempio n. 8
0
arg_t _getfsys(void)
{
        struct mount *m = fs_tab_get(dev);
	if (m == NULL || m->m_dev == NO_DEVICE) {
		udata.u_error = ENXIO;
		return (-1);
	}
	return uput((char *) m->m_fs, (char *) buf, sizeof(struct filesys));
}
Esempio n. 9
0
int16_t _uname(void)
{
        uint16_t size = sizeof(sysinfo) + uname_len;
        if (size > len)
                size = len;
	sysinfo.memk = procmem;
	sysinfo.usedk = pagemap_mem_used();
	uput(&sysinfo, buf, size);
	return size;
}
Esempio n. 10
0
File: tty.c Progetto: jfernand/FUZIX
int tty_ioctl(uint8_t minor, uint16_t request, char *data)
{				/* Data in User Space */
	if (!minor)
		minor = udata.u_ptab->p_tty;
	if (minor < 1 || minor > NUM_DEV_TTY + 1) {
		udata.u_error = ENODEV;
		return -1;
	}
	if (deadflag[minor]) {
	        udata.u_error = ENXIO;
	        return -1;
        }
	switch (request) {
	case TCGETS:
		uput(&ttydata[minor], data, sizeof(struct termios));
		break;
	case TCSETSW:
		/* We don't have an output queue really so for now drop
		   through */
	case TCSETS:
	case TCSETSF:
		uget(data, &ttydata[minor], sizeof(struct termios));
		if (request == TCSETSF)
			clrq(&ttyinq[minor]);
                tty_setup(minor);
		break;
	case TIOCINQ:
		uput(&ttyinq[minor].q_count, data, 2);
		break;
	case TIOCFLUSH:
		clrq(&ttyinq[minor]);
		break;
        case TIOCHANGUP:
                tty_hangup(minor);
                return 0;
	default:
		udata.u_error = ENOTTY;
		return (-1);
	}
	return (0);
}
Esempio n. 11
0
static int sa_put(struct socket *s, int type, struct sockaddr_in *u)
{
	struct sockaddrs *sa = &s->s_addr[type];
	static struct sockaddr_in sin;
	memset(&sin, 0, sizeof(sin));
	sin.sin_addr.s_addr = sa->addr;
	sin.sin_port = sa->port;
	sin.sin_family = AF_INET;
	if (u && uput(u, &sin, sizeof(sin)) == -1)
		return -1;
	return 0;
}
Esempio n. 12
0
arg_t _getgroups(void)
{
	if (groups == 0)
		return udata.u_ngroup;
	if (ngroup < udata.u_ngroup) {
		udata.u_error = EINVAL;
		return -1;
	}
	if (uput(udata.u_groups, groups, udata.u_ngroup * sizeof(uint16_t)) < 0)
		return -1;
	return udata.u_ngroup;
}
Esempio n. 13
0
uint8_t write_core_image(void)
{
	inoptr parent = NULLINODE;
	inoptr ino;

	udata.u_error = 0;

	/* FIXME: need to think more about the case sp is lala */
	if (uput("core", (uint8_t *)udata.u_syscall_sp - 5, 5))
		return 0;

	ino = n_open((char *)udata.u_syscall_sp - 5, &parent);
	if (ino) {
		i_deref(parent);
		return 0;
	}
	if (parent) {
		i_lock(parent);
		if ((ino = newfile(parent, "core")) != NULL) {
			ino->c_node.i_mode = F_REG | 0400;
			setftime(ino, A_TIME | M_TIME | C_TIME);
			wr_inode(ino);
			f_trunc(ino);
#if 0
	/* FIXME address ranges for different models - move core writer
	   for address spaces into helpers ?  */
			/* FIXME: need to add some arch specific header bits, and
			   also pull stuff like the true sp and registers out of
			   the return stack properly */

			corehdr.ch_base = pagemap_base;
			corehdr.ch_break = udata.u_break;
			corehdr.ch_sp = udata.u_syscall_sp;
			corehdr.ch_top = PROGTOP;
			udata.u_offset = 0;
			udata.u_base = (uint8_t *)&corehdr;
			udata.u_sysio = true;
			udata.u_count = sizeof(corehdr);
			writei(ino, 0);
			udata.u_sysio = false;
			udata.u_base = (uint8_t *)pagemap_base;
			udata.u_count = udata.u_break - pagemap_base;
			writei(ino, 0);
			udata.u_base = udata.u_sp;
			udata.u_count = PROGTOP - (uint32_t)udata.u_sp;
			writei(ino, 0);
#endif
			i_unlock_deref(ino);
			return W_COREDUMP;
		}
	}
	return 0;
}
Esempio n. 14
0
int fd_ioctl(uint8_t minor, uarg_t request, char *buffer)
{
    switch(request) {
    case FDIO_GETCAP:
        return uput(&fdcap, buffer, sizeof(struct fdcinfo));
    case FDIO_GETINFO:
        return uput(&fdcap, buffer, sizeof(struct fdcinfo));
    case FDIO_SETINFO:
        /* Whatever - when they query to check they'll get no changes */
        return 0;
    case FDIO_FMTTRK:
        /* Virtual fd has no format mechanism */
        return 0;
    case FDIO_RESTORE:
        /* Virtual restore is meaningless */
        return 0;
    case FDIO_SETSKEW:
        return uput(skewtab + minor, buffer, 32);
    default:
        return -1;
    }
}
Esempio n. 15
0
int gfx_draw_op(uarg_t arg, char *ptr)
{
	int err=0;
	int l;
	int c = 8;	/* 4 x uint16_t */
	uint16_t *p = (uint16_t *)(char *)0x5e00;

	map_for_video();
	l = ugetw(ptr);
	if (l < 6 || l > 512){
		err = EINVAL;
		goto ret;
	}
	if (arg != GFXIOC_READ)
		c = l;
	if (uget(ptr + 2, (char *)0x5e00, c)){
		err = EFAULT;
		goto ret;
	}
	switch(arg) {
	case GFXIOC_DRAW:
		/* TODO
		   if (draw_validate(ptr, l, 256, 192))  - or 128!
		   return EINVAL */
		video_cmd( ( char *)0x5e00 );
		break;
	case GFXIOC_WRITE:
	case GFXIOC_READ:
		if (l < 8){
			err= EINVAL;
			break;
		}
		l -= 8;
		if (p[0] > 191 || p[1] > 31 || p[2] > 191 || p[3] > 31 ||
		    p[0] + p[2] > 192 || p[1] + p[3] > 32 ||
		    (p[2] * p[3]) > l) {
			err = -EFAULT;
			break;
		}
		if (arg == GFXIOC_READ) {
			video_read( (char *)0x5e00 );
			if (uput( (char *)0x5e00 + 8, ptr+10, l-2))
				err = EFAULT;
			break;
		}
		video_write( (char *)0x5e00 );
	}
 ret:
	map_for_kernel();
	return err;
}
Esempio n. 16
0
uint8_t write_core_image(void)
{
	inoptr parent = NULLINODE;
	inoptr ino;

	udata.u_error = 0;

	/* FIXME: need to think more about the case sp is lala */
	if (uput("core", udata.u_syscall_sp - 5, 5))
		return 0;

	ino = n_open(udata.u_syscall_sp - 5, &parent);
	if (ino) {
		i_deref(parent);
		return 0;
	}
	if (parent) {
		i_lock(parent);
		if (ino = newfile(parent, "core")) {
			ino->c_node.i_mode = F_REG | 0400;
			setftime(ino, A_TIME | M_TIME | C_TIME);
			wr_inode(ino);
			f_trunc(ino);

			/* FIXME: need to add some arch specific header bits, and
			   also pull stuff like the true sp and registers out of
			   the return stack properly */

			corehdr.ch_base = MAPBASE;
			corehdr.ch_break = udata.u_break;
			corehdr.ch_sp = udata.u_syscall_sp;
			corehdr.ch_top = PROGTOP;
			udata.u_offset = 0;
			udata.u_base = (uint8_t *)&corehdr;
			udata.u_sysio = true;
			udata.u_count = sizeof(corehdr);
			writei(ino, 0);
			udata.u_sysio = false;
			udata.u_base = MAPBASE;
			udata.u_count = udata.u_break - MAPBASE;
			writei(ino, 0);
			udata.u_base = udata.u_sp;
			udata.u_count = PROGTOP - (uint16_t)udata.u_sp;
			writei(ino, 0);
			i_unlock_deref(ino);
			return W_COREDUMP;
		}
	}
	return 0;
}
Esempio n. 17
0
arg_t _uname(void)
{
        uint16_t size = sizeof(sysinfo) + uname_len;
        if (size > len)
                size = len;
	sysinfo.memk = procmem;
	sysinfo.usedk = pagemap_mem_used();
	sysinfo.nproc = PTABSIZE;
	sysinfo.ticks = ticks_per_dsecond * 10;
	sysinfo.loadavg[0] = loadavg[0].average;
	sysinfo.loadavg[1] = loadavg[1].average;
	sysinfo.loadavg[2] = loadavg[2].average;
	uput(&sysinfo, buf, size);
	return size;
}
Esempio n. 18
0
arg_t _time(void)
{
	time_t t;
	switch (type) {
		case 0:
			rdtime(&t);
			break;
		case 1:
			t.low = ticks.full;
			t.high = 0;
			break;
		default:
			udata.u_error = EINVAL;
			return -1;
	}
	return uput(&t, tvec, sizeof(t));
}
Esempio n. 19
0
/* We copy the 32bit offset in and out rather than passing it
   as a 32bit OS might */
arg_t _lseek(void)
{
	inoptr ino;
	struct oft *o;
	off_t p;
	off_t n;
	
	if (uget(offset, &n, sizeof(n)))
	        return -1;

	if ((ino = getinode(file)) == NULLINODE)
		return (-1);

	if (getmode(ino) == MODE_R(F_PIPE)) {
		udata.u_error = ESPIPE;
		return (-1);
	}

	o = &of_tab[udata.u_files[file]];
	p = o->o_ptr;

	switch (flag) {
	case 0:
		p = n;
		break;
	case 1:
		p += n;
		break;
	case 2:
		p = ino->c_node.i_size + n;
		break;
	default:
                goto bad;
	}
	if (p < 0)
	        goto bad;
        o->o_ptr = p;
	uput(&p, offset, sizeof(n));
	return 0;
bad:
	udata.u_error = EINVAL;
	return (-1);

}
Esempio n. 20
0
int platform_rtc_read(void)
{
    uint16_t len = sizeof(struct cmos_rtc);
    struct cmos_rtc cmos;
    uint8_t *p;
    uint8_t r, y;

    if (udata.u_count < len)
        len = udata.u_count;

    if (rtc_secl == 255) {
      udata.u_error = EOPNOTSUPP;
      return -1;
    }

    /* We do a full set of reads and if the seconds change retry - we
       need to retry the lost as we might read as the second changes for
       new year */
    do {
      p = cmos.data.bytes;
      r = rtc_secl;
      y  = (rtc_yearh << 4) | rtc_yearl;
      if (y >= 0x70)
          *p++ = 0x19;
      else
          *p++ = 0x20;
      *p++ = y;
      *p++ = ((rtc_monh  & 1)<< 4) | rtc_monl;
      *p++ = ((rtc_dayh & 3) << 4) | rtc_dayl;
      *p++ = ((rtc_hourh & 3) << 4) | rtc_hourl;
      *p++ = ((rtc_minh & 7) << 4) | rtc_minl;
      *p++ = ((rtc_sech & 7) << 4) | rtc_secl;
    } while ((r ^ rtc_secl) & 0x0F);

    cmos.type = CMOS_RTC_BCD;
    if (uput(&cmos, udata.u_base, len) == -1)
        return -1;
    return len;
}
Esempio n. 21
0
File: tty.c Progetto: 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;
}
Esempio n. 22
0
arg_t _execve(void)
{
	/* Not ideal on stack */
	struct binfmt_flat binflat;
	inoptr ino;
	char **nargv;		/* In user space */
	char **nenvp;		/* In user space */
	struct s_argblk *abuf, *ebuf;
	int argc;
	uint32_t bin_size;	/* Will need to be bigger on some cpus */
	uaddr_t progbase, top;
	uaddr_t go;
	uint32_t true_brk;

	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 = sizeof(struct binfmt_flat);
	udata.u_base = (void *)&binflat;
	udata.u_sysio = true;

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

	/* FIXME: ugly - save this as valid_hdr modifies it */
	true_brk = binflat.bss_end;

	/* Hard coded for our 68K format. We don't quite use the ucLinux
	   names, we don't want to load a ucLinux binary in error! */
	if (memcmp(binflat.magic, "bFLT", 4) || !valid_hdr(ino, &binflat)) {
		udata.u_error = ENOEXEC;
		goto nogood2;
	}

	/* Memory needed */
	bin_size = binflat.bss_end + binflat.stack_size;

	/* Overflow ? */
	if (bin_size < binflat.bss_end) {
		udata.u_error = ENOEXEC;
		goto nogood2;
	}
	
	/* 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;

	/* This must be the last test as it makes changes if it works */
	/* FIXME: need to update this to support split code/data and to fix
	   stack handling nicely */
	/* FIXME: ENOMEM fix needs to go to 16bit ? */
	if ((udata.u_error = pagemap_realloc(0, bin_size, 0)) != 0)
		goto nogood3;

	/* 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_codebase = progbase = pagemap_base();
	/* From this point on we are commmited to the exec() completing
	   so we can start writing over the old program */
	uput(&binflat, (uint8_t *)progbase, sizeof(struct binfmt_flat));

	/* 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;

	top = progbase + bin_size;

	udata.u_top = top;
	udata.u_ptab->p_top = top;

//	kprintf("user space at %p\n", progbase);
//	kprintf("top at %p\n", progbase + bin_size);

	bin_size = binflat.reloc_start + 4 * binflat.reloc_count;
	go = (uint32_t)progbase + binflat.entry;

	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.
	 */

	 if (bin_size > sizeof(struct binfmt_flat)) {
		/* We copied the header already */
		bin_size -= sizeof(struct binfmt_flat);
		udata.u_base = (uint8_t *)progbase +
					sizeof(struct binfmt_flat);
		udata.u_count = bin_size;
		udata.u_sysio = false;
		readi(ino, 0);
		if (udata.u_done != bin_size)
			goto nogood4;
	}

	/* Header isn't counted in relocations */
	relocate(&binflat, progbase, bin_size);
	/* This may wipe the relocations */	
	uzero((uint8_t *)progbase + binflat.data_end,
		binflat.bss_end - binflat.data_end + binflat.stack_size);

	/* Use of brk eats into the stack allocation */

	/* Use the temporary we saved (hack) as we mangled bss_end */
	udata.u_break = udata.u_codebase + true_brk;

	/* 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 - 4), abuf, &argc);
	nenvp = wargs((char *) (nargv), ebuf, NULL);

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

	tmpfree(abuf);
	tmpfree(ebuf);
	i_unlock_deref(ino);

	/* Shove argc and the address of argv just below envp */
	uputl((uint32_t) nargv, nenvp - 1);
	uputl((uint32_t) argc, nenvp - 2);

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

	/*
	 * Sort of - it's a good way to deal with all the stupidity of
	 * random 68K platforms we will have to handle, and a nice place
	 * to stuff the signal trampoline 8)
	 */
	install_vdso();

//	kprintf("Go = %p ISP = %p\n", go, udata.u_isp);

	doexec(go);

nogood4:
	/* Must not run userspace */
	ssig(udata.u_ptab, SIGKILL);
nogood3:
	tmpfree(abuf);
	tmpfree(ebuf);
nogood2:
nogood:
	i_unlock_deref(ino);
	return (-1);
}
Esempio n. 23
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);
}
Esempio n. 24
0
/*
 *	This works because our uput and uget (see trs80-bank.s) switch
 *	to kernel logical bank 2 when copying, as kernel bank 1 is only
 *	code so it knows that any copy must be to common or bank 2. Without
 *	that this would need a double buffer.
 */
void blktou(void *uaddr, struct blkbuf *buf, uint16_t off, uint16_t len)
{
    uput(buf->__bf_data + off, uaddr, len);
}