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$"); 29 30 #include <stand.h> 31 32 #include "bootstrap.h" 33 #include "libofw.h" 34 #include "libzfs.h" 35 36 static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **); 37 38 /* 39 * Point (dev) at an allocated device specifier for the device matching the 40 * path in (devspec). If it contains an explicit device specification, 41 * use that. If not, use the default device. 42 */ 43 int 44 ofw_getdev(void **vdev, const char *devspec, const char **path) 45 { 46 struct ofw_devdesc **dev = (struct ofw_devdesc **)vdev; 47 int rv; 48 49 /* 50 * If it looks like this is just a path and no 51 * device, go with the current device. 52 */ 53 if ((devspec == NULL) || 54 ((strchr(devspec, '@') == NULL) && 55 (strchr(devspec, ':') == NULL))) { 56 57 if (((rv = ofw_parsedev(dev, getenv("currdev"), NULL)) == 0) && 58 (path != NULL)) 59 *path = devspec; 60 return(rv); 61 } 62 63 /* 64 * Try to parse the device name off the beginning of the devspec 65 */ 66 return(ofw_parsedev(dev, devspec, path)); 67 } 68 69 /* 70 * Point (dev) at an allocated device specifier matching the string version 71 * at the beginning of (devspec). Return a pointer to the remaining 72 * text in (path). 73 */ 74 static int 75 ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path) 76 { 77 struct ofw_devdesc *idev; 78 struct devsw *dv; 79 phandle_t handle; 80 const char *p; 81 const char *s; 82 char *ep; 83 char name[256]; 84 char type[64]; 85 int err; 86 int len; 87 int i; 88 89 for (p = s = devspec; *s != '\0'; p = s) { 90 if ((s = strchr(p + 1, '/')) == NULL) 91 s = strchr(p, '\0'); 92 len = s - devspec; 93 bcopy(devspec, name, len); 94 name[len] = '\0'; 95 if ((handle = OF_finddevice(name)) == -1) { 96 bcopy(name, type, len); 97 type[len] = '\0'; 98 } else if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1) 99 continue; 100 for (i = 0; (dv = devsw[i]) != NULL; i++) { 101 if (strncmp(dv->dv_name, type, strlen(dv->dv_name)) == 0) 102 goto found; 103 } 104 } 105 return(ENOENT); 106 107 found: 108 if (path != NULL) 109 *path = s; 110 idev = malloc(sizeof(struct ofw_devdesc)); 111 if (idev == NULL) { 112 printf("ofw_parsedev: malloc failed\n"); 113 return ENOMEM; 114 } 115 strcpy(idev->d_path, name); 116 idev->dd.d_dev = dv; 117 if (dv->dv_type == DEVT_ZFS) { 118 p = devspec + strlen(dv->dv_name); 119 err = zfs_parsedev((struct zfs_devdesc *)idev, p, path); 120 if (err != 0) { 121 free(idev); 122 return (err); 123 } 124 } 125 126 if (dev == NULL) { 127 free(idev); 128 } else { 129 *dev = idev; 130 } 131 return(0); 132 } 133 134 int 135 ofw_setcurrdev(struct env_var *ev, int flags, const void *value) 136 { 137 struct ofw_devdesc *ncurr; 138 int rv; 139 140 if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0) 141 return rv; 142 143 free(ncurr); 144 env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 145 return 0; 146 } 147