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: stable/9/usr.sbin/ofwdump/ofw_util.c 129589 2004-05-22 16:51:11Z marius $");
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
ofw_open(int mode)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
ofw_close(int fd)62 ofw_close(int fd)
63 {
64
65 close(fd);
66 }
67
68 phandle_t
ofw_root(int fd)69 ofw_root(int fd)
70 {
71
72 return (ofw_peer(fd, 0));
73 }
74
75 phandle_t
ofw_optnode(int fd)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
ofw_peer(int fd,phandle_t node)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
ofw_child(int fd,phandle_t node)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
ofw_finddevice(int fd,const char * name)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
ofw_firstprop(int fd,phandle_t node,char * buf,int buflen)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
ofw_nextprop(int fd,phandle_t node,const char * prev,char * buf,int buflen)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 *
ofw_malloc(int size)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
ofw_getprop(int fd,phandle_t node,const char * name,void * buf,int buflen)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
ofw_setprop(int fd,phandle_t node,const char * name,const void * buf,int buflen)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
ofw_getproplen(int fd,phandle_t node,const char * name)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
ofw_getprop_alloc(int fd,phandle_t node,const char * name,void ** buf,int * buflen,int reserve)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