Exemple #1
0
static int
strategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf,
    size_t *rsize)
{
	struct of_dev *dev = devdata;
	u_quad_t pos;
	int n;
	
	if (rw != F_READ)
		return EPERM;
	if (dev->type != OFDEV_DISK)
		panic("strategy");
	
	DNPRINTF(BOOT_D_OFDEV, "strategy: block %lx, partition offset %lx, "
	    "blksz %lx\n", (long)blk, (long)dev->partoff, (long)dev->bsize);
	DNPRINTF(BOOT_D_OFDEV, "strategy: seek position should be: %lx\n", 
	    (long)((blk + dev->partoff) * dev->bsize));
	pos = (u_quad_t)(blk + dev->partoff) * dev->bsize;
	
	for (;;) {
		DNPRINTF(BOOT_D_OFDEV, "strategy: seeking to %lx\n", (long)pos);
		if (OF_seek(dev->handle, pos) < 0)
			break;
		DNPRINTF(BOOT_D_OFDEV, "strategy: reading %lx at %p\n",
		    (long)size, buf);
		n = OF_read(dev->handle, buf, size);
		if (n == -2)
			continue;
		if (n < 0)
			break;
		*rsize = n;
		return 0;
	}
	return EIO;
}
Exemple #2
0
int
load_disklabel(struct of_dev *ofdev, struct disklabel *label)
{
	char buf[DEV_BSIZE];
	size_t read;
	int error = 0;
	char *errmsg = NULL;

	/* First try to find a disklabel without MBR partitions */
	DNPRINTF(BOOT_D_OFDEV, "load_disklabel: trying to read disklabel\n");
	if (strategy(ofdev, F_READ,
		     LABELSECTOR, DEV_BSIZE, buf, &read) != 0
	    || read != DEV_BSIZE
	    || (errmsg = getdisklabel(buf, label))) {
#ifdef BOOT_DEBUG
		if (errmsg)
			DNPRINTF(BOOT_D_OFDEV,
			    "load_disklabel: getdisklabel says %s\n", errmsg);
#endif
		/* Else try MBR partitions */
		errmsg = search_label(ofdev, LABELSECTOR, buf,
		    label, 0);
		if (errmsg) { 
			printf("load_disklabel: search_label says %s\n",
			    errmsg);
			error = ERDLAB;
		}
	}

	return (error);
}
int
spec_open_clone(struct vop_open_args *ap)
{
	struct vnode *cvp, *vp = ap->a_vp;
	struct cloneinfo *cip;
	int error, i;

	DNPRINTF("cloning vnode\n");

	if (minor(vp->v_rdev) >= (1 << CLONE_SHIFT))
		return (ENXIO);

	for (i = 1; i < sizeof(vp->v_specbitmap) * NBBY; i++)
		if (isclr(vp->v_specbitmap, i)) {
			setbit(vp->v_specbitmap, i);
			break;
		}

	if (i == sizeof(vp->v_specbitmap) * NBBY)
		return (EBUSY); /* too many open instances */

	error = cdevvp(makedev(major(vp->v_rdev),
	    (i << CLONE_SHIFT) | minor(vp->v_rdev)), &cvp);
	if (error) {
		clrbit(vp->v_specbitmap, i);
		return (error); /* out of vnodes */
	}

	VOP_UNLOCK(vp, 0, ap->a_p);

	error = cdevsw[major(vp->v_rdev)].d_open(cvp->v_rdev, ap->a_mode,
	    S_IFCHR, ap->a_p);

	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_p);

	if (error) {
		vput(cvp);
		clrbit(vp->v_specbitmap, i);
		return (error); /* device open failed */
	}

	cvp->v_flag |= VCLONE;

	cip = malloc(sizeof(struct cloneinfo), M_TEMP, M_WAITOK);
	cip->ci_data = vp->v_data;
	cip->ci_vp = cvp;

	cvp->v_specparent = vp;
	vp->v_flag |= VCLONED;
	vp->v_data = cip;

	DNPRINTF("clone of vnode %p is vnode %p\n", vp, cvp);

	return (0); /* device cloned */
}
Exemple #4
0
/*
 * Find a valid disklabel.
 */
static char *
search_label(struct of_dev *devp, u_long off, char *buf, struct disklabel *lp,
    u_long off0)
{
	size_t read;
	struct mbr_partition *p;
	int i;
	u_long poff;
	static int recursion;

	struct disklabel *dlp;
	struct sun_disklabel *slp;
	int error;
	
	/* minimal requirements for archetypal disk label */
	if (lp->d_secperunit == 0)
		lp->d_secperunit = 0x1fffffff;
	lp->d_npartitions = MAXPARTITIONS;
	if (lp->d_partitions[0].p_size == 0)
		lp->d_partitions[0].p_size = 0x1fffffff;
	lp->d_partitions[0].p_offset = 0;

	if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
	    || read != DEV_BSIZE)
		return ("Cannot read label");

	/* Check for a disk label. */
	dlp = (struct disklabel *) (buf + LABELOFFSET);
	if (dlp->d_magic == DISKMAGIC) {
		if (dkcksum(dlp))
			return ("corrupt disk label");
		*lp = *dlp;
		DNPRINTF(BOOT_D_OFDEV, "search_label: found disk label\n");
		return (NULL);
	}

	/* Check for a Sun disk label (for PROM compatibility). */
	slp = (struct sun_disklabel *)buf;
	if (slp->sl_magic == SUN_DKMAGIC) {
		if (disklabel_sun_to_bsd(slp, lp) != 0)
			return ("corrupt disk label");
		DNPRINTF(BOOT_D_OFDEV, "search_label: found disk label\n");
		return (NULL);
	}

	bzero(buf, sizeof(buf));
	return ("no disk label");
}
Exemple #5
0
int
vndclose(dev_t dev, int flags, int mode, struct proc *p)
{
	int unit = DISKUNIT(dev);
	struct vnd_softc *sc;
	int part;

	DNPRINTF(VDB_FOLLOW, "vndclose(%x, %x, %x, %p)\n", dev, flags, mode, p);

	if (unit >= numvnd)
		return (ENXIO);
	sc = &vnd_softc[unit];

	disk_lock_nointr(&sc->sc_dk);

	part = DISKPART(dev);

	disk_closepart(&sc->sc_dk, part, mode);

#if 0
	if (sc->sc_dk.dk_openmask == 0)
		sc->sc_flags &= ~VNF_HAVELABEL;
#endif

	disk_unlock(&sc->sc_dk);
	return (0);
}
Exemple #6
0
static char *
filename(char *str, char *ppart)
{
	char *cp, *lp;
	char savec;
	int dhandle;
	char devtype[16];
	
	lp = str;
	devtype[0] = 0;
	*ppart = 0;
	for (cp = str; *cp; lp = cp) {
		/* For each component of the path name... */
		while (*++cp && *cp != '/');
		savec = *cp;
		*cp = 0;
		/* ...look whether there is a device with this name */
		dhandle = OF_finddevice(str);
		DNPRINTF(BOOT_D_OFDEV, "filename: OF_finddevice(%s) says %x\n",
		    str, dhandle);
		*cp = savec;
		if (dhandle == -1) {
			/* if not, lp is the delimiter between device and path */
			/* if the last component was a block device... */
			if (!strcmp(devtype, "block")) {
				/* search for arguments */
				DNPRINTF(BOOT_D_OFDEV, "filename: hunting for "
				    "arguments in %s\n", str);
				for (cp = lp;
				     --cp >= str && *cp != '/' && *cp != '-';);
				if (cp >= str && *cp == '-') {
					/* found arguments, make firmware ignore them */
					*cp = 0;
					for (cp = lp; *--cp && *cp != ',';);
					if (*++cp >= 'a' && *cp <= 'a' + MAXPARTITIONS)
						*ppart = *cp;
				}
			}
			DNPRINTF(BOOT_D_OFDEV, "filename: found %s\n", lp);
			return lp;
		} else if (OF_getprop(dhandle, "device_type", devtype, sizeof devtype) < 0)
			devtype[0] = 0;
	}
	DNPRINTF(BOOT_D_OFDEV, "filename: not found\n", lp);
	return 0;
}
Exemple #7
0
/*
 * cancel, remove, etc. downloads
 */
void
xtp_handle_dl(struct tab *t, uint8_t cmd, int id)
{
	struct download		find, *d = NULL;

	DNPRINTF(XT_D_DOWNLOAD, "download control: cmd %d, id %d\n", cmd, id);

	/* some commands require a valid download id */
	if (cmd != XT_XTP_DL_LIST) {
		/* lookup download in question */
		find.id = id;
		d = RB_FIND(download_list, &downloads, &find);

		if (d == NULL) {
			show_oops(t, "%s: no such download", __func__);
			return;
		}
	}

	/* decide what to do */
	switch (cmd) {
	case XT_XTP_DL_START:
		/* our downloads always needs to be
		 * restarted if called from here
		 */
		download_start(t, d, XT_DL_RESTART);
		break;
	case XT_XTP_DL_CANCEL:
		webkit_download_cancel(d->download);
		g_object_unref(d->download);
		RB_REMOVE(download_list, &downloads, d);
		break;
	case XT_XTP_DL_UNLINK:
#ifdef __MINGW32__
		unlink(webkit_download_get_destination_uri(d->download));
#else
		unlink(webkit_download_get_destination_uri(d->download) +
		    strlen("file://"));
#endif
		/* FALLTHROUGH */
	case XT_XTP_DL_REMOVE:
		webkit_download_cancel(d->download); /* just incase */
		g_object_unref(d->download);
		RB_REMOVE(download_list, &downloads, d);
		break;
	case XT_XTP_DL_LIST:
		/* Nothing */
		break;
	default:
		show_oops(t, "%s: unknown command", __func__);
		break;
	};
	xtp_page_dl(t, NULL);
}
Exemple #8
0
int
strategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf,
    size_t *rsize)
{
	struct of_dev *dev = devdata;
	u_quad_t pos;
	int n;
	
	if (rw != F_READ)
		return EPERM;
#ifdef SOFTRAID
	/* Intercept strategy for softraid volumes. */
	if (dev->type == OFDEV_SOFTRAID)
		return sr_strategy(bootdev_dip->sr_vol, rw,
		    blk, size, buf, rsize);
#endif
	if (dev->type != OFDEV_DISK)
		panic("strategy");
	
	DNPRINTF(BOOT_D_OFDEV, "strategy: block %lx, partition offset %lx, "
	    "blksz %lx\n", (long)blk, (long)dev->partoff, (long)dev->bsize);
	DNPRINTF(BOOT_D_OFDEV, "strategy: seek position should be: %lx\n", 
	    (long)((blk + dev->partoff) * dev->bsize));
	pos = (u_quad_t)(blk + dev->partoff) * dev->bsize;
	
	for (;;) {
		DNPRINTF(BOOT_D_OFDEV, "strategy: seeking to %lx\n", (long)pos);
		if (OF_seek(dev->handle, pos) < 0)
			break;
		DNPRINTF(BOOT_D_OFDEV, "strategy: reading %lx at %p\n",
		    (long)size, buf);
		n = OF_read(dev->handle, buf, size);
		if (n == -2)
			continue;
		if (n < 0)
			break;
		*rsize = n;
		return 0;
	}
	return EIO;
}
Exemple #9
0
void
print_cookie(char *msg, SoupCookie *c)
{
	if (c == NULL)
		return;

	if (msg) {
		DNPRINTF(XT_D_COOKIE, "%s\n", msg);
	}

	DNPRINTF(XT_D_COOKIE, "name     : %s\n", c->name);
	DNPRINTF(XT_D_COOKIE, "value    : %s\n", c->value);
	DNPRINTF(XT_D_COOKIE, "domain   : %s\n", c->domain);
	DNPRINTF(XT_D_COOKIE, "path     : %s\n", c->path);
	DNPRINTF(XT_D_COOKIE, "expires  : %s\n",
	    c->expires ? soup_date_to_string(c->expires, SOUP_DATE_HTTP) : "");
	DNPRINTF(XT_D_COOKIE, "secure   : %d\n", c->secure);
	DNPRINTF(XT_D_COOKIE, "http_only: %d\n", c->http_only);
	DNPRINTF(XT_D_COOKIE, "====================================\n");
}
Exemple #10
0
int
mfi_pci_find_device(void *aux) {
	struct pci_attach_args	*pa = aux;
	int			i;

	for (i = 0; mfi_pci_devices[i].mpd_vendor; i++) {
		if (mfi_pci_devices[i].mpd_vendor == PCI_VENDOR(pa->pa_id) &&
		    mfi_pci_devices[i].mpd_product == PCI_PRODUCT(pa->pa_id)) {
		    	DNPRINTF(MFI_D_MISC, "mfi_pci_find_device: %i\n", i);
			return (i);
		}
	}

	return (-1);
}
Exemple #11
0
int
mfi_pci_match(struct device *parent, void *match, void *aux)
{
	int			i;

	if ((i = mfi_pci_find_device(aux)) != -1) {
		DNPRINTF(MFI_D_MISC,
		    "mfi_pci_match: vendor: %04x  product: %04x\n",
		    mfi_pci_devices[i].mpd_vendor,
		    mfi_pci_devices[i].mpd_product);

		return (1);
	}

	return (0);
}
Exemple #12
0
/*
 * generate a session key to secure xtp commands.
 * pass in a ptr to the key in question and it will
 * be modified in place.
 */
void
generate_xtp_session_key(char **key)
{
	uint8_t			rand_bytes[XT_XTP_SES_KEY_SZ];

	/* free old key */
	if (*key)
		g_free(*key);

	/* make a new one */
	arc4random_buf(rand_bytes, XT_XTP_SES_KEY_SZ);
	*key = g_strdup_printf(XT_XTP_SES_KEY_HEX_FMT,
	    rand_bytes[0], rand_bytes[1], rand_bytes[2], rand_bytes[3],
	    rand_bytes[4], rand_bytes[5], rand_bytes[6], rand_bytes[7]);

	DNPRINTF(XT_D_DOWNLOAD, "%s: new session key '%s'\n", __func__, *key);
}
Exemple #13
0
size_t
vndbdevsize(struct vnode *vp, struct proc *p)
{
	struct partinfo pi;
	struct bdevsw *bsw;
	dev_t dev;

	dev = vp->v_rdev;
	bsw = bdevsw_lookup(dev);
	if (bsw->d_ioctl == NULL)
		return (0);
	if (bsw->d_ioctl(dev, DIOCGPART, (caddr_t)&pi, FREAD, p))
		return (0);
	DNPRINTF(VDB_INIT, "vndbdevsize: size %llu secsize %u\n",
	    DL_GETPSIZE(pi.part), pi.disklab->d_secsize);
	return (DL_GETPSIZE(pi.part));
}
Exemple #14
0
void
vndclear(struct vnd_softc *sc)
{
	struct vnode *vp = sc->sc_vp;
	struct proc *p = curproc;		/* XXX */

	DNPRINTF(VDB_FOLLOW, "vndclear(%p): vp %p\n", sc, vp);

	if (vp == NULL)
		panic("vndioctl: null vp");
	(void) vn_close(vp, VNDRW(sc), sc->sc_cred, p);
	crfree(sc->sc_cred);
	sc->sc_flags = 0;
	sc->sc_vp = NULL;
	sc->sc_cred = NULL;
	sc->sc_size = 0;
	memset(sc->sc_file, 0, sizeof(sc->sc_file));
}
Exemple #15
0
int
vndopen(dev_t dev, int flags, int mode, struct proc *p)
{
	int unit = DISKUNIT(dev);
	struct vnd_softc *sc;
	int error = 0, part;

	DNPRINTF(VDB_FOLLOW, "vndopen(%x, %x, %x, %p)\n", dev, flags, mode, p);

	if (unit >= numvnd)
		return (ENXIO);
	sc = &vnd_softc[unit];

	if ((error = disk_lock(&sc->sc_dk)) != 0)
		return (error);

	if ((flags & FWRITE) && (sc->sc_flags & VNF_READONLY)) {
		error = EROFS;
		goto bad;
	}

	if ((sc->sc_flags & VNF_INITED) &&
	    (sc->sc_flags & VNF_HAVELABEL) == 0 &&
	    sc->sc_dk.dk_openmask == 0) {
		sc->sc_flags |= VNF_HAVELABEL;
		vndgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0);
	}

	part = DISKPART(dev);
	error = disk_openpart(&sc->sc_dk, part, mode,
	    (sc->sc_flags & VNF_HAVELABEL) != 0);

bad:
	disk_unlock(&sc->sc_dk);
	return (error);
}
Exemple #16
0
/*
 * Given a SunOS disk label, set lp to a BSD disk label.
 * The BSD label is cleared out before this is called.
 */
static int
disklabel_sun_to_bsd(struct sun_disklabel *sl, struct disklabel *lp)
{
	struct sun_preamble *preamble = (struct sun_preamble *)sl;
	struct sun_partinfo *ppp;
	struct sun_dkpart *spp;
	struct partition *npp;
	u_short cksum = 0, *sp1, *sp2;
	int i, secpercyl;

	/* Verify the XOR check. */
	sp1 = (u_short *)sl;
	sp2 = (u_short *)(sl + 1);
	while (sp1 < sp2)
		cksum ^= *sp1++;
	if (cksum != 0)
		return (EINVAL);	/* SunOS disk label, bad checksum */

	/* Format conversion. */
	lp->d_magic = DISKMAGIC;
	lp->d_magic2 = DISKMAGIC;
	lp->d_flags = D_VENDOR;
	memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));

	lp->d_secsize = DEV_BSIZE;
	lp->d_nsectors = sl->sl_nsectors;
	lp->d_ntracks = sl->sl_ntracks;
	lp->d_ncylinders = sl->sl_ncylinders;

	secpercyl = sl->sl_nsectors * sl->sl_ntracks;
	lp->d_secpercyl = secpercyl;
	if (DL_GETDSIZE(lp) == 0)
		DL_SETDSIZE(lp, (u_int64_t)secpercyl * sl->sl_ncylinders);
	lp->d_version = 1;

	memcpy(&lp->d_uid, &sl->sl_uid, sizeof(lp->d_uid));

	lp->d_acylinders = sl->sl_acylinders;

	lp->d_npartitions = MAXPARTITIONS;
	/* These are as defined in <ufs/ffs/fs.h> */
	lp->d_bbsize = 8192;	/* XXX */
	lp->d_sbsize = 8192;	/* XXX */

	for (i = 0; i < 8; i++) {
		spp = &sl->sl_part[i];
		npp = &lp->d_partitions[i];
		DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl);
		DL_SETPSIZE(npp, spp->sdkp_nsectors);
		if (DL_GETPSIZE(npp) == 0) {
			npp->p_fstype = FS_UNUSED;
		} else {
			npp->p_fstype = sun_fstypes[i];
			if (npp->p_fstype == FS_BSDFFS) {
				/*
				 * The sun label does not store the FFS fields,
				 * so just set them with default values here.
				 */
				npp->p_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
				npp->p_cpg = 16;
			}
		}
	}

	/* Clear "extended" partition info, tentatively */
	for (i = 0; i < SUNXPART; i++) {
		npp = &lp->d_partitions[i+8];
		DL_SETPOFFSET(npp, 0);
		DL_SETPSIZE(npp, 0);
		npp->p_fstype = FS_UNUSED;
	}

	/* Check to see if there's an "extended" partition table
	 * SL_XPMAG partitions had checksums up to just before the
	 * (new) sl_types variable, while SL_XPMAGTYP partitions have
	 * checksums up to the just before the (new) sl_xxx1 variable.
	 * Also, disklabels created prior to the addition of sl_uid will
	 * have a checksum to just before the sl_uid variable.
	 */
	if ((sl->sl_xpmag == SL_XPMAG &&
	    sun_extended_sum(sl, &sl->sl_types) == sl->sl_xpsum) ||
	    (sl->sl_xpmag == SL_XPMAGTYP &&
	    sun_extended_sum(sl, &sl->sl_uid) == sl->sl_xpsum) ||
	    (sl->sl_xpmag == SL_XPMAGTYP &&
	    sun_extended_sum(sl, &sl->sl_xxx1) == sl->sl_xpsum)) {
		/*
		 * There is.  Copy over the "extended" partitions.
		 * This code parallels the loop for partitions a-h.
		 */
		for (i = 0; i < SUNXPART; i++) {
			spp = &sl->sl_xpart[i];
			npp = &lp->d_partitions[i+8];
			DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl);
			DL_SETPSIZE(npp, spp->sdkp_nsectors);
			if (DL_GETPSIZE(npp) == 0) {
				npp->p_fstype = FS_UNUSED;
				continue;
			}
			npp->p_fstype = FS_BSDFFS;
			npp->p_fragblock =
			    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
			npp->p_cpg = 16;
		}
		if (sl->sl_xpmag == SL_XPMAGTYP) {
			for (i = 0; i < MAXPARTITIONS; i++) {
				npp = &lp->d_partitions[i];
				npp->p_fstype = sl->sl_types[i];
				npp->p_fragblock = sl->sl_fragblock[i];
				npp->p_cpg = sl->sl_cpg[i];
			}
		}
	} else if (preamble->sl_nparts <= 8) {
		/*
		 * A more traditional Sun label.  Recognise certain filesystem
		 * types from it, if they are available.
		 */
		i = preamble->sl_nparts;
		if (i == 0)
			i = 8;

		npp = &lp->d_partitions[i-1];
		ppp = &preamble->sl_part[i-1];
		for (; i > 0; i--, npp--, ppp--) {
			if (npp->p_size == 0)
				continue;
			if ((ppp->spi_tag == 0) && (ppp->spi_flag == 0))
				continue;

			switch (ppp->spi_tag) {
			case SPTAG_SUNOS_ROOT:
			case SPTAG_SUNOS_USR:
			case SPTAG_SUNOS_VAR:
			case SPTAG_SUNOS_HOME:
				npp->p_fstype = FS_BSDFFS;
				npp->p_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
				npp->p_cpg = 16;
				break;
			case SPTAG_LINUX_EXT2:
				npp->p_fstype = FS_EXT2FS;
				break;
			default:
				/* FS_SWAP for _SUNOS_SWAP and _LINUX_SWAP? */
				npp->p_fstype = FS_UNUSED;
				break;
			}
		}
	}

	lp->d_checksum = 0;
	lp->d_checksum = dkcksum(lp);
	DNPRINTF(BOOT_D_OFDEV, "disklabel_sun_to_bsd: success!\n");
	return (0);
}
Exemple #17
0
int
devopen(struct open_file *of, const char *name, char **file)
{
	char *cp;
	char partition;
	char fname[256];
	char buf[DEV_BSIZE];
	struct disklabel label;
	int handle, part;
	size_t read;
	char *errmsg = NULL;
	int error = 0;

	if (ofdev.handle != -1)
		panic("devopen");
	if (of->f_flags != F_READ)
		return EPERM;
	DNPRINTF(BOOT_D_OFDEV, "devopen: you want %s\n", name);
	strlcpy(fname, name, sizeof fname);
	cp = filename(fname, &partition);
	if (cp) {
		strlcpy(buf, cp, sizeof buf);
		*cp = 0;
	}
	if (!cp || !*buf)
		strlcpy(buf, DEFAULT_KERNEL, sizeof buf);
	if (!*fname)
		strlcpy(fname, bootdev, sizeof fname);
	strlcpy(opened_name, fname, sizeof opened_name);
	if (partition) {
		cp = opened_name + strlen(opened_name);
		*cp++ = ':';
		*cp++ = partition;
		*cp = 0;
	}
	if (*buf != '/')
		strlcat(opened_name, "/", sizeof opened_name);
	strlcat(opened_name, buf, sizeof opened_name);
	*file = opened_name + strlen(fname) + 1;
	DNPRINTF(BOOT_D_OFDEV, "devopen: trying %s\n", fname);
	if ((handle = OF_finddevice(fname)) == -1)
		return ENOENT;
	DNPRINTF(BOOT_D_OFDEV, "devopen: found %s\n", fname);
	if (OF_getprop(handle, "name", buf, sizeof buf) < 0)
		return ENXIO;
	DNPRINTF(BOOT_D_OFDEV, "devopen: %s is called %s\n", fname, buf);
	if (OF_getprop(handle, "device_type", buf, sizeof buf) < 0)
		return ENXIO;
	DNPRINTF(BOOT_D_OFDEV, "devopen: %s is a %s device\n", fname, buf);
	DNPRINTF(BOOT_D_OFDEV, "devopen: opening %s\n", fname);
	if ((handle = OF_open(fname)) == -1) {
		DNPRINTF(BOOT_D_OFDEV, "devopen: open of %s failed\n", fname);
		return ENXIO;
	}
	DNPRINTF(BOOT_D_OFDEV, "devopen: %s is now open\n", fname);
	bzero(&ofdev, sizeof ofdev);
	ofdev.handle = handle;
	if (!strcmp(buf, "block")) {
		ofdev.type = OFDEV_DISK;
		ofdev.bsize = DEV_BSIZE;
		/* First try to find a disklabel without MBR partitions */
		DNPRINTF(BOOT_D_OFDEV, "devopen: trying to read disklabel\n");
		if (strategy(&ofdev, F_READ,
			     LABELSECTOR, DEV_BSIZE, buf, &read) != 0
		    || read != DEV_BSIZE
		    || (errmsg = getdisklabel(buf, &label))) {
#ifdef BOOT_DEBUG
			if (errmsg)
				DNPRINTF(BOOT_D_OFDEV,
				    "devopen: getdisklabel says %s\n", errmsg);
#endif
			/* Else try MBR partitions */
			errmsg = search_label(&ofdev, LABELSECTOR, buf,
			    &label, 0);
			if (errmsg) { 
				printf("devopen: search_label says %s\n", errmsg);
				error = ERDLAB;
			}
			if (error && error != ERDLAB)
				goto bad;
		}

		if (error == ERDLAB) {
			if (partition)
				/* User specified a parititon, but there is none */
				goto bad;
			/* No, label, just use complete disk */
			ofdev.partoff = 0;
		} else {
			part = partition ? partition - 'a' : 0;
			ofdev.partoff = label.d_partitions[part].p_offset;
			DNPRINTF(BOOT_D_OFDEV, "devopen: setting partition %d "
			    "offset %x\n", part, ofdev.partoff);
		}
		
		of->f_dev = devsw;
		of->f_devdata = &ofdev;
#ifdef SPARC_BOOT_UFS
		bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]);
#endif
#ifdef SPARC_BOOT_HSFS
		bcopy(&file_system_cd9660, &file_system[nfsys++],
		    sizeof file_system[0]);
#endif
		DNPRINTF(BOOT_D_OFDEV, "devopen: return 0\n");
		return 0;
	}
#ifdef NETBOOT
	if (!strcmp(buf, "network")) {
		ofdev.type = OFDEV_NET;
		of->f_dev = devsw;
		of->f_devdata = &ofdev;
		bcopy(&file_system_nfs, file_system, sizeof file_system[0]);
		nfsys = 1;
		if (error = net_open(&ofdev))
			goto bad;
		return 0;
	}
#endif
	error = EFTYPE;
bad:
	DNPRINTF(BOOT_D_OFDEV, "devopen: error %d, cannot open device\n",
	    error);
	OF_close(handle);
	ofdev.handle = -1;
	return error;
}
Exemple #18
0
void
sr_raid1_set_chunk_state(struct sr_discipline *sd, int c, int new_state)
{
	int			old_state, s;

	DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid_set_chunk_state %d -> %d\n",
	    DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
	    sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname, c, new_state);

	/* ok to go to splbio since this only happens in error path */
	s = splbio();
	old_state = sd->sd_vol.sv_chunks[c]->src_meta.scm_status;

	/* multiple IOs to the same chunk that fail will come through here */
	if (old_state == new_state)
		goto done;

	switch (old_state) {
	case BIOC_SDONLINE:
		switch (new_state) {
		case BIOC_SDOFFLINE:
		case BIOC_SDSCRUB:
			break;
		default:
			goto die;
		}
		break;

	case BIOC_SDOFFLINE:
		switch (new_state) {
		case BIOC_SDREBUILD:
		case BIOC_SDHOTSPARE:
			break;
		default:
			goto die;
		}
		break;

	case BIOC_SDSCRUB:
		if (new_state == BIOC_SDONLINE) {
			;
		} else
			goto die;
		break;

	case BIOC_SDREBUILD:
		switch (new_state) {
		case BIOC_SDONLINE:
			break;
		case BIOC_SDOFFLINE:
			/* Abort rebuild since the rebuild chunk disappeared. */
			sd->sd_reb_abort = 1;
			break;
		default:
			goto die;
		}
		break;

	case BIOC_SDHOTSPARE:
		switch (new_state) {
		case BIOC_SDOFFLINE:
		case BIOC_SDREBUILD:
			break;
		default:
			goto die;
		}
		break;

	default:
die:
		splx(s); /* XXX */
		panic("%s: %s: %s: invalid chunk state transition "
		    "%d -> %d\n", DEVNAME(sd->sd_sc),
		    sd->sd_meta->ssd_devname,
		    sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname,
		    old_state, new_state);
		/* NOTREACHED */
	}

	sd->sd_vol.sv_chunks[c]->src_meta.scm_status = new_state;
	sd->sd_set_vol_state(sd);

	sd->sd_must_flush = 1;
	workq_add_task(NULL, 0, sr_meta_save_callback, sd, NULL);
done:
	splx(s);
}
Exemple #19
0
/*
 * is the url xtp protocol? (xxxt://)
 * if so, parse and despatch correct bahvior
 */
int
parse_xtp_url(struct tab *t, const char *url)
{
	char			*dup = NULL, *p, *last = NULL;
	uint8_t			n_tokens = 0;
	char			*tokens[4] = {NULL, NULL, NULL, ""};
	struct xtp_despatch	*dsp, *dsp_match = NULL;
	uint8_t			req_class;
	int			ret = FALSE;

	/*
	 * tokens array meaning:
	 *   tokens[0] = class
	 *   tokens[1] = session key
	 *   tokens[2] = action
	 *   tokens[3] = optional argument
	 */

	DNPRINTF(XT_D_URL, "%s: url %s\n", __func__, url);

	if (strncmp(url, XT_XTP_STR, strlen(XT_XTP_STR)))
		goto clean;

	dup = g_strdup(url + strlen(XT_XTP_STR));

	/* split out the url */
	for ((p = strtok_r(dup, "/", &last)); p;
	    (p = strtok_r(NULL, "/", &last))) {
		if (n_tokens < 4)
			tokens[n_tokens++] = p;
	}

	/* should be atleast three fields 'class/seskey/command/arg' */
	if (n_tokens < 3)
		goto clean;

	dsp = xtp_despatches;
	req_class = atoi(tokens[0]);
	while (dsp->xtp_class) {
		if (dsp->xtp_class == req_class) {
			dsp_match = dsp;
			break;
		}
		dsp++;
	}

	/* did we find one atall? */
	if (dsp_match == NULL) {
		show_oops(t, "%s: no matching xtp despatch found", __func__);
		goto clean;
	}

	/* check session key and call despatch function */
	if (validate_xtp_session_key(t, *(dsp_match->session_key), tokens[1])) {
		ret = TRUE; /* all is well, this was a valid xtp request */
		dsp_match->handle_func(t, atoi(tokens[2]), atoi(tokens[3]));
	}

clean:
	if (dup)
		g_free(dup);

	return (ret);
}
Exemple #20
0
/* ARGSUSED */
int
vndioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
{
	int unit = DISKUNIT(dev);
	struct disklabel *lp;
	struct vnd_softc *sc;
	struct vnd_ioctl *vio;
	struct vnd_user *vnu;
	struct vattr vattr;
	struct nameidata nd;
	int error, part, pmask;

	DNPRINTF(VDB_FOLLOW, "vndioctl(%x, %lx, %p, %x, %p): unit %d\n",
	    dev, cmd, addr, flag, p, unit);

	error = suser(p, 0);
	if (error)
		return (error);
	if (unit >= numvnd)
		return (ENXIO);

	sc = &vnd_softc[unit];
	vio = (struct vnd_ioctl *)addr;
	switch (cmd) {

	case VNDIOCSET:
		if (sc->sc_flags & VNF_INITED)
			return (EBUSY);

		/* Geometry eventually has to fit into label fields */
		if (vio->vnd_secsize > UINT_MAX ||
		    vio->vnd_ntracks > UINT_MAX ||
		    vio->vnd_nsectors > UINT_MAX)
			return (EINVAL);

		if ((error = disk_lock(&sc->sc_dk)) != 0)
			return (error);

		if ((error = copyinstr(vio->vnd_file, sc->sc_file,
		    sizeof(sc->sc_file), NULL))) {
			disk_unlock(&sc->sc_dk);
			return (error);
		}

		/* Set geometry for device. */
		sc->sc_secsize = vio->vnd_secsize;
		sc->sc_ntracks = vio->vnd_ntracks;
		sc->sc_nsectors = vio->vnd_nsectors;

		/*
		 * Open for read and write first. This lets vn_open() weed out
		 * directories, sockets, etc. so we don't have to worry about
		 * them.
		 */
		NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vnd_file, p);
		sc->sc_flags &= ~VNF_READONLY;
		error = vn_open(&nd, FREAD|FWRITE, 0);
		if (error == EROFS) {
			sc->sc_flags |= VNF_READONLY;
			error = vn_open(&nd, FREAD, 0);
		}
		if (error) {
			disk_unlock(&sc->sc_dk);
			return (error);
		}

		if (nd.ni_vp->v_type == VBLK)
			sc->sc_size = vndbdevsize(nd.ni_vp, p);
		else {
			error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
			if (error) {
				VOP_UNLOCK(nd.ni_vp, 0, p);
				vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p);
				disk_unlock(&sc->sc_dk);
				return (error);
			}
			sc->sc_size = vattr.va_size / sc->sc_secsize;
		}
		VOP_UNLOCK(nd.ni_vp, 0, p);
		sc->sc_vp = nd.ni_vp;
		if ((error = vndsetcred(sc, p->p_ucred)) != 0) {
			(void) vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p);
			disk_unlock(&sc->sc_dk);
			return (error);
		}

		if (vio->vnd_keylen > 0) {
			char key[BLF_MAXUTILIZED];

			if (vio->vnd_keylen > sizeof(key))
				vio->vnd_keylen = sizeof(key);

			if ((error = copyin(vio->vnd_key, key,
			    vio->vnd_keylen)) != 0) {
				(void) vn_close(nd.ni_vp, VNDRW(sc),
				    p->p_ucred, p);
				disk_unlock(&sc->sc_dk);
				return (error);
			}

			sc->sc_keyctx = malloc(sizeof(*sc->sc_keyctx), M_DEVBUF,
			    M_WAITOK);
			blf_key(sc->sc_keyctx, key, vio->vnd_keylen);
			explicit_bzero(key, vio->vnd_keylen);
		} else
			sc->sc_keyctx = NULL;

		vio->vnd_size = sc->sc_size * sc->sc_secsize;
		sc->sc_flags |= VNF_INITED;

		DNPRINTF(VDB_INIT, "vndioctl: SET vp %p size %llx\n",
		    sc->sc_vp, (unsigned long long)sc->sc_size);

		/* Attach the disk. */
		sc->sc_dk.dk_name = sc->sc_dev.dv_xname;
		disk_attach(&sc->sc_dev, &sc->sc_dk);

		disk_unlock(&sc->sc_dk);

		break;

	case VNDIOCCLR:
		if ((sc->sc_flags & VNF_INITED) == 0)
			return (ENXIO);

		if ((error = disk_lock(&sc->sc_dk)) != 0)
			return (error);

		/*
		 * Don't unconfigure if any other partitions are open
		 * or if both the character and block flavors of this
		 * partition are open.
		 */
		part = DISKPART(dev);
		pmask = (1 << part);
		if ((sc->sc_dk.dk_openmask & ~pmask) ||
		    ((sc->sc_dk.dk_bopenmask & pmask) &&
		    (sc->sc_dk.dk_copenmask & pmask))) {
			disk_unlock(&sc->sc_dk);
			return (EBUSY);
		}

		vndclear(sc);
		DNPRINTF(VDB_INIT, "vndioctl: CLRed\n");

		/* Free crypto key */
		if (sc->sc_keyctx) {
			explicit_bzero(sc->sc_keyctx, sizeof(*sc->sc_keyctx));
			free(sc->sc_keyctx, M_DEVBUF, sizeof(*sc->sc_keyctx));
		}

		/* Detach the disk. */
		disk_detach(&sc->sc_dk);
		disk_unlock(&sc->sc_dk);
		break;

	case VNDIOCGET:
		vnu = (struct vnd_user *)addr;

		if (vnu->vnu_unit == -1)
			vnu->vnu_unit = unit;
		if (vnu->vnu_unit >= numvnd)
			return (ENXIO);
		if (vnu->vnu_unit < 0)
			return (EINVAL);

		sc = &vnd_softc[vnu->vnu_unit];

		if (sc->sc_flags & VNF_INITED) {
			error = VOP_GETATTR(sc->sc_vp, &vattr, p->p_ucred, p);
			if (error)
				return (error);

			strlcpy(vnu->vnu_file, sc->sc_file,
			    sizeof(vnu->vnu_file));
			vnu->vnu_dev = vattr.va_fsid;
			vnu->vnu_ino = vattr.va_fileid;
		} else {
			vnu->vnu_dev = 0;
			vnu->vnu_ino = 0;
		}

		break;

	case DIOCRLDINFO:
		if ((sc->sc_flags & VNF_HAVELABEL) == 0)
			return (ENOTTY);
		lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
		vndgetdisklabel(dev, sc, lp, 0);
		*(sc->sc_dk.dk_label) = *lp;
		free(lp, M_TEMP, sizeof(*lp));
		return (0);

	case DIOCGPDINFO:
		if ((sc->sc_flags & VNF_HAVELABEL) == 0)
			return (ENOTTY);
		vndgetdisklabel(dev, sc, (struct disklabel *)addr, 1);
		return (0);

	case DIOCGDINFO:
		if ((sc->sc_flags & VNF_HAVELABEL) == 0)
			return (ENOTTY);
		*(struct disklabel *)addr = *(sc->sc_dk.dk_label);
		return (0);

	case DIOCGPART:
		if ((sc->sc_flags & VNF_HAVELABEL) == 0)
			return (ENOTTY);
		((struct partinfo *)addr)->disklab = sc->sc_dk.dk_label;
		((struct partinfo *)addr)->part =
		    &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)];
		return (0);

	case DIOCWDINFO:
	case DIOCSDINFO:
		if ((sc->sc_flags & VNF_HAVELABEL) == 0)
			return (ENOTTY);
		if ((flag & FWRITE) == 0)
			return (EBADF);

		if ((error = disk_lock(&sc->sc_dk)) != 0)
			return (error);

		error = setdisklabel(sc->sc_dk.dk_label,
		    (struct disklabel *)addr, /* sc->sc_dk.dk_openmask */ 0);
		if (error == 0) {
			if (cmd == DIOCWDINFO)
				error = writedisklabel(DISKLABELDEV(dev),
				    vndstrategy, sc->sc_dk.dk_label);
		}

		disk_unlock(&sc->sc_dk);
		return (error);

	default:
		return (ENOTTY);
	}

	return (0);
}
Exemple #21
0
void
vndstrategy(struct buf *bp)
{
	int unit = DISKUNIT(bp->b_dev);
	struct vnd_softc *sc;
	struct partition *p;
	off_t off;
	long origbcount;
	int s;

	DNPRINTF(VDB_FOLLOW, "vndstrategy(%p): unit %d\n", bp, unit);

	if (unit >= numvnd) {
		bp->b_error = ENXIO;
		goto bad;
	}
	sc = &vnd_softc[unit];

	if ((sc->sc_flags & VNF_HAVELABEL) == 0) {
		bp->b_error = ENXIO;
		goto bad;
	}

	/*
	 * Many of the distrib scripts assume they can issue arbitrary
	 * sized requests to raw vnd devices irrespective of the
	 * emulated disk geometry.
	 *
	 * To continue supporting this, round the block count up to a
	 * multiple of d_secsize for bounds_check_with_label(), and
	 * then restore afterwards.
	 *
	 * We only do this for non-encrypted vnd, because encryption
	 * requires operating on blocks at a time.
	 */
	origbcount = bp->b_bcount;
	if (sc->sc_keyctx == NULL) {
		u_int32_t secsize = sc->sc_dk.dk_label->d_secsize;
		bp->b_bcount = ((origbcount + secsize - 1) & ~(secsize - 1));
#ifdef DIAGNOSTIC
		if (bp->b_bcount != origbcount) {
			struct proc *pr = curproc;
			printf("%s: sloppy %s from proc %d (%s): "
			    "blkno %lld bcount %ld\n", sc->sc_dev.dv_xname,
			    (bp->b_flags & B_READ) ? "read" : "write",
			    pr->p_pid, pr->p_comm, (long long)bp->b_blkno,
			    origbcount);
		}
#endif
	}

	if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1) {
		bp->b_resid = bp->b_bcount = origbcount;
		goto done;
	}

	if (origbcount < bp->b_bcount)
		bp->b_bcount = origbcount;

	p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
	off = DL_GETPOFFSET(p) * sc->sc_dk.dk_label->d_secsize +
	    (u_int64_t)bp->b_blkno * DEV_BSIZE;

	if (sc->sc_keyctx && !(bp->b_flags & B_READ))
		vndencryptbuf(sc, bp, 1);

	/*
	 * Use IO_NOLIMIT because upper layer has already checked I/O
	 * for limits, so there is no need to do it again.
	 */
	bp->b_error = vn_rdwr((bp->b_flags & B_READ) ? UIO_READ : UIO_WRITE,
	    sc->sc_vp, bp->b_data, bp->b_bcount, off, UIO_SYSSPACE, IO_NOLIMIT,
	    sc->sc_cred, &bp->b_resid, curproc);
	if (bp->b_error)
		bp->b_flags |= B_ERROR;

	/* Data in buffer cache needs to be in clear */
	if (sc->sc_keyctx)
		vndencryptbuf(sc, bp, 0);

	goto done;

 bad:
	bp->b_flags |= B_ERROR;
	bp->b_resid = bp->b_bcount;
 done:
	s = splbio();
	biodone(bp);
	splx(s);
}
Exemple #22
0
int
sr_concat_rw(struct sr_workunit *wu)
{
	struct sr_discipline	*sd = wu->swu_dis;
	struct scsi_xfer	*xs = wu->swu_xs;
	struct sr_ccb		*ccb;
	struct sr_chunk		*scp;
	daddr_t			blkno;
	int64_t			lbaoffs, offset;
	int64_t			no_chunk, chunkend, chunk, chunksize;
	int64_t			length, leftover;
	u_int8_t		*data;

	/* blkno and scsi error will be handled by sr_validate_io */
	if (sr_validate_io(wu, &blkno, "sr_concat_rw"))
		goto bad;

	no_chunk = sd->sd_meta->ssdi.ssd_chunk_no;

	DNPRINTF(SR_D_DIS, "%s: %s: front end io: blkno %lld size %d\n",
	    DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
	    (long long)blkno, xs->datalen);

	/* All offsets are in bytes. */
	lbaoffs = blkno << DEV_BSHIFT;
	leftover = xs->datalen;
	data = xs->data;
	for (;;) {

		chunkend = 0;
		offset = lbaoffs;
		for (chunk = 0; chunk < no_chunk; chunk++) {
			chunksize = sd->sd_vol.sv_chunks[chunk]->src_size <<
			    DEV_BSHIFT;
			chunkend += chunksize;
			if (lbaoffs < chunkend)
				break;
			offset -= chunksize;
		}
		if (lbaoffs > chunkend)
			goto bad;

		length = MIN(MIN(leftover, chunkend - lbaoffs), MAXPHYS);

		/* make sure chunk is online */
		scp = sd->sd_vol.sv_chunks[chunk];
		if (scp->src_meta.scm_status != BIOC_SDONLINE)
			goto bad;

		DNPRINTF(SR_D_DIS, "%s: %s %s io lbaoffs %lld "
		    "chunk %lld chunkend %lld offset %lld length %lld "
		    "leftover %lld data %p\n",
		    DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_name,
		    lbaoffs, chunk, chunkend, offset, length, leftover, data);

		blkno = offset >> DEV_BSHIFT;
		ccb = sr_ccb_rw(sd, chunk, blkno, length, data, xs->flags, 0);
		if (!ccb) {
			/* should never happen but handle more gracefully */
			printf("%s: %s: too many ccbs queued\n",
			    DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname);
			goto bad;
		}
		sr_wu_enqueue_ccb(wu, ccb);

		leftover -= length;
		if (leftover == 0)
			break;
		data += length;
		lbaoffs += length;
	}

	sr_schedule_wu(wu);

	return (0);

bad:
	/* wu is unwound by sr_wu_put */
	return (1);
}
Exemple #23
0
int
devopen(struct open_file *of, const char *name, char **file)
{
	char *cp;
	char partition;
	char fname[256];
	char buf[DEV_BSIZE];
	struct disklabel label;
	int handle, part;
	int error = 0;
#ifdef SOFTRAID
	char volno;
#endif

	if (ofdev.handle != -1)
		panic("devopen");
	if (of->f_flags != F_READ)
		return EPERM;
	DNPRINTF(BOOT_D_OFDEV, "devopen: you want %s\n", name);
	if (strlcpy(fname, name, sizeof fname) >= sizeof fname)
		return ENAMETOOLONG;
#ifdef SOFTRAID
	if (bootdev_dip) {
		if (fname[0] == 's' && fname[1] == 'r' &&
		    '0' <= fname[2] && fname[2] <= '9') {
			volno = fname[2];
			if ('a' <= fname[3] &&
			    fname[3] <= 'a' + MAXPARTITIONS) {
				partition = fname[3];
				if (fname[4] == ':')
					cp = &fname[5];
				else
					cp = &fname[4];
			} else {
				partition = 'a';
				cp = &fname[3];
			}
		} else {
			volno = '0';
			partition = 'a';
			cp = &fname[0];
		}
		snprintf(buf, sizeof buf, "sr%c:%c", volno, partition);
		if (strlcpy(opened_name, buf, sizeof opened_name)
		    >= sizeof opened_name)
			return ENAMETOOLONG;
		*file = opened_name + strlen(opened_name);
		if (!*cp) {
			if (strlcpy(buf, DEFAULT_KERNEL, sizeof buf)
			    >= sizeof buf)
				return ENAMETOOLONG;
		} else {
			if (snprintf(buf, sizeof buf, "%s%s",
			    *cp == '/' ? "" : "/", cp) >= sizeof buf)
				return ENAMETOOLONG;
		}
		if (strlcat(opened_name, buf, sizeof opened_name) >=
		    sizeof opened_name)
			return ENAMETOOLONG;
	} else {
#endif
		cp = filename(fname, &partition);
		if (cp) {
			if (strlcpy(buf, cp, sizeof buf) >= sizeof buf)
				return ENAMETOOLONG;
			*cp = 0;
		}
		if (!cp || !*buf) {
			if (strlcpy(buf, DEFAULT_KERNEL, sizeof buf)
			    >= sizeof buf)
				return ENAMETOOLONG;
		}
		if (!*fname) {
			if (strlcpy(fname, bootdev, sizeof fname)
			    >= sizeof fname)
				return ENAMETOOLONG;
		}
		if (strlcpy(opened_name, fname,
		    partition ? (sizeof opened_name) - 2 : sizeof opened_name)
		    >= sizeof opened_name)
			return ENAMETOOLONG;
		if (partition) {
			cp = opened_name + strlen(opened_name);
			*cp++ = ':';
			*cp++ = partition;
			*cp = 0;
		}
		if (*buf != '/') {
			if (strlcat(opened_name, "/", sizeof opened_name) >=
			    sizeof opened_name)
				return ENAMETOOLONG;
		}
		if (strlcat(opened_name, buf, sizeof opened_name) >=
		    sizeof opened_name)
			return ENAMETOOLONG;
		*file = opened_name + strlen(fname) + 1;
#ifdef SOFTRAID
	}
#endif
	DNPRINTF(BOOT_D_OFDEV, "devopen: trying %s\n", fname);
#ifdef SOFTRAID
	if (bootdev_dip) {
		/* Redirect to the softraid boot volume. */
		struct partition *pp;

		bzero(&ofdev, sizeof ofdev);
		ofdev.type = OFDEV_SOFTRAID;

		if (partition) {
			if (partition < 'a' ||
			    partition >= 'a' + MAXPARTITIONS) {
			    	printf("invalid partition '%c'\n", partition);
				return EINVAL;
			}
			part = partition - 'a';
			pp = &bootdev_dip->disklabel.d_partitions[part];
			if (pp->p_fstype == FS_UNUSED || pp->p_size == 0) {
			    	printf("invalid partition '%c'\n", partition);
				return EINVAL;
			}
			bootdev_dip->sr_vol->sbv_part = partition;
		} else
			bootdev_dip->sr_vol->sbv_part = 'a';

		of->f_dev = devsw;
		of->f_devdata = &ofdev;

#ifdef SPARC_BOOT_UFS
		bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]);
#else
#error "-DSOFTRAID requires -DSPARC_BOOT_UFS"
#endif
		return 0;
	}
#endif
	if ((handle = OF_finddevice(fname)) == -1)
		return ENOENT;
	DNPRINTF(BOOT_D_OFDEV, "devopen: found %s\n", fname);
	if (OF_getprop(handle, "name", buf, sizeof buf) < 0)
		return ENXIO;
	DNPRINTF(BOOT_D_OFDEV, "devopen: %s is called %s\n", fname, buf);
	if (OF_getprop(handle, "device_type", buf, sizeof buf) < 0)
		return ENXIO;
	DNPRINTF(BOOT_D_OFDEV, "devopen: %s is a %s device\n", fname, buf);
	DNPRINTF(BOOT_D_OFDEV, "devopen: opening %s\n", fname);
	if ((handle = OF_open(fname)) == -1) {
		DNPRINTF(BOOT_D_OFDEV, "devopen: open of %s failed\n", fname);
		return ENXIO;
	}
	DNPRINTF(BOOT_D_OFDEV, "devopen: %s is now open\n", fname);
	bzero(&ofdev, sizeof ofdev);
	ofdev.handle = handle;
	ofdev.type = OFDEV_DISK;
	ofdev.bsize = DEV_BSIZE;
	if (!strcmp(buf, "block")) {
		error = load_disklabel(&ofdev, &label);
		if (error && error != ERDLAB)
			goto bad;
		else if (error == ERDLAB) {
			if (partition)
				/* User specified a parititon, but there is none */
				goto bad;
			/* No, label, just use complete disk */
			ofdev.partoff = 0;
		} else {
			part = partition ? partition - 'a' : 0;
			ofdev.partoff = label.d_partitions[part].p_offset;
			DNPRINTF(BOOT_D_OFDEV, "devopen: setting partition %d "
			    "offset %x\n", part, ofdev.partoff);
		}
		
		of->f_dev = devsw;
		of->f_devdata = &ofdev;
#ifdef SPARC_BOOT_UFS
		bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]);
#endif
#ifdef SPARC_BOOT_HSFS
		bcopy(&file_system_cd9660, &file_system[nfsys++],
		    sizeof file_system[0]);
#endif
		DNPRINTF(BOOT_D_OFDEV, "devopen: return 0\n");
		return 0;
	}
#ifdef NETBOOT
	if (!strcmp(buf, "network")) {
		ofdev.type = OFDEV_NET;
		of->f_dev = devsw;
		of->f_devdata = &ofdev;
		bcopy(&file_system_nfs, file_system, sizeof file_system[0]);
		nfsys = 1;
		if (error = net_open(&ofdev))
			goto bad;
		return 0;
	}
#endif
	error = EFTYPE;
bad:
	DNPRINTF(BOOT_D_OFDEV, "devopen: error %d, cannot open device\n",
	    error);
	OF_close(handle);
	ofdev.handle = -1;
	return error;
}
Exemple #24
0
int
sys_pledge(struct proc *p, void *v, register_t *retval)
{
	struct sys_pledge_args /* {
		syscallarg(const char *)request;
		syscallarg(const char **)paths;
	} */	*uap = v;
	uint64_t flags = 0;
	int error;

	if (SCARG(uap, request)) {
		size_t rbuflen;
		char *rbuf, *rp, *pn;
		uint64_t f;

		rbuf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
		error = copyinstr(SCARG(uap, request), rbuf, MAXPATHLEN,
		    &rbuflen);
		if (error) {
			free(rbuf, M_TEMP, MAXPATHLEN);
			return (error);
		}
#ifdef KTRACE
		if (KTRPOINT(p, KTR_STRUCT))
			ktrstruct(p, "pledgereq", rbuf, rbuflen-1);
#endif

		for (rp = rbuf; rp && *rp && error == 0; rp = pn) {
			pn = strchr(rp, ' ');	/* find terminator */
			if (pn) {
				while (*pn == ' ')
					*pn++ = '\0';
			}

			if ((f = pledgereq_flags(rp)) == 0) {
				free(rbuf, M_TEMP, MAXPATHLEN);
				return (EINVAL);
			}
			flags |= f;
		}
		free(rbuf, M_TEMP, MAXPATHLEN);

		/*
		 * if we are already pledged, allow only promises reductions.
		 * flags doesn't contain flags outside _USERSET: they will be
		 * relearned.
		 */
		if (ISSET(p->p_p->ps_flags, PS_PLEDGE) &&
		    (((flags | p->p_p->ps_pledge) != p->p_p->ps_pledge)))
			return (EPERM);
	}

	if (SCARG(uap, paths)) {
#if 1
		return (EINVAL);
#else
		const char **u = SCARG(uap, paths), *sp;
		struct whitepaths *wl;
		char *path, *rdir = NULL, *cwd = NULL;
		size_t pathlen, rdirlen, cwdlen;

		size_t maxargs = 0;
		int i, error;

		if (p->p_p->ps_pledgepaths)
			return (EPERM);

		/* Count paths */
		for (i = 0; i < PLEDGE_MAXPATHS; i++) {
			if ((error = copyin(u + i, &sp, sizeof(sp))) != 0)
				return (error);
			if (sp == NULL)
				break;
		}
		if (i == PLEDGE_MAXPATHS)
			return (E2BIG);

		wl = malloc(sizeof *wl + sizeof(struct whitepath) * (i+1),
		    M_TEMP, M_WAITOK | M_ZERO);
		wl->wl_size = sizeof *wl + sizeof(struct whitepath) * (i+1);
		wl->wl_count = i;
		wl->wl_ref = 1;

		path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);

		/* Copy in */
		for (i = 0; i < wl->wl_count; i++) {
			char *resolved = NULL;
			size_t resolvedlen;

			if ((error = copyin(u + i, &sp, sizeof(sp))) != 0)
				break;
			if (sp == NULL)
				break;
			if ((error = copyinstr(sp, path, MAXPATHLEN, &pathlen)) != 0)
				break;
#ifdef KTRACE
			if (KTRPOINT(p, KTR_STRUCT))
				ktrstruct(p, "pledgepath", path, pathlen-1);
#endif

			error = resolvpath(p, &rdir, &rdirlen, &cwd, &cwdlen,
			    path, pathlen, &resolved, &resolvedlen);

			if (error != 0)
				/* resolved is allocated only if !error */
				break;

			maxargs += resolvedlen;
			if (maxargs > ARG_MAX) {
				error = E2BIG;
				free(resolved, M_TEMP, resolvedlen);
				break;
			}
			wl->wl_paths[i].name = resolved;
			wl->wl_paths[i].len = resolvedlen;
		}
		free(rdir, M_TEMP, rdirlen);
		free(cwd, M_TEMP, cwdlen);
		free(path, M_TEMP, MAXPATHLEN);

		if (error) {
			for (i = 0; i < wl->wl_count; i++)
				free(wl->wl_paths[i].name,
				    M_TEMP, wl->wl_paths[i].len);
			free(wl, M_TEMP, wl->wl_size);
			return (error);
		}
		p->p_p->ps_pledgepaths = wl;

#ifdef DEBUG_PLEDGE
		/* print paths registered as whilelisted (viewed as without chroot) */
		DNPRINTF(1, "pledge: %s(%d): paths loaded:\n", p->p_comm,
		    p->p_pid);
		for (i = 0; i < wl->wl_count; i++)
			if (wl->wl_paths[i].name)
				DNPRINTF(1, "pledge: %d=\"%s\" [%lld]\n", i,
				    wl->wl_paths[i].name,
				    (long long)wl->wl_paths[i].len);
#endif
#endif
	}

	if (SCARG(uap, request)) {
		p->p_p->ps_pledge = flags;
		p->p_p->ps_flags |= PS_PLEDGE;
	}

	return (0);
}
Exemple #25
0
void
soup_cookie_jar_add_cookie(SoupCookieJar *jar, SoupCookie *cookie)
{
	struct wl_entry		*w = NULL;
	SoupCookie		*c;
	FILE			*r_cookie_f;
	char			*public_suffix;

	DNPRINTF(XT_D_COOKIE, "soup_cookie_jar_add_cookie: %p %p %p\n",
	    jar, p_cookiejar, s_cookiejar);

	if (cookies_enabled == 0)
		return;

	/* see if we are up and running */
	if (p_cookiejar == NULL) {
		_soup_cookie_jar_add_cookie(jar, cookie);
		return;
	}
	/* disallow p_cookiejar adds, shouldn't happen */
	if (jar == p_cookiejar)
		return;

	/* sanity */
	if (jar == NULL || cookie == NULL)
		return;

	/* check if domain is valid */
	public_suffix = tld_get_suffix(cookie->domain[0] == '.' ?
			cookie->domain + 1 : cookie->domain);

	if (public_suffix == NULL ||
	    (enable_cookie_whitelist &&
	    (w = wl_find(cookie->domain, &c_wl)) == NULL)) {
		blocked_cookies++;
		DNPRINTF(XT_D_COOKIE,
		    "soup_cookie_jar_add_cookie: reject %s\n",
		    cookie->domain);
		if (save_rejected_cookies) {
			if ((r_cookie_f = fopen(rc_fname, "a+")) == NULL) {
				show_oops(NULL, "can't open reject cookie file");
				return;
			}
			fseek(r_cookie_f, 0, SEEK_END);
			fprintf(r_cookie_f, "%s%s\t%s\t%s\t%s\t%lu\t%s\t%s\n",
			    cookie->http_only ? "#HttpOnly_" : "",
			    cookie->domain,
			    *cookie->domain == '.' ? "TRUE" : "FALSE",
			    cookie->path,
			    cookie->secure ? "TRUE" : "FALSE",
			    cookie->expires ?
			        (gulong)soup_date_to_time_t(cookie->expires) :
			        0,
			    cookie->name,
			    cookie->value);
			fflush(r_cookie_f);
			fclose(r_cookie_f);
		}
		if (!allow_volatile_cookies)
			return;
	}

	if (cookie->expires == NULL && session_timeout) {
		soup_cookie_set_expires(cookie,
		    soup_date_new_from_now(session_timeout));
		print_cookie("modified add cookie", cookie);
	}

	/* see if we are white listed for persistence */
	if ((w && w->handy) || (enable_cookie_whitelist == 0)) {
		/* add to persistent jar */
		c = soup_cookie_copy(cookie);
		print_cookie("soup_cookie_jar_add_cookie p_cookiejar", c);
		_soup_cookie_jar_add_cookie(p_cookiejar, c);
	}

	/* add to session jar */
	print_cookie("soup_cookie_jar_add_cookie s_cookiejar", cookie);
	_soup_cookie_jar_add_cookie(s_cookiejar, cookie);
}
Exemple #26
0
/*
 * wlpath lookup - only done after namei lookup has succeeded on the last compoent of
 * a namei lookup, with a possibly non-canonicalized path given in "origpath" from namei.
 */
int
pledge_namei_wlpath(struct proc *p, struct nameidata *ni)
{
	struct whitepaths *wl = p->p_p->ps_pledgepaths;
	char *rdir = NULL, *cwd = NULL, *resolved = NULL;
	size_t rdirlen, cwdlen, resolvedlen;
	int i, error, pardir_found;

	/*
	 * If a whitelist is set, compare canonical paths.  Anything
	 * not on the whitelist gets ENOENT.
	 */
	if (ni->ni_p_path == NULL)
		return(0);

	KASSERT(p->p_p->ps_pledgepaths);

	// XXX change later or more help from namei?
	error = resolvpath(p, &rdir, &rdirlen, &cwd, &cwdlen,
	    ni->ni_p_path, ni->ni_p_length+1, &resolved, &resolvedlen);

	free(rdir, M_TEMP, rdirlen);
	free(cwd, M_TEMP, cwdlen);

	if (error != 0)
		/* resolved is allocated only if !error */
		return (error);

	/* print resolved path (viewed as without chroot) */
	DNPRINTF(2, "pledge_namei: resolved=\"%s\" [%lld] strlen=%lld\n",
	    resolved, (long long)resolvedlen,
	    (long long)strlen(resolved));

	error = ENOENT;
	pardir_found = 0;
	for (i = 0; i < wl->wl_count && wl->wl_paths[i].name && error; i++) {
		int substr = substrcmp(wl->wl_paths[i].name,
		    wl->wl_paths[i].len - 1, resolved, resolvedlen - 1);

		/* print check between registered wl_path and resolved */
		DNPRINTF(3,
		    "pledge: check: \"%s\" (%ld) \"%s\" (%ld) = %d\n",
		    wl->wl_paths[i].name, wl->wl_paths[i].len - 1,
		    resolved, resolvedlen - 1,
		    substr);

		/* wl_paths[i].name is a substring of resolved */
		if (substr == 1) {
			u_char term = resolved[wl->wl_paths[i].len - 1];

			if (term == '\0' || term == '/' ||
			    wl->wl_paths[i].name[1] == '\0')
				error = 0;

			/* resolved is a substring of wl_paths[i].name */
		} else if (substr == 2) {
			u_char term = wl->wl_paths[i].name[resolvedlen - 1];

			if (resolved[1] == '\0' || term == '/')
				pardir_found = 1;
		}
	}
	if (pardir_found)
		switch (p->p_pledge_syscall) {
		case SYS_stat:
		case SYS_lstat:
		case SYS_fstatat:
		case SYS_fstat:
			ni->ni_pledge |= PLEDGE_STATLIE;
			error = 0;
		}

#ifdef DEBUG_PLEDGE
	if (error == ENOENT)
		/* print the path that is reported as ENOENT */
		DNPRINTF(1, "pledge: %s(%d): wl_path ENOENT: \"%s\"\n",
		    p->p_comm, p->p_pid, resolved);
#endif

	free(resolved, M_TEMP, resolvedlen);
	return (error);			/* Don't hint why it failed */
}
Exemple #27
0
int
sr_raid0_rw(struct sr_workunit *wu)
{
	struct sr_discipline	*sd = wu->swu_dis;
	struct scsi_xfer	*xs = wu->swu_xs;
	struct sr_ccb		*ccb;
	struct sr_chunk		*scp;
	daddr_t			blkno;
	int64_t			chunkoffs, lbaoffs, offset, stripoffs;
	int64_t			strip_bits, strip_no, strip_size;
	int64_t			chunk, no_chunk;
	int64_t			length, leftover;
	u_int8_t		*data;

	/* blkno and scsi error will be handled by sr_validate_io */
	if (sr_validate_io(wu, &blkno, "sr_raid0_rw"))
		goto bad;

	strip_size = sd->sd_meta->ssdi.ssd_strip_size;
	strip_bits = sd->mds.mdd_raid0.sr0_strip_bits;
	no_chunk = sd->sd_meta->ssdi.ssd_chunk_no;

	DNPRINTF(SR_D_DIS, "%s: %s: front end io: blkno %lld size %d\n",
	    DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
	    (long long)blkno, xs->datalen);

	/* all offs are in bytes */
	lbaoffs = blkno << DEV_BSHIFT;
	strip_no = lbaoffs >> strip_bits;
	chunk = strip_no % no_chunk;
	stripoffs = lbaoffs & (strip_size - 1);
	chunkoffs = (strip_no / no_chunk) << strip_bits;
	offset = chunkoffs + stripoffs;
	length = MIN(xs->datalen, strip_size - stripoffs);
	leftover = xs->datalen;
	data = xs->data;
	for (;;) {
		/* make sure chunk is online */
		scp = sd->sd_vol.sv_chunks[chunk];
		if (scp->src_meta.scm_status != BIOC_SDONLINE)
			goto bad;

		DNPRINTF(SR_D_DIS, "%s: %s %s io lbaoffs %lld "
		    "strip_no %lld chunk %lld stripoffs %lld "
		    "chunkoffs %lld offset %lld length %lld "
		    "leftover %lld data %p\n",
		    DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_name,
		    lbaoffs, strip_no, chunk, stripoffs, chunkoffs, offset,
		    length, leftover, data);

		blkno = offset >> DEV_BSHIFT;
		ccb = sr_ccb_rw(sd, chunk, blkno, length, data, xs->flags, 0);
		if (!ccb) {
			/* should never happen but handle more gracefully */
			printf("%s: %s: too many ccbs queued\n",
			    DEVNAME(sd->sd_sc),
			    sd->sd_meta->ssd_devname);
			goto bad;
		}
		sr_wu_enqueue_ccb(wu, ccb);

		leftover -= length;
		if (leftover == 0)
			break;

		data += length;
		if (++chunk > no_chunk - 1) {
			chunk = 0;
			offset += length;
		} else if (wu->swu_io_count == 1)
			offset -= stripoffs;
		length = MIN(leftover,strip_size);
	}

	sr_schedule_wu(wu);

	return (0);

bad:
	/* wu is unwound by sr_wu_put */
	return (1);
}
Exemple #28
0
void
sr_raid1_set_vol_state(struct sr_discipline *sd)
{
	int			states[SR_MAX_STATES];
	int			new_state, i, s, nd;
	int			old_state = sd->sd_vol_status;

	DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state\n",
	    DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname);

	nd = sd->sd_meta->ssdi.ssd_chunk_no;

#ifdef SR_DEBUG
	for (i = 0; i < nd; i++)
		DNPRINTF(SR_D_STATE, "%s: chunk %d status = %u\n",
		    DEVNAME(sd->sd_sc), i,
		    sd->sd_vol.sv_chunks[i]->src_meta.scm_status);
#endif

	for (i = 0; i < SR_MAX_STATES; i++)
		states[i] = 0;

	for (i = 0; i < nd; i++) {
		s = sd->sd_vol.sv_chunks[i]->src_meta.scm_status;
		if (s >= SR_MAX_STATES)
			panic("%s: %s: %s: invalid chunk state",
			    DEVNAME(sd->sd_sc),
			    sd->sd_meta->ssd_devname,
			    sd->sd_vol.sv_chunks[i]->src_meta.scmi.scm_devname);
		states[s]++;
	}

	if (states[BIOC_SDONLINE] == nd)
		new_state = BIOC_SVONLINE;
	else if (states[BIOC_SDONLINE] == 0)
		new_state = BIOC_SVOFFLINE;
	else if (states[BIOC_SDSCRUB] != 0)
		new_state = BIOC_SVSCRUB;
	else if (states[BIOC_SDREBUILD] != 0)
		new_state = BIOC_SVREBUILD;
	else if (states[BIOC_SDOFFLINE] != 0)
		new_state = BIOC_SVDEGRADED;
	else {
		DNPRINTF(SR_D_STATE, "%s: invalid volume state, old state "
		    "was %d\n", DEVNAME(sd->sd_sc), old_state);
		panic("invalid volume state");
	}

	DNPRINTF(SR_D_STATE, "%s: %s: sr_raid1_set_vol_state %d -> %d\n",
	    DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname,
	    old_state, new_state);

	switch (old_state) {
	case BIOC_SVONLINE:
		switch (new_state) {
		case BIOC_SVONLINE: /* can go to same state */
		case BIOC_SVOFFLINE:
		case BIOC_SVDEGRADED:
		case BIOC_SVREBUILD: /* happens on boot */
			break;
		default:
			goto die;
		}
		break;

	case BIOC_SVOFFLINE:
		/* XXX this might be a little too much */
		goto die;

	case BIOC_SVSCRUB:
		switch (new_state) {
		case BIOC_SVONLINE:
		case BIOC_SVOFFLINE:
		case BIOC_SVDEGRADED:
		case BIOC_SVSCRUB: /* can go to same state */
			break;
		default:
			goto die;
		}
		break;

	case BIOC_SVBUILDING:
		switch (new_state) {
		case BIOC_SVONLINE:
		case BIOC_SVOFFLINE:
		case BIOC_SVBUILDING: /* can go to the same state */
			break;
		default:
			goto die;
		}
		break;

	case BIOC_SVREBUILD:
		switch (new_state) {
		case BIOC_SVONLINE:
		case BIOC_SVOFFLINE:
		case BIOC_SVDEGRADED:
		case BIOC_SVREBUILD: /* can go to the same state */
			break;
		default:
			goto die;
		}
		break;

	case BIOC_SVDEGRADED:
		switch (new_state) {
		case BIOC_SVOFFLINE:
		case BIOC_SVREBUILD:
		case BIOC_SVDEGRADED: /* can go to the same state */
			break;
		default:
			goto die;
		}
		break;

	default:
die:
		panic("%s: %s: invalid volume state transition "
		    "%d -> %d\n", DEVNAME(sd->sd_sc),
		    sd->sd_meta->ssd_devname,
		    old_state, new_state);
		/* NOTREACHED */
	}

	sd->sd_vol_status = new_state;

	/* If we have just become degraded, look for a hotspare. */
	if (new_state == BIOC_SVDEGRADED)
		workq_add_task(NULL, 0, sr_hotspare_rebuild_callback, sd, NULL);
}