/* * 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). */ static int ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path) { struct ofw_devdesc *idev; struct devsw *dv; phandle_t handle; const char *p; const char *s; char *ep; char name[256]; char type[64]; int err; 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) { bcopy(name, type, len); type[len] = '\0'; } else 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(dv->dv_name)) == 0) goto found; } } return(ENOENT); found: if (path != NULL) *path = s; idev = malloc(sizeof(struct ofw_devdesc)); if (idev == NULL) { printf("ofw_parsedev: malloc failed\n"); return ENOMEM; } strcpy(idev->d_path, name); idev->d_dev = dv; idev->d_type = dv->dv_type; if (idev->d_type == DEVT_ZFS) { p = devspec + strlen(dv->dv_name); err = zfs_parsedev((struct zfs_devdesc *)idev, p, path); if (err != 0) { free(idev); return (err); } } if (dev == NULL) { free(idev); } else { *dev = idev; } return(0); }
/* * 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 i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path) { struct i386_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, dv = NULL; devsw[i] != NULL; i++) { if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) { dv = devsw[i]; break; } } if (dv == NULL) return(ENOENT); idev = malloc(sizeof(struct i386_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: err = disk_parsedev((struct disk_devdesc *)idev, np, path); if (err != 0) goto fail; break; case DEVT_CD: 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; } } else { cp = (char *)np; } if (*cp && (*cp != ':')) { err = EINVAL; goto fail; } idev->d_unit = unit; if (path != NULL) *path = (*cp == 0) ? cp : cp + 1; break; case DEVT_ZFS: err = zfs_parsedev((struct zfs_devdesc *)idev, np, path); if (err != 0) goto fail; break; default: err = EINVAL; goto fail; } idev->d_dev = dv; idev->d_type = dv->dv_type; if (dev == NULL) { free(idev); } else { *dev = idev; } return(0); fail: free(idev); return(err); }
/* * 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 i386_parsedev(struct i386_devdesc **dev, const char *devspec, const char **path) { struct i386_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]; break; } } if (dv == NULL) return(ENOENT); idev = malloc(sizeof(struct i386_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; } #ifdef LOADER_GPT_SUPPORT if (*cp == 'p') { /* got a GPT partition */ np = cp + 1; slice = strtol(np, &cp, 10); if (cp == np) { err = ESLICE; goto fail; } if (*cp && (*cp != ':')) { err = EINVAL; goto fail; } partition = 0xff; } else { #endif 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'; /* got a partition number */ if ((partition < 0) || (partition >= MAXPARTITIONS)) { err = EPART; goto fail; } cp++; } #ifdef LOADER_GPT_SUPPORT } #endif } else { cp = np; } if (*cp && (*cp != ':')) { err = EINVAL; goto fail; } idev->d_unit = unit; idev->d_kind.biosdisk.slice = slice; idev->d_kind.biosdisk.partition = partition; if (path != NULL) *path = (*cp == 0) ? cp : cp + 1; break; case DEVT_CD: 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; } } else { cp = np; } if (*cp && (*cp != ':')) { err = EINVAL; goto fail; } idev->d_unit = unit; if (path != NULL) *path = (*cp == 0) ? cp : cp + 1; break; case DEVT_ZFS: err = zfs_parsedev((struct zfs_devdesc *)idev, np, path); if (err != 0) goto fail; break; default: err = EINVAL; goto fail; } idev->d_dev = dv; idev->d_type = dv->dv_type; if (dev == NULL) { free(idev); } else { *dev = idev; } return(0); fail: free(idev); return(err); }
/* * 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: idev = malloc(sizeof(struct disk_devdesc)); if (idev == NULL) return (ENOMEM); err = disk_parsedev((struct disk_devdesc *)idev, np, path); if (err != 0) goto fail; break; #ifdef EFI_ZFS_BOOT case DEVT_ZFS: idev = malloc(sizeof(struct zfs_devdesc)); if (idev == NULL) return (ENOMEM); err = zfs_parsedev((struct zfs_devdesc*)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; idev->d_type = dv->dv_type; if (dev != NULL) *dev = idev; else free(idev); return (0); fail: free(idev); return (err); }