xref: /freebsd/usr.sbin/ofwdump/ofw_util.c (revision 1db64f89363c97858961c4df0b7d02f3223723cf)
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/types.h>
27 #include <sys/ioctl.h>
28 
29 #include <dev/ofw/openfirmio.h>
30 
31 #include <err.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sysexits.h>
38 #include <unistd.h>
39 
40 #include "pathnames.h"
41 #include "ofw_util.h"
42 
43 #define	OFW_IOCTL(fd, cmd, val)	do {					\
44 	if (ioctl(fd, cmd, val) == -1)					\
45 		err(EX_IOERR, "ioctl(..., " #cmd ", ...) failed");	\
46 } while (0)
47 
48 int
49 ofw_open(int mode)
50 {
51 	int fd;
52 
53 	if ((fd = open(PATH_DEV_OPENFIRM, mode)) == -1)
54 		err(EX_UNAVAILABLE, "could not open " PATH_DEV_OPENFIRM);
55 	return (fd);
56 }
57 
58 void
59 ofw_close(int fd)
60 {
61 
62 	close(fd);
63 }
64 
65 phandle_t
66 ofw_root(int fd)
67 {
68 
69 	return (ofw_peer(fd, 0));
70 }
71 
72 phandle_t
73 ofw_optnode(int fd)
74 {
75 	phandle_t rv;
76 
77 	OFW_IOCTL(fd, OFIOCGETOPTNODE, &rv);
78 	return (rv);
79 }
80 
81 phandle_t
82 ofw_peer(int fd, phandle_t node)
83 {
84 	phandle_t rv;
85 
86 	rv = node;
87 	OFW_IOCTL(fd, OFIOCGETNEXT, &rv);
88 	return (rv);
89 }
90 
91 phandle_t
92 ofw_child(int fd, phandle_t node)
93 {
94 	phandle_t rv;
95 
96 	rv = node;
97 	OFW_IOCTL(fd, OFIOCGETCHILD, &rv);
98 	return (rv);
99 }
100 
101 phandle_t
102 ofw_finddevice(int fd, const char *name)
103 {
104 	struct ofiocdesc d;
105 
106 	d.of_nodeid = 0;
107 	d.of_namelen = strlen(name);
108 	d.of_name = name;
109 	d.of_buflen = 0;
110 	d.of_buf = NULL;
111 	if (ioctl(fd, OFIOCFINDDEVICE, &d) == -1) {
112 		if (errno == ENOENT)
113 			err(EX_UNAVAILABLE, "Node '%s' not found", name);
114 		else
115 			err(EX_IOERR,
116 			    "ioctl(..., OFIOCFINDDEVICE, ...) failed");
117 	}
118 	return (d.of_nodeid);
119 }
120 
121 int
122 ofw_firstprop(int fd, phandle_t node, char *buf, int buflen)
123 {
124 
125 	return (ofw_nextprop(fd, node, NULL, buf, buflen));
126 }
127 
128 int
129 ofw_nextprop(int fd, phandle_t node, const char *prev, char *buf, int buflen)
130 {
131 	struct ofiocdesc d;
132 
133 	d.of_nodeid = node;
134 	d.of_namelen = prev != NULL ? strlen(prev) : 0;
135 	d.of_name = prev;
136 	d.of_buflen = buflen;
137 	d.of_buf = buf;
138 	if (ioctl(fd, OFIOCNEXTPROP, &d) == -1) {
139 		if (errno == ENOENT)
140 			return (0);
141 		else
142 			err(EX_IOERR, "ioctl(..., OFIOCNEXTPROP, ...) failed");
143 	}
144 	return (d.of_buflen);
145 }
146 
147 static void *
148 ofw_malloc(int size)
149 {
150 	void *p;
151 
152 	if ((p = malloc(size)) == NULL)
153 		err(EX_OSERR, "malloc() failed");
154 	return (p);
155 }
156 
157 int
158 ofw_getprop(int fd, phandle_t node, const char *name, void *buf, int buflen)
159 {
160 	struct ofiocdesc d;
161 
162 	d.of_nodeid = node;
163 	d.of_namelen = strlen(name);
164 	d.of_name = name;
165 	d.of_buflen = buflen;
166 	d.of_buf = buf;
167 	OFW_IOCTL(fd, OFIOCGET, &d);
168 	return (d.of_buflen);
169 }
170 
171 int
172 ofw_setprop(int fd, phandle_t node, const char *name, const void *buf,
173     int buflen)
174 {
175 	struct ofiocdesc d;
176 
177 	d.of_nodeid = node;
178 	d.of_namelen = strlen(name);
179 	d.of_name = name;
180 	d.of_buflen = buflen;
181 	d.of_buf = ofw_malloc(buflen);
182 	memcpy(d.of_buf, buf, buflen);
183 	OFW_IOCTL(fd, OFIOCSET, &d);
184 	free(d.of_buf);
185 	return (d.of_buflen);
186 }
187 
188 int
189 ofw_getproplen(int fd, phandle_t node, const char *name)
190 {
191 	struct ofiocdesc d;
192 
193 	d.of_nodeid = node;
194 	d.of_namelen = strlen(name);
195 	d.of_name = name;
196 	OFW_IOCTL(fd, OFIOCGETPROPLEN, &d);
197 	return (d.of_buflen);
198 }
199 
200 int
201 ofw_getprop_alloc(int fd, phandle_t node, const char *name, void **buf,
202     int *buflen, int reserve)
203 {
204 	struct ofiocdesc d;
205 	int len, rv;
206 
207 	do {
208 		len = ofw_getproplen(fd, node, name);
209 		if (len < 0)
210 			return (len);
211 		if (*buflen < len + reserve) {
212 			if (*buf != NULL)
213 				free(*buf);
214 			*buflen = len + reserve + OFIOCMAXVALUE;
215 			*buf = ofw_malloc(*buflen);
216 		}
217 		d.of_nodeid = node;
218 		d.of_namelen = strlen(name);
219 		d.of_name = name;
220 		d.of_buflen = *buflen - reserve;
221 		d.of_buf = *buf;
222 		rv = ioctl(fd, OFIOCGET, &d);
223 	} while (rv == -1 && errno == ENOMEM);
224 	if (rv == -1)
225 		err(EX_IOERR, "ioctl(..., OFIOCGET, ...) failed");
226 	return (d.of_buflen);
227 }
228