devicename.c revision 294720
150764Smarkm/*- 2233294Sstas * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3233294Sstas * Copyright (c) 2006 Marcel Moolenaar 4233294Sstas * All rights reserved. 550764Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 950764Smarkm * 1. Redistributions of source code must retain the above copyright 10233294Sstas * notice, this list of conditions and the following disclaimer. 11233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 1250764Smarkm * notice, this list of conditions and the following disclaimer in the 13233294Sstas * documentation and/or other materials provided with the distribution. 14233294Sstas * 15233294Sstas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1650764Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2050764Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25233294Sstas * SUCH DAMAGE. 26233294Sstas */ 27233294Sstas 28233294Sstas#include <sys/cdefs.h> 29233294Sstas__FBSDID("$FreeBSD: stable/10/sys/boot/efi/loader/devicename.c 294720 2016-01-25 10:50:11Z smh $"); 30233294Sstas 31233294Sstas#include <stand.h> 3250764Smarkm#include <string.h> 3350764Smarkm#include <sys/disklabel.h> 34233294Sstas#include "bootstrap.h" 3550764Smarkm 3650764Smarkm#include <efi.h> 3750764Smarkm#include <efilib.h> 3850764Smarkm 3950764Smarkmstatic int efi_parsedev(struct devdesc **, const char *, const char **); 40233294Sstas 41233294Sstas/* 42233294Sstas * Point (dev) at an allocated device specifier for the device matching the 43233294Sstas * path in (devspec). If it contains an explicit device specification, 44233294Sstas * use that. If not, use the default device. 45233294Sstas */ 46233294Sstasint 4750764Smarkmefi_getdev(void **vdev, const char *devspec, const char **path) 4850764Smarkm{ 4950764Smarkm struct devdesc **dev = (struct devdesc **)vdev; 50233294Sstas int rv; 5150764Smarkm 5250764Smarkm /* 53233294Sstas * If it looks like this is just a path and no device, then 54233294Sstas * use the current device instead. 55233294Sstas */ 56233294Sstas if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) { 57233294Sstas rv = efi_parsedev(dev, getenv("currdev"), NULL); 58233294Sstas if (rv == 0 && path != NULL) 59233294Sstas *path = devspec; 60233294Sstas return (rv); 61233294Sstas } 62233294Sstas 63233294Sstas /* Parse the device name off the beginning of the devspec. */ 64233294Sstas return (efi_parsedev(dev, devspec, path)); 65233294Sstas} 66233294Sstas 67233294Sstas/* 68233294Sstas * Point (dev) at an allocated device specifier matching the string version 69233294Sstas * at the beginning of (devspec). Return a pointer to the remaining 7050764Smarkm * text in (path). 7150764Smarkm * 7250764Smarkm * In all cases, the beginning of (devspec) is compared to the names 7350764Smarkm * of known devices in the device switch, and then any following text 7450764Smarkm * is parsed according to the rules applied to the device type. 7550764Smarkm * 7650764Smarkm * For disk-type devices, the syntax is: 7750764Smarkm * 7850764Smarkm * fs<unit>: 79233294Sstas */ 80233294Sstasstatic int 81233294Sstasefi_parsedev(struct devdesc **dev, const char *devspec, const char **path) 8250764Smarkm{ 8350764Smarkm struct devdesc *idev; 8450764Smarkm struct devsw *dv; 85127804Snectar char *cp; 8650764Smarkm const char *np; 87127804Snectar int i, err; 8850764Smarkm 8950764Smarkm /* minimum length check */ 9050764Smarkm if (strlen(devspec) < 2) 9150764Smarkm return (EINVAL); 9250764Smarkm 9350764Smarkm /* look for a device that matches */ 9450764Smarkm for (i = 0; devsw[i] != NULL; i++) { 9550764Smarkm dv = devsw[i]; 9650764Smarkm if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name))) 9750764Smarkm break; 98127804Snectar } 99127804Snectar if (devsw[i] == NULL) 10050764Smarkm return (ENOENT); 10150764Smarkm 102233294Sstas idev = malloc(sizeof(struct devdesc)); 103233294Sstas if (idev == NULL) 10450764Smarkm return (ENOMEM); 10550764Smarkm 10650764Smarkm idev->d_dev = dv; 10750764Smarkm idev->d_type = dv->dv_type; 10850764Smarkm idev->d_unit = -1; 10950764Smarkm 11050764Smarkm err = 0; 11150764Smarkm np = devspec + strlen(dv->dv_name); 112 if (*np != '\0' && *np != ':') { 113 idev->d_unit = strtol(np, &cp, 0); 114 if (cp == np) { 115 idev->d_unit = -1; 116 free(idev); 117 return (EUNIT); 118 } 119 } 120 if (*cp != '\0' && *cp != ':') { 121 free(idev); 122 return (EINVAL); 123 } 124 125 if (path != NULL) 126 *path = (*cp == 0) ? cp : cp + 1; 127 if (dev != NULL) 128 *dev = idev; 129 else 130 free(idev); 131 return (0); 132} 133 134char * 135efi_fmtdev(void *vdev) 136{ 137 struct devdesc *dev = (struct devdesc *)vdev; 138 static char buf[32]; /* XXX device length constant? */ 139 140 switch(dev->d_type) { 141 case DEVT_NONE: 142 strcpy(buf, "(no device)"); 143 break; 144 145 default: 146 sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); 147 break; 148 } 149 150 return (buf); 151} 152 153/* 154 * Set currdev to suit the value being supplied in (value) 155 */ 156int 157efi_setcurrdev(struct env_var *ev, int flags, const void *value) 158{ 159 struct devdesc *ncurr; 160 int rv; 161 162 rv = efi_parsedev(&ncurr, value, NULL); 163 if (rv != 0) 164 return (rv); 165 166 free(ncurr); 167 env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 168 return (0); 169} 170