devicename.c revision 236076
1/*- 2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/9/sys/boot/ofw/libofw/devicename.c 236076 2012-05-26 08:54:26Z marius $"); 29 30#include <stand.h> 31 32#include "bootstrap.h" 33#include "libofw.h" 34 35static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **); 36 37/* 38 * Point (dev) at an allocated device specifier for the device matching the 39 * path in (devspec). If it contains an explicit device specification, 40 * use that. If not, use the default device. 41 */ 42int 43ofw_getdev(void **vdev, const char *devspec, const char **path) 44{ 45 struct ofw_devdesc **dev = (struct ofw_devdesc **)vdev; 46 int rv; 47 48 /* 49 * If it looks like this is just a path and no 50 * device, go with the current device. 51 */ 52 if ((devspec == NULL) || 53 ((strchr(devspec, '@') == NULL) && 54 (strchr(devspec, ':') == NULL))) { 55 56 if (((rv = ofw_parsedev(dev, getenv("currdev"), NULL)) == 0) && 57 (path != NULL)) 58 *path = devspec; 59 return(rv); 60 } 61 62 /* 63 * Try to parse the device name off the beginning of the devspec 64 */ 65 return(ofw_parsedev(dev, devspec, path)); 66} 67 68/* 69 * Point (dev) at an allocated device specifier matching the string version 70 * at the beginning of (devspec). Return a pointer to the remaining 71 * text in (path). 72 */ 73static int 74ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path) 75{ 76 struct ofw_devdesc *idev; 77 struct devsw *dv; 78 phandle_t handle; 79 const char *p; 80 const char *s; 81 char *ep; 82 char name[256]; 83 char type[64]; 84 int len; 85 int i; 86 87 for (p = s = devspec; *s != '\0'; p = s) { 88 if ((s = strchr(p + 1, '/')) == NULL) 89 s = strchr(p, '\0'); 90 len = s - devspec; 91 bcopy(devspec, name, len); 92 name[len] = '\0'; 93 if ((handle = OF_finddevice(name)) == -1) { 94 bcopy(name, type, len); 95 type[len] = '\0'; 96 } else if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1) 97 continue; 98 for (i = 0; (dv = devsw[i]) != NULL; i++) { 99 if (strncmp(dv->dv_name, type, strlen(dv->dv_name)) == 0) 100 goto found; 101 } 102 } 103 return(ENOENT); 104 105found: 106 if (path != NULL && *s != '\0') 107 *path = s; 108 idev = malloc(sizeof(struct ofw_devdesc)); 109 if (idev == NULL) { 110 printf("ofw_parsedev: malloc failed\n"); 111 return ENOMEM; 112 } 113 strcpy(idev->d_path, name); 114 idev->d_dev = dv; 115 idev->d_type = dv->dv_type; 116 if (idev->d_type == DEVT_ZFS) { 117 idev->d_unit = 0; 118 p = name + strlen(dv->dv_name); 119 if (*p && (*p != ':')) { 120 idev->d_unit = strtol(p, &ep, 0); 121 if (ep == p) { 122 free(idev); 123 return (EUNIT); 124 } 125 } 126 } 127 128 if (dev == NULL) { 129 free(idev); 130 } else { 131 *dev = idev; 132 } 133 return(0); 134} 135 136int 137ofw_setcurrdev(struct env_var *ev, int flags, const void *value) 138{ 139 struct ofw_devdesc *ncurr; 140 int rv; 141 142 if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0) 143 return rv; 144 145 free(ncurr); 146 env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 147 return 0; 148} 149