diff options
Diffstat (limited to 'sys/boot/ofw/libofw/devicename.c')
-rw-r--r-- | sys/boot/ofw/libofw/devicename.c | 204 |
1 files changed, 36 insertions, 168 deletions
diff --git a/sys/boot/ofw/libofw/devicename.c b/sys/boot/ofw/libofw/devicename.c index 6eb08fa..c2c5f36 100644 --- a/sys/boot/ofw/libofw/devicename.c +++ b/sys/boot/ofw/libofw/devicename.c @@ -30,7 +30,7 @@ #include <sys/disklabel.h> #include "libofw.h" -static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **); +static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **); /* * Point (dev) at an allocated device specifier for the device matching the @@ -42,14 +42,13 @@ ofw_getdev(void **vdev, const char *devspec, const char **path) { struct ofw_devdesc **dev = (struct ofw_devdesc **)vdev; int rv; - + /* * If it looks like this is just a path and no * device, go with the current device. */ if ((devspec == NULL) || - (devspec[0] == '/') || - (strchr(devspec, ':') == NULL)) { + (strchr(devspec, '@') == NULL)) { if (((rv = ofw_parsedev(dev, getenv("currdev"), NULL)) == 0) && (path != NULL)) @@ -67,110 +66,42 @@ ofw_getdev(void **vdev, const char *devspec, const char **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: - * - * disk<unit>[s<slice>][<partition>]: - * */ static int ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path) { - struct ofw_devdesc *idev; + struct ofw_devdesc *idev; struct devsw *dv; - int i, unit, slice, partition, err; - char *cp; - const char *np; - - /* minimum length check */ - if (strlen(devspec) < 2) - return(EINVAL); - - /* look for a device that matches */ - for (i = 0, dv = NULL; devsw[i] != NULL; i++) { - if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) { - dv = devsw[i]; + phandle_t handle; + const char *p; + const char *s; + char name[256]; + char type[64]; + int len; + int i; + + for (p = s = devspec; *s != '\0'; p = s) { + if ((s = strchr(p + 1, '/')) == NULL) + s = strchr(p, '\0'); + len = s - devspec; + bcopy(devspec, name, len); + name[len] = '\0'; + if ((handle = OF_finddevice(name)) == -1) break; + if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1) + continue; + for (i = 0; (dv = devsw[i]) != NULL; i++) { + if (strncmp(dv->dv_name, type, strlen(type)) == 0) + goto found; } } + return(ENOENT); - if (dv == NULL) - return(ENOENT); +found: + if (*s != '\0') + *path = s; idev = malloc(sizeof(struct ofw_devdesc)); - err = 0; - np = (devspec + strlen(dv->dv_name)); - - switch(dv->dv_type) { - case DEVT_NONE: /* XXX what to do here? Do we care? */ - break; - - case DEVT_DISK: - unit = -1; - slice = -1; - partition = -1; - if (*np && (*np != ':')) { - unit = strtol(np, &cp, 10); /* next comes the unit number */ - if (cp == np) { - err = EUNIT; - goto fail; - } - if (*cp == 's') { /* got a slice number */ - np = cp + 1; - slice = strtol(np, &cp, 10); - if (cp == np) { - err = ESLICE; - goto fail; - } - } - if (*cp && (*cp != ':')) { - partition = *cp - 'a'; /* get a partition number */ - if ((partition < 0) || (partition >= MAXPARTITIONS)) { - err = EPART; - goto fail; - } - cp++; - } - } - if (*cp && (*cp != ':')) { - err = EINVAL; - goto fail; - } - - idev->d_kind.ofwdisk.unit = unit; - idev->d_kind.ofwdisk.slice = slice; - idev->d_kind.ofwdisk.partition = partition; - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; - break; - - case DEVT_NET: - unit = 0; - - if (*np && (*np != ':')) { - unit = strtol(np, &cp, 0); /* get unit number if present */ - if (cp == np) { - err = EUNIT; - goto fail; - } - } - if (*cp && (*cp != ':')) { - err = EINVAL; - goto fail; - } - - idev->d_kind.netif.unit = unit; - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; - break; - - default: - err = EINVAL; - goto fail; - } + strcpy(idev->d_path, name); idev->d_dev = dv; idev->d_type = dv->dv_type; if (dev == NULL) { @@ -179,81 +110,18 @@ ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path) *dev = idev; } return(0); - - fail: - free(idev); - return(err); -} - -/* - * Hack to correctly parse bootpath for currdev. Also, enter the device into - * the device array in the case of lazy probing (i.e. on sparc64). This has the - * effect that the disk the loader was loaded from will always be the first - * in the list, but it saves lots of time. - */ -int -ofw_parseofwdev(struct ofw_devdesc *dev, const char *devspec) -{ - char *cp, *ep; - int i; - struct devsw *dv; - -#ifdef __sparc64__ - ofwd_enter_dev(devspec); -#endif - if ((dev->d_kind.ofwdisk.unit = ofwd_getunit(devspec)) == -1) - return EUNIT; - if ((cp = strrchr(devspec, ',')) == 0) - return EINVAL; - cp++; - if (*cp != ',') - return ESLICE; - ep = ++cp; - dev->d_kind.ofwdisk.slice = strtol(cp, &cp, 10) + 1; - if (cp == ep) - return ESLICE; - if (*cp != ':') - return EPART; - dev->d_kind.ofwdisk.partition = *++cp - 'a'; -} - -char * -ofw_fmtdev(void *vdev) -{ - struct ofw_devdesc *dev = (struct ofw_devdesc *)vdev; - static char buf[128]; - char *cp; - - switch(dev->d_type) { - case DEVT_NONE: - strcpy(buf, "(no device)"); - break; - - case DEVT_DISK: - sprintf(buf, "%s%ds%d%c:", dev->d_dev->dv_name, - dev->d_kind.ofwdisk.unit, dev->d_kind.ofwdisk.slice, - dev->d_kind.ofwdisk.partition + 'a'); - break; - - case DEVT_NET: - sprintf(buf, "%s%d:", dev->d_dev->dv_name, - dev->d_kind.netif.unit); - break; - } - - return buf; } int ofw_setcurrdev(struct env_var *ev, int flags, void *value) { - struct ofw_devdesc *ncurr; - int rv; + struct ofw_devdesc *ncurr; + int rv; - if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0) - return rv; + if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0) + return rv; - free(ncurr); - env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); - return 0; + free(ncurr); + env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); + return 0; } |