xref: /freebsd/usr.sbin/ofwdump/ofw_util.c (revision 81ad6265)
1 /*-
2  * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
23  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28 
29 #include <sys/types.h>
30 #include <sys/ioctl.h>
31 
32 #include <dev/ofw/openfirmio.h>
33 
34 #include <err.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sysexits.h>
41 #include <unistd.h>
42 
43 #include "pathnames.h"
44 #include "ofw_util.h"
45 
46 #define	OFW_IOCTL(fd, cmd, val)	do {					\
47 	if (ioctl(fd, cmd, val) == -1)					\
48 		err(EX_IOERR, "ioctl(..., " #cmd ", ...) failed");	\
49 } while (0)
50 
51 int
52 ofw_open(int mode)
53 {
54 	int fd;
55 
56 	if ((fd = open(PATH_DEV_OPENFIRM, mode)) == -1)
57 		err(EX_UNAVAILABLE, "could not open " PATH_DEV_OPENFIRM);
58 	return (fd);
59 }
60 
61 void
62 ofw_close(int fd)
63 {
64 
65 	close(fd);
66 }
67 
68 phandle_t
69 ofw_root(int fd)
70 {
71 
72 	return (ofw_peer(fd, 0));
73 }
74 
75 phandle_t
76 ofw_optnode(int fd)
77 {
78 	phandle_t rv;
79 
80 	OFW_IOCTL(fd, OFIOCGETOPTNODE, &rv);
81 	return (rv);
82 }
83 
84 phandle_t
85 ofw_peer(int fd, phandle_t node)
86 {
87 	phandle_t rv;
88 
89 	rv = node;
90 	OFW_IOCTL(fd, OFIOCGETNEXT, &rv);
91 	return (rv);
92 }
93 
94 phandle_t
95 ofw_child(int fd, phandle_t node)
96 {
97 	phandle_t rv;
98 
99 	rv = node;
100 	OFW_IOCTL(fd, OFIOCGETCHILD, &rv);
101 	return (rv);
102 }
103 
104 phandle_t
105 ofw_finddevice(int fd, const char *name)
106 {
107 	struct ofiocdesc d;
108 
109 	d.of_nodeid = 0;
110 	d.of_namelen = strlen(name);
111 	d.of_name = name;
112 	d.of_buflen = 0;
113 	d.of_buf = NULL;
114 	if (ioctl(fd, OFIOCFINDDEVICE, &d) == -1) {
115 		if (errno == ENOENT)
116 			err(EX_UNAVAILABLE, "Node '%s' not found", name);
117 		else
118 			err(EX_IOERR,
119 			    "ioctl(..., OFIOCFINDDEVICE, ...) failed");
120 	}
121 	return (d.of_nodeid);
122 }
123 
124 int
125 ofw_firstprop(int fd, phandle_t node, char *buf, int buflen)
126 {
127 
128 	return (ofw_nextprop(fd, node, NULL, buf, buflen));
129 }
130 
131 int
132 ofw_nextprop(int fd, phandle_t node, const char *prev, char *buf, int buflen)
133 {
134 	struct ofiocdesc d;
135 
136 	d.of_nodeid = node;
137 	d.of_namelen = prev != NULL ? strlen(prev) : 0;
138 	d.of_name = prev;
139 	d.of_buflen = buflen;
140 	d.of_buf = buf;
141 	if (ioctl(fd, OFIOCNEXTPROP, &d) == -1) {
142 		if (errno == ENOENT)
143 			return (0);
144 		else
145 			err(EX_IOERR, "ioctl(..., OFIOCNEXTPROP, ...) failed");
146 	}
147 	return (d.of_buflen);
148 }
149 
150 static void *
151 ofw_malloc(int size)
152 {
153 	void *p;
154 
155 	if ((p = malloc(size)) == NULL)
156 		err(EX_OSERR, "malloc() failed");
157 	return (p);
158 }
159 
160 int
161 ofw_getprop(int fd, phandle_t node, const char *name, void *buf, int buflen)
162 {
163 	struct ofiocdesc d;
164 
165 	d.of_nodeid = node;
166 	d.of_namelen = strlen(name);
167 	d.of_name = name;
168 	d.of_buflen = buflen;
169 	d.of_buf = buf;
170 	OFW_IOCTL(fd, OFIOCGET, &d);
171 	return (d.of_buflen);
172 }
173 
174 int
175 ofw_setprop(int fd, phandle_t node, const char *name, const void *buf,
176     int buflen)
177 {
178 	struct ofiocdesc d;
179 
180 	d.of_nodeid = node;
181 	d.of_namelen = strlen(name);
182 	d.of_name = name;
183 	d.of_buflen = buflen;
184 	d.of_buf = ofw_malloc(buflen);
185 	memcpy(d.of_buf, buf, buflen);
186 	OFW_IOCTL(fd, OFIOCSET, &d);
187 	free(d.of_buf);
188 	return (d.of_buflen);
189 }
190 
191 int
192 ofw_getproplen(int fd, phandle_t node, const char *name)
193 {
194 	struct ofiocdesc d;
195 
196 	d.of_nodeid = node;
197 	d.of_namelen = strlen(name);
198 	d.of_name = name;
199 	OFW_IOCTL(fd, OFIOCGETPROPLEN, &d);
200 	return (d.of_buflen);
201 }
202 
203 int
204 ofw_getprop_alloc(int fd, phandle_t node, const char *name, void **buf,
205     int *buflen, int reserve)
206 {
207 	struct ofiocdesc d;
208 	int len, rv;
209 
210 	do {
211 		len = ofw_getproplen(fd, node, name);
212 		if (len < 0)
213 			return (len);
214 		if (*buflen < len + reserve) {
215 			if (*buf != NULL)
216 				free(*buf);
217 			*buflen = len + reserve + OFIOCMAXVALUE;
218 			*buf = ofw_malloc(*buflen);
219 		}
220 		d.of_nodeid = node;
221 		d.of_namelen = strlen(name);
222 		d.of_name = name;
223 		d.of_buflen = *buflen - reserve;
224 		d.of_buf = *buf;
225 		rv = ioctl(fd, OFIOCGET, &d);
226 	} while (rv == -1 && errno == ENOMEM);
227 	if (rv == -1)
228 		err(EX_IOERR, "ioctl(..., OFIOCGET, ...) failed");
229 	return (d.of_buflen);
230 }
231