devicename.c revision 245424
138465Smsmith/*- 238465Smsmith * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 338465Smsmith * All rights reserved. 438465Smsmith * 538465Smsmith * Redistribution and use in source and binary forms, with or without 638465Smsmith * modification, are permitted provided that the following conditions 738465Smsmith * are met: 838465Smsmith * 1. Redistributions of source code must retain the above copyright 938465Smsmith * notice, this list of conditions and the following disclaimer. 1038465Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1138465Smsmith * notice, this list of conditions and the following disclaimer in the 1238465Smsmith * documentation and/or other materials provided with the distribution. 1338465Smsmith * 1438465Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1538465Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1638465Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1738465Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1838465Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1938465Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2038465Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2138465Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2238465Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2338465Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2438465Smsmith * SUCH DAMAGE. 2538465Smsmith */ 2638465Smsmith 27119482Sobrien#include <sys/cdefs.h> 28119482Sobrien__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/devicename.c 245424 2013-01-14 15:05:22Z sbruno $"); 29119482Sobrien 3038465Smsmith#include <stand.h> 3138465Smsmith#include <string.h> 3238465Smsmith#include "bootstrap.h" 33239066Sae#include "disk.h" 3438465Smsmith#include "libi386.h" 35235329Savg#include "../zfs/libzfs.h" 3638465Smsmith 3739673Sdfrstatic int i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path); 3838465Smsmith 3938465Smsmith/* 4038465Smsmith * Point (dev) at an allocated device specifier for the device matching the 4138465Smsmith * path in (devspec). If it contains an explicit device specification, 4238465Smsmith * use that. If not, use the default device. 4338465Smsmith */ 4438465Smsmithint 4539673Sdfri386_getdev(void **vdev, const char *devspec, const char **path) 4638465Smsmith{ 4738465Smsmith struct i386_devdesc **dev = (struct i386_devdesc **)vdev; 4838465Smsmith int rv; 4938465Smsmith 5038465Smsmith /* 5138465Smsmith * If it looks like this is just a path and no 5238465Smsmith * device, go with the current device. 5338465Smsmith */ 5438465Smsmith if ((devspec == NULL) || 5538465Smsmith (devspec[0] == '/') || 5638465Smsmith (strchr(devspec, ':') == NULL)) { 5738465Smsmith 5838465Smsmith if (((rv = i386_parsedev(dev, getenv("currdev"), NULL)) == 0) && 5938465Smsmith (path != NULL)) 6038465Smsmith *path = devspec; 6138465Smsmith return(rv); 6238465Smsmith } 6338465Smsmith 6438465Smsmith /* 6538465Smsmith * Try to parse the device name off the beginning of the devspec 6638465Smsmith */ 6738465Smsmith return(i386_parsedev(dev, devspec, path)); 6838465Smsmith} 6938465Smsmith 7038465Smsmith/* 7138465Smsmith * Point (dev) at an allocated device specifier matching the string version 7238465Smsmith * at the beginning of (devspec). Return a pointer to the remaining 7338465Smsmith * text in (path). 7438465Smsmith * 7538465Smsmith * In all cases, the beginning of (devspec) is compared to the names 7638465Smsmith * of known devices in the device switch, and then any following text 7738465Smsmith * is parsed according to the rules applied to the device type. 7838465Smsmith * 7938465Smsmith * For disk-type devices, the syntax is: 8038465Smsmith * 8138465Smsmith * disk<unit>[s<slice>][<partition>]: 8238465Smsmith * 8338465Smsmith */ 8438465Smsmithstatic int 8539673Sdfri386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path) 8638465Smsmith{ 8738465Smsmith struct i386_devdesc *idev; 8838465Smsmith struct devsw *dv; 89239066Sae int i, unit, err; 9039673Sdfr char *cp; 9139673Sdfr const char *np; 9238465Smsmith 9338465Smsmith /* minimum length check */ 9438465Smsmith if (strlen(devspec) < 2) 9538465Smsmith return(EINVAL); 9638465Smsmith 9738465Smsmith /* look for a device that matches */ 9838465Smsmith for (i = 0, dv = NULL; devsw[i] != NULL; i++) { 9938465Smsmith if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) { 10038465Smsmith dv = devsw[i]; 10138465Smsmith break; 10238465Smsmith } 10338465Smsmith } 10438465Smsmith if (dv == NULL) 10538465Smsmith return(ENOENT); 10638465Smsmith idev = malloc(sizeof(struct i386_devdesc)); 10738465Smsmith err = 0; 10838465Smsmith np = (devspec + strlen(dv->dv_name)); 10938465Smsmith 11038465Smsmith switch(dv->dv_type) { 11138465Smsmith case DEVT_NONE: /* XXX what to do here? Do we care? */ 11238465Smsmith break; 11338465Smsmith 11438465Smsmith case DEVT_DISK: 115239066Sae err = disk_parsedev((struct disk_devdesc *)idev, np, path); 116239066Sae if (err != 0) 11738465Smsmith goto fail; 11838465Smsmith break; 11986091Sjhb 12086091Sjhb case DEVT_CD: 12138465Smsmith case DEVT_NET: 12238465Smsmith unit = 0; 12386091Sjhb 12438465Smsmith if (*np && (*np != ':')) { 12538465Smsmith unit = strtol(np, &cp, 0); /* get unit number if present */ 12638465Smsmith if (cp == np) { 12738465Smsmith err = EUNIT; 12838465Smsmith goto fail; 12938465Smsmith } 130181282Scperciva } else { 131245424Ssbruno cp = (char *)np; 13238465Smsmith } 13338465Smsmith if (*cp && (*cp != ':')) { 13438465Smsmith err = EINVAL; 13538465Smsmith goto fail; 13638465Smsmith } 13786091Sjhb 138163897Smarcel idev->d_unit = unit; 13938465Smsmith if (path != NULL) 14038465Smsmith *path = (*cp == 0) ? cp : cp + 1; 14138465Smsmith break; 142235329Savg case DEVT_ZFS: 143235329Savg err = zfs_parsedev((struct zfs_devdesc *)idev, np, path); 144235329Savg if (err != 0) 145235329Savg goto fail; 146235329Savg break; 14738465Smsmith default: 14838465Smsmith err = EINVAL; 14938465Smsmith goto fail; 15038465Smsmith } 15138465Smsmith idev->d_dev = dv; 15238465Smsmith idev->d_type = dv->dv_type; 15338465Smsmith if (dev == NULL) { 15438465Smsmith free(idev); 15538465Smsmith } else { 15638465Smsmith *dev = idev; 15738465Smsmith } 15838465Smsmith return(0); 15938465Smsmith 16038465Smsmith fail: 16138465Smsmith free(idev); 16238465Smsmith return(err); 16338465Smsmith} 16438465Smsmith 16538465Smsmith 16638465Smsmithchar * 16738465Smsmithi386_fmtdev(void *vdev) 16838465Smsmith{ 16938465Smsmith struct i386_devdesc *dev = (struct i386_devdesc *)vdev; 17038465Smsmith static char buf[128]; /* XXX device length constant? */ 171239066Sae 17238465Smsmith switch(dev->d_type) { 17338465Smsmith case DEVT_NONE: 17438465Smsmith strcpy(buf, "(no device)"); 17538465Smsmith break; 17638465Smsmith 17786091Sjhb case DEVT_CD: 178239066Sae case DEVT_NET: 179163897Smarcel sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); 18086091Sjhb break; 18186091Sjhb 18238465Smsmith case DEVT_DISK: 183239066Sae return (disk_fmtdev(vdev)); 18438465Smsmith 185235329Savg case DEVT_ZFS: 186235329Savg return(zfs_fmtdev(vdev)); 18738465Smsmith } 18838465Smsmith return(buf); 18938465Smsmith} 19038465Smsmith 19138465Smsmith 19238465Smsmith/* 19338465Smsmith * Set currdev to suit the value being supplied in (value) 19438465Smsmith */ 19538465Smsmithint 196146697Sjhbi386_setcurrdev(struct env_var *ev, int flags, const void *value) 19738465Smsmith{ 19838465Smsmith struct i386_devdesc *ncurr; 19938465Smsmith int rv; 20039662Smsmith 20138465Smsmith if ((rv = i386_parsedev(&ncurr, value, NULL)) != 0) 20238465Smsmith return(rv); 20338465Smsmith free(ncurr); 20438465Smsmith env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 20538465Smsmith return(0); 20638465Smsmith} 207