devicename.c revision 106738
1169691Skan/*-
2169691Skan * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3169691Skan * All rights reserved.
4169691Skan *
5169691Skan * Redistribution and use in source and binary forms, with or without
6169691Skan * modification, are permitted provided that the following conditions
7169691Skan * are met:
8169691Skan * 1. Redistributions of source code must retain the above copyright
9169691Skan *    notice, this list of conditions and the following disclaimer.
10169691Skan * 2. Redistributions in binary form must reproduce the above copyright
11169691Skan *    notice, this list of conditions and the following disclaimer in the
12169691Skan *    documentation and/or other materials provided with the distribution.
13169691Skan *
14169691Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15169691Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16169691Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17169691Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18169691Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19169691Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20169691Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21169691Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22169691Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23169691Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24169691Skan * SUCH DAMAGE.
25169691Skan *
26169691Skan * $FreeBSD: head/sys/boot/ofw/libofw/devicename.c 106738 2002-11-10 19:17:36Z jake $
27169691Skan */
28169691Skan
29169691Skan#include <stand.h>
30169691Skan#include <sys/disklabel.h>
31169691Skan#include "libofw.h"
32169691Skan
33169691Skanstatic int ofw_parsedev(struct ofw_devdesc **, const char *, const char **);
34169691Skan
35169691Skan/*
36169691Skan * Point (dev) at an allocated device specifier for the device matching the
37169691Skan * path in (devspec). If it contains an explicit device specification,
38169691Skan * use that.  If not, use the default device.
39169691Skan */
40169691Skanint
41169691Skanofw_getdev(void **vdev, const char *devspec, const char **path)
42169691Skan{
43169691Skan    struct ofw_devdesc **dev = (struct ofw_devdesc **)vdev;
44169691Skan    int				rv;
45169691Skan
46169691Skan    /*
47169691Skan     * If it looks like this is just a path and no
48169691Skan     * device, go with the current device.
49169691Skan     */
50169691Skan    if ((devspec == NULL) ||
51169691Skan	(strchr(devspec, '@') == NULL)) {
52169691Skan
53169691Skan	if (((rv = ofw_parsedev(dev, getenv("currdev"), NULL)) == 0) &&
54169691Skan	    (path != NULL))
55169691Skan		*path = devspec;
56169691Skan	return(rv);
57169691Skan    }
58169691Skan
59169691Skan    /*
60169691Skan     * Try to parse the device name off the beginning of the devspec
61169691Skan     */
62169691Skan    return(ofw_parsedev(dev, devspec, path));
63169691Skan}
64169691Skan
65169691Skan/*
66169691Skan * Point (dev) at an allocated device specifier matching the string version
67169691Skan * at the beginning of (devspec).  Return a pointer to the remaining
68169691Skan * text in (path).
69169691Skan */
70169691Skanstatic int
71169691Skanofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path)
72169691Skan{
73169691Skan    struct ofw_devdesc	*idev;
74169691Skan    struct devsw	*dv;
75169691Skan    phandle_t		handle;
76169691Skan    const char		*p;
77169691Skan    const char		*s;
78169691Skan    char		name[256];
79169691Skan    char		type[64];
80169691Skan    int			len;
81169691Skan    int			i;
82169691Skan
83169691Skan    for (p = s = devspec; *s != '\0'; p = s) {
84169691Skan	if ((s = strchr(p + 1, '/')) == NULL)
85	    s = strchr(p, '\0');
86	len = s - devspec;
87	bcopy(devspec, name, len);
88	name[len] = '\0';
89	if ((handle = OF_finddevice(name)) == -1)
90	    break;
91	if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1)
92	    continue;
93	for (i = 0; (dv = devsw[i]) != NULL; i++) {
94	    if (strncmp(dv->dv_name, type, strlen(type)) == 0)
95		goto found;
96	}
97    }
98    return(ENOENT);
99
100found:
101    if (*s != '\0')
102	*path = s;
103    idev = malloc(sizeof(struct ofw_devdesc));
104    strcpy(idev->d_path, name);
105    idev->d_dev = dv;
106    idev->d_type = dv->dv_type;
107    if (dev == NULL) {
108	free(idev);
109    } else {
110	*dev = idev;
111    }
112    return(0);
113}
114
115int
116ofw_setcurrdev(struct env_var *ev, int flags, void *value)
117{
118    struct ofw_devdesc	*ncurr;
119    int			rv;
120
121    if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0)
122	return rv;
123
124    free(ncurr);
125    env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
126    return 0;
127}
128