static void do_open (vfs_task_t *client, vfsmsg_t *msg) { int fd; int fp; fd = find_empty_fd(client); if (fd < 0) { msg->openclose.fd = -1; return; } fp = find_empty_filp(); if (fp < 0) { msg->openclose.fd = -1; return; } filp[fp].dev = msg->openclose.dev; filp[fp].ino = msg->openclose.ino; filp[fp].pos = 0; /* Get the node */ msg->cmd = VFS_INODE_GRAB; msg->iget.ino = filp[fp].ino; sendrec(devtab[filp[fp].dev], msg, sizeof(vfsmsg_t)); if (msg->iget.ino < 0) { /* Node not found on dev */ msg->openclose.fd = -1; return; } filp[fp].refcnt++; client->fd[fd] = fp; msg->openclose.fd = fd; return; }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) { /* Initialize the process manager. * Memory use info is collected from the boot monitor, the kernel, and * all processes compiled into the system image. Initially this information * is put into an array mem_chunks. Elements of mem_chunks are struct memory, * and hold base, size pairs in units of clicks. This array is small, there * should be no more than 8 chunks. After the array of chunks has been built * the contents are used to initialize the hole list. Space for the hole list * is reserved as an array with twice as many elements as the maximum number * of processes allowed. It is managed as a linked list, and elements of the * array are struct hole, which, in addition to storage for a base and size in * click units also contain space for a link, a pointer to another element. */ int s; static struct boot_image image[NR_BOOT_PROCS]; register struct boot_image *ip; static char core_sigs[] = { SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT, SIGFPE, SIGBUS, SIGSEGV }; static char ign_sigs[] = { SIGCHLD, SIGWINCH, SIGCONT }; static char noign_sigs[] = { SIGILL, SIGTRAP, SIGEMT, SIGFPE, SIGBUS, SIGSEGV }; register struct mproc *rmp; register char *sig_ptr; message mess; /* Initialize process table, including timers. */ for (rmp=&mproc[0]; rmp<&mproc[NR_PROCS]; rmp++) { init_timer(&rmp->mp_timer); rmp->mp_magic = MP_MAGIC; } /* Build the set of signals which cause core dumps, and the set of signals * that are by default ignored. */ sigemptyset(&core_sset); for (sig_ptr = core_sigs; sig_ptr < core_sigs+sizeof(core_sigs); sig_ptr++) sigaddset(&core_sset, *sig_ptr); sigemptyset(&ign_sset); for (sig_ptr = ign_sigs; sig_ptr < ign_sigs+sizeof(ign_sigs); sig_ptr++) sigaddset(&ign_sset, *sig_ptr); sigemptyset(&noign_sset); for (sig_ptr = noign_sigs; sig_ptr < noign_sigs+sizeof(noign_sigs); sig_ptr++) sigaddset(&noign_sset, *sig_ptr); /* Obtain a copy of the boot monitor parameters and the kernel info struct. * Parse the list of free memory chunks. This list is what the boot monitor * reported, but it must be corrected for the kernel and system processes. */ if ((s=sys_getmonparams(monitor_params, sizeof(monitor_params))) != OK) panic("get monitor params failed: %d", s); if ((s=sys_getkinfo(&kinfo)) != OK) panic("get kernel info failed: %d", s); /* Initialize PM's process table. Request a copy of the system image table * that is defined at the kernel level to see which slots to fill in. */ if (OK != (s=sys_getimage(image))) panic("couldn't get image table: %d", s); procs_in_use = 0; /* start populating table */ for (ip = &image[0]; ip < &image[NR_BOOT_PROCS]; ip++) { if (ip->proc_nr >= 0) { /* task have negative nrs */ procs_in_use += 1; /* found user process */ /* Set process details found in the image table. */ rmp = &mproc[ip->proc_nr]; strlcpy(rmp->mp_name, ip->proc_name, PROC_NAME_LEN); (void) sigemptyset(&rmp->mp_ignore); (void) sigemptyset(&rmp->mp_sigmask); (void) sigemptyset(&rmp->mp_catch); if (ip->proc_nr == INIT_PROC_NR) { /* user process */ /* INIT is root, we make it father of itself. This is * not really OK, INIT should have no father, i.e. * a father with pid NO_PID. But PM currently assumes * that mp_parent always points to a valid slot number. */ rmp->mp_parent = INIT_PROC_NR; rmp->mp_procgrp = rmp->mp_pid = INIT_PID; rmp->mp_flags |= IN_USE; /* Set scheduling info */ rmp->mp_scheduler = KERNEL; rmp->mp_nice = get_nice_value(USR_Q); } else { /* system process */ if(ip->proc_nr == RS_PROC_NR) { rmp->mp_parent = INIT_PROC_NR; } else { rmp->mp_parent = RS_PROC_NR; } rmp->mp_pid = get_free_pid(); rmp->mp_flags |= IN_USE | PRIV_PROC; /* RS schedules this process */ rmp->mp_scheduler = NONE; rmp->mp_nice = get_nice_value(SRV_Q); } /* Get kernel endpoint identifier. */ rmp->mp_endpoint = ip->endpoint; /* Tell VFS about this system process. */ mess.m_type = PM_INIT; mess.PM_SLOT = ip->proc_nr; mess.PM_PID = rmp->mp_pid; mess.PM_PROC = rmp->mp_endpoint; if (OK != (s=send(VFS_PROC_NR, &mess))) panic("can't sync up with VFS: %d", s); } } /* Tell VFS that no more system processes follow and synchronize. */ mess.PR_ENDPT = NONE; if (sendrec(VFS_PROC_NR, &mess) != OK || mess.m_type != OK) panic("can't sync up with VFS"); #if defined(__i386__) uts_val.machine[0] = 'i'; strcpy(uts_val.machine + 1, itoa(getprocessor())); #elif defined(__arm__) strcpy(uts_val.machine, "arm"); #endif system_hz = sys_hz(); /* Initialize user-space scheduling. */ sched_init(); return(OK); }
/*===========================================================================* * 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; }
/*===========================================================================* * fbd_transfer_copy * *===========================================================================*/ static ssize_t fbd_transfer_copy(int do_write, u64_t position, endpoint_t endpt, iovec_t *iov, unsigned int count, size_t size, int flags) { /* Interpose on the request. */ iovec_s_t iovec[NR_IOREQS]; struct vscp_vec vscp_vec[SCPVEC_NR]; cp_grant_id_t grant; size_t off, len; message m; char *ptr; int i, j, r; ssize_t rsize; assert(count > 0 && count <= SCPVEC_NR); if (size > BUF_SIZE) { printf("FBD: allocating memory for %d bytes\n", size); ptr = alloc_contig(size, 0, NULL); assert(ptr != NULL); } else ptr = fbd_buf; /* For write operations, first copy in the data to write. */ if (do_write) { for (i = off = 0; i < count; i++) { len = iov[i].iov_size; vscp_vec[i].v_from = endpt; vscp_vec[i].v_to = SELF; vscp_vec[i].v_gid = iov[i].iov_addr; vscp_vec[i].v_offset = 0; vscp_vec[i].v_addr = (vir_bytes) (ptr + off); vscp_vec[i].v_bytes = len; off += len; } if ((r = sys_vsafecopy(vscp_vec, i)) != OK) panic("vsafecopy failed (%d)\n", r); /* Trigger write hook. */ rule_io_hook(ptr, size, position, FBD_FLAG_WRITE); } /* Allocate grants for the data, in the same chunking as the original * vector. This avoids performance fluctuations with bad hardware as * observed with the filter driver. */ for (i = off = 0; i < count; i++) { len = iov[i].iov_size; iovec[i].iov_size = len; iovec[i].iov_grant = cpf_grant_direct(driver_endpt, (vir_bytes) (ptr + off), len, do_write ? CPF_READ : CPF_WRITE); assert(iovec[i].iov_grant != GRANT_INVALID); off += len; } grant = cpf_grant_direct(driver_endpt, (vir_bytes) iovec, count * sizeof(iovec[0]), CPF_READ); assert(grant != GRANT_INVALID); m.m_type = do_write ? BDEV_SCATTER : BDEV_GATHER; m.BDEV_MINOR = driver_minor; m.BDEV_COUNT = count; m.BDEV_GRANT = grant; m.BDEV_FLAGS = flags; m.BDEV_ID = 0; m.BDEV_POS_LO = ex64lo(position); m.BDEV_POS_HI = ex64hi(position); if ((r = sendrec(driver_endpt, &m)) != OK) panic("sendrec to driver failed (%d)\n", r); if (m.m_type != BDEV_REPLY) panic("invalid reply from driver (%d)\n", m.m_type); cpf_revoke(grant); for (i = 0; i < count; i++) cpf_revoke(iovec[i].iov_grant); /* For read operations, finish by copying out the data read. */ if (!do_write) { /* Trigger read hook. */ rule_io_hook(ptr, size, position, FBD_FLAG_READ); /* Upon success, copy back whatever has been processed. */ rsize = m.BDEV_STATUS; for (i = j = off = 0; rsize > 0 && i < count; i++) { len = MIN(rsize, iov[i].iov_size); vscp_vec[j].v_from = SELF; vscp_vec[j].v_to = endpt; vscp_vec[j].v_gid = iov[i].iov_addr; vscp_vec[j].v_offset = 0; vscp_vec[j].v_addr = (vir_bytes) (ptr + off); vscp_vec[j].v_bytes = len; off += len; rsize -= len; j++; } if (j > 0 && (r = sys_vsafecopy(vscp_vec, j)) != OK) panic("vsafecopy failed (%d)\n", r); } if (ptr != fbd_buf) free_contig(ptr, size); return m.BDEV_STATUS; }
static void serve(struct muth *muth, va_list args) { vavar(struct hthead *, req); vavar(int, fd); vavar(int, sfd); FILE *is, *os, *outi, *outo, *erri, *erro; struct charbuf head; struct hthead *resp; size_t read; char buf[8192]; sfd = reconn(); is = mtstdopen(fd, 1, 60, "r+", NULL); os = mtstdopen(sfd, 1, 600, "r+", NULL); outi = NULL; mtiopipe(&outi, &outo); mtiopipe(&erri, &erro); mustart(outplex, mtstdopen(dup(sfd), 1, 600, "r+", NULL), outo, FCGI_STDOUT, erro, FCGI_STDERR, NULL); mustart(errhandler, erri); if(begreq(os, 1)) goto out; bufinit(head); mkcgienv(req, &head); if(sendrec(os, FCGI_PARAMS, 1, head.b, head.d)) goto out; if(sendrec(os, FCGI_PARAMS, 1, NULL, 0)) goto out; buffree(head); if(fflush(os)) goto out; while(!feof(is)) { read = fread(buf, 1, sizeof(buf), is); if(ferror(is)) goto out; if(sendrec(os, FCGI_STDIN, 1, buf, read)) goto out; } if(sendrec(os, FCGI_STDIN, 1, NULL, 0)) goto out; if(fflush(os)) goto out; if((resp = parseresp(outi)) == NULL) goto out; writeresp(is, resp); freehthead(resp); fputc('\n', is); if(passdata(outi, is) < 0) goto out; out: freehthead(req); buffree(head); shutdown(sfd, SHUT_RDWR); if(outi != NULL) fclose(outi); fclose(is); fclose(os); }
static int begreq(FILE *out, int rid) { char rec[] = {0, 1, 0, 0, 0, 0, 0, 0}; return(sendrec(out, FCGI_BEGIN_REQUEST, rid, rec, 8)); }
/*==========================================================================* * do_vrdwt * *==========================================================================*/ PRIVATE int do_vrdwt(message* mp) /* mp - pointer to read or write message */ { /* Carry out an device read or write to/from a vector of user addresses. * The "user addresses" are assumed to be safe, i.e. FS transferring to/from * its own buffers, so they are not checked. */ static iovec_t iovec[NR_IOREQS]; iovec_t *iov; phys_bytes iovec_size; unsigned nr_req, position; int r; message m_dd; /*message for disk driver*/ nr_req = mp->COUNT; /* Length of I/O vector */ position = mp->POSITION; /* Copy the vector from the caller to kernel space. */ if (nr_req > NR_IOREQS) nr_req = NR_IOREQS; iovec_size = (phys_bytes) (nr_req * sizeof(iovec[0])); if (OK != sys_datacopy(mp->m_source, (vir_bytes) mp->ADDRESS, SELF, (vir_bytes) iovec, iovec_size)) panic("Crypt Drive","bad I/O vector by", s); iov = iovec; while(nr_req>0){ vir_bytes user_vir = iov->iov_addr; /*User program mem addresss*/ unsigned count = iov->iov_size; /* number of byted to copy */ printf("CryptDrive: Size:%d , DST:%d , POS:%d, REQ: %d/%d \n",count, user_vir, position, nr_req, mp->COUNT); if(mp->m_type == DEV_GATHER){ m_dd.m_type=DEV_READ; m_dd.DEVICE=mp->DEVICE; m_dd.m_source=thispid; m_dd.COUNT=count; m_dd.POSITION=position; m_dd.ADDRESS=(vir_bytes) buffer; if(OK != sendrec(DRVR_PROC_NR, &m_dd)) panic("CryptDrive","do_rdv messaging failed",s); /* decrypt here - this line here */ /*from here to caller*/ sys_vircopy(SELF, D, buffer, proc_nr, D, user_vir, m_dd.COUNT); } if(mp->m_type == DEV_SCATTER){ /*from caller to here*/ sys_vircopy(proc_nr, D, user_vir, SELF, D, buffer, count); /*ENCYPT Here - this line no more no less*/ m_dd.m_type=DEV_WRITE; m_dd.DEVICE=mp->DEVICE; m_dd.m_source=thispid; m_dd.COUNT=count; m_dd.POSITION=position; m_dd.ADDRESS=(vir_bytes) buffer; if(OK != sendrec(DRVR_PROC_NR, &m_dd)) panic("CryptDrive","do_wtv messaging failed",s); count=m_dd.REP_STATUS; } /* Book the number of bytes transferred. */ position += count; iov->iov_addr += count; if ((iov->iov_size -= count) == 0) { iov++; nr_req--; } /* vector done; next request */ } /* Copy the I/O vector back to the caller. */ if (mp->m_source >= 0) { sys_datacopy(SELF, (vir_bytes) iovec, mp->m_source, (vir_bytes) mp->ADDRESS, iovec_size); } mp->m_type = TASK_REPLY; mp->REP_PROC_NR = proc_nr; mp->m_source=thispid; /* Status is ok */ mp->REP_STATUS = OK; send(device_caller, mp); return(OK); }
static void do_pipe (vfs_task_t *client, vfsmsg_t *msg) { int fd; int fp; int ino; /* Create inode on device */ msg->cmd = VFS_MKNOD; sendrec(devtab[pipedev_idx], msg, sizeof(vfsmsg_t)); if (msg->mknod.ino < 0) { msg->pipe.result = -1; return; /* Cannot create node */ } ino = msg->mknod.ino; /* Get this new node 2x */ msg->cmd = VFS_INODE_GRAB; msg->iget.ino = ino; sendrec(devtab[pipedev_idx], msg, sizeof(vfsmsg_t)); if (msg->iget.ino < 0) { msg->pipe.result = -1; return; /* Cannot get node */ } msg->cmd = VFS_INODE_GRAB; msg->iget.ino = ino; sendrec(devtab[pipedev_idx], msg, sizeof(vfsmsg_t)); if (msg->iget.ino < 0) { msg->pipe.result = -1; return; /* Cannot get node */ } /* input */ fp = find_empty_filp(); if (fp < 0) { msg->pipe.result = -1; return; } fd = find_empty_fd(client); if (fd < 0) { msg->pipe.result = -1; return; } filp[fp].dev = pipedev_idx; filp[fp].ino = ino; filp[fp].refcnt++; client->fd[fd] = fp; msg->pipe.fdi = fd; /* output */ fp = find_empty_filp(); if (fp < 0) { msg->pipe.result = -1; return; } fd = find_empty_fd(client); if (fd < 0) { msg->pipe.result = -1; return; } filp[fp].dev = pipedev_idx; filp[fp].ino = ino; filp[fp].refcnt++; client->fd[fd] = fp; msg->pipe.fdo = fd; msg->pipe.result = 0; return; }
id_t IPCMessage::SendAndReceive(id_t recipient) { return sendrec(recipient, Message()); }