xref: /titanic_54/usr/src/boot/sys/boot/i386/libi386/devicename.c (revision 71552555a08e75de9106ae6e2ed4827b54c78330)
1*71552555SToomas Soome /*
24a5d661aSToomas Soome  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
34a5d661aSToomas Soome  * All rights reserved.
44a5d661aSToomas Soome  *
54a5d661aSToomas Soome  * Redistribution and use in source and binary forms, with or without
64a5d661aSToomas Soome  * modification, are permitted provided that the following conditions
74a5d661aSToomas Soome  * are met:
84a5d661aSToomas Soome  * 1. Redistributions of source code must retain the above copyright
94a5d661aSToomas Soome  *    notice, this list of conditions and the following disclaimer.
104a5d661aSToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
114a5d661aSToomas Soome  *    notice, this list of conditions and the following disclaimer in the
124a5d661aSToomas Soome  *    documentation and/or other materials provided with the distribution.
134a5d661aSToomas Soome  *
144a5d661aSToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
154a5d661aSToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
164a5d661aSToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
174a5d661aSToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
184a5d661aSToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
194a5d661aSToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
204a5d661aSToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
214a5d661aSToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
224a5d661aSToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
234a5d661aSToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
244a5d661aSToomas Soome  * SUCH DAMAGE.
254a5d661aSToomas Soome  */
264a5d661aSToomas Soome 
274a5d661aSToomas Soome #include <sys/cdefs.h>
284a5d661aSToomas Soome 
294a5d661aSToomas Soome #include <stand.h>
304a5d661aSToomas Soome #include <string.h>
31*71552555SToomas Soome #include <sys/param.h>
324a5d661aSToomas Soome #include "bootstrap.h"
334a5d661aSToomas Soome #include "disk.h"
344a5d661aSToomas Soome #include "libi386.h"
354a5d661aSToomas Soome #include "../zfs/libzfs.h"
364a5d661aSToomas Soome 
37*71552555SToomas Soome static int i386_parsedev(struct i386_devdesc **, const char *, const char **);
384a5d661aSToomas Soome 
394a5d661aSToomas Soome /*
40*71552555SToomas Soome  * Point dev at an allocated device specifier for the device matching the
41*71552555SToomas Soome  * path in devspec. If it contains an explicit device specification,
424a5d661aSToomas Soome  * use that.  If not, use the default device.
434a5d661aSToomas Soome  */
444a5d661aSToomas Soome int
i386_getdev(void ** vdev,const char * devspec,const char ** path)454a5d661aSToomas Soome i386_getdev(void **vdev, const char *devspec, const char **path)
464a5d661aSToomas Soome {
474a5d661aSToomas Soome 	struct i386_devdesc **dev = (struct i386_devdesc **)vdev;
484a5d661aSToomas Soome 	int rv;
494a5d661aSToomas Soome 
504a5d661aSToomas Soome 	/*
514a5d661aSToomas Soome 	 * If it looks like this is just a path and no
524a5d661aSToomas Soome 	 * device, go with the current device.
534a5d661aSToomas Soome 	 */
544a5d661aSToomas Soome 	if ((devspec == NULL) ||
55*71552555SToomas Soome 	    (devspec[0] == '/') || (strchr(devspec, ':') == NULL)) {
564a5d661aSToomas Soome 
57*71552555SToomas Soome 		rv = i386_parsedev(dev, getenv("currdev"), NULL);
58*71552555SToomas Soome 		if (rv == 0 && path != NULL)
594a5d661aSToomas Soome 			*path = devspec;
604a5d661aSToomas Soome 		return (rv);
614a5d661aSToomas Soome 	}
624a5d661aSToomas Soome 
634a5d661aSToomas Soome 	/*
644a5d661aSToomas Soome 	 * Try to parse the device name off the beginning of the devspec
654a5d661aSToomas Soome 	 */
664a5d661aSToomas Soome 	return (i386_parsedev(dev, devspec, path));
674a5d661aSToomas Soome }
684a5d661aSToomas Soome 
694a5d661aSToomas Soome /*
704a5d661aSToomas Soome  * Point (dev) at an allocated device specifier matching the string version
714a5d661aSToomas Soome  * at the beginning of (devspec).  Return a pointer to the remaining
724a5d661aSToomas Soome  * text in (path).
734a5d661aSToomas Soome  *
744a5d661aSToomas Soome  * In all cases, the beginning of (devspec) is compared to the names
754a5d661aSToomas Soome  * of known devices in the device switch, and then any following text
764a5d661aSToomas Soome  * is parsed according to the rules applied to the device type.
774a5d661aSToomas Soome  *
784a5d661aSToomas Soome  * For disk-type devices, the syntax is:
794a5d661aSToomas Soome  *
804a5d661aSToomas Soome  * disk<unit>[s<slice>][<partition>]:
814a5d661aSToomas Soome  *
824a5d661aSToomas Soome  */
834a5d661aSToomas Soome static int
i386_parsedev(struct i386_devdesc ** dev,const char * devspec,const char ** path)844a5d661aSToomas Soome i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path)
854a5d661aSToomas Soome {
864a5d661aSToomas Soome 	struct i386_devdesc *idev;
874a5d661aSToomas Soome 	struct devsw *dv;
884a5d661aSToomas Soome 	int i, unit, err;
894a5d661aSToomas Soome 	char *cp;
904a5d661aSToomas Soome 	const char *np;
914a5d661aSToomas Soome 
924a5d661aSToomas Soome 	/* minimum length check */
934a5d661aSToomas Soome 	if (strlen(devspec) < 2)
944a5d661aSToomas Soome 		return (EINVAL);
954a5d661aSToomas Soome 
964a5d661aSToomas Soome 	/* look for a device that matches */
974a5d661aSToomas Soome 	for (i = 0, dv = NULL; devsw[i] != NULL; i++) {
984a5d661aSToomas Soome 		dv = devsw[i];
99*71552555SToomas Soome 		if (strncmp(devspec, dv->dv_name, strlen(dv->dv_name)) == 0)
1004a5d661aSToomas Soome 			break;
1014a5d661aSToomas Soome 	}
102*71552555SToomas Soome 	if (devsw[i] == NULL)
1034a5d661aSToomas Soome 		return (ENOENT);
104*71552555SToomas Soome 
105*71552555SToomas Soome 	np = devspec + strlen(dv->dv_name);
106*71552555SToomas Soome 	idev = NULL;
1074a5d661aSToomas Soome 	err = 0;
1084a5d661aSToomas Soome 
1094a5d661aSToomas Soome 	switch (dv->dv_type) {
110*71552555SToomas Soome 	case DEVT_NONE:
1114a5d661aSToomas Soome 		break;
1124a5d661aSToomas Soome 
1134a5d661aSToomas Soome 	case DEVT_DISK:
114*71552555SToomas Soome 		idev = malloc(sizeof (struct i386_devdesc));
115*71552555SToomas Soome 		if (idev == NULL)
116*71552555SToomas Soome 			return (ENOMEM);
117*71552555SToomas Soome 
1184a5d661aSToomas Soome 		err = disk_parsedev((struct disk_devdesc *)idev, np, path);
1194a5d661aSToomas Soome 		if (err != 0)
1204a5d661aSToomas Soome 			goto fail;
1214a5d661aSToomas Soome 		break;
1224a5d661aSToomas Soome 
123*71552555SToomas Soome 	case DEVT_ZFS:
124*71552555SToomas Soome 		idev = malloc(sizeof (struct zfs_devdesc));
125*71552555SToomas Soome 		if (idev == NULL)
126*71552555SToomas Soome 			return (ENOMEM);
127*71552555SToomas Soome 
128*71552555SToomas Soome 		err = zfs_parsedev((struct zfs_devdesc *)idev, np, path);
129*71552555SToomas Soome 		if (err != 0)
130*71552555SToomas Soome 			goto fail;
131*71552555SToomas Soome 		break;
132*71552555SToomas Soome 
133*71552555SToomas Soome 	default:
134*71552555SToomas Soome 		idev = malloc(sizeof (struct devdesc));
135*71552555SToomas Soome 		if (idev == NULL)
136*71552555SToomas Soome 			return (ENOMEM);
137*71552555SToomas Soome 
1384a5d661aSToomas Soome 		unit = 0;
139*71552555SToomas Soome 		cp = (char *)np;
1404a5d661aSToomas Soome 
1414a5d661aSToomas Soome 		if (*np && (*np != ':')) {
142*71552555SToomas Soome 			/* get unit number if present */
143*71552555SToomas Soome 			unit = strtol(np, &cp, 0);
1444a5d661aSToomas Soome 			if (cp == np) {
1454a5d661aSToomas Soome 				err = EUNIT;
1464a5d661aSToomas Soome 				goto fail;
1474a5d661aSToomas Soome 			}
1484a5d661aSToomas Soome 		}
1494a5d661aSToomas Soome 		if (*cp && (*cp != ':')) {
1504a5d661aSToomas Soome 			err = EINVAL;
1514a5d661aSToomas Soome 			goto fail;
1524a5d661aSToomas Soome 		}
1534a5d661aSToomas Soome 
1544a5d661aSToomas Soome 		idev->d_unit = unit;
1554a5d661aSToomas Soome 		if (path != NULL)
156*71552555SToomas Soome 			*path = (*cp == '\0') ? cp : cp + 1;
1574a5d661aSToomas Soome 		break;
1584a5d661aSToomas Soome 	}
159*71552555SToomas Soome 
1604a5d661aSToomas Soome 	idev->d_dev = dv;
1614a5d661aSToomas Soome 	idev->d_type = dv->dv_type;
162*71552555SToomas Soome 
163*71552555SToomas Soome 	if (dev != NULL)
1644a5d661aSToomas Soome 		*dev = idev;
165*71552555SToomas Soome 	else
166*71552555SToomas Soome 		free(idev);
1674a5d661aSToomas Soome 	return (0);
1684a5d661aSToomas Soome 
1694a5d661aSToomas Soome fail:
1704a5d661aSToomas Soome 	free(idev);
1714a5d661aSToomas Soome 	return (err);
1724a5d661aSToomas Soome }
1734a5d661aSToomas Soome 
1744a5d661aSToomas Soome 
1754a5d661aSToomas Soome char *
i386_fmtdev(void * vdev)1764a5d661aSToomas Soome i386_fmtdev(void *vdev)
1774a5d661aSToomas Soome {
1784a5d661aSToomas Soome 	struct i386_devdesc *dev = (struct i386_devdesc *)vdev;
179*71552555SToomas Soome 	static char buf[SPECNAMELEN + 1];
1804a5d661aSToomas Soome 
1814a5d661aSToomas Soome 	switch (dev->d_type) {
1824a5d661aSToomas Soome 	case DEVT_NONE:
183*71552555SToomas Soome 		strlcpy(buf, "(no device)", sizeof (buf));
1844a5d661aSToomas Soome 		break;
1854a5d661aSToomas Soome 
1864a5d661aSToomas Soome 	case DEVT_DISK:
1874a5d661aSToomas Soome 		return (disk_fmtdev(vdev));
1884a5d661aSToomas Soome 
1894a5d661aSToomas Soome 	case DEVT_ZFS:
1904a5d661aSToomas Soome 		return (zfs_fmtdev(vdev));
191*71552555SToomas Soome 
192*71552555SToomas Soome 	default:
193*71552555SToomas Soome 		snprintf(buf, sizeof (buf), "%s%d:", dev->d_dev->dv_name,
194*71552555SToomas Soome 		    dev->d_unit);
195*71552555SToomas Soome 		break;
1964a5d661aSToomas Soome 	}
1974a5d661aSToomas Soome 	return (buf);
1984a5d661aSToomas Soome }
1994a5d661aSToomas Soome 
2004a5d661aSToomas Soome 
2014a5d661aSToomas Soome /*
2024a5d661aSToomas Soome  * Set currdev to suit the value being supplied in (value)
2034a5d661aSToomas Soome  */
2044a5d661aSToomas Soome int
i386_setcurrdev(struct env_var * ev,int flags,const void * value)2054a5d661aSToomas Soome i386_setcurrdev(struct env_var *ev, int flags, const void *value)
2064a5d661aSToomas Soome {
2074a5d661aSToomas Soome 	struct i386_devdesc *ncurr;
2084a5d661aSToomas Soome 	int rv;
2094a5d661aSToomas Soome 
2104a5d661aSToomas Soome 	if ((rv = i386_parsedev(&ncurr, value, NULL)) != 0)
2114a5d661aSToomas Soome 		return (rv);
212*71552555SToomas Soome 
2134a5d661aSToomas Soome 	free(ncurr);
2144a5d661aSToomas Soome 	env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
2154a5d661aSToomas Soome 	return (0);
2164a5d661aSToomas Soome }
217