devicename.c revision 146697
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 146697 2005-05-27 19:28:04Z jhb $"); 29119482Sobrien 3038465Smsmith#include <stand.h> 3138465Smsmith#include <string.h> 3238465Smsmith#include <sys/disklabel.h> 3338465Smsmith#include "bootstrap.h" 3438465Smsmith#include "libi386.h" 3538465Smsmith 3639673Sdfrstatic int i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path); 3738465Smsmith 3838465Smsmith/* 3938465Smsmith * Point (dev) at an allocated device specifier for the device matching the 4038465Smsmith * path in (devspec). If it contains an explicit device specification, 4138465Smsmith * use that. If not, use the default device. 4238465Smsmith */ 4338465Smsmithint 4439673Sdfri386_getdev(void **vdev, const char *devspec, const char **path) 4538465Smsmith{ 4638465Smsmith struct i386_devdesc **dev = (struct i386_devdesc **)vdev; 4738465Smsmith int rv; 4838465Smsmith 4938465Smsmith /* 5038465Smsmith * If it looks like this is just a path and no 5138465Smsmith * device, go with the current device. 5238465Smsmith */ 5338465Smsmith if ((devspec == NULL) || 5438465Smsmith (devspec[0] == '/') || 5538465Smsmith (strchr(devspec, ':') == NULL)) { 5638465Smsmith 5738465Smsmith if (((rv = i386_parsedev(dev, getenv("currdev"), NULL)) == 0) && 5838465Smsmith (path != NULL)) 5938465Smsmith *path = devspec; 6038465Smsmith return(rv); 6138465Smsmith } 6238465Smsmith 6338465Smsmith /* 6438465Smsmith * Try to parse the device name off the beginning of the devspec 6538465Smsmith */ 6638465Smsmith return(i386_parsedev(dev, devspec, path)); 6738465Smsmith} 6838465Smsmith 6938465Smsmith/* 7038465Smsmith * Point (dev) at an allocated device specifier matching the string version 7138465Smsmith * at the beginning of (devspec). Return a pointer to the remaining 7238465Smsmith * text in (path). 7338465Smsmith * 7438465Smsmith * In all cases, the beginning of (devspec) is compared to the names 7538465Smsmith * of known devices in the device switch, and then any following text 7638465Smsmith * is parsed according to the rules applied to the device type. 7738465Smsmith * 7838465Smsmith * For disk-type devices, the syntax is: 7938465Smsmith * 8038465Smsmith * disk<unit>[s<slice>][<partition>]: 8138465Smsmith * 8238465Smsmith */ 8338465Smsmithstatic int 8439673Sdfri386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path) 8538465Smsmith{ 8638465Smsmith struct i386_devdesc *idev; 8738465Smsmith struct devsw *dv; 8838465Smsmith int i, unit, slice, partition, err; 8939673Sdfr char *cp; 9039673Sdfr const char *np; 9138465Smsmith 9238465Smsmith /* minimum length check */ 9338465Smsmith if (strlen(devspec) < 2) 9438465Smsmith return(EINVAL); 9538465Smsmith 9638465Smsmith /* look for a device that matches */ 9738465Smsmith for (i = 0, dv = NULL; devsw[i] != NULL; i++) { 9838465Smsmith if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) { 9938465Smsmith dv = devsw[i]; 10038465Smsmith break; 10138465Smsmith } 10238465Smsmith } 10338465Smsmith if (dv == NULL) 10438465Smsmith return(ENOENT); 10538465Smsmith idev = malloc(sizeof(struct i386_devdesc)); 10638465Smsmith err = 0; 10738465Smsmith np = (devspec + strlen(dv->dv_name)); 10838465Smsmith 10938465Smsmith switch(dv->dv_type) { 11038465Smsmith case DEVT_NONE: /* XXX what to do here? Do we care? */ 11138465Smsmith break; 11238465Smsmith 11338465Smsmith case DEVT_DISK: 11438465Smsmith unit = -1; 11538465Smsmith slice = -1; 11638465Smsmith partition = -1; 11738465Smsmith if (*np && (*np != ':')) { 11838465Smsmith unit = strtol(np, &cp, 10); /* next comes the unit number */ 11938465Smsmith if (cp == np) { 12038465Smsmith err = EUNIT; 12138465Smsmith goto fail; 12238465Smsmith } 12338465Smsmith if (*cp == 's') { /* got a slice number */ 12438465Smsmith np = cp + 1; 12538465Smsmith slice = strtol(np, &cp, 10); 12638465Smsmith if (cp == np) { 12738465Smsmith err = ESLICE; 12838465Smsmith goto fail; 12938465Smsmith } 13038465Smsmith } 13138465Smsmith if (*cp && (*cp != ':')) { 13238465Smsmith partition = *cp - 'a'; /* get a partition number */ 13338465Smsmith if ((partition < 0) || (partition >= MAXPARTITIONS)) { 13438465Smsmith err = EPART; 13538465Smsmith goto fail; 13638465Smsmith } 13738465Smsmith cp++; 13838465Smsmith } 13938465Smsmith } 14038465Smsmith if (*cp && (*cp != ':')) { 14138465Smsmith err = EINVAL; 14238465Smsmith goto fail; 14338465Smsmith } 14438465Smsmith 14538465Smsmith idev->d_kind.biosdisk.unit = unit; 14638465Smsmith idev->d_kind.biosdisk.slice = slice; 14738465Smsmith idev->d_kind.biosdisk.partition = partition; 14838465Smsmith if (path != NULL) 14938465Smsmith *path = (*cp == 0) ? cp : cp + 1; 15038465Smsmith break; 15186091Sjhb 15286091Sjhb case DEVT_CD: 15338465Smsmith case DEVT_NET: 15438465Smsmith unit = 0; 15586091Sjhb 15638465Smsmith if (*np && (*np != ':')) { 15738465Smsmith unit = strtol(np, &cp, 0); /* get unit number if present */ 15838465Smsmith if (cp == np) { 15938465Smsmith err = EUNIT; 16038465Smsmith goto fail; 16138465Smsmith } 16238465Smsmith } 16338465Smsmith if (*cp && (*cp != ':')) { 16438465Smsmith err = EINVAL; 16538465Smsmith goto fail; 16638465Smsmith } 16786091Sjhb 16886091Sjhb if (dv->dv_type == DEVT_NET) 16986091Sjhb idev->d_kind.netif.unit = unit; 17086091Sjhb else 17186091Sjhb idev->d_kind.bioscd.unit = unit; 17238465Smsmith if (path != NULL) 17338465Smsmith *path = (*cp == 0) ? cp : cp + 1; 17438465Smsmith break; 17538465Smsmith 17638465Smsmith default: 17738465Smsmith err = EINVAL; 17838465Smsmith goto fail; 17938465Smsmith } 18038465Smsmith idev->d_dev = dv; 18138465Smsmith idev->d_type = dv->dv_type; 18238465Smsmith if (dev == NULL) { 18338465Smsmith free(idev); 18438465Smsmith } else { 18538465Smsmith *dev = idev; 18638465Smsmith } 18738465Smsmith return(0); 18838465Smsmith 18938465Smsmith fail: 19038465Smsmith free(idev); 19138465Smsmith return(err); 19238465Smsmith} 19338465Smsmith 19438465Smsmith 19538465Smsmithchar * 19638465Smsmithi386_fmtdev(void *vdev) 19738465Smsmith{ 19838465Smsmith struct i386_devdesc *dev = (struct i386_devdesc *)vdev; 19938465Smsmith static char buf[128]; /* XXX device length constant? */ 20038465Smsmith char *cp; 20138465Smsmith 20238465Smsmith switch(dev->d_type) { 20338465Smsmith case DEVT_NONE: 20438465Smsmith strcpy(buf, "(no device)"); 20538465Smsmith break; 20638465Smsmith 20786091Sjhb case DEVT_CD: 20886091Sjhb sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_kind.bioscd.unit); 20986091Sjhb break; 21086091Sjhb 21138465Smsmith case DEVT_DISK: 21238465Smsmith cp = buf; 21338465Smsmith cp += sprintf(cp, "%s%d", dev->d_dev->dv_name, dev->d_kind.biosdisk.unit); 21438465Smsmith if (dev->d_kind.biosdisk.slice > 0) 21538465Smsmith cp += sprintf(cp, "s%d", dev->d_kind.biosdisk.slice); 21638465Smsmith if (dev->d_kind.biosdisk.partition >= 0) 21738465Smsmith cp += sprintf(cp, "%c", dev->d_kind.biosdisk.partition + 'a'); 21838465Smsmith strcat(cp, ":"); 21938465Smsmith break; 22038465Smsmith 22138465Smsmith case DEVT_NET: 22238465Smsmith sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_kind.netif.unit); 22338465Smsmith break; 22438465Smsmith } 22538465Smsmith return(buf); 22638465Smsmith} 22738465Smsmith 22838465Smsmith 22938465Smsmith/* 23038465Smsmith * Set currdev to suit the value being supplied in (value) 23138465Smsmith */ 23238465Smsmithint 233146697Sjhbi386_setcurrdev(struct env_var *ev, int flags, const void *value) 23438465Smsmith{ 23538465Smsmith struct i386_devdesc *ncurr; 23638465Smsmith int rv; 23739662Smsmith 23838465Smsmith if ((rv = i386_parsedev(&ncurr, value, NULL)) != 0) 23938465Smsmith return(rv); 24038465Smsmith free(ncurr); 24138465Smsmith env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 24238465Smsmith return(0); 24338465Smsmith} 24438465Smsmith 245