Exemple #1
0
/* check the permissions of a socket file */
static int check_perms(int minor, struct sockaddr_un *addr)
{
	int rc;
	message vfs_m;
	cp_grant_id_t grant_id;

	grant_id = cpf_grant_direct(VFS_PROC_NR, (vir_bytes) addr->sun_path,
					UNIX_PATH_MAX, CPF_READ | CPF_WRITE);

	/* ask the VFS to verify the permissions */
	memset(&vfs_m, '\0', sizeof(message));

	vfs_m.m_type = PFS_REQ_CHECK_PERMS;
	vfs_m.USER_ENDPT = uds_fd_table[minor].owner;
	vfs_m.IO_GRANT = (char *) grant_id;
	vfs_m.COUNT = UNIX_PATH_MAX;

	rc = sendrec(VFS_PROC_NR, &vfs_m);
	cpf_revoke(grant_id);
	if (OK != rc) {
                printf("(uds) sendrec error... req_nr: %d err: %d\n",
			vfs_m.m_type, rc);

		return EIO;
	}

#if DEBUG == 1
	printf("(uds) VFS reply => %d\n", vfs_m.m_type);
	printf("(uds) Canonical Path => %s\n", addr->sun_path);
#endif

	return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
}
Exemple #2
0
/*===========================================================================*
 *				req_newdriver          			     *
 *===========================================================================*/
PUBLIC int req_newdriver(
  endpoint_t fs_e,
  dev_t dev,
  char *label
)
{
  cp_grant_id_t grant_id;
  size_t len;
  message m;
  int r;

  /* Grant access to label */
  len = strlen(label) + 1;
  grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
  if (grant_id == -1)
	panic("req_newdriver: cpf_grant_direct failed");

  /* Fill in request message */
  m.m_type = REQ_NEW_DRIVER;
  m.REQ_DEV = dev;
  m.REQ_GRANT = grant_id;
  m.REQ_PATH_LEN = len;

  /* Issue request */
  r = fs_sendrec(fs_e, &m);

  cpf_revoke(grant_id);

  return(r);
}
Exemple #3
0
PRIVATE int do_invoke_ds(int type, const char *ds_name)
{
	cp_grant_id_t g_key;
	size_t len_key;
	int access, r;

	if(type == DS_CHECK || type == DS_RETRIEVE_LABEL) {
		len_key = DS_MAX_KEYLEN;
		access = CPF_WRITE;
	} else {
		len_key = strlen(ds_name)+1;
		access = CPF_READ;
	}

	/* Grant for key. */
	g_key = cpf_grant_direct(DS_PROC_NR, (vir_bytes) ds_name,
		len_key, access);
	if(!GRANT_VALID(g_key)) 
		return errno;

	m.DS_KEY_GRANT = g_key;
	m.DS_KEY_LEN = len_key;

	r = _taskcall(DS_PROC_NR, type, &m);

	cpf_revoke(g_key);
	return r;
}
Exemple #4
0
/*===========================================================================*
 *				req_link	       			     *
 *===========================================================================*/
PUBLIC int req_link(
  endpoint_t fs_e,
  ino_t link_parent,
  char *lastc,
  ino_t linked_file
)
{
  int r;
  cp_grant_id_t grant_id;
  const size_t len = strlen(lastc) + 1;
  message m;

  grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
  if(grant_id == -1)
	  panic("req_link: cpf_grant_direct failed");

  /* Fill in request message */
  m.m_type = REQ_LINK;
  m.REQ_INODE_NR = linked_file;
  m.REQ_DIR_INO = link_parent;
  m.REQ_GRANT = grant_id;
  m.REQ_PATH_LEN = len;

  /* Send/rec request */
  r = fs_sendrec(fs_e, &m);
  cpf_revoke(grant_id);
  
  return(r);
}
Exemple #5
0
/*===========================================================================*
 *				req_mkdir	      			     *
 *===========================================================================*/
PUBLIC int req_mkdir(
  endpoint_t fs_e,
  ino_t inode_nr,
  char *lastc,
  uid_t uid,
  gid_t gid,
  mode_t dmode
)
{
  int r;
  cp_grant_id_t grant_id;
  size_t len;
  message m;
  
  len = strlen(lastc) + 1;
  grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
  if(grant_id == -1)
	  panic("req_mkdir: cpf_grant_direct failed");

  /* Fill in request message */
  m.m_type = REQ_MKDIR;
  m.REQ_INODE_NR = inode_nr;
  m.REQ_MODE = dmode;
  m.REQ_UID = uid;
  m.REQ_GID = gid;
  m.REQ_GRANT = grant_id;
  m.REQ_PATH_LEN = len;

  /* Send/rec request */
  r = fs_sendrec(fs_e, &m);
  cpf_revoke(grant_id);

  return(r);
}
Exemple #6
0
static int bdev_rdwt_setup(int req, dev_t dev, u64_t pos, char *buf,
  size_t count, int flags, message *m)
{
/* Set up a single-buffer read/write request.
 */
  endpoint_t endpt;
  cp_grant_id_t grant;
  int access;

  assert((ssize_t) count >= 0);

  if ((endpt = bdev_driver_get(dev)) == NONE)
	return EDEADSRCDST;

  access = (req == BDEV_READ) ? CPF_WRITE : CPF_READ;

  grant = cpf_grant_direct(endpt, (vir_bytes) buf, count, access);

  if (!GRANT_VALID(grant)) {
	printf("bdev: unable to allocate grant!\n");
	return EINVAL;
  }

  memset(m, 0, sizeof(*m));
  m->m_type = req;
  m->BDEV_MINOR = minor(dev);
  m->BDEV_POS_LO = ex64lo(pos);
  m->BDEV_POS_HI = ex64hi(pos);
  m->BDEV_COUNT = count;
  m->BDEV_GRANT = grant;
  m->BDEV_FLAGS = flags;

  return OK;
}
Exemple #7
0
/*****************************************************************************
 *         usb_send_urb                                                      *
 ****************************************************************************/
int usb_send_urb(struct usb_urb* urb)
{
	message msg;
	int res;
	cp_grant_id_t gid;
	if (urb == NULL) {
		return EINVAL;
	}

	if (hcd_ep == 0) {
		return EINVAL;
	}

	/* setup grant */
	gid = cpf_grant_direct(hcd_ep,(vir_bytes) &urb->dev_id,
	         urb->urb_size - sizeof(void*),CPF_WRITE|CPF_READ);
	
	if (gid == -1) {
		printf("usb_send_urb: grant failed: "
		      "cpf_grant_direct(%d,%p,%d)\n", hcd_ep, urb, urb->urb_size);
		return EINVAL;
	}
	
	urb->gid = gid; 
	
	/* prepare message */
	msg.m_type         = USB_RQ_SEND_URB;
	msg.USB_GRANT_ID   = gid;
	msg.USB_GRANT_SIZE = urb->urb_size-sizeof(void*);
		
	/* send message */
	res = sendrec(hcd_ep, &msg);

	if (res != 0) {
		panic("usb_send_urb: could not talk to hcd: %d", res);
	}
	
	if (msg.m_type != USB_REPLY) {
		panic("usb_send_urb: got illegal response from hcd: %d", msg.m_type);
	}

	if (msg.USB_RESULT != 0) {
		panic("usb_send_urb: hcd could not enqueue URB: %ld", msg.USB_RESULT);
	}
	
	/* everything ok, add urb to pending_urbs */
	urb->urb_id = msg.USB_URB_ID;
	urb->next = pending_urbs;
	pending_urbs = urb;
	
	/* done. */

	/* (The HCD will send us a message when the URB is completed.) */

	return res;
}
Exemple #8
0
/*===========================================================================*
 *				single_grant				     *
 *===========================================================================*/
static int single_grant(endpoint_t endpt, vir_bytes buf, int access,
                        cp_grant_id_t *gid, iovec_s_t vector[NR_IOREQS], size_t size)
{
    /* Create grants for a vectored request to a single driver.
     */
    cp_grant_id_t grant;
    size_t chunk;
    int count;

    /* Split up the request into chunks, if requested. This makes no
     * difference at all, except that this works around a weird performance
     * bug with large DMA PRDs on some machines.
     */
    if (CHUNK_SIZE > 0) chunk = CHUNK_SIZE;
    else chunk = size;

    /* Fill in the vector, creating a grant for each item. */
    for (count = 0; size > 0 && count < NR_IOREQS; count++) {
        /* The last chunk will contain all the remaining data. */
        if (chunk > size || count == NR_IOREQS - 1)
            chunk = size;

        grant = cpf_grant_direct(endpt, buf, chunk, access);
        if (!GRANT_VALID(grant))
            panic("invalid grant: %d", grant);

        vector[count].iov_grant = grant;
        vector[count].iov_size = chunk;

        buf += chunk;
        size -= chunk;
    }

    /* Then create a grant for the vector itself. */
    *gid = cpf_grant_direct(endpt, (vir_bytes) vector,
                            sizeof(vector[0]) * count, CPF_READ);

    if (!GRANT_VALID(*gid))
        panic("invalid grant: %d", *gid);

    return count;
}
Exemple #9
0
int ds_retrieve_map(const char *ds_name, char *vaddr, size_t *length,
		int nr_snapshot, int flags)
{
	cp_grant_id_t gid;
	int r;

	/* Map a mapped memory range. */
	if(flags & DSMF_MAP_MAPPED) {
		/* Request DS to grant. */
		m.DS_FLAGS = DSF_TYPE_MAP | DSMF_MAP_MAPPED;
		r = do_invoke_ds(DS_RETRIEVE, ds_name);
		if(r != OK)
			return r;

		/* Do the safemap. */
		if(*length > (size_t) m.DS_VAL_LEN)
			*length = (size_t) m.DS_VAL_LEN;
		*length = (size_t) CLICK_FLOOR(*length);
		r = sys_safemap(DS_PROC_NR, m.DS_VAL, 0,
				(vir_bytes)vaddr, *length, D, 0);

	/* Copy mapped memory range or a snapshot. */
	} else if(flags & (DSMF_COPY_MAPPED|DSMF_COPY_SNAPSHOT)) {
		/* Grant for memory range first. */
		gid = cpf_grant_direct(DS_PROC_NR, (vir_bytes)vaddr,
				*length, CPF_WRITE);
		if(!GRANT_VALID(gid))
			return errno;

		m.DS_VAL = gid;
		m.DS_VAL_LEN = *length;
		if(flags & DSMF_COPY_MAPPED) {
			m.DS_FLAGS = DSF_TYPE_MAP | DSMF_COPY_MAPPED;
		}
		else {
			m.DS_NR_SNAPSHOT = nr_snapshot;
			m.DS_FLAGS = DSF_TYPE_MAP | DSMF_COPY_SNAPSHOT;
		}
		r = do_invoke_ds(DS_RETRIEVE, ds_name);
		*length = m.DS_VAL_LEN;
		cpf_revoke(gid);
	}
	else {
		return EINVAL;
	}

	return r;
}
Exemple #10
0
/*===========================================================================*
 *				req_create				     *
 *===========================================================================*/
PUBLIC int req_create(
  int fs_e,
  ino_t inode_nr,
  int omode,
  uid_t uid,
  gid_t gid,
  char *path,
  node_details_t *res
)
{
  int r;
  cp_grant_id_t grant_id;
  size_t len;
  message m;

  if (path[0] == '/')
  	panic("req_create: filename starts with '/'");

  len = strlen(path) + 1;
  grant_id = cpf_grant_direct(fs_e, (vir_bytes) path, len, CPF_READ);
  if (grant_id == -1)
	panic("req_create: cpf_grant_direct failed");

  /* Fill in request message */
  m.m_type	= REQ_CREATE;
  m.REQ_INODE_NR = inode_nr;
  m.REQ_MODE	= omode;
  m.REQ_UID	= uid;
  m.REQ_GID	= gid;
  m.REQ_GRANT	= grant_id;
  m.REQ_PATH_LEN = len;

  /* Send/rec request */
  r = fs_sendrec(fs_e, &m);
  cpf_revoke(grant_id);
  if (r != OK) return(r);

  /* Fill in response structure */
  res->fs_e	= m.m_source;
  res->inode_nr	= m.RES_INODE_NR;
  res->fmode	= m.RES_MODE;
  res->fsize	= m.RES_FILE_SIZE_LO;
  res->uid	= m.RES_UID;
  res->gid	= m.RES_GID;
  res->dev	= m.RES_DEV;
  
  return(OK);
}
Exemple #11
0
/*===========================================================================*
 *				pci_dev_name				     *
 *===========================================================================*/
PUBLIC char *pci_dev_name(u16_t vid, u16_t did)
{
	static char name[PCIINFO_ENTRY_SIZE];	/* We need a better interface for this */

	int r;
	cp_grant_id_t gid;
	message m;

	gid= cpf_grant_direct(pci_procnr, (vir_bytes)name, sizeof(name),
		CPF_WRITE);
	if (gid == -1)
	{
		printf("pci_dev_name: cpf_grant_direct failed: %d\n",
			errno);
		return NULL;
	}

	m.m_type= BUSC_PCI_DEV_NAME_S;
	m.m7_i1= vid;
	m.m7_i2= did;
	m.m7_i3= sizeof(name);
	m.m7_i4= gid;

	r= sendrec(pci_procnr, &m);
	cpf_revoke(gid);
	if (r != 0)
		panic("pci_dev_name: can't talk to PCI: %d", r);

	if (m.m_type == ENOENT)
	{
#if DEBUG
		printf("pci_dev_name: got no name\n");
#endif
		return NULL;	/* No name for this device */
	}
	if (m.m_type != 0)
		panic("pci_dev_name: got bad reply from PCI: %d", m.m_type);

	name[sizeof(name)-1]= '\0';	/* Make sure that the string is NUL
					 * terminated.
					 */

#if DEBUG
	printf("pci_dev_name: got name %s\n", name);
#endif
	return name;
}
Exemple #12
0
/*===========================================================================*
 *				req_getdents	     			     *
 *===========================================================================*/
PUBLIC int req_getdents(
  endpoint_t fs_e,
  ino_t inode_nr,
  u64_t pos,
  char *buf,
  size_t size,
  u64_t *new_pos,
  int direct
)
{
  int r;
  message m;
  cp_grant_id_t grant_id;

  if (direct) {
	grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size,
								CPF_WRITE);
  } else {
	grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size,
								CPF_WRITE);
  }

  if (grant_id < 0)
  	panic("req_getdents: cpf_grant_direct/cpf_grant_magic failed: %d",
								grant_id);

  m.m_type = REQ_GETDENTS;
  m.REQ_INODE_NR = inode_nr;
  m.REQ_GRANT = grant_id;
  m.REQ_MEM_SIZE = size;
  m.REQ_SEEK_POS_LO = ex64lo(pos);
  m.REQ_SEEK_POS_HI = 0;	/* Not used for now, so clear it. */
  
  r = fs_sendrec(fs_e, &m);
  cpf_revoke(grant_id);
  
  if (r == OK) {
	  *new_pos = cvul64(m.RES_SEEK_POS_LO);
	  r = m.RES_NBYTES;
  }

  return(r);
}
Exemple #13
0
int ds_retrieve_mem(const char *ds_name, char *vaddr, size_t *length)
{
	cp_grant_id_t gid;
	int r;

	/* Grant for memory range. */
	gid = cpf_grant_direct(DS_PROC_NR, (vir_bytes)vaddr, *length, CPF_WRITE);
	if(!GRANT_VALID(gid))
		return errno;

	m.DS_VAL = gid;
	m.DS_VAL_LEN = *length;
	m.DS_FLAGS = DSF_TYPE_MEM;
	r = do_invoke_ds(DS_RETRIEVE, ds_name);
	*length = m.DS_VAL_LEN;
	cpf_revoke(gid);

	return r;
}
Exemple #14
0
int ds_publish_mem(const char *ds_name, void *vaddr, size_t length, int flags)
{
	cp_grant_id_t gid;
	int r;

	/* Grant for memory range. */
	gid = cpf_grant_direct(DS_PROC_NR, (vir_bytes)vaddr, length, CPF_READ);
	if(!GRANT_VALID(gid))
		return errno;

	m.DS_VAL = gid;
	m.DS_VAL_LEN = length;
	m.DS_FLAGS = DSF_TYPE_MEM | flags;

	r = do_invoke_ds(DS_PUBLISH, ds_name);
	cpf_revoke(gid);

	return r;
}
Exemple #15
0
/*===========================================================================*
 *				fbd_transfer_direct			     *
 *===========================================================================*/
static ssize_t fbd_transfer_direct(int do_write, u64_t position,
                                   endpoint_t endpt, iovec_t *iov, unsigned int count, int flags)
{
    /* Forward the entire transfer request, without any intervention. */
    iovec_s_t iovec[NR_IOREQS];
    cp_grant_id_t grant;
    message m;
    int i, r;

    for (i = 0; i < count; i++) {
        iovec[i].iov_size = iov[i].iov_size;
        iovec[i].iov_grant = cpf_grant_indirect(driver_endpt, endpt,
                                                iov[i].iov_addr);
        assert(iovec[i].iov_grant != GRANT_INVALID);
    }

    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);

    return m.BDEV_STATUS;
}
Exemple #16
0
/*===========================================================================*
 *				fbd_transfer_direct			     *
 *===========================================================================*/
static ssize_t fbd_transfer_direct(int do_write, u64_t position,
	endpoint_t endpt, iovec_t *iov, unsigned int count, int flags)
{
	/* Forward the entire transfer request, without any intervention. */
	iovec_s_t iovec[NR_IOREQS];
	cp_grant_id_t grant;
	message m;
	int i, r;

	for (i = 0; i < count; i++) {
		iovec[i].iov_size = iov[i].iov_size;
		iovec[i].iov_grant = cpf_grant_indirect(driver_endpt, endpt,
			iov[i].iov_addr);
		assert(iovec[i].iov_grant != GRANT_INVALID);
	}

	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.m_lbdev_lblockdriver_msg.minor = driver_minor;
	m.m_lbdev_lblockdriver_msg.count = count;
	m.m_lbdev_lblockdriver_msg.grant = grant;
	m.m_lbdev_lblockdriver_msg.flags = flags;
	m.m_lbdev_lblockdriver_msg.id = 0;
	m.m_lbdev_lblockdriver_msg.pos = position;

	if ((r = ipc_sendrec(driver_endpt, &m)) != OK)
		panic("ipc_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);

	return m.m_lblockdriver_lbdev_reply.status;
}
Exemple #17
0
/*===========================================================================*
 *				    main				     *
 *===========================================================================*/
int main(int argc, char **argv)
{
	endpoint_t ep_self, ep_requestor, ep_child;
	cp_grant_id_t gid;
	int i, r, pid;
	char *buf;
	int status;

	/* SEF local startup. */
	env_setargs(argc, argv);
	sef_local_startup();

	/* Prepare work. */
	buf = (char*) CLICK_CEIL(buf_buf);
	fid_send = open(FIFO_GRANTOR, O_WRONLY);
	fid_get = open(FIFO_REQUESTOR, O_RDONLY);
	if(fid_get < 0 || fid_send < 0) {
		printf("GRANTOR: can't open fifo files.\n");
		return 1;
	}

	/* Get the requestor's endpoint. */
	read(fid_get, &ep_requestor, sizeof(ep_requestor));
	dprint("GRANTOR: getting requestor's endpoint: %d\n", ep_requestor);

	/* Grant. */
	gid = cpf_grant_direct(ep_requestor, (long)buf, BUF_SIZE,
		CPF_READ | CPF_WRITE | CPF_MAP);
	ep_self = getprocnr();
	dprint("GRANTOR: sending my endpoint %d and gid %d\n", ep_self, gid);
	write(fid_send, &ep_self, sizeof(ep_self));
	write(fid_send, &gid, sizeof(gid));

	/* Test safemap. */
	buf[0] = 0;
	FIFO_NOTIFY(fid_send);
	FIFO_WAIT(fid_get);

	return 0;
}
Exemple #18
0
int
checkperms(endpoint_t endpt, char *path, size_t size)
{
	cp_grant_id_t grant;
	message m;
	int r;

	if ((grant = cpf_grant_direct(VFS_PROC_NR, (vir_bytes) path, size,
	    CPF_READ | CPF_WRITE)) == GRANT_INVALID)
		return ENOMEM;

	memset(&m, 0, sizeof(m));
	m.m_lsys_vfs_checkperms.endpt = endpt;
	m.m_lsys_vfs_checkperms.grant = grant;
	m.m_lsys_vfs_checkperms.count = size;

	r = _taskcall(VFS_PROC_NR, VFS_CHECKPERMS, &m);

	cpf_revoke(grant);

	return r;
}
Exemple #19
0
int ds_publish_map(const char *ds_name, void *vaddr, size_t length, int flags)
{
	cp_grant_id_t gid;
	int r;

	if(((vir_bytes)vaddr % CLICK_SIZE != 0) || (length % CLICK_SIZE != 0))
		return EINVAL;

	/* Grant for mapped memory range. */
	gid = cpf_grant_direct(DS_PROC_NR, (vir_bytes)vaddr, length,
			CPF_READ | CPF_MAP);
	if(!GRANT_VALID(gid))
		return errno;

	m.DS_VAL = gid;
	m.DS_VAL_LEN = length;
	m.DS_FLAGS = DSF_TYPE_MAP | flags;

	r = do_invoke_ds(DS_PUBLISH, ds_name);

	return r;
}
Exemple #20
0
static int bdev_ioctl_setup(dev_t dev, int request, void *buf, message *m)
{
/* Set up an I/O control request.
 */
  endpoint_t endpt;
  size_t size;
  cp_grant_id_t grant;
  int access;

  if ((endpt = bdev_driver_get(dev)) == NONE)
	return EDEADSRCDST;

  if (_MINIX_IOCTL_BIG(request))
	size = _MINIX_IOCTL_SIZE_BIG(request);
  else
	size = _MINIX_IOCTL_SIZE(request);

  access = 0;
  if (_MINIX_IOCTL_IOR(access)) access |= CPF_WRITE;
  if (_MINIX_IOCTL_IOW(access)) access |= CPF_READ;

  /* The size may be 0, in which case 'buf' need not be a valid pointer. */
  grant = cpf_grant_direct(endpt, (vir_bytes) buf, size, access);

  if (!GRANT_VALID(grant)) {
	printf("bdev: unable to allocate grant!\n");
	return EINVAL;
  }

  memset(m, 0, sizeof(*m));
  m->m_type = BDEV_IOCTL;
  m->BDEV_MINOR = minor(dev);
  m->BDEV_REQUEST = request;
  m->BDEV_GRANT = grant;

  return OK;
}
Exemple #21
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;
}
Exemple #22
0
/*===========================================================================*
 *		            sef_cb_init_fresh                                *
 *===========================================================================*/
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
{
/* Initialize the reincarnation server. */
  struct boot_image *ip;
  int s,i;
  int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs;
  struct rproc *rp;
  struct rproc *replica_rp;
  struct rprocpub *rpub;
  struct boot_image image[NR_BOOT_PROCS];
  struct boot_image_priv *boot_image_priv;
  struct boot_image_sys *boot_image_sys;
  struct boot_image_dev *boot_image_dev;
  int pid, replica_pid;
  endpoint_t replica_endpoint;
  int ipc_to;
  int *calls;
  int all_c[] = { ALL_C, NULL_C };
  int no_c[] = {  NULL_C };

  /* See if we run in verbose mode. */
  env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);

  if ((s = sys_getinfo(GET_HZ, &system_hz, sizeof(system_hz), 0, 0)) != OK)
	  panic("Cannot get system timer frequency\n");

  /* Initialize the global init descriptor. */
  rinit.rproctab_gid = cpf_grant_direct(ANY, (vir_bytes) rprocpub,
      sizeof(rprocpub), CPF_READ);
  if(!GRANT_VALID(rinit.rproctab_gid)) {
      panic("unable to create rprocpub table grant: %d", rinit.rproctab_gid);
  }

  /* Initialize some global variables. */
  rupdate.flags = 0;
  shutting_down = FALSE;

  /* Get a copy of the boot image table. */
  if ((s = sys_getimage(image)) != OK) {
      panic("unable to get copy of boot image table: %d", s);
  }

  /* Determine the number of system services in the boot image table. */
  nr_image_srvs = 0;
  for(i=0;i<NR_BOOT_PROCS;i++) {
      ip = &image[i];

      /* System services only. */
      if(iskerneln(_ENDPOINT_P(ip->endpoint))) {
          continue;
      }
      nr_image_srvs++;
  }

  /* Determine the number of entries in the boot image priv table and make sure
   * it matches the number of system services in the boot image table.
   */
  nr_image_priv_srvs = 0;
  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
      boot_image_priv = &boot_image_priv_table[i];

      /* System services only. */
      if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
          continue;
      }
      nr_image_priv_srvs++;
  }
  if(nr_image_srvs != nr_image_priv_srvs) {
	panic("boot image table and boot image priv table mismatch");
  }

  /* Reset the system process table. */
  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
      rp->r_flags = 0;
      rp->r_pub = &rprocpub[rp - rproc];
      rp->r_pub->in_use = FALSE;
  }

  /* Initialize the system process table in 4 steps, each of them following
   * the appearance of system services in the boot image priv table.
   * - Step 1: set priviliges, sys properties, and dev properties (if any)
   * for every system service.
   */
  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
      boot_image_priv = &boot_image_priv_table[i];

      /* System services only. */
      if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
          continue;
      }

      /* Lookup the corresponding entries in other tables. */
      boot_image_info_lookup(boot_image_priv->endpoint, image,
          &ip, NULL, &boot_image_sys, &boot_image_dev);
      rp = &rproc[boot_image_priv - boot_image_priv_table];
      rpub = rp->r_pub;

      /*
       * Set privileges.
       */
      /* Get label. */
      strcpy(rpub->label, boot_image_priv->label);

      /* Force a static priv id for system services in the boot image. */
      rp->r_priv.s_id = static_priv_id(
          _ENDPOINT_P(boot_image_priv->endpoint));
      
      /* Initialize privilege bitmaps and signal manager. */
      rp->r_priv.s_flags = boot_image_priv->flags;          /* priv flags */
      rp->r_priv.s_trap_mask= SRV_OR_USR(rp, SRV_T, USR_T); /* traps */
      ipc_to = SRV_OR_USR(rp, SRV_M, USR_M);                /* targets */
      fill_send_mask(&rp->r_priv.s_ipc_to, ipc_to == ALL_M);
      rp->r_priv.s_sig_mgr= SRV_OR_USR(rp, SRV_SM, USR_SM); /* sig mgr */
      rp->r_priv.s_bak_sig_mgr = NONE;                      /* backup sig mgr */
      
      /* Initialize kernel call mask bitmap. */
      calls = SRV_OR_USR(rp, SRV_KC, USR_KC) == ALL_C ? all_c : no_c;
      fill_call_mask(calls, NR_SYS_CALLS,
          rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE);

      /* Set the privilege structure. */
      if(boot_image_priv->endpoint != RS_PROC_NR) {
          if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv)))
              != OK) {
              panic("unable to set privilege structure: %d", s);
          }
      }

      /* Synch the privilege structure with the kernel. */
      if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) {
          panic("unable to synch privilege structure: %d", s);
      }

      /*
       * Set sys properties.
       */
      rpub->sys_flags = boot_image_sys->flags;        /* sys flags */

      /*
       * Set dev properties.
       */
      rpub->dev_flags = boot_image_dev->flags;        /* device flags */
      rpub->dev_nr = boot_image_dev->dev_nr;          /* major device number */
      rpub->dev_style = boot_image_dev->dev_style;    /* device style */
      rpub->dev_style2 = boot_image_dev->dev_style2;  /* device style 2 */

      /* Get process name. */
      strcpy(rpub->proc_name, ip->proc_name);

      /* Build command settings. */
      rp->r_cmd[0]= '\0';
      rp->r_script[0]= '\0';
      build_cmd_dep(rp);

      /* Initialize vm call mask bitmap. */
      calls = SRV_OR_USR(rp, SRV_VC, USR_VC) == ALL_C ? all_c : no_c;
      fill_call_mask(calls, NR_VM_CALLS, rpub->vm_call_mask, VM_RQ_BASE, TRUE);

      /* Scheduling parameters. */
      rp->r_scheduler = SRV_OR_USR(rp, SRV_SCH, USR_SCH);
      rp->r_priority = SRV_OR_USR(rp, SRV_Q, USR_Q);
      rp->r_quantum = SRV_OR_USR(rp, SRV_QT, USR_QT);

      /* Get some settings from the boot image table. */
      rpub->endpoint = ip->endpoint;

      /* Set some defaults. */
      rp->r_old_rp = NULL;                     /* no old version yet */
      rp->r_new_rp = NULL;                     /* no new version yet */
      rp->r_prev_rp = NULL;                    /* no prev replica yet */
      rp->r_next_rp = NULL;                    /* no next replica yet */
      rp->r_uid = 0;                           /* root */
      rp->r_check_tm = 0;                      /* not checked yet */
      getuptime(&rp->r_alive_tm);              /* currently alive */
      rp->r_stop_tm = 0;                       /* not exiting yet */
      rp->r_restarts = 0;                      /* no restarts so far */
      rp->r_period = 0;                        /* no period yet */
      rp->r_exec = NULL;                       /* no in-memory copy yet */
      rp->r_exec_len = 0;

      /* Mark as in use and active. */
      rp->r_flags = RS_IN_USE | RS_ACTIVE;
      rproc_ptr[_ENDPOINT_P(rpub->endpoint)]= rp;
      rpub->in_use = TRUE;
  }

  /* - Step 2: allow every system service in the boot image to run. */
  nr_uncaught_init_srvs = 0;
  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
      boot_image_priv = &boot_image_priv_table[i];

      /* System services only. */
      if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
          continue;
      }

      /* Lookup the corresponding slot in the system process table. */
      rp = &rproc[boot_image_priv - boot_image_priv_table];
      rpub = rp->r_pub;

      /* RS is already running as we speak. */
      if(boot_image_priv->endpoint == RS_PROC_NR) {
          if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) {
              panic("unable to initialize RS: %d", s);
          }
          continue;
      }

      /* Allow the service to run. */
      if ((s = sched_init_proc(rp)) != OK) {
          panic("unable to initialize scheduling: %d", s);
      }
      if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
          panic("unable to initialize privileges: %d", s);
      }

      /* Initialize service. We assume every service will always get
       * back to us here at boot time.
       */
      if(boot_image_priv->flags & SYS_PROC) {
          if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) {
              panic("unable to initialize service: %d", s);
          }
          if(rpub->sys_flags & SF_SYNCH_BOOT) {
              /* Catch init ready message now to synchronize. */
              catch_boot_init_ready(rpub->endpoint);
          }
          else {
              /* Catch init ready message later. */
              nr_uncaught_init_srvs++;
          }
      }
  }

  /* - Step 3: let every system service complete initialization by
   * catching all the init ready messages left.
   */
  while(nr_uncaught_init_srvs) {
      catch_boot_init_ready(ANY);
      nr_uncaught_init_srvs--;
  }

  /* - Step 4: all the system services in the boot image are now running.
   * Complete the initialization of the system process table in collaboration
   * with other system services.
   */
  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
      boot_image_priv = &boot_image_priv_table[i];

      /* System services only. */
      if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
          continue;
      }

      /* Lookup the corresponding slot in the system process table. */
      rp = &rproc[boot_image_priv - boot_image_priv_table];
      rpub = rp->r_pub;

      /* Get pid from PM. */
      rp->r_pid = getnpid(rpub->endpoint);
      if(rp->r_pid == -1) {
          panic("unable to get pid");
      }
  }

  /* Set alarm to periodically check service status. */
  if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
      panic("couldn't set alarm: %d", s);

  /* Now create a new RS instance with a private page table and let the current
   * instance live update into the replica. Clone RS' own slot first.
   */
  rp = rproc_ptr[_ENDPOINT_P(RS_PROC_NR)];
  if((s = clone_slot(rp, &replica_rp)) != OK) {
      panic("unable to clone current RS instance: %d", s);
  }

  /* Fork a new RS instance. */
  pid = srv_fork();
  if(pid == -1) {
      panic("unable to fork a new RS instance");
  }
  replica_pid = pid ? pid : getpid();
  replica_endpoint = getnprocnr(replica_pid);
  replica_rp->r_pid = replica_pid;
  replica_rp->r_pub->endpoint = replica_endpoint;

  if(pid == 0) {
      /* New RS instance running. */

      /* Live update the old instance into the new one. */
      s = update_service(&rp, &replica_rp, RS_SWAP);
      if(s != OK) {
          panic("unable to live update RS: %d", s);
      }
      cpf_reload();

      /* Clean up the old RS instance, the new instance will take over. */
      cleanup_service(rp);

      /* Map out our own text and data. */
      unmap_ok = 1;
      _minix_unmapzero();

      /* Ask VM to pin memory for the new RS instance. */
      if((s = vm_memctl(RS_PROC_NR, VM_RS_MEM_PIN)) != OK) {
          panic("unable to pin memory for the new RS instance: %d", s);
      }
  }
  else {
      /* Old RS instance running. */

      /* Set up privileges for the new instance and let it run. */
      s = sys_privctl(replica_endpoint, SYS_PRIV_SET_SYS, &(replica_rp->r_priv));
      if(s != OK) {
          panic("unable to set privileges for the new RS instance: %d", s);
      }
      if ((s = sched_init_proc(replica_rp)) != OK) {
          panic("unable to initialize RS replica scheduling: %d", s);
      }
      s = sys_privctl(replica_endpoint, SYS_PRIV_YIELD, NULL);
      if(s != OK) {
          panic("unable to yield control to the new RS instance: %d", s);
      }
      NOT_REACHABLE;
  }

  return(OK);
}
Exemple #23
0
/*===========================================================================*
 *				req_lookup	                   	     *
 *===========================================================================*/
PUBLIC int req_lookup(
  endpoint_t fs_e,
  ino_t dir_ino,
  ino_t root_ino,
  uid_t uid,
  gid_t gid,
  int flags,
  lookup_res_t *res,
  struct fproc *rfp
)
{
  int r;
  size_t len;
  cp_grant_id_t grant_id, grant_id2;
  message m;
  vfs_ucred_t credentials;

  grant_id = cpf_grant_direct(fs_e, (vir_bytes) user_fullpath,
			      sizeof(user_fullpath), CPF_READ | CPF_WRITE);
  if(grant_id == -1)
	  panic("req_lookup: cpf_grant_direct failed");

  len = strlen(user_fullpath) + 1;

  m.m_type		= REQ_LOOKUP;
  m.REQ_GRANT		= grant_id;
  m.REQ_PATH_LEN 	= len;
  m.REQ_PATH_SIZE 	= sizeof(user_fullpath);
  m.REQ_DIR_INO 	= dir_ino;
  m.REQ_ROOT_INO 	= root_ino;

  if(rfp->fp_ngroups > 0) { /* Is the process member of multiple groups? */
  	/* In that case the FS has to copy the uid/gid credentials */
  	int i;

  	/* Set credentials */
  	credentials.vu_uid = rfp->fp_effuid;
  	credentials.vu_gid = rfp->fp_effgid;
  	credentials.vu_ngroups = rfp->fp_ngroups;
  	for (i = 0; i < rfp->fp_ngroups; i++) 
  		credentials.vu_sgroups[i] = rfp->fp_sgroups[i];

	grant_id2 = cpf_grant_direct(fs_e, (vir_bytes) &credentials,
				     sizeof(credentials), CPF_READ);
	if(grant_id2 == -1)
		panic("req_lookup: cpf_grant_direct failed");

	m.REQ_GRANT2	= grant_id2;
	m.REQ_UCRED_SIZE= sizeof(credentials);
  	flags		|= PATH_GET_UCRED;
  } else {
  	/* When there's only one gid, we can send it directly */
	m.REQ_UID	= uid;
	m.REQ_GID	= gid;
	flags		&= ~PATH_GET_UCRED;
  }

  m.REQ_FLAGS		= flags;

  /* Send/rec request */
  r = fs_sendrec(fs_e, &m);
  cpf_revoke(grant_id);
  if(rfp->fp_ngroups > 0) cpf_revoke(grant_id2); 

  /* Fill in response according to the return value */
  res->fs_e = m.m_source;

  switch (r) {
  case OK:
	  res->inode_nr = m.RES_INODE_NR;
	  res->fmode = m.RES_MODE;
	  res->fsize = m.RES_FILE_SIZE_LO;
	  res->dev = m.RES_DEV;
	  res->uid= m.RES_UID;
	  res->gid= m.RES_GID;
	  break;
  case EENTERMOUNT:
	  res->inode_nr = m.RES_INODE_NR;
	  res->char_processed = m.RES_OFFSET;
	  res->symloop = m.RES_SYMLOOP;
	  break;
  case ELEAVEMOUNT:
	  res->char_processed = m.RES_OFFSET;
	  res->symloop = m.RES_SYMLOOP;
	  break;
  case ESYMLINK:
	  res->char_processed = m.RES_OFFSET;
	  res->symloop = m.RES_SYMLOOP;
	  break;
  default:
	  break;
  }
  
  return(r);
}
Exemple #24
0
static int bdev_vrdwt_setup(int req, dev_t dev, u64_t pos, iovec_t *vec,
  int count, int flags, message *m, iovec_s_t *gvec)
{
/* Set up a vectored read/write request.
 */
  ssize_t size;
  endpoint_t endpt;
  cp_grant_id_t grant;
  int i, access;

  assert(count <= NR_IOREQS);

  if ((endpt = bdev_driver_get(dev)) == NONE)
	return EDEADSRCDST;

  access = (req == BDEV_GATHER) ? CPF_WRITE : CPF_READ;
  size = 0;

  for (i = 0; i < count; i++) {
	grant = cpf_grant_direct(endpt, vec[i].iov_addr, vec[i].iov_size,
		access);

	if (!GRANT_VALID(grant)) {
		printf("bdev: unable to allocate grant!\n");

		for (i--; i >= 0; i--)
			cpf_revoke(gvec[i].iov_grant);

		return EINVAL;
	}

	gvec[i].iov_grant = grant;
	gvec[i].iov_size = vec[i].iov_size;

	assert((ssize_t) (size + vec[i].iov_size) > size);

	size += vec[i].iov_size;
  }

  grant = cpf_grant_direct(endpt, (vir_bytes) gvec, sizeof(gvec[0]) * count,
	CPF_READ);

  if (!GRANT_VALID(grant)) {
	printf("bdev: unable to allocate grant!\n");

	for (i = count - 1; i >= 0; i--)
		cpf_revoke(gvec[i].iov_grant);

	return EINVAL;
  }

  memset(m, 0, sizeof(*m));
  m->m_type = req;
  m->BDEV_MINOR = minor(dev);
  m->BDEV_POS_LO = ex64lo(pos);
  m->BDEV_POS_HI = ex64hi(pos);
  m->BDEV_COUNT = count;
  m->BDEV_GRANT = grant;
  m->BDEV_FLAGS = flags;

  return OK;
}
Exemple #25
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.m_lbdev_lblockdriver_msg.minor = driver_minor;
	m.m_lbdev_lblockdriver_msg.count = count;
	m.m_lbdev_lblockdriver_msg.grant = grant;
	m.m_lbdev_lblockdriver_msg.flags = flags;
	m.m_lbdev_lblockdriver_msg.id = 0;
	m.m_lbdev_lblockdriver_msg.pos = position;

	if ((r = ipc_sendrec(driver_endpt, &m)) != OK)
		panic("ipc_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.m_lblockdriver_lbdev_reply.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.m_lblockdriver_lbdev_reply.status;
}
Exemple #26
0
/*===========================================================================*
 *		            sef_cb_init_fresh                                *
 *===========================================================================*/
PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
{
/* Initialize the reincarnation server. */
  struct sigaction sa;
  struct boot_image *ip;
  int s,i,j;
  int nr_image_srvs, nr_image_priv_srvs, nr_uncaught_init_srvs;
  struct rproc *rp;
  struct rprocpub *rpub;
  struct boot_image image[NR_BOOT_PROCS];
  struct mproc mproc[NR_PROCS];
  struct exec header;
  struct boot_image_priv *boot_image_priv;
  struct boot_image_sys *boot_image_sys;
  struct boot_image_dev *boot_image_dev;

  /* See if we run in verbose mode. */
  env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);

  /* Initialize the global init descriptor. */
  rinit.rproctab_gid = cpf_grant_direct(ANY, (vir_bytes) rprocpub,
      sizeof(rprocpub), CPF_READ);
  if(!GRANT_VALID(rinit.rproctab_gid)) {
      panic("RS", "unable to create rprocpub table grant", rinit.rproctab_gid);
  }

  /* Initialize the global update descriptor. */
  rupdate.flags = 0;

  /* Get a copy of the boot image table. */
  if ((s = sys_getimage(image)) != OK) {
      panic("RS", "unable to get copy of boot image table", s);
  }

  /* Determine the number of system services in the boot image table and
   * compute the size required for the boot image buffer.
   */
  nr_image_srvs = 0;
  boot_image_buffer_size = 0;
  for(i=0;i<NR_BOOT_PROCS;i++) {
      ip = &image[i];

      /* System services only. */
      if(iskerneln(_ENDPOINT_P(ip->endpoint))) {
          continue;
      }
      nr_image_srvs++;

      /* Lookup the corresponding entry in the boot image sys table. */
      boot_image_info_lookup(ip->endpoint, image,
          NULL, NULL, &boot_image_sys, NULL);

      /* If we must keep a copy of this system service, read the header
       * and increase the size of the boot image buffer.
       */
      if(boot_image_sys->flags & SF_USE_COPY) {
          if((s = sys_getaoutheader(&header, i)) != OK) {
              panic("RS", "unable to get copy of a.out header", s);
          }
          boot_image_buffer_size += header.a_hdrlen
              + header.a_text + header.a_data;
      }
  }

  /* Determine the number of entries in the boot image priv table and make sure
   * it matches the number of system services in the boot image table.
   */
  nr_image_priv_srvs = 0;
  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
      boot_image_priv = &boot_image_priv_table[i];

      /* System services only. */
      if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
          continue;
      }
      nr_image_priv_srvs++;
  }
  if(nr_image_srvs != nr_image_priv_srvs) {
      panic("RS", "boot image table and boot image priv table mismatch",
          NO_NUM);
  }

  /* Allocate boot image buffer. */
  if(boot_image_buffer_size > 0) {
      boot_image_buffer = rs_startup_sbrk(boot_image_buffer_size);
      if(boot_image_buffer == (char *) -1) {
          panic("RS", "unable to allocate boot image buffer", NO_NUM);
      }
  }

  /* Reset the system process table. */
  for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
      rp->r_flags = 0;
      rp->r_pub = &rprocpub[rp - rproc];
      rp->r_pub->in_use = FALSE;
  }

  /* Initialize the system process table in 4 steps, each of them following
   * the appearance of system services in the boot image priv table.
   * - Step 1: get a copy of the executable image of every system service that
   * requires it while it is not yet running.
   * In addition, set priviliges, sys properties, and dev properties (if any)
   * for every system service.
   */
  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
      boot_image_priv = &boot_image_priv_table[i];

      /* System services only. */
      if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
          continue;
      }

      /* Lookup the corresponding entries in other tables. */
      boot_image_info_lookup(boot_image_priv->endpoint, image,
          &ip, NULL, &boot_image_sys, &boot_image_dev);
      rp = &rproc[boot_image_priv - boot_image_priv_table];
      rpub = rp->r_pub;

      /*
       * Get a copy of the executable image if required.
       */
      rp->r_exec_len = 0;
      rp->r_exec = NULL;
      if(boot_image_sys->flags & SF_USE_COPY) {
          exec_image_copy(ip - image, ip, rp);
      }

      /*
       * Set privileges.
       */
      /* Get label. */
      strcpy(rpub->label, boot_image_priv->label);

      if(boot_image_priv->endpoint != RS_PROC_NR) {
          /* Force a static priv id for system services in the boot image. */
          rp->r_priv.s_id = static_priv_id(
              _ENDPOINT_P(boot_image_priv->endpoint));

          /* Initialize privilege bitmaps. */
          rp->r_priv.s_flags = boot_image_priv->flags;         /* priv flags */
          rp->r_priv.s_trap_mask = boot_image_priv->trap_mask; /* traps */
          memcpy(&rp->r_priv.s_ipc_to, &boot_image_priv->ipc_to,
                            sizeof(rp->r_priv.s_ipc_to));      /* targets */

          /* Initialize kernel call mask bitmap from unordered set. */
          fill_call_mask(boot_image_priv->k_calls, NR_SYS_CALLS,
              rp->r_priv.s_k_call_mask, KERNEL_CALL, TRUE);

          /* Set the privilege structure. */
          if ((s = sys_privctl(ip->endpoint, SYS_PRIV_SET_SYS, &(rp->r_priv)))
              != OK) {
              panic("RS", "unable to set privilege structure", s);
          }
      }

      /* Synch the privilege structure with the kernel. */
      if ((s = sys_getpriv(&(rp->r_priv), ip->endpoint)) != OK) {
          panic("RS", "unable to synch privilege structure", s);
      }

      /*
       * Set sys properties.
       */
      rpub->sys_flags = boot_image_sys->flags;        /* sys flags */

      /*
       * Set dev properties.
       */
      rpub->dev_nr = boot_image_dev->dev_nr;          /* major device number */
      rpub->dev_style = boot_image_dev->dev_style;    /* device style */
      rpub->period = boot_image_dev->period;          /* heartbeat period */

      /* Get process name. */
      strcpy(rpub->proc_name, ip->proc_name);

      /* Get command settings. */
      rp->r_cmd[0]= '\0';
      rp->r_argv[0] = rp->r_cmd;
      rp->r_argv[1] = NULL;
      rp->r_argc = 1;
      rp->r_script[0]= '\0';

      /* Initialize vm call mask bitmap from unordered set. */
      fill_call_mask(boot_image_priv->vm_calls, NR_VM_CALLS,
          rpub->vm_call_mask, VM_RQ_BASE, TRUE);

      /* Get some settings from the boot image table. */
      rp->r_nice = ip->priority;
      rpub->endpoint = ip->endpoint;

      /* Set some defaults. */
      rp->r_uid = 0;                           /* root */
      rp->r_check_tm = 0;                      /* not checked yet */
      getuptime(&rp->r_alive_tm);              /* currently alive */
      rp->r_stop_tm = 0;                       /* not exiting yet */
      rp->r_restarts = 0;                      /* no restarts so far */
      rp->r_set_resources = 0;                 /* don't set resources */

      /* Mark as in use. */
      rp->r_flags = RS_IN_USE;
      rproc_ptr[_ENDPOINT_P(rpub->endpoint)]= rp;
      rpub->in_use = TRUE;
  }

  /* - Step 2: allow every system service in the boot image to run.
   */
  nr_uncaught_init_srvs = 0;
  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
      boot_image_priv = &boot_image_priv_table[i];

      /* System services only. */
      if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
          continue;
      }

      /* Ignore RS. */
      if(boot_image_priv->endpoint == RS_PROC_NR) {
          continue;
      }

      /* Lookup the corresponding slot in the system process table. */
      rp = &rproc[boot_image_priv - boot_image_priv_table];
      rpub = rp->r_pub;

      /* Allow the service to run. */
      if ((s = sys_privctl(rpub->endpoint, SYS_PRIV_ALLOW, NULL)) != OK) {
          panic("RS", "unable to initialize privileges", s);
      }

      /* Initialize service. We assume every service will always get
       * back to us here at boot time.
       */
      if(boot_image_priv->flags & SYS_PROC) {
          if ((s = init_service(rp, SEF_INIT_FRESH)) != OK) {
              panic("RS", "unable to initialize service", s);
          }
          if(rpub->sys_flags & SF_SYNCH_BOOT) {
              /* Catch init ready message now to synchronize. */
              catch_boot_init_ready(rpub->endpoint);
          }
          else {
              /* Catch init ready message later. */
              nr_uncaught_init_srvs++;
          }
      }
  }

  /* - Step 3: let every system service complete initialization by
   * catching all the init ready messages left.
   */
  while(nr_uncaught_init_srvs) {
      catch_boot_init_ready(ANY);
      nr_uncaught_init_srvs--;
  }

  /* - Step 4: all the system services in the boot image are now running.
   * Complete the initialization of the system process table in collaboration
   * with other system processes.
   */
  if ((s = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc)) != OK) {
      panic("RS", "unable to get copy of PM process table", s);
  }
  for (i=0; boot_image_priv_table[i].endpoint != NULL_BOOT_NR; i++) {
      boot_image_priv = &boot_image_priv_table[i];

      /* System services only. */
      if(iskerneln(_ENDPOINT_P(boot_image_priv->endpoint))) {
          continue;
      }

      /* Lookup the corresponding slot in the system process table. */
      rp = &rproc[boot_image_priv - boot_image_priv_table];
      rpub = rp->r_pub;

      /* Get pid from PM process table. */
      rp->r_pid = NO_PID;
      for (j = 0; j < NR_PROCS; j++) {
          if (mproc[j].mp_endpoint == rpub->endpoint) {
              rp->r_pid = mproc[j].mp_pid;
              break;
          }
      }
      if(j == NR_PROCS) {
          panic("RS", "unable to get pid", NO_NUM);
      }
  }

  /*
   * Now complete RS initialization process in collaboration with other
   * system services.
   */
  /* Let the rest of the system know about our dynamically allocated buffer. */
  if(boot_image_buffer_size > 0) {
      boot_image_buffer = rs_startup_sbrk_synch(boot_image_buffer_size);
      if(boot_image_buffer == (char *) -1) {
          panic("RS", "unable to synch boot image buffer", NO_NUM);
      }
  }

  /* Set alarm to periodically check service status. */
  if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
      panic("RS", "couldn't set alarm", s);

  /* Install signal handlers. Ask PM to transform signal into message. */
  sa.sa_handler = SIG_MESS;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno);
  if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno);

  /* Initialize the exec pipe. */
  if (pipe(exec_pipe) == -1)
	panic("RS", "pipe failed", errno);
  if (fcntl(exec_pipe[0], F_SETFD,
	fcntl(exec_pipe[0], F_GETFD) | FD_CLOEXEC) == -1)
  {
	panic("RS", "fcntl set FD_CLOEXEC on pipe input failed", errno);
  }
  if (fcntl(exec_pipe[1], F_SETFD,
	fcntl(exec_pipe[1], F_GETFD) | FD_CLOEXEC) == -1)
  {
	panic("RS", "fcntl set FD_CLOEXEC on pipe output failed", errno);
  }
  if (fcntl(exec_pipe[0], F_SETFL,
	fcntl(exec_pipe[0], F_GETFL) | O_NONBLOCK) == -1)
  {
	panic("RS", "fcntl set O_NONBLOCK on pipe input failed", errno);
  }

 /* Map out our own text and data. This is normally done in crtso.o
  * but RS is an exception - we don't get to talk to VM so early on.
  * That's why we override munmap() and munmap_text() in utility.c.
  *
  * _minix_unmapzero() is the same code in crtso.o that normally does
  * it on startup. It's best that it's there as crtso.o knows exactly
  * what the ranges are of the filler data.
  */
  unmap_ok = 1;
  _minix_unmapzero();

  return(OK);
}