Beispiel #1
0
static void
do_open (vfs_task_t *client, vfsmsg_t *msg) {
    int fd;
    int fp;

    fd = find_empty_fd(client);
    if (fd < 0) {
        msg->openclose.fd = -1;
        return;
    }
    fp = find_empty_filp();
    if (fp < 0) {
        msg->openclose.fd = -1;
        return;
    }

    filp[fp].dev = msg->openclose.dev;
    filp[fp].ino = msg->openclose.ino;
    filp[fp].pos = 0;

    /* Get the node */
    msg->cmd = VFS_INODE_GRAB;
    msg->iget.ino = filp[fp].ino;
    sendrec(devtab[filp[fp].dev], msg, sizeof(vfsmsg_t));

    if (msg->iget.ino < 0) {
        /* Node not found on dev */
        msg->openclose.fd = -1;
        return;
    }

    filp[fp].refcnt++;
    client->fd[fd] = fp;

    msg->openclose.fd = fd;
    return;
}
/*===========================================================================*
 *		            sef_cb_init_fresh                                *
 *===========================================================================*/
static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
{
/* Initialize the process manager. 
 * Memory use info is collected from the boot monitor, the kernel, and
 * all processes compiled into the system image. Initially this information
 * is put into an array mem_chunks. Elements of mem_chunks are struct memory,
 * and hold base, size pairs in units of clicks. This array is small, there
 * should be no more than 8 chunks. After the array of chunks has been built
 * the contents are used to initialize the hole list. Space for the hole list
 * is reserved as an array with twice as many elements as the maximum number
 * of processes allowed. It is managed as a linked list, and elements of the
 * array are struct hole, which, in addition to storage for a base and size in 
 * click units also contain space for a link, a pointer to another element.
*/
  int s;
  static struct boot_image image[NR_BOOT_PROCS];
  register struct boot_image *ip;
  static char core_sigs[] = { SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
				SIGEMT, SIGFPE, SIGBUS, SIGSEGV };
  static char ign_sigs[] = { SIGCHLD, SIGWINCH, SIGCONT };
  static char noign_sigs[] = { SIGILL, SIGTRAP, SIGEMT, SIGFPE, 
				SIGBUS, SIGSEGV };
  register struct mproc *rmp;
  register char *sig_ptr;
  message mess;

  /* Initialize process table, including timers. */
  for (rmp=&mproc[0]; rmp<&mproc[NR_PROCS]; rmp++) {
	init_timer(&rmp->mp_timer);
	rmp->mp_magic = MP_MAGIC;
  }

  /* Build the set of signals which cause core dumps, and the set of signals
   * that are by default ignored.
   */
  sigemptyset(&core_sset);
  for (sig_ptr = core_sigs; sig_ptr < core_sigs+sizeof(core_sigs); sig_ptr++)
	sigaddset(&core_sset, *sig_ptr);
  sigemptyset(&ign_sset);
  for (sig_ptr = ign_sigs; sig_ptr < ign_sigs+sizeof(ign_sigs); sig_ptr++)
	sigaddset(&ign_sset, *sig_ptr);
  sigemptyset(&noign_sset);
  for (sig_ptr = noign_sigs; sig_ptr < noign_sigs+sizeof(noign_sigs); sig_ptr++)
	sigaddset(&noign_sset, *sig_ptr);

  /* Obtain a copy of the boot monitor parameters and the kernel info struct.  
   * Parse the list of free memory chunks. This list is what the boot monitor 
   * reported, but it must be corrected for the kernel and system processes.
   */
  if ((s=sys_getmonparams(monitor_params, sizeof(monitor_params))) != OK)
      panic("get monitor params failed: %d", s);
  if ((s=sys_getkinfo(&kinfo)) != OK)
      panic("get kernel info failed: %d", s);

  /* Initialize PM's process table. Request a copy of the system image table 
   * that is defined at the kernel level to see which slots to fill in.
   */
  if (OK != (s=sys_getimage(image))) 
  	panic("couldn't get image table: %d", s);
  procs_in_use = 0;				/* start populating table */
  for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) {
  	if (ip->proc_nr >= 0) {			/* task have negative nrs */
  		procs_in_use += 1;		/* found user process */

		/* Set process details found in the image table. */
		rmp = &mproc[ip->proc_nr];	
  		strlcpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN); 
  		(void) sigemptyset(&rmp->mp_ignore);	
  		(void) sigemptyset(&rmp->mp_sigmask);
  		(void) sigemptyset(&rmp->mp_catch);
		if (ip->proc_nr == INIT_PROC_NR) {	/* user process */
  			/* INIT is root, we make it father of itself. This is
  			 * not really OK, INIT should have no father, i.e.
  			 * a father with pid NO_PID. But PM currently assumes 
  			 * that mp_parent always points to a valid slot number.
  			 */
  			rmp->mp_parent = INIT_PROC_NR;
  			rmp->mp_procgrp = rmp->mp_pid = INIT_PID;
			rmp->mp_flags |= IN_USE; 

			/* Set scheduling info */
			rmp->mp_scheduler = KERNEL;
			rmp->mp_nice = get_nice_value(USR_Q);
		}
		else {					/* system process */
  			if(ip->proc_nr == RS_PROC_NR) {
  				rmp->mp_parent = INIT_PROC_NR;
  			}
  			else {
  				rmp->mp_parent = RS_PROC_NR;
  			}
  			rmp->mp_pid = get_free_pid();
			rmp->mp_flags |= IN_USE | PRIV_PROC;

			/* RS schedules this process */
			rmp->mp_scheduler = NONE;
			rmp->mp_nice = get_nice_value(SRV_Q);
		}

		/* Get kernel endpoint identifier. */
		rmp->mp_endpoint = ip->endpoint;

		/* Tell VFS about this system process. */
		mess.m_type = PM_INIT;
		mess.PM_SLOT = ip->proc_nr;
		mess.PM_PID = rmp->mp_pid;
		mess.PM_PROC = rmp->mp_endpoint;
  		if (OK != (s=send(VFS_PROC_NR, &mess)))
			panic("can't sync up with VFS: %d", s);
  	}
  }

  /* Tell VFS that no more system processes follow and synchronize. */
  mess.PR_ENDPT = NONE;
  if (sendrec(VFS_PROC_NR, &mess) != OK || mess.m_type != OK)
	panic("can't sync up with VFS");

#if defined(__i386__)
        uts_val.machine[0] = 'i';
        strcpy(uts_val.machine + 1, itoa(getprocessor()));
#elif defined(__arm__)
        strcpy(uts_val.machine, "arm");
#endif  

 system_hz = sys_hz();

  /* Initialize user-space scheduling. */
  sched_init();

  return(OK);
}
Beispiel #3
0
/*===========================================================================*
 *				driver_open				     *
 *===========================================================================*/
static int driver_open(int which)
{
    /* Perform an open or close operation on the driver. This is
     * unfinished code: we should never be doing a blocking sendrec() to
     * the driver.
     */
    message msg;
    cp_grant_id_t gid;
    struct partition part;
    sector_t sectors;
    int r;

    memset(&msg, 0, sizeof(msg));
    msg.m_type = BDEV_OPEN;
    msg.BDEV_MINOR = driver[which].minor;
    msg.BDEV_ACCESS = R_BIT | W_BIT;
    msg.BDEV_ID = 0;
    r = sendrec(driver[which].endpt, &msg);

    if (r != OK) {
        /* Should we restart the driver now? */
        printf("Filter: driver_open: sendrec returned %d\n", r);

        return RET_REDO;
    }

    if(msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
        printf("Filter: driver_open: sendrec returned %d, %d\n",
               msg.m_type, msg.BDEV_STATUS);

        return RET_REDO;
    }

    /* Take the opportunity to retrieve the hard disk size. */
    gid = cpf_grant_direct(driver[which].endpt,
                           (vir_bytes) &part, sizeof(part), CPF_WRITE);
    if(!GRANT_VALID(gid))
        panic("invalid grant: %d", gid);

    memset(&msg, 0, sizeof(msg));
    msg.m_type = BDEV_IOCTL;
    msg.BDEV_MINOR = driver[which].minor;
    msg.BDEV_REQUEST = DIOCGETP;
    msg.BDEV_GRANT = gid;
    msg.BDEV_ID = 0;

    r = sendrec(driver[which].endpt, &msg);

    cpf_revoke(gid);

    if (r != OK || msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
        /* Not sure what to do here, either. */
        printf("Filter: ioctl(DIOCGETP) returned (%d, %d)\n",
               r, msg.m_type);

        return RET_REDO;
    }

    if(!size_known) {
        disk_size = part.size;
        size_known = 1;
        sectors = div64u(disk_size, SECTOR_SIZE);
        if(cmp64(mul64u(sectors, SECTOR_SIZE), disk_size)) {
            printf("Filter: partition too large\n");

            return RET_REDO;
        }
#if DEBUG
        printf("Filter: partition size: 0x%s / %lu sectors\n",
               print64(disk_size), sectors);
#endif
    } else {
        if(cmp64(disk_size, part.size)) {
            printf("Filter: partition size mismatch (%s != %s)\n",
                   print64(part.size), print64(disk_size));

            return RET_REDO;
        }
    }

    return OK;
}
Beispiel #4
0
/*===========================================================================*
 *				fbd_transfer_copy			     *
 *===========================================================================*/
static ssize_t fbd_transfer_copy(int do_write, u64_t position,
                                 endpoint_t endpt, iovec_t *iov, unsigned int count, size_t size,
                                 int flags)
{
    /* Interpose on the request. */
    iovec_s_t iovec[NR_IOREQS];
    struct vscp_vec vscp_vec[SCPVEC_NR];
    cp_grant_id_t grant;
    size_t off, len;
    message m;
    char *ptr;
    int i, j, r;
    ssize_t rsize;

    assert(count > 0 && count <= SCPVEC_NR);

    if (size > BUF_SIZE) {
        printf("FBD: allocating memory for %d bytes\n", size);

        ptr = alloc_contig(size, 0, NULL);

        assert(ptr != NULL);
    }
    else ptr = fbd_buf;

    /* For write operations, first copy in the data to write. */
    if (do_write) {
        for (i = off = 0; i < count; i++) {
            len = iov[i].iov_size;

            vscp_vec[i].v_from = endpt;
            vscp_vec[i].v_to = SELF;
            vscp_vec[i].v_gid = iov[i].iov_addr;
            vscp_vec[i].v_offset = 0;
            vscp_vec[i].v_addr = (vir_bytes) (ptr + off);
            vscp_vec[i].v_bytes = len;

            off += len;
        }

        if ((r = sys_vsafecopy(vscp_vec, i)) != OK)
            panic("vsafecopy failed (%d)\n", r);

        /* Trigger write hook. */
        rule_io_hook(ptr, size, position, FBD_FLAG_WRITE);
    }

    /* Allocate grants for the data, in the same chunking as the original
     * vector. This avoids performance fluctuations with bad hardware as
     * observed with the filter driver.
     */
    for (i = off = 0; i < count; i++) {
        len = iov[i].iov_size;

        iovec[i].iov_size = len;
        iovec[i].iov_grant = cpf_grant_direct(driver_endpt,
                                              (vir_bytes) (ptr + off), len,
                                              do_write ? CPF_READ : CPF_WRITE);
        assert(iovec[i].iov_grant != GRANT_INVALID);

        off += len;
    }

    grant = cpf_grant_direct(driver_endpt, (vir_bytes) iovec,
                             count * sizeof(iovec[0]), CPF_READ);
    assert(grant != GRANT_INVALID);

    m.m_type = do_write ? BDEV_SCATTER : BDEV_GATHER;
    m.BDEV_MINOR = driver_minor;
    m.BDEV_COUNT = count;
    m.BDEV_GRANT = grant;
    m.BDEV_FLAGS = flags;
    m.BDEV_ID = 0;
    m.BDEV_POS_LO = ex64lo(position);
    m.BDEV_POS_HI = ex64hi(position);

    if ((r = sendrec(driver_endpt, &m)) != OK)
        panic("sendrec to driver failed (%d)\n", r);

    if (m.m_type != BDEV_REPLY)
        panic("invalid reply from driver (%d)\n", m.m_type);

    cpf_revoke(grant);

    for (i = 0; i < count; i++)
        cpf_revoke(iovec[i].iov_grant);

    /* For read operations, finish by copying out the data read. */
    if (!do_write) {
        /* Trigger read hook. */
        rule_io_hook(ptr, size, position, FBD_FLAG_READ);

        /* Upon success, copy back whatever has been processed. */
        rsize = m.BDEV_STATUS;
        for (i = j = off = 0; rsize > 0 && i < count; i++) {
            len = MIN(rsize, iov[i].iov_size);

            vscp_vec[j].v_from = SELF;
            vscp_vec[j].v_to = endpt;
            vscp_vec[j].v_gid = iov[i].iov_addr;
            vscp_vec[j].v_offset = 0;
            vscp_vec[j].v_addr = (vir_bytes) (ptr + off);
            vscp_vec[j].v_bytes = len;

            off += len;
            rsize -= len;
            j++;
        }

        if (j > 0 && (r = sys_vsafecopy(vscp_vec, j)) != OK)
            panic("vsafecopy failed (%d)\n", r);
    }

    if (ptr != fbd_buf)
        free_contig(ptr, size);

    return m.BDEV_STATUS;
}
Beispiel #5
0
static void serve(struct muth *muth, va_list args)
{
    vavar(struct hthead *, req);
    vavar(int, fd);
    vavar(int, sfd);
    FILE *is, *os, *outi, *outo, *erri, *erro;
    struct charbuf head;
    struct hthead *resp;
    size_t read;
    char buf[8192];
    
    sfd = reconn();
    is = mtstdopen(fd, 1, 60, "r+", NULL);
    os = mtstdopen(sfd, 1, 600, "r+", NULL);
    
    outi = NULL;
    mtiopipe(&outi, &outo); mtiopipe(&erri, &erro);
    mustart(outplex, mtstdopen(dup(sfd), 1, 600, "r+", NULL), outo, FCGI_STDOUT, erro, FCGI_STDERR, NULL);
    mustart(errhandler, erri);
    
    if(begreq(os, 1))
	goto out;
    bufinit(head);
    mkcgienv(req, &head);
    if(sendrec(os, FCGI_PARAMS, 1, head.b, head.d))
	goto out;
    if(sendrec(os, FCGI_PARAMS, 1, NULL, 0))
	goto out;
    buffree(head);
    if(fflush(os))
	goto out;
    
    while(!feof(is)) {
	read = fread(buf, 1, sizeof(buf), is);
	if(ferror(is))
	    goto out;
	if(sendrec(os, FCGI_STDIN, 1, buf, read))
	    goto out;
    }
    if(sendrec(os, FCGI_STDIN, 1, NULL, 0))
	goto out;
    if(fflush(os))
	goto out;
    
    if((resp = parseresp(outi)) == NULL)
	goto out;
    writeresp(is, resp);
    freehthead(resp);
    fputc('\n', is);
    if(passdata(outi, is) < 0)
	goto out;
    
out:
    freehthead(req);
    buffree(head);
    shutdown(sfd, SHUT_RDWR);
    if(outi != NULL)
	fclose(outi);
    fclose(is);
    fclose(os);
}
Beispiel #6
0
static int begreq(FILE *out, int rid)
{
    char rec[] = {0, 1, 0, 0, 0, 0, 0, 0};
    
    return(sendrec(out, FCGI_BEGIN_REQUEST, rid, rec, 8));
}
/*==========================================================================*
 *				do_vrdwt				    *
 *==========================================================================*/
PRIVATE int do_vrdwt(message* mp)
 /* mp - pointer to read or write message */
{
/* Carry out an device read or write to/from a vector of user addresses.
 * The "user addresses" are assumed to be safe, i.e. FS transferring to/from
 * its own buffers, so they are not checked.
 */
  static iovec_t iovec[NR_IOREQS];
  iovec_t *iov;
  phys_bytes iovec_size;
  unsigned nr_req, position;
  int r;
  message m_dd; /*message for disk driver*/
  nr_req = mp->COUNT;	/* Length of I/O vector */
  position = mp->POSITION;

		/* Copy the vector from the caller to kernel space. */
		if (nr_req > NR_IOREQS) nr_req = NR_IOREQS;
			iovec_size = (phys_bytes) (nr_req * sizeof(iovec[0]));

		if (OK != sys_datacopy(mp->m_source, (vir_bytes) mp->ADDRESS, 
				SELF, (vir_bytes) iovec, iovec_size))
			panic("Crypt Drive","bad I/O vector by", s);
		iov = iovec;
  
	while(nr_req>0){
		vir_bytes user_vir = iov->iov_addr; /*User program mem addresss*/
		unsigned count = iov->iov_size; /* number of byted to copy */
		
		printf("CryptDrive: Size:%d , DST:%d , POS:%d, REQ: %d/%d \n",count, user_vir, position, nr_req, mp->COUNT);
		
		if(mp->m_type == DEV_GATHER){
			m_dd.m_type=DEV_READ;
			m_dd.DEVICE=mp->DEVICE;
			m_dd.m_source=thispid;
			m_dd.COUNT=count;
			m_dd.POSITION=position;
			m_dd.ADDRESS=(vir_bytes)  buffer;	
			if(OK != sendrec(DRVR_PROC_NR, &m_dd))
				panic("CryptDrive","do_rdv messaging failed",s);
			
			/* decrypt here  - this line here */
			/*from here to caller*/
			sys_vircopy(SELF, D, buffer, proc_nr, D, user_vir, m_dd.COUNT);
			
		}
		if(mp->m_type == DEV_SCATTER){
			/*from caller to here*/
			sys_vircopy(proc_nr, D, user_vir, SELF, D, buffer, count);
			/*ENCYPT Here - this line no more no less*/
			
			m_dd.m_type=DEV_WRITE;
			m_dd.DEVICE=mp->DEVICE;
			m_dd.m_source=thispid;
			m_dd.COUNT=count;
			m_dd.POSITION=position;
			m_dd.ADDRESS=(vir_bytes)  buffer;	
			if(OK != sendrec(DRVR_PROC_NR, &m_dd))
				panic("CryptDrive","do_wtv messaging failed",s);
			count=m_dd.REP_STATUS;
		}
		
		/* Book the number of bytes transferred. */
        position += count;
        iov->iov_addr += count;
        if ((iov->iov_size -= count) == 0) { iov++; nr_req--; } /* vector done; next request */
	}
	
	/* Copy the I/O vector back to the caller. */
	if (mp->m_source >= 0) {
		sys_datacopy(SELF, (vir_bytes) iovec, 
			mp->m_source, (vir_bytes) mp->ADDRESS, iovec_size);
	}

	mp->m_type = TASK_REPLY;
	mp->REP_PROC_NR = proc_nr;
	mp->m_source=thispid;
	/* Status is ok */
	mp->REP_STATUS = OK;	
	send(device_caller, mp);
	
	return(OK);
}
Beispiel #8
0
static void
do_pipe (vfs_task_t *client, vfsmsg_t *msg) {
    int fd;
    int fp;
    int ino;

    /* Create inode on device */
    msg->cmd = VFS_MKNOD;
    sendrec(devtab[pipedev_idx], msg, sizeof(vfsmsg_t));
    if (msg->mknod.ino < 0) {
        msg->pipe.result = -1;
        return; /* Cannot create node */
    }
    ino = msg->mknod.ino;

    /* Get this new node  2x */
    msg->cmd = VFS_INODE_GRAB;
    msg->iget.ino = ino;
    sendrec(devtab[pipedev_idx], msg, sizeof(vfsmsg_t));

    if (msg->iget.ino < 0) {
        msg->pipe.result = -1;
        return; /* Cannot get node */
    }

    msg->cmd = VFS_INODE_GRAB;
    msg->iget.ino = ino;
    sendrec(devtab[pipedev_idx], msg, sizeof(vfsmsg_t));

    if (msg->iget.ino < 0) {
        msg->pipe.result = -1;
        return; /* Cannot get node */
    }

    /* input */
    fp = find_empty_filp();
    if (fp < 0) {
        msg->pipe.result = -1;
        return;
    }
    fd = find_empty_fd(client);
    if (fd < 0) {
        msg->pipe.result = -1;
        return;
    }
    filp[fp].dev = pipedev_idx;
    filp[fp].ino = ino;
    filp[fp].refcnt++;
    client->fd[fd] = fp;
    msg->pipe.fdi = fd;

    /* output */
    fp = find_empty_filp();
    if (fp < 0) {
        msg->pipe.result = -1;
        return;
    }
    fd = find_empty_fd(client);
    if (fd < 0) {
        msg->pipe.result = -1;
        return;
    }
    filp[fp].dev = pipedev_idx;
    filp[fp].ino = ino;
    filp[fp].refcnt++;
    client->fd[fd] = fp;
    msg->pipe.fdo = fd;

    msg->pipe.result = 0;
    return;
}
Beispiel #9
0
id_t IPCMessage::SendAndReceive(id_t recipient)
{
  return sendrec(recipient, Message());
}