Home | History | Annotate | Line # | Download | only in ski
devicename.c revision 1.7
      1 /*	$NetBSD: devicename.c,v 1.6 2014/03/27 18:22:56 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 Michael Smith <msmith (at) freebsd.org>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 /* __FBSDID("$FreeBSD: src/sys/boot/ia64/libski/devicename.c,v 1.2 2003/09/08 09:11:32 obrien Exp $"); */
     31 
     32 #include <lib/libsa/stand.h>
     33 #include <lib/libsa/loadfile.h>
     34 #include <lib/libkern/libkern.h>
     35 #include <sys/disklabel.h>
     36 
     37 #include <bootstrap.h>
     38 #include "libski.h"
     39 
     40 static int	ski_parsedev(struct ski_devdesc **dev, const char *devspec, const char **path);
     41 
     42 /*
     43  * Point (dev) at an allocated device specifier for the device matching the
     44  * path in (devspec). If it contains an explicit device specification,
     45  * use that.  If not, use the default device.
     46  */
     47 int
     48 ski_getdev(void **vdev, const char *devspec, const char **path)
     49 {
     50 	struct ski_devdesc **dev = (struct ski_devdesc **)vdev;
     51 	int		rv;
     52 
     53 	/*
     54 	 * If it looks like this is just a path and no
     55 	 * device, go with the current device.
     56 	 */
     57 	if ((devspec == NULL) ||
     58 	    (devspec[0] == '/') ||
     59 	    (strchr(devspec, ':') == NULL)) {
     60 
     61 		if (((rv = ski_parsedev(dev, getenv("currdev"), NULL)) == 0) &&
     62 		    (path != NULL))
     63 			*path = devspec;
     64 		return(rv);
     65 	}
     66 
     67 	/*
     68 	 * Try to parse the device name off the beginning of the devspec
     69 	 */
     70 	return(ski_parsedev(dev, devspec, path));
     71 }
     72 
     73 /*
     74  * Point (dev) at an allocated device specifier matching the string version
     75  * at the beginning of (devspec).  Return a pointer to the remaining
     76  * text in (path).
     77  *
     78  * In all cases, the beginning of (devspec) is compared to the names
     79  * of known devices in the device switch, and then any following text
     80  * is parsed according to the rules applied to the device type.
     81  *
     82  * For disk-type devices, the syntax is:
     83  *
     84  * disk<unit>[s<slice>][<partition>]:
     85  *
     86  */
     87 static int
     88 ski_parsedev(struct ski_devdesc **dev, const char *devspec, const char **path)
     89 {
     90 	struct ski_devdesc *idev;
     91 	struct devsw	*dv;
     92 	int dv_type;
     93 	int		i, unit, slice, partition, err;
     94 	char		*cp;
     95 	const char	*np;
     96 
     97 	/* minimum length check */
     98 	if (strlen(devspec) < 2)
     99 		return(EINVAL);
    100 
    101 	/* look for a device that matches */
    102 	for (i = 0, dv = NULL; i < ndevs; i++) {
    103 		if (!strncmp(devspec, devsw[i].dv_name, strlen(devsw[i].dv_name))) {
    104 			dv = &devsw[i];
    105 			break;
    106 		}
    107 	}
    108 
    109 	if (dv == NULL)
    110 		return(ENOENT);
    111 	idev = alloc(sizeof(struct ski_devdesc));
    112 	err = 0;
    113 	np = (devspec + strlen(dv->dv_name));
    114 
    115 	/* XXX: Fixme */
    116 	dv_type = DEVT_DISK;
    117 
    118 	switch(dv_type) {
    119 	case DEVT_NONE:			/* XXX what to do here?  Do we care? */
    120 		break;
    121 
    122 	case DEVT_DISK:			/* XXX: Need to fix DEVT_DISK for NetBSD disk conventions. */
    123 		unit = -1;
    124 		slice = -1;
    125 		partition = -1;
    126 		if (*np && (*np != ':')) {
    127 			unit = strtol(np, &cp, 10);	/* next comes the unit number */
    128 			if (cp == np) {
    129 				err = EUNIT;
    130 				goto fail;
    131 			}
    132 			if (*cp == 's') {		/* got a slice number */
    133 				np = cp + 1;
    134 				slice = strtol(np, &cp, 10);
    135 				if (cp == np) {
    136 					err = EPART;
    137 					goto fail;
    138 				}
    139 			}
    140 			if (*cp && (*cp != ':')) {
    141 				partition = *cp - 'a';		/* get a partition number */
    142 				if ((partition < 0) || (partition >= MAXPARTITIONS)) {
    143 					err = EPART;
    144 					goto fail;
    145 				}
    146 				cp++;
    147 			}
    148 		}
    149 		if (*cp && (*cp != ':')) {
    150 			err = EINVAL;
    151 			goto fail;
    152 		}
    153 
    154 		idev->d_kind.skidisk.unit = unit;
    155 		idev->d_kind.skidisk.slice = slice;
    156 		idev->d_kind.skidisk.partition = partition;
    157 
    158 		if (path != NULL)
    159 			*path = (*cp == 0) ? cp : cp + 1;
    160 		break;
    161 
    162 	case DEVT_NET:
    163 		unit = 0;
    164 
    165 		if (*np && (*np != ':')) {
    166 			unit = strtol(np, &cp, 0);	/* get unit number if present */
    167 			if (cp == np) {
    168 				err = EUNIT;
    169 				goto fail;
    170 			}
    171 		}
    172 		if (*cp && (*cp != ':')) {
    173 			err = EINVAL;
    174 			goto fail;
    175 		}
    176 
    177 		idev->d_kind.netif.unit = unit;
    178 		if (path != NULL)
    179 			*path = (*cp == 0) ? cp : cp + 1;
    180 		break;
    181 
    182 	default:
    183 		err = EINVAL;
    184 		goto fail;
    185 	}
    186 	idev->d_dev = dv;
    187 	idev->d_type = dv_type;
    188 	if (dev == NULL) {
    189 		free(idev);
    190 	} else {
    191 		*dev = idev;
    192 	}
    193 	return(0);
    194 
    195  fail:
    196 	free(idev);
    197 	return(err);
    198 }
    199 
    200 
    201 char *
    202 ski_fmtdev(void *vdev)
    203 {
    204 	struct ski_devdesc *dev = (struct ski_devdesc *)vdev;
    205 	static char	buf[128];	/* XXX device length constant? */
    206 	size_t len, buflen = sizeof(buf);
    207 
    208 	switch(dev->d_type) {
    209 	case DEVT_NONE:
    210 		strlcpy(buf, "(no device)", buflen);
    211 		break;
    212 
    213 	case DEVT_DISK:
    214 		len = snprintf(buf, buflen, "%s%d", dev->d_dev->dv_name, dev->d_kind.skidisk.unit);
    215 		if (len > buflen)
    216 			len = buflen;
    217 		if (dev->d_kind.skidisk.slice > 0) {
    218 			len += snprintf(buf + len, buflen - len, "s%d", dev->d_kind.skidisk.slice);
    219 			if (len > buflen)
    220 				len = buflen;
    221 		}
    222 		if (dev->d_kind.skidisk.partition >= 0) {
    223 			len += snprintf(buf + len, buflen - len, "%c", dev->d_kind.skidisk.partition + 'a');
    224 			if (len > buflen)
    225 				len = buflen;
    226 		}
    227 		strlcat(buf, ":", buflen - len);
    228 		break;
    229 
    230 	case DEVT_NET:
    231 		snprintf(buf, buflen - len, "%s%d:", dev->d_dev->dv_name, dev->d_kind.netif.unit);
    232 		break;
    233 	}
    234 	return(buf);
    235 }
    236 
    237 
    238 /*
    239  * Set currdev to suit the value being supplied in (value)
    240  */
    241 int
    242 ski_setcurrdev(struct env_var *ev, int flags, void *value)
    243 {
    244 	struct ski_devdesc *ncurr;
    245 	int		rv;
    246 
    247 	if ((rv = ski_parsedev(&ncurr, value, NULL)) != 0)
    248 		return(rv);
    249 	free(ncurr);
    250 	env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
    251 	return(0);
    252 }
    253 
    254