]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/ofwdump/ofw_util.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / ofwdump / ofw_util.c
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 }