/* 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. */ }
/*===========================================================================* * 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); }
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; }
/*===========================================================================* * 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); }
/*===========================================================================* * 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); }
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; }
/***************************************************************************** * 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; }
/*===========================================================================* * 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; }
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; }
/*===========================================================================* * 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); }
/*===========================================================================* * 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; }
/*===========================================================================* * 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); }
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; }
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; }
/*===========================================================================* * 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; }
/*===========================================================================* * 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; }
/*===========================================================================* * 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; }
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; }
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; }
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; }
/*===========================================================================* * 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; }
/*===========================================================================* * 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); }
/*===========================================================================* * 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); }
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; }
/*===========================================================================* * 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; }
/*===========================================================================* * 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); }