Пример #1
0
/*
 * Point (dev) at an allocated device specifier matching the string version
 * at the beginning of (devspec).  Return a pointer to the remaining
 * text in (path).
 */
static int
ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path)
{
    struct ofw_devdesc	*idev;
    struct devsw	*dv;
    phandle_t		handle;
    const char		*p;
    const char		*s;
    char		*ep;
    char		name[256];
    char		type[64];
    int			err;
    int			len;
    int			i;

    for (p = s = devspec; *s != '\0'; p = s) {
	if ((s = strchr(p + 1, '/')) == NULL)
	    s = strchr(p, '\0');
	len = s - devspec;
	bcopy(devspec, name, len);
	name[len] = '\0';
	if ((handle = OF_finddevice(name)) == -1) {
	    bcopy(name, type, len);
	    type[len] = '\0';
	} else if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1)
	    continue;
	for (i = 0; (dv = devsw[i]) != NULL; i++) {
	    if (strncmp(dv->dv_name, type, strlen(dv->dv_name)) == 0)
		goto found;
	}
    }
    return(ENOENT);

found:
    if (path != NULL)
	*path = s;
    idev = malloc(sizeof(struct ofw_devdesc));
    if (idev == NULL) {
	printf("ofw_parsedev: malloc failed\n");
	return ENOMEM;
    }
    strcpy(idev->d_path, name);
    idev->d_dev = dv;
    idev->d_type = dv->dv_type;
    if (idev->d_type == DEVT_ZFS) {
	p = devspec + strlen(dv->dv_name);
	err = zfs_parsedev((struct zfs_devdesc *)idev, p, path);
	if (err != 0) {
	    free(idev);
	    return (err);
	}
    }

    if (dev == NULL) {
	free(idev);
    } else {
	*dev = idev;
    }
    return(0);
}
Пример #2
0
/*
 * Point (dev) at an allocated device specifier matching the string version
 * at the beginning of (devspec).  Return a pointer to the remaining
 * text in (path).
 *
 * In all cases, the beginning of (devspec) is compared to the names
 * of known devices in the device switch, and then any following text
 * is parsed according to the rules applied to the device type.
 *
 * For disk-type devices, the syntax is:
 *
 * disk<unit>[s<slice>][<partition>]:
 *
 */
static int
i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path)
{
    struct i386_devdesc *idev;
    struct devsw	*dv;
    int			i, unit, err;
    char		*cp;
    const char		*np;

    /* minimum length check */
    if (strlen(devspec) < 2)
        return(EINVAL);

    /* look for a device that matches */
    for (i = 0, dv = NULL; devsw[i] != NULL; i++) {
        if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) {
            dv = devsw[i];
            break;
        }
    }
    if (dv == NULL)
        return(ENOENT);
    idev = malloc(sizeof(struct i386_devdesc));
    err = 0;
    np = (devspec + strlen(dv->dv_name));

    switch(dv->dv_type) {
    case DEVT_NONE:			/* XXX what to do here?  Do we care? */
        break;

    case DEVT_DISK:
        err = disk_parsedev((struct disk_devdesc *)idev, np, path);
        if (err != 0)
            goto fail;
        break;

    case DEVT_CD:
    case DEVT_NET:
        unit = 0;

        if (*np && (*np != ':')) {
            unit = strtol(np, &cp, 0);	/* get unit number if present */
            if (cp == np) {
                err = EUNIT;
                goto fail;
            }
        } else {
            cp = (char *)np;
        }
        if (*cp && (*cp != ':')) {
            err = EINVAL;
            goto fail;
        }

        idev->d_unit = unit;
        if (path != NULL)
            *path = (*cp == 0) ? cp : cp + 1;
        break;
    case DEVT_ZFS:
        err = zfs_parsedev((struct zfs_devdesc *)idev, np, path);
        if (err != 0)
            goto fail;
        break;
    default:
        err = EINVAL;
        goto fail;
    }
    idev->d_dev = dv;
    idev->d_type = dv->dv_type;
    if (dev == NULL) {
        free(idev);
    } else {
        *dev = idev;
    }
    return(0);

fail:
    free(idev);
    return(err);
}
Пример #3
0
/*
 * Point (dev) at an allocated device specifier matching the string version
 * at the beginning of (devspec).  Return a pointer to the remaining
 * text in (path).
 *
 * In all cases, the beginning of (devspec) is compared to the names
 * of known devices in the device switch, and then any following text
 * is parsed according to the rules applied to the device type.
 *
 * For disk-type devices, the syntax is:
 *
 * disk<unit>[s<slice>][<partition>]:
 *
 */
static int
i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path)
{
    struct i386_devdesc *idev;
    struct devsw	*dv;
    int			i, unit, slice, partition, err;
    char		*cp;
    const char		*np;

    /* minimum length check */
    if (strlen(devspec) < 2)
        return(EINVAL);

    /* look for a device that matches */
    for (i = 0, dv = NULL; devsw[i] != NULL; i++) {
        if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) {
            dv = devsw[i];
            break;
        }
    }
    if (dv == NULL)
        return(ENOENT);
    idev = malloc(sizeof(struct i386_devdesc));
    err = 0;
    np = (devspec + strlen(dv->dv_name));

    switch(dv->dv_type) {
    case DEVT_NONE:			/* XXX what to do here?  Do we care? */
        break;

    case DEVT_DISK:
        unit = -1;
        slice = -1;
        partition = -1;
        if (*np && (*np != ':')) {
            unit = strtol(np, &cp, 10);	/* next comes the unit number */
            if (cp == np) {
                err = EUNIT;
                goto fail;
            }
#ifdef LOADER_GPT_SUPPORT
            if (*cp == 'p') {		/* got a GPT partition */
                np = cp + 1;
                slice = strtol(np, &cp, 10);
                if (cp == np) {
                    err = ESLICE;
                    goto fail;
                }
                if (*cp && (*cp != ':')) {
                    err = EINVAL;
                    goto fail;
                }
                partition = 0xff;
            } else {
#endif
                if (*cp == 's') {		/* got a slice number */
                    np = cp + 1;
                    slice = strtol(np, &cp, 10);
                    if (cp == np) {
                        err = ESLICE;
                        goto fail;
                    }
                }
                if (*cp && (*cp != ':')) {
                    partition = *cp - 'a';	/* got a partition number */
                    if ((partition < 0) || (partition >= MAXPARTITIONS)) {
                        err = EPART;
                        goto fail;
                    }
                    cp++;
                }
#ifdef LOADER_GPT_SUPPORT
            }
#endif
        } else {
            cp = np;
        }
        if (*cp && (*cp != ':')) {
            err = EINVAL;
            goto fail;
        }

        idev->d_unit = unit;
        idev->d_kind.biosdisk.slice = slice;
        idev->d_kind.biosdisk.partition = partition;
        if (path != NULL)
            *path = (*cp == 0) ? cp : cp + 1;
        break;

    case DEVT_CD:
    case DEVT_NET:
        unit = 0;

        if (*np && (*np != ':')) {
            unit = strtol(np, &cp, 0);	/* get unit number if present */
            if (cp == np) {
                err = EUNIT;
                goto fail;
            }
        } else {
            cp = np;
        }
        if (*cp && (*cp != ':')) {
            err = EINVAL;
            goto fail;
        }

        idev->d_unit = unit;
        if (path != NULL)
            *path = (*cp == 0) ? cp : cp + 1;
        break;
    case DEVT_ZFS:
        err = zfs_parsedev((struct zfs_devdesc *)idev, np, path);
        if (err != 0)
            goto fail;
        break;
    default:
        err = EINVAL;
        goto fail;
    }
    idev->d_dev = dv;
    idev->d_type = dv->dv_type;
    if (dev == NULL) {
        free(idev);
    } else {
        *dev = idev;
    }
    return(0);

fail:
    free(idev);
    return(err);
}
Пример #4
0
/*
 * Point (dev) at an allocated device specifier matching the string version
 * at the beginning of (devspec).  Return a pointer to the remaining
 * text in (path).
 *
 * In all cases, the beginning of (devspec) is compared to the names
 * of known devices in the device switch, and then any following text
 * is parsed according to the rules applied to the device type.
 *
 * For disk-type devices, the syntax is:
 *
 * fs<unit>:
 */
static int
efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
{
	struct devdesc *idev;
	struct devsw *dv;
	int i, unit, err;
	char *cp;
	const char *np;

	/* minimum length check */
	if (strlen(devspec) < 2)
		return (EINVAL);

	/* look for a device that matches */
	for (i = 0; devsw[i] != NULL; i++) {
		dv = devsw[i];
		if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name)))
			break;
	}
	if (devsw[i] == NULL)
		return (ENOENT);

	np = devspec + strlen(dv->dv_name);
	idev = NULL;
	err = 0;

	switch (dv->dv_type) {
	case DEVT_NONE:
		break;

	case DEVT_DISK:
		idev = malloc(sizeof(struct disk_devdesc));
		if (idev == NULL)
			return (ENOMEM);

		err = disk_parsedev((struct disk_devdesc *)idev, np, path);
		if (err != 0)
			goto fail;
		break;

#ifdef EFI_ZFS_BOOT
	case DEVT_ZFS:
		idev = malloc(sizeof(struct zfs_devdesc));
		if (idev == NULL)
			return (ENOMEM);

		err = zfs_parsedev((struct zfs_devdesc*)idev, np, path);
		if (err != 0)
			goto fail;
		break;
#endif
	default:
		idev = malloc(sizeof(struct devdesc));
		if (idev == NULL)
			return (ENOMEM);

		unit = 0;
		cp = (char *)np;

		if (*np != '\0' && *np != ':') {
			errno = 0;
			unit = strtol(np, &cp, 0);
			if (errno != 0 || cp == np) {
				err = EUNIT;
				goto fail;
			}
		}
		if (*cp != '\0' && *cp != ':') {
			err = EINVAL;
			goto fail;
		}

		idev->d_unit = unit;
		if (path != NULL)
			*path = (*cp == 0) ? cp : cp + 1;
		break;
	}

	idev->d_dev = dv;
	idev->d_type = dv->dv_type;

	if (dev != NULL)
		*dev = idev;
	else
		free(idev);
	return (0);

fail:
	free(idev);
	return (err);
}