Changeset View
Changeset View
Standalone View
Standalone View
stand/efi/libefi/devicename.c
Show All 33 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <bootstrap.h> | #include <bootstrap.h> | ||||
#include <disk.h> | #include <disk.h> | ||||
#include <efi.h> | #include <efi.h> | ||||
#include <efilib.h> | #include <efilib.h> | ||||
#include <efizfs.h> | #include <efizfs.h> | ||||
static int efi_parsedev(struct devdesc **, const char *, const char **); | |||||
/* | /* | ||||
* Point (dev) at an allocated device specifier for the device matching the | * Point (dev) at an allocated device specifier for the device matching the | ||||
* path in (devspec). If it contains an explicit device specification, | * path in (devspec). If it contains an explicit device specification, | ||||
* use that. If not, use the default device. | * use that. If not, use the default device. | ||||
*/ | */ | ||||
int | int | ||||
efi_getdev(void **vdev, const char *devspec, const char **path) | efi_getdev(void **vdev, const char *devspec, const char **path) | ||||
{ | { | ||||
struct devdesc **dev = (struct devdesc **)vdev; | struct devdesc **dev = (struct devdesc **)vdev; | ||||
int rv; | int rv; | ||||
/* | /* | ||||
* If it looks like this is just a path and no device, then | * If it looks like this is just a path and no device, then | ||||
* use the current device instead. | * use the current device instead. | ||||
*/ | */ | ||||
if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) { | if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) { | ||||
rv = efi_parsedev(dev, getenv("currdev"), NULL); | rv = devparse(dev, getenv("currdev"), NULL); | ||||
if (rv == 0 && path != NULL) | if (rv == 0 && path != NULL) | ||||
*path = devspec; | *path = devspec; | ||||
return (rv); | return (rv); | ||||
} | } | ||||
/* Parse the device name off the beginning of the devspec. */ | return (devparse(dev, devspec, path)); | ||||
return (efi_parsedev(dev, devspec, path)); | |||||
} | } | ||||
/* | /* | ||||
* Point (dev) at an allocated device specifier matching the string version | |||||
* at the beginning of (devspec). Return a pointer to the remaining | |||||
* text in (path). | |||||
* | |||||
* In all cases, the beginning of (devspec) is compared to the names | |||||
* of known devices in the device switch, and then any following text | |||||
* is parsed according to the rules applied to the device type. | |||||
* | |||||
* For disk-type devices, the syntax is: | |||||
* | |||||
* fs<unit>: | |||||
*/ | |||||
static int | |||||
efi_parsedev(struct devdesc **dev, const char *devspec, const char **path) | |||||
{ | |||||
struct devdesc *idev; | |||||
struct devsw *dv; | |||||
int i, unit, err; | |||||
char *cp; | |||||
const char *np; | |||||
/* minimum length check */ | |||||
if (strlen(devspec) < 2) | |||||
return (EINVAL); | |||||
/* look for a device that matches */ | |||||
for (i = 0; devsw[i] != NULL; i++) { | |||||
dv = devsw[i]; | |||||
if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name))) | |||||
break; | |||||
} | |||||
if (devsw[i] == NULL) | |||||
return (ENOENT); | |||||
np = devspec + strlen(dv->dv_name); | |||||
idev = NULL; | |||||
err = 0; | |||||
switch (dv->dv_type) { | |||||
case DEVT_NONE: | |||||
break; | |||||
case DEVT_DISK: | |||||
err = disk_parsedev(&idev, np, path); | |||||
if (err != 0) | |||||
goto fail; | |||||
break; | |||||
#ifdef EFI_ZFS_BOOT | |||||
case DEVT_ZFS: | |||||
err = zfs_parsedev(&idev, np, path); | |||||
if (err != 0) | |||||
goto fail; | |||||
break; | |||||
#endif | |||||
default: | |||||
idev = malloc(sizeof(struct devdesc)); | |||||
if (idev == NULL) | |||||
return (ENOMEM); | |||||
unit = 0; | |||||
cp = (char *)np; | |||||
if (*np != '\0' && *np != ':') { | |||||
errno = 0; | |||||
unit = strtol(np, &cp, 0); | |||||
if (errno != 0 || cp == np) { | |||||
err = EUNIT; | |||||
goto fail; | |||||
} | |||||
} | |||||
if (*cp != '\0' && *cp != ':') { | |||||
err = EINVAL; | |||||
goto fail; | |||||
} | |||||
idev->d_unit = unit; | |||||
if (path != NULL) | |||||
*path = (*cp == 0) ? cp : cp + 1; | |||||
break; | |||||
} | |||||
idev->d_dev = dv; | |||||
if (dev != NULL) | |||||
*dev = idev; | |||||
else | |||||
free(idev); | |||||
return (0); | |||||
fail: | |||||
free(idev); | |||||
return (err); | |||||
} | |||||
/* | |||||
* Set currdev to suit the value being supplied in (value) | * Set currdev to suit the value being supplied in (value) | ||||
*/ | */ | ||||
int | int | ||||
efi_setcurrdev(struct env_var *ev, int flags, const void *value) | efi_setcurrdev(struct env_var *ev, int flags, const void *value) | ||||
{ | { | ||||
struct devdesc *ncurr; | struct devdesc *ncurr; | ||||
int rv; | int rv; | ||||
rv = efi_parsedev(&ncurr, value, NULL); | rv = devparse(&ncurr, value, NULL); | ||||
if (rv != 0) | if (rv != 0) | ||||
return (rv); | return (rv); | ||||
free(ncurr); | free(ncurr); | ||||
return (mount_currdev(ev, flags, value)); | return (mount_currdev(ev, flags, value)); | ||||
} | } |