devicename.c revision 68548
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 * 2650477Speter * $FreeBSD: head/sys/boot/ofw/libofw/devicename.c 68548 2000-11-10 06:39:58Z benno $ 2738465Smsmith */ 2838465Smsmith 2938465Smsmith#include <stand.h> 3038465Smsmith#include <sys/disklabel.h> 3167227Sobrien#include "libofw.h" 3238465Smsmith 3367227Sobrienstatic int ofw_parsedev(struct ofw_devdesc **, const char *, const char **); 3438465Smsmith 3538465Smsmith/* 3638465Smsmith * Point (dev) at an allocated device specifier for the device matching the 3738465Smsmith * path in (devspec). If it contains an explicit device specification, 3838465Smsmith * use that. If not, use the default device. 3938465Smsmith */ 4038465Smsmithint 4167227Sobrienofw_getdev(void **vdev, const char *devspec, const char **path) 4238465Smsmith{ 4367227Sobrien struct ofw_devdesc **dev = (struct ofw_devdesc **)vdev; 4438465Smsmith int rv; 4538465Smsmith 4638465Smsmith /* 4738465Smsmith * If it looks like this is just a path and no 4838465Smsmith * device, go with the current device. 4938465Smsmith */ 5038465Smsmith if ((devspec == NULL) || 5138465Smsmith (devspec[0] == '/') || 5238465Smsmith (strchr(devspec, ':') == NULL)) { 5338465Smsmith 5467227Sobrien if (((rv = ofw_parsedev(dev, getenv("currdev"), NULL)) == 0) && 5538465Smsmith (path != NULL)) 5638465Smsmith *path = devspec; 5738465Smsmith return(rv); 5838465Smsmith } 5938465Smsmith 6038465Smsmith /* 6138465Smsmith * Try to parse the device name off the beginning of the devspec 6238465Smsmith */ 6367227Sobrien return(ofw_parsedev(dev, devspec, path)); 6438465Smsmith} 6538465Smsmith 6638465Smsmith/* 6738465Smsmith * Point (dev) at an allocated device specifier matching the string version 6838465Smsmith * at the beginning of (devspec). Return a pointer to the remaining 6938465Smsmith * text in (path). 7038465Smsmith * 7138465Smsmith * In all cases, the beginning of (devspec) is compared to the names 7238465Smsmith * of known devices in the device switch, and then any following text 7338465Smsmith * is parsed according to the rules applied to the device type. 7438465Smsmith * 7538465Smsmith * For disk-type devices, the syntax is: 7638465Smsmith * 7738465Smsmith * disk<unit>[s<slice>][<partition>]: 7838465Smsmith * 7938465Smsmith */ 8038465Smsmithstatic int 8167227Sobrienofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path) 8238465Smsmith{ 8367227Sobrien struct ofw_devdesc *idev; 8438465Smsmith struct devsw *dv; 8538465Smsmith int i, unit, slice, partition, err; 8639673Sdfr char *cp; 8739673Sdfr const char *np; 8838465Smsmith 8938465Smsmith /* minimum length check */ 9038465Smsmith if (strlen(devspec) < 2) 9138465Smsmith return(EINVAL); 9238465Smsmith 9338465Smsmith /* look for a device that matches */ 9438465Smsmith for (i = 0, dv = NULL; devsw[i] != NULL; i++) { 9538465Smsmith if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) { 9638465Smsmith dv = devsw[i]; 9738465Smsmith break; 9838465Smsmith } 9938465Smsmith } 10038465Smsmith 10138465Smsmith if (dv == NULL) 10238465Smsmith return(ENOENT); 10367227Sobrien idev = malloc(sizeof(struct ofw_devdesc)); 10438465Smsmith err = 0; 10538465Smsmith np = (devspec + strlen(dv->dv_name)); 10638465Smsmith 10738465Smsmith switch(dv->dv_type) { 10838465Smsmith case DEVT_NONE: /* XXX what to do here? Do we care? */ 10938465Smsmith break; 11038465Smsmith 11138465Smsmith case DEVT_DISK: 11238465Smsmith unit = -1; 11338465Smsmith slice = -1; 11438465Smsmith partition = -1; 11538465Smsmith if (*np && (*np != ':')) { 11638465Smsmith unit = strtol(np, &cp, 10); /* next comes the unit number */ 11738465Smsmith if (cp == np) { 11838465Smsmith err = EUNIT; 11938465Smsmith goto fail; 12038465Smsmith } 12138465Smsmith if (*cp == 's') { /* got a slice number */ 12238465Smsmith np = cp + 1; 12338465Smsmith slice = strtol(np, &cp, 10); 12438465Smsmith if (cp == np) { 12538465Smsmith err = ESLICE; 12638465Smsmith goto fail; 12738465Smsmith } 12838465Smsmith } 12938465Smsmith if (*cp && (*cp != ':')) { 13038465Smsmith partition = *cp - 'a'; /* get a partition number */ 13138465Smsmith if ((partition < 0) || (partition >= MAXPARTITIONS)) { 13238465Smsmith err = EPART; 13338465Smsmith goto fail; 13438465Smsmith } 13538465Smsmith cp++; 13638465Smsmith } 13738465Smsmith } 13838465Smsmith if (*cp && (*cp != ':')) { 13938465Smsmith err = EINVAL; 14038465Smsmith goto fail; 14138465Smsmith } 14238465Smsmith 14367227Sobrien idev->d_kind.ofwdisk.unit = unit; 14467227Sobrien idev->d_kind.ofwdisk.slice = slice; 14567227Sobrien idev->d_kind.ofwdisk.partition = partition; 14638465Smsmith if (path != NULL) 14738465Smsmith *path = (*cp == 0) ? cp : cp + 1; 14838465Smsmith break; 14938465Smsmith 15038465Smsmith case DEVT_NET: 15138465Smsmith unit = 0; 15238465Smsmith 15338465Smsmith if (*np && (*np != ':')) { 15438465Smsmith unit = strtol(np, &cp, 0); /* get unit number if present */ 15538465Smsmith if (cp == np) { 15638465Smsmith err = EUNIT; 15738465Smsmith goto fail; 15838465Smsmith } 15938465Smsmith } 16038465Smsmith if (*cp && (*cp != ':')) { 16138465Smsmith err = EINVAL; 16238465Smsmith goto fail; 16338465Smsmith } 16438465Smsmith 16538465Smsmith idev->d_kind.netif.unit = unit; 16638465Smsmith if (path != NULL) 16738465Smsmith *path = (*cp == 0) ? cp : cp + 1; 16838465Smsmith break; 16938465Smsmith 17038465Smsmith default: 17138465Smsmith err = EINVAL; 17238465Smsmith goto fail; 17338465Smsmith } 17438465Smsmith idev->d_dev = dv; 17538465Smsmith idev->d_type = dv->dv_type; 17638475Sdfr if (dev == NULL) { 17738475Sdfr free(idev); 17838475Sdfr } else { 17938465Smsmith *dev = idev; 18038475Sdfr } 18138465Smsmith return(0); 18238465Smsmith 18338465Smsmith fail: 18438465Smsmith free(idev); 18538465Smsmith return(err); 18638465Smsmith} 18768548Sbenno 18868548Sbennochar * 18968548Sbennoofw_fmtdev(void *vdev) 19068548Sbenno{ 19168548Sbenno struct ofw_devdesc *dev = (struct ofw_devdesc *)vdev; 19268548Sbenno static char buf[128]; 19368548Sbenno char *cp; 19468548Sbenno 19568548Sbenno switch(dev->d_type) { 19668548Sbenno case DEVT_NONE: 19768548Sbenno strcpy(buf, "(no device)"); 19868548Sbenno break; 19968548Sbenno 20068548Sbenno case DEVT_DISK: 20168548Sbenno /* XXX Insert stuff here */ 20268548Sbenno sprintf(buf, "%s%d:", dev->d_dev->dv_name, 20368548Sbenno dev->d_kind.ofwdisk.unit); 20468548Sbenno break; 20568548Sbenno 20668548Sbenno case DEVT_NET: 20768548Sbenno sprintf(buf, "%s%d:", dev->d_dev->dv_name, 20868548Sbenno dev->d_kind.netif.unit); 20968548Sbenno break; 21068548Sbenno } 21168548Sbenno 21268548Sbenno return buf; 21368548Sbenno} 21468548Sbenno 21568548Sbennoint 21668548Sbennoofw_setcurrdev(struct env_var *ev, int flags, void *value) 21768548Sbenno{ 21868548Sbenno struct ofw_devdesc *ncurr; 21968548Sbenno int rv; 22068548Sbenno 22168548Sbenno if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0) 22268548Sbenno return rv; 22368548Sbenno 22468548Sbenno free(ncurr); 22568548Sbenno env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 22668548Sbenno return 0; 22768548Sbenno} 228