xref: /freebsd/stand/libofw/devicename.c (revision 4cddd20e1ea8b9c622c72edfad3e64f70e9d56a9)
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