177943Sdfr/*- 277943Sdfr * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3164010Smarcel * Copyright (c) 2006 Marcel Moolenaar 477943Sdfr * All rights reserved. 577943Sdfr * 677943Sdfr * Redistribution and use in source and binary forms, with or without 777943Sdfr * modification, are permitted provided that the following conditions 877943Sdfr * are met: 977943Sdfr * 1. Redistributions of source code must retain the above copyright 1077943Sdfr * notice, this list of conditions and the following disclaimer. 1177943Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1277943Sdfr * notice, this list of conditions and the following disclaimer in the 1377943Sdfr * documentation and/or other materials provided with the distribution. 1477943Sdfr * 1577943Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1677943Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1777943Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1877943Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1977943Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2077943Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2177943Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2277943Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2377943Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2477943Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2577943Sdfr * SUCH DAMAGE. 2677943Sdfr */ 2777943Sdfr 28124140Sobrien#include <sys/cdefs.h> 29124140Sobrien__FBSDID("$FreeBSD$"); 30124140Sobrien 3177943Sdfr#include <stand.h> 3277943Sdfr#include <string.h> 3377943Sdfr#include <sys/disklabel.h> 3477943Sdfr#include "bootstrap.h" 3577943Sdfr 3677943Sdfr#include <efi.h> 3777943Sdfr#include <efilib.h> 3877943Sdfr 39164010Smarcelstatic int ia64_parsedev(struct devdesc **, const char *, const char **); 4077943Sdfr 4177943Sdfr/* 4277943Sdfr * Point (dev) at an allocated device specifier for the device matching the 4377943Sdfr * path in (devspec). If it contains an explicit device specification, 4477943Sdfr * use that. If not, use the default device. 4577943Sdfr */ 4677943Sdfrint 47164010Smarcelia64_getdev(void **vdev, const char *devspec, const char **path) 4877943Sdfr{ 49164010Smarcel struct devdesc **dev = (struct devdesc **)vdev; 50164010Smarcel int rv; 51164010Smarcel 5283190Sdfr /* 53164010Smarcel * If it looks like this is just a path and no device, then 54164010Smarcel * use the current device instead. 5583190Sdfr */ 56164010Smarcel if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) { 57164010Smarcel rv = ia64_parsedev(dev, getenv("currdev"), NULL); 58164010Smarcel if (rv == 0 && path != NULL) 5983190Sdfr *path = devspec; 60164010Smarcel return (rv); 6183190Sdfr } 62164010Smarcel 63164010Smarcel /* Parse the device name off the beginning of the devspec. */ 64164010Smarcel return (ia64_parsedev(dev, devspec, path)); 6577943Sdfr} 6677943Sdfr 6777943Sdfr/* 6877943Sdfr * Point (dev) at an allocated device specifier matching the string version 6977943Sdfr * at the beginning of (devspec). Return a pointer to the remaining 7077943Sdfr * text in (path). 7177943Sdfr * 7277943Sdfr * In all cases, the beginning of (devspec) is compared to the names 7377943Sdfr * of known devices in the device switch, and then any following text 7477943Sdfr * is parsed according to the rules applied to the device type. 7577943Sdfr * 7677943Sdfr * For disk-type devices, the syntax is: 7777943Sdfr * 78164010Smarcel * fs<unit>: 7977943Sdfr */ 8077943Sdfrstatic int 81164010Smarcelia64_parsedev(struct devdesc **dev, const char *devspec, const char **path) 8277943Sdfr{ 83164010Smarcel struct devdesc *idev; 84164010Smarcel struct devsw *dv; 85164010Smarcel char *cp; 86164010Smarcel const char *np; 87164010Smarcel int i, err; 8877943Sdfr 8983190Sdfr /* minimum length check */ 9083190Sdfr if (strlen(devspec) < 2) 91164010Smarcel return (EINVAL); 9277943Sdfr 9383190Sdfr /* look for a device that matches */ 94164010Smarcel for (i = 0; devsw[i] != NULL; i++) { 95164010Smarcel dv = devsw[i]; 96164010Smarcel if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name))) 9783190Sdfr break; 9877943Sdfr } 99164010Smarcel if (devsw[i] == NULL) 100164010Smarcel return (ENOENT); 10177943Sdfr 102164010Smarcel idev = malloc(sizeof(struct devdesc)); 103164010Smarcel if (idev == NULL) 104164010Smarcel return (ENOMEM); 10577943Sdfr 106164010Smarcel idev->d_dev = dv; 107164010Smarcel idev->d_type = dv->dv_type; 108164010Smarcel idev->d_unit = -1; 10977943Sdfr 110164010Smarcel err = 0; 111164010Smarcel np = devspec + strlen(dv->dv_name); 112164010Smarcel if (*np != '\0' && *np != ':') { 113164010Smarcel idev->d_unit = strtol(np, &cp, 0); 114164010Smarcel if (cp == np) { 115164010Smarcel idev->d_unit = -1; 116164010Smarcel free(idev); 117164010Smarcel return (EUNIT); 11883190Sdfr } 11977943Sdfr } 120164010Smarcel if (*cp != '\0' && *cp != ':') { 12183190Sdfr free(idev); 122164010Smarcel return (EINVAL); 12377943Sdfr } 12477943Sdfr 125164010Smarcel if (path != NULL) 126164010Smarcel *path = (*cp == 0) ? cp : cp + 1; 127164010Smarcel if (dev != NULL) 128164010Smarcel *dev = idev; 129164010Smarcel else 130164010Smarcel free(idev); 131164010Smarcel return (0); 13277943Sdfr} 13377943Sdfr 13477943Sdfrchar * 135164010Smarcelia64_fmtdev(void *vdev) 13677943Sdfr{ 137164010Smarcel struct devdesc *dev = (struct devdesc *)vdev; 138164010Smarcel static char buf[32]; /* XXX device length constant? */ 139164010Smarcel 14083190Sdfr switch(dev->d_type) { 14183190Sdfr case DEVT_NONE: 14283190Sdfr strcpy(buf, "(no device)"); 14383190Sdfr break; 14477943Sdfr 145164010Smarcel default: 146163897Smarcel sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); 14783190Sdfr break; 14883190Sdfr } 149164010Smarcel 15083190Sdfr return(buf); 15177943Sdfr} 15277943Sdfr 15377943Sdfr/* 15477943Sdfr * Set currdev to suit the value being supplied in (value) 15577943Sdfr */ 15677943Sdfrint 157164010Smarcelia64_setcurrdev(struct env_var *ev, int flags, const void *value) 15877943Sdfr{ 159164010Smarcel struct devdesc *ncurr; 160164010Smarcel int rv; 161164010Smarcel 162164010Smarcel rv = ia64_parsedev(&ncurr, value, NULL); 163164010Smarcel if (rv != 0) 16483190Sdfr return(rv); 165164010Smarcel 16683190Sdfr free(ncurr); 16783190Sdfr env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 168164010Smarcel return (0); 16977943Sdfr} 170