Пример #1
0
/*===========================================================================*
 *				driver_init				     *
 *===========================================================================*/
void driver_init(void)
{
    /* Initialize the driver layer. */
    int r;

    memset(driver, 0, sizeof(driver));

    /* Endpoints unknown. */
    driver[DRIVER_MAIN].endpt = NONE;
    driver[DRIVER_BACKUP].endpt = NONE;

    /* Get disk driver's and this proc's endpoint. */
    driver[DRIVER_MAIN].label = MAIN_LABEL;
    driver[DRIVER_MAIN].minor = MAIN_MINOR;

    /* No up received yet but expected when the driver starts. */
    driver[DRIVER_MAIN].up_event = UP_EXPECTED;
    driver[DRIVER_BACKUP].up_event = UP_EXPECTED;

    r = ds_retrieve_label_endpt(driver[DRIVER_MAIN].label,
                                &driver[DRIVER_MAIN].endpt);
    if (r != OK) {
        printf("Filter: failed to get main disk driver's endpoint: "
               "%d\n", r);
        bad_driver(DRIVER_MAIN, BD_DEAD, EFAULT);
        check_driver(DRIVER_MAIN);
    }
    else if (driver_open(DRIVER_MAIN) != OK) {
        panic("unhandled driver_open failure");
    }

    if(USE_MIRROR) {
        driver[DRIVER_BACKUP].label = BACKUP_LABEL;
        driver[DRIVER_BACKUP].minor = BACKUP_MINOR;

        if(!strcmp(driver[DRIVER_MAIN].label,
                   driver[DRIVER_BACKUP].label)) {
            panic("same driver: not tested");
        }

        r = ds_retrieve_label_endpt(driver[DRIVER_BACKUP].label,
                                    &driver[DRIVER_BACKUP].endpt);
        if (r != OK) {
            printf("Filter: failed to get backup disk driver's "
                   "endpoint: %d\n", r);
            bad_driver(DRIVER_BACKUP, BD_DEAD, EFAULT);
            check_driver(DRIVER_BACKUP);
        }
        else if (driver_open(DRIVER_BACKUP) != OK) {
            panic("unhandled driver_open failure");
        }
    }
}
Пример #2
0
/*****************************************************************************
 *         usb_init                                                          *
 ****************************************************************************/
int usb_init(char *name) 
{
	int res;
	message msg;

	/* get the endpoint of the HCD */
	res = ds_retrieve_label_endpt("usbd", &hcd_ep);

	if (res != 0) {
		panic("usb_init: ds_retrieve_label_endpt failed for 'usb': %d", res);
	}

	msg.m_type = USB_RQ_INIT;

	strncpy(msg.USB_RB_INIT_NAME, name, M3_LONG_STRING);
	
	res = sendrec(hcd_ep, &msg);

	if (res != 0) {
		panic("usb_init: can't talk to USB: %d", res);
	}

	if (msg.m_type != USB_REPLY) {
		panic("usb_init: bad reply from USB: %d", msg.m_type);
	}

	if (msg.USB_RESULT != 0 ) {
		panic("usb_init: init failed: %ld", msg.USB_RESULT);
	}

	return 0;
}
Пример #3
0
/*===========================================================================*
 *				new_driver_ep				     *
 *===========================================================================*/
static int new_driver_ep(int which)
{
    /* See if a new driver instance has already been started for the given
     * driver, by retrieving its entry from DS.
     */
    int r;
    endpoint_t endpt;

    r = ds_retrieve_label_endpt(driver[which].label, &endpt);

    if (r != OK) {
        printf("Filter: DS query for %s failed\n",
               driver[which].label);

        return 0;
    }

    if (endpt == driver[which].endpt) {
#if DEBUG
        printf("Filter: same endpoint for %s\n", driver[which].label);
#endif
        return 0;
    }

#if DEBUG
    printf("Filter: new enpdoint for %s: %d -> %d\n", driver[which].label,
           driver[which].endpt, endpt);
#endif

    driver[which].endpt = endpt;

    return 1;
}
Пример #4
0
/*===========================================================================*
 *				do_reboot				     *
 *===========================================================================*/
int do_reboot()
{
    message m;

    /* Check permission to abort the system. */
    if (mp->mp_effuid != SUPER_USER) return(EPERM);

    /* See how the system should be aborted. */
    abort_flag = m_in.m_lc_pm_reboot.how;

    /* notify readclock (some arm systems power off via RTC alarms) */
    if (abort_flag & RB_POWERDOWN) {
        endpoint_t readclock_ep;
        if (ds_retrieve_label_endpt("readclock.drv", &readclock_ep) == OK) {
            message m; /* no params to set, nothing we can do if it fails */
            _taskcall(readclock_ep, RTCDEV_PWR_OFF, &m);
        }
    }

    /* Order matters here. When VFS is told to reboot, it exits all its
     * processes, and then would be confused if they're exited again by
     * SIGKILL. So first kill, then reboot.
     */

    check_sig(-1, SIGKILL, FALSE /* ksig*/); /* kill all users except init */
    sys_stop(INIT_PROC_NR);		   /* stop init, but keep it around */

    /* Tell VFS to reboot */
    memset(&m, 0, sizeof(m));
    m.m_type = VFS_PM_REBOOT;

    tell_vfs(&mproc[VFS_PROC_NR], &m);

    return(SUSPEND);			/* don't reply to caller */
}
Пример #5
0
/*===========================================================================*
 *				do_mapdriver		 		     *
 *===========================================================================*/
int do_mapdriver(void)
{
/* Create a device->driver mapping. RS will tell us which major is driven by
 * this driver, what type of device it is (regular, TTY, asynchronous, clone,
 * etc), and its label. This label is registered with DS, and allows us to
 * retrieve the driver's endpoint.
 */
  int r, slot;
  devmajor_t major;
  endpoint_t endpoint;
  vir_bytes label_vir;
  size_t label_len;
  char label[LABEL_MAX];
  struct fproc *rfp;

  /* Only RS can map drivers. */
  if (who_e != RS_PROC_NR) return(EPERM);

  label_vir = job_m_in.m_lsys_vfs_mapdriver.label;
  label_len = job_m_in.m_lsys_vfs_mapdriver.labellen;
  major = job_m_in.m_lsys_vfs_mapdriver.major;

  /* Get the label */
  if (label_len > sizeof(label)) { /* Can we store this label? */
	printf("VFS: do_mapdriver: label too long\n");
	return(EINVAL);
  }
  r = sys_vircopy(who_e, label_vir, SELF, (vir_bytes) label, label_len,
	CP_FLAG_TRY);
  if (r != OK) {
	printf("VFS: do_mapdriver: sys_vircopy failed: %d\n", r);
	return(EINVAL);
  }
  if (label[label_len-1] != '\0') {
	printf("VFS: do_mapdriver: label not null-terminated\n");
	return(EINVAL);
  }

  /* Now we know how the driver is called, fetch its endpoint */
  r = ds_retrieve_label_endpt(label, &endpoint);
  if (r != OK) {
	printf("VFS: do_mapdriver: label '%s' unknown\n", label);
	return(EINVAL);
  }

  /* Process is a service */
  if (isokendpt(endpoint, &slot) != OK) {
	printf("VFS: can't map driver to unknown endpoint %d\n", endpoint);
	return(EINVAL);
  }
  rfp = &fproc[slot];
  rfp->fp_flags |= FP_SRV_PROC;

  /* Try to update device mapping. */
  return map_driver(label, major, endpoint);
}
Пример #6
0
/*===========================================================================*
 *                              do_mount                                     *
 *===========================================================================*/
PUBLIC int do_mount()
{
/* Perform the mount(name, mfile, mount_flags) system call. */
  endpoint_t fs_e;
  int r, slot, rdonly, nodev;
  char fullpath[PATH_MAX];
  char mount_label[LABEL_MAX];
  dev_t dev;

  /* Only the super-user may do MOUNT. */
  if (!super_user) return(EPERM);

  /* FS process' endpoint number */
  if (m_in.mount_flags & MS_LABEL16) {
	/* Get the label from the caller, and ask DS for the endpoint. */
	r = sys_datacopy(who_e, (vir_bytes) m_in.fs_label, SELF,
		(vir_bytes) mount_label, (phys_bytes) sizeof(mount_label));
	if (r != OK) return(r);

	mount_label[sizeof(mount_label)-1] = 0;

	r = ds_retrieve_label_endpt(mount_label, &fs_e);
	if (r != OK) return(r);
  } else {
	/* Legacy support: get the endpoint from the request itself. */
	fs_e = (endpoint_t) m_in.fs_label;
	mount_label[0] = 0;
  }

  /* Sanity check on process number. */
  if (isokendpt(fs_e, &slot) != OK) return(EINVAL);

  /* Should the file system be mounted read-only? */
  rdonly = (m_in.mount_flags & MS_RDONLY);

  /* A null string for block special device means don't use a device at all. */
  nodev = (m_in.name1_length == 0);
  if (!nodev) {
	/* If 'name' is not for a block special file, return error. */
	if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
		return(err_code);
	if ((dev = name_to_dev(FALSE /*allow_mountpt*/, fullpath)) == NO_DEV)
		return(err_code);
  } else {
	/* Find a free pseudo-device as substitute for an actual device. */
	if ((dev = find_free_nonedev()) == NO_DEV)
		return(err_code);
  }

  /* Fetch the name of the mountpoint */
  if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
	return(err_code);

  /* Do the actual job */
  return mount_fs(dev, fullpath, fs_e, rdonly, mount_label);
}
Пример #7
0
/*===========================================================================*
 *				fs_readsuper				     *
 *===========================================================================*/
PUBLIC int fs_readsuper() {

  cp_grant_id_t label_gid;
  size_t label_len;
  int r = OK;
  endpoint_t driver_e;
  int readonly;

  fs_dev    = fs_m_in.REQ_DEV;
  label_gid = fs_m_in.REQ_GRANT;
  label_len = fs_m_in.REQ_PATH_LEN;
  readonly  = 1;			/* Always mount devices read only. */

  if (label_len > sizeof(fs_dev_label)) 
	return(EINVAL);

  r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label,
		       label_len, D);
  if (r != OK) {
	printf("ISOFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r);
	return(EINVAL);
  }

  r = ds_retrieve_label_endpt(fs_dev_label, &driver_e);
  if (r != OK) {
	printf("ISOFS %s:%d ds_retrieve_label_endpt failed for '%s': %d\n",
		__FILE__, __LINE__, fs_dev_label, r);
	return(EINVAL);
  }

  /* Map the driver endpoint for this major */
  driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e =  driver_e;

  /* Open the device the file system lives on */
  if (dev_open(driver_e, fs_dev, driver_e,
	readonly ? R_BIT : (R_BIT|W_BIT)) != OK) {
        return(EINVAL);
  }

  /* Read the superblock */
  r = read_vds(&v_pri, fs_dev);
  if (r != OK)
	return(r);

  /* Return some root inode properties */
  fs_m_out.RES_INODE_NR = ID_DIR_RECORD(v_pri.dir_rec_root);
  fs_m_out.RES_MODE = v_pri.dir_rec_root->d_mode;
  fs_m_out.RES_FILE_SIZE_LO = v_pri.dir_rec_root->d_file_size;
  fs_m_out.RES_UID = SYS_UID; /* Always root */
  fs_m_out.RES_GID = SYS_GID; /* operator */

  fs_m_out.RES_CONREQS = 1;	/* We can handle only 1 request at a time */

  return(r);
}
Пример #8
0
/*===========================================================================*
 *				do_mapdriver		 		     *
 *===========================================================================*/
PUBLIC int do_mapdriver()
{
	int r, flags, major;
	endpoint_t endpoint;
	vir_bytes label_vir;
	size_t label_len;
	char label[LABEL_MAX];

	/* Only RS can map drivers. */
	if (who_e != RS_PROC_NR)
	{
		printf("vfs: unauthorized call of do_mapdriver by proc %d\n",
			who_e);
		return(EPERM);
	}

	/* Get the label */
	label_vir= (vir_bytes)m_in.md_label;
	label_len= m_in.md_label_len;

	if (label_len+1 > sizeof(label))
	{
		printf("vfs:do_mapdriver: label too long\n");
		return EINVAL;
	}

	r= sys_vircopy(who_e, D, label_vir, SELF, D, (vir_bytes)label,
		label_len);
	if (r != OK)
	{
		printf("vfs:do_mapdriver: sys_vircopy failed: %d\n", r);
		return EINVAL;
	}

	label[label_len]= '\0';

	r= ds_retrieve_label_endpt(label, &endpoint);
	if (r != OK)
	{
		printf("vfs:do_mapdriver: ds doesn't know '%s'\n", label);
		return EINVAL;
	}

	/* Try to update device mapping. */
	major= m_in.md_major;
	flags= m_in.md_flags;
	r= map_driver(label, major, endpoint, m_in.md_style, flags);

	return(r);
}
Пример #9
0
endpoint_t bdev_driver_update(dev_t dev)
{
/* Update the endpoint of a driver. The caller of this function already knows
 * that the current endpoint may no longer be valid, and must be updated.
 * Return the new endpoint upon success, and NONE otherwise.
 */
  endpoint_t endpt;
  int r, major, nr_tries;

  major = major(dev);

  assert(major >= 0 && major < NR_DEVICES);
  assert(driver_tab[major].label[0] != '\0');

  /* Repeatedly retrieve the endpoint for the driver label, and see if it is a
   * different, valid endpoint. If retrieval fails at first, we have to wait.
   * We use polling, as opposed to a DS subscription, for a number of reasons:
   * 1) DS supports only one subscription per process, and our main program may
   *    already have a subscription;
   * 2) if we block on receiving a notification from DS, we cannot impose an
   *    upper bound on the retry time;
   * 3) temporarily subscribing and then unsubscribing may cause leftover DS
   *    notifications, which the main program would then have to deal with.
   *    As of writing, unsubscribing from DS is not possible at all, anyway.
   *
   * In the normal case, the driver's label/endpoint mapping entry disappears
   * completely for a short moment, before being replaced with the new mapping.
   * Hence, failure to retrieve the entry at all does not constitute permanent
   * failure. In fact, there is no way to determine reliably that a driver has
   * failed permanently in the current approach. For this we simply rely on the
   * retry limit.
   */
  for (nr_tries = 0; nr_tries < DS_NR_TRIES; nr_tries++) {
	r = ds_retrieve_label_endpt(driver_tab[major].label, &endpt);

	if (r == OK && endpt != NONE && endpt != driver_tab[major].endpt) {
		driver_tab[major].endpt = endpt;

		return endpt;
	}

	if (nr_tries < DS_NR_TRIES - 1)
		micro_delay(DS_DELAY);
  }

  driver_tab[major].endpt = NONE;

  return NONE;
}
Пример #10
0
/*===========================================================================*
 *				pci_init				     *
 *===========================================================================*/
PUBLIC void pci_init(void)
{
	int r;
	message m;

	r= ds_retrieve_label_endpt("pci", &pci_procnr);
	if (r != 0)
		panic("pci_init: unable to obtain label for 'pci': %d", r);

	m.m_type= BUSC_PCI_INIT;
	r= sendrec(pci_procnr, &m);
	if (r != 0)
		panic("pci_init: can't talk to PCI: %d", r);
	if (m.m_type != 0)
		panic("pci_init: got bad reply from PCI: %d", m.m_type);
}
Пример #11
0
/*
 * Perform synchronous communication with PTYFS, if PTYFS is actually running.
 * This function is expected to return only once PTYFS has acknowledged
 * processing the request, in order to avoid race conditions between PTYFS and
 * userland.  The function must always fail when PTYFS is not available for any
 * reason.  Return OK on success, or an IPC-level error on failure.
 */
static int
ptyfs_sendrec(message * m_ptr)
{
    endpoint_t endpt;

    /*
     * New pseudoterminals are created sufficiently rarely that we need not
     * optimize this by for example caching the PTYFS endpoint,  especially
     * since caching brings along new issues, such as having to reissue the
     * request if the cached endpoint turns out to be outdated (e.g., when
     * ptyfs is unmounted and remounted for whatever reason).
     */
    if (ds_retrieve_label_endpt("ptyfs", &endpt) != OK)
        return EDEADSRCDST; /* ptyfs is not available */

    return ipc_sendrec(endpt, m_ptr);
}
Пример #12
0
/*===========================================================================*
 *				do_mapdriver		 		     *
 *===========================================================================*/
int do_mapdriver()
{
/* Create a device->driver mapping. RS will tell us which major is driven by
 * this driver, what type of device it is (regular, TTY, asynchronous, clone,
 * etc), and its label. This label is registered with DS, and allows us to
 * retrieve the driver's endpoint.
 */
  int r, flags, major, style;
  endpoint_t endpoint;
  vir_bytes label_vir;
  size_t label_len;
  char label[LABEL_MAX];

  /* Only RS can map drivers. */
  if (who_e != RS_PROC_NR) return(EPERM);

  label_vir = (vir_bytes) job_m_in.md_label;
  label_len = (size_t) job_m_in.md_label_len;
  major = job_m_in.md_major;
  flags = job_m_in.md_flags;
  style = job_m_in.md_style;

  /* Get the label */
  if (label_len+1 > sizeof(label)) { /* Can we store this label? */
	printf("VFS: do_mapdriver: label too long\n");
	return(EINVAL);
  }
  r = sys_vircopy(who_e, label_vir, SELF, (vir_bytes) label, label_len);
  if (r != OK) {
	printf("VFS: do_mapdriver: sys_vircopy failed: %d\n", r);
	return(EINVAL);
  }
  label[label_len] = '\0';	/* Terminate label */

  /* Now we know how the driver is called, fetch its endpoint */
  r = ds_retrieve_label_endpt(label, &endpoint);
  if (r != OK) {
	printf("VFS: do_mapdriver: label '%s' unknown\n", label);
	return(EINVAL);
  }

  /* Try to update device mapping. */
  return map_driver(label, major, endpoint, style, flags);
}
Пример #13
0
/*===========================================================================*
 *				test_label				     *
 *===========================================================================*/
void test_label(void)
{
	int r;
	char label[DS_MAX_KEYLEN];
	endpoint_t endpoint;

	/* Retrieve own label and endpoint. */
	r = ds_retrieve_label_name(label, getprocnr());
	assert(r == OK);
	r = ds_retrieve_label_endpt(label, &endpoint);
	assert(r == OK && endpoint == getprocnr());

	/* Publish and delete. */
	r = ds_publish_label(label, endpoint, 0);
	assert(r == EPERM);
	r = ds_delete_label(label);
	assert(r == EPERM);

	printf("DSTEST: LABEL test successful!\n");
}
Пример #14
0
/*===========================================================================*
 *				sef_cb_init_fresh			     *
 *===========================================================================*/
static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
{
	clock_t uptime;
	int r;

	/* Parse the given parameters. */
	if (env_argc > 1)
		optset_parse(optset_table, env_argv[1]);

	if (driver_label[0] == '\0')
		panic("no driver label given");

	if (ds_retrieve_label_endpt(driver_label, &driver_endpt))
		panic("unable to resolve driver label");

	if (driver_minor > 255)
		panic("no or invalid driver minor given");

#if DEBUG
	printf("FBD: driver label '%s' (endpt %d), minor %d\n",
		driver_label, driver_endpt, driver_minor);
#endif

	/* Initialize resources. */
	fbd_buf = alloc_contig(BUF_SIZE, 0, NULL);

	assert(fbd_buf != NULL);

	if ((r = getticks(&uptime)) != OK)
		panic("getuptime failed (%d)\n", r);

	srand48(uptime);

	/* Announce we are up! */
	blockdriver_announce(type);

	return OK;
}
Пример #15
0
/*===========================================================================*
 *				fs_readsuper				     *
 *===========================================================================*/
PUBLIC int fs_readsuper()
{
/* This function reads the superblock of the partition, gets the root inode
 * and sends back the details of them. Note, that the FS process does not
 * know the index of the vmnt object which refers to it, whenever the pathname 
 * lookup leaves a partition an ELEAVEMOUNT error is transferred back 
 * so that the VFS knows that it has to find the vnode on which this FS 
 * process' partition is mounted on.
 */
  struct inode *root_ip;
  cp_grant_id_t label_gid;
  size_t label_len;
  int r;
  endpoint_t driver_e;
  int readonly, isroot;

  fs_dev    = (dev_t) fs_m_in.REQ_DEV;
  label_gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
  label_len = (size_t) fs_m_in.REQ_PATH_LEN;
  readonly  = (fs_m_in.REQ_FLAGS & REQ_RDONLY) ? 1 : 0;
  isroot    = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0;

  if (label_len > sizeof(fs_dev_label))
	return(EINVAL);

  r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0,
		       (vir_bytes) fs_dev_label, label_len, D);
  if (r != OK) {
	printf("MFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r);
	return(EINVAL);
  }

  r = ds_retrieve_label_endpt(fs_dev_label, &driver_e);
  if (r != OK) {
	printf("MFS %s:%d ds_retrieve_label_endpt failed for '%s': %d\n",
		__FILE__, __LINE__, fs_dev_label, r);
	return(EINVAL);
  }

  /* Map the driver endpoint for this major */
  bdev_driver(fs_dev, driver_e);

  /* Open the device the file system lives on. */
  if (bdev_open(fs_dev, readonly ? R_BIT : (R_BIT|W_BIT) ) != OK) {
        return(EINVAL);
  }
  
  /* Fill in the super block. */
  superblock.s_dev = fs_dev;	/* read_super() needs to know which dev */
  r = read_super(&superblock);

  /* Is it recognized as a Minix filesystem? */
  if (r != OK) {
	superblock.s_dev = NO_DEV;
	bdev_close(fs_dev);
	return(r);
  }

  set_blocksize(&superblock);
  
  /* Get the root inode of the mounted file system. */
  if( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NULL)  {
	printf("MFS: couldn't get root inode\n");
	superblock.s_dev = NO_DEV;
	bdev_close(fs_dev);
	return(EINVAL);
  }
  
  if(root_ip->i_mode == 0) {
	printf("%s:%d zero mode for root inode?\n", __FILE__, __LINE__);
	put_inode(root_ip);
	superblock.s_dev = NO_DEV;
	bdev_close(fs_dev);
	return(EINVAL);
  }

  superblock.s_rd_only = readonly;
  superblock.s_is_root = isroot;
  
  /* Root inode properties */
  fs_m_out.RES_INODE_NR = root_ip->i_num;
  fs_m_out.RES_MODE = root_ip->i_mode;
  fs_m_out.RES_FILE_SIZE_LO = root_ip->i_size;
  fs_m_out.RES_UID = root_ip->i_uid;
  fs_m_out.RES_GID = root_ip->i_gid;

  fs_m_out.RES_CONREQS = 1;	/* We can handle only 1 request at a time */

  return(r);
}