1475008d6SBrandon Bergren /*-
2475008d6SBrandon Bergren * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3475008d6SBrandon Bergren * All rights reserved.
4475008d6SBrandon Bergren *
5475008d6SBrandon Bergren * Redistribution and use in source and binary forms, with or without
6475008d6SBrandon Bergren * modification, are permitted provided that the following conditions
7475008d6SBrandon Bergren * are met:
8475008d6SBrandon Bergren * 1. Redistributions of source code must retain the above copyright
9475008d6SBrandon Bergren * notice, this list of conditions and the following disclaimer.
10475008d6SBrandon Bergren * 2. Redistributions in binary form must reproduce the above copyright
11475008d6SBrandon Bergren * notice, this list of conditions and the following disclaimer in the
12475008d6SBrandon Bergren * documentation and/or other materials provided with the distribution.
13475008d6SBrandon Bergren *
14475008d6SBrandon Bergren * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15475008d6SBrandon Bergren * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16475008d6SBrandon Bergren * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17475008d6SBrandon Bergren * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18475008d6SBrandon Bergren * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19475008d6SBrandon Bergren * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20475008d6SBrandon Bergren * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21475008d6SBrandon Bergren * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22475008d6SBrandon Bergren * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23475008d6SBrandon Bergren * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24475008d6SBrandon Bergren * SUCH DAMAGE.
25475008d6SBrandon Bergren */
26475008d6SBrandon Bergren
27475008d6SBrandon Bergren #include <stand.h>
28475008d6SBrandon Bergren
29475008d6SBrandon Bergren #include "bootstrap.h"
30475008d6SBrandon Bergren #include "libofw.h"
31475008d6SBrandon Bergren
32475008d6SBrandon Bergren /*
33475008d6SBrandon Bergren * Point (dev) at an allocated device specifier for the device matching the
34475008d6SBrandon Bergren * path in (devspec). If it contains an explicit device specification,
35475008d6SBrandon Bergren * use that. If not, use the default device.
36475008d6SBrandon Bergren */
37475008d6SBrandon Bergren int
ofw_getdev(void ** vdev,const char * devspec,const char ** path)38475008d6SBrandon Bergren ofw_getdev(void **vdev, const char *devspec, const char **path)
39475008d6SBrandon Bergren {
4085400175SWarner Losh struct devdesc **dev = (struct devdesc **)vdev;
41475008d6SBrandon Bergren int rv;
42475008d6SBrandon Bergren
43475008d6SBrandon Bergren /*
4485400175SWarner Losh * If it looks like this is just a path and no device, go with the
4585400175SWarner Losh * current device.
46475008d6SBrandon Bergren */
47b60164c9SWarner Losh if (devspec == NULL || strpbrk(devspec, ":@") == NULL) {
4885400175SWarner Losh rv = devparse(dev, getenv("currdev"), NULL);
4985400175SWarner Losh if (rv == 0 && path != NULL)
50475008d6SBrandon Bergren *path = devspec;
51475008d6SBrandon Bergren return (rv);
52475008d6SBrandon Bergren }
53475008d6SBrandon Bergren
54475008d6SBrandon Bergren /*
55475008d6SBrandon Bergren * Try to parse the device name off the beginning of the devspec
56475008d6SBrandon Bergren */
5785400175SWarner Losh return (devparse(dev, devspec, path));
58475008d6SBrandon Bergren }
59475008d6SBrandon Bergren
60475008d6SBrandon Bergren /*
61ed3cc2f2SWarner Losh * Search the OFW (path) for a node that's of (want_type).
62ed3cc2f2SWarner Losh */
63ed3cc2f2SWarner Losh phandle_t
ofw_path_to_handle(const char * ofwpath,const char * want_type,const char ** path)64ed3cc2f2SWarner Losh ofw_path_to_handle(const char *ofwpath, const char *want_type, const char **path)
65ed3cc2f2SWarner Losh {
66ed3cc2f2SWarner Losh const char *p, *s;
67ed3cc2f2SWarner Losh char name[256];
68ed3cc2f2SWarner Losh char type[64];
69ed3cc2f2SWarner Losh phandle_t handle;
70ed3cc2f2SWarner Losh int len;
71ed3cc2f2SWarner Losh
72ed3cc2f2SWarner Losh for (p = s = ofwpath; *s != '\0'; p = s) {
73ed3cc2f2SWarner Losh if ((s = strchr(p + 1, '/')) == NULL)
74ed3cc2f2SWarner Losh s = strchr(p, '\0');
75ed3cc2f2SWarner Losh len = s - ofwpath;
76ed3cc2f2SWarner Losh if (len >= sizeof(name))
77ed3cc2f2SWarner Losh return ((phandle_t)-1);
78ed3cc2f2SWarner Losh bcopy(ofwpath, name, len);
79ed3cc2f2SWarner Losh name[len] = '\0';
80ed3cc2f2SWarner Losh if ((handle = OF_finddevice(name)) == -1)
81ed3cc2f2SWarner Losh continue;
82ed3cc2f2SWarner Losh if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1)
83ed3cc2f2SWarner Losh continue;
84ed3cc2f2SWarner Losh if (strcmp(want_type, type) == 0) {
85ed3cc2f2SWarner Losh *path = s;
86ed3cc2f2SWarner Losh return (handle);
87ed3cc2f2SWarner Losh }
88ed3cc2f2SWarner Losh }
89ed3cc2f2SWarner Losh return ((phandle_t)-1);
90ed3cc2f2SWarner Losh }
91ed3cc2f2SWarner Losh
92475008d6SBrandon Bergren int
ofw_common_parsedev(struct devdesc ** dev,const char * devspec,const char ** path,const char * ofwtype)93f9ce8da8SWarner Losh ofw_common_parsedev(struct devdesc **dev, const char *devspec, const char **path,
94f9ce8da8SWarner Losh const char *ofwtype)
95f9ce8da8SWarner Losh {
96f9ce8da8SWarner Losh const char *rem_path;
97f9ce8da8SWarner Losh struct ofw_devdesc *idev;
98f9ce8da8SWarner Losh
99f9ce8da8SWarner Losh if (ofw_path_to_handle(devspec, ofwtype, &rem_path) == -1)
100f9ce8da8SWarner Losh return (ENOENT);
101f9ce8da8SWarner Losh idev = malloc(sizeof(struct ofw_devdesc));
102f9ce8da8SWarner Losh if (idev == NULL) {
103f9ce8da8SWarner Losh printf("ofw_parsedev: malloc failed\n");
104*4cddd20eSWarner Losh return (ENOMEM);
105f9ce8da8SWarner Losh };
106f9ce8da8SWarner Losh strlcpy(idev->d_path, devspec, min(rem_path - devspec + 1,
107f9ce8da8SWarner Losh sizeof(idev->d_path)));
108f9ce8da8SWarner Losh *dev = &idev->dd;
109f9ce8da8SWarner Losh if (path != NULL)
110f9ce8da8SWarner Losh *path = rem_path;
111*4cddd20eSWarner Losh return (0);
112f9ce8da8SWarner Losh }
113