ofhandlers.c revision 1.3 1 /* $NetBSD: ofhandlers.c,v 1.3 2007/01/16 17:32:04 hubertf Exp $ */
2
3 /*-
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/types.h>
40 #include <sys/ioctl.h>
41 #include <err.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <unistd.h>
47
48 #include <dev/ofw/openfirmio.h>
49
50 #include "defs.h"
51
52 extern char *path_openfirm;
53 extern int eval;
54 extern int verbose;
55
56 static char err_str[BUFSIZE];
57
58 static void of_notsupp (struct extabent *, struct ofiocdesc *, char *);
59 static void of_uint32h (struct extabent *, struct ofiocdesc *, char *);
60 static void of_uint32d (struct extabent *, struct ofiocdesc *, char *);
61
62 /*
63 * There are several known fields that I either don't know how to
64 * deal with or require special treatment.
65 */
66 static struct extabent ofextab[] = {
67 { "security-password", of_notsupp },
68 { "security-mode", of_notsupp },
69 { "oem-logo", of_notsupp },
70 { "oem-banner", of_notsupp },
71 { "real-base", of_uint32h },
72 { "real-size", of_uint32h },
73 { "load-base", of_uint32h },
74 { "virt-base", of_uint32h },
75 { "virt-size", of_uint32h },
76 { "screen-#columns", of_uint32d },
77 { "screen-#rows", of_uint32d },
78 { "selftest-#megs", of_uint32d },
79 { NULL, of_notsupp },
80 };
81
82 #define BARF(str1, str2) { \
83 snprintf(err_str, sizeof err_str, "%s: %s", (str1), (str2)); \
84 ++eval; \
85 return (err_str); \
86 };
87
88 void
89 of_action(keyword, arg)
90 char *keyword, *arg;
91 {
92 char *cp;
93
94 if ((cp = of_handler(keyword, arg)) != NULL)
95 warnx("%s", cp);
96 return;
97 }
98
99 char *
100 of_handler(keyword, arg)
101 char *keyword, *arg;
102 {
103 struct ofiocdesc ofio;
104 struct extabent *ex;
105 char ofio_buf[BUFSIZE];
106 int fd, optnode;
107
108 if ((fd = open(path_openfirm, arg ? O_RDWR : O_RDONLY, 0640)) < 0)
109 BARF(path_openfirm, strerror(errno));
110
111 /* Check to see if it's a special-case keyword. */
112 for (ex = ofextab; ex->ex_keyword != NULL; ++ex)
113 if (strcmp(ex->ex_keyword, keyword) == 0)
114 break;
115
116 if (ioctl(fd, OFIOCGETOPTNODE, (char *)&optnode) < 0)
117 BARF("OFIOCGETOPTNODE", strerror(errno));
118
119 memset(&ofio_buf[0], 0, sizeof(ofio_buf));
120 memset(&ofio, 0, sizeof(ofio));
121 ofio.of_nodeid = optnode;
122 ofio.of_name = keyword;
123 ofio.of_namelen = strlen(ofio.of_name);
124
125 if (arg) {
126 if (verbose) {
127 printf("old: ");
128
129 ofio.of_buf = &ofio_buf[0];
130 ofio.of_buflen = sizeof(ofio_buf);
131 if (ioctl(fd, OFIOCGET, (char *)&ofio) < 0)
132 BARF("OFIOCGET", strerror(errno));
133
134 if (ofio.of_buflen <= 0) {
135 printf("nothing available for %s\n", keyword);
136 goto out;
137 }
138
139 if (ex->ex_keyword != NULL)
140 (*ex->ex_handler)(ex, &ofio, NULL);
141 else
142 printf("%s\n", ofio.of_buf);
143 }
144 out:
145 if (ex->ex_keyword != NULL)
146 (*ex->ex_handler)(ex, &ofio, arg);
147 else {
148 ofio.of_buf = arg;
149 ofio.of_buflen = strlen(arg);
150 }
151
152 if (ioctl(fd, OFIOCSET, (char *)&ofio) < 0)
153 BARF("invalid keyword", keyword);
154
155 if (verbose) {
156 printf("new: ");
157 if (ex->ex_keyword != NULL)
158 (*ex->ex_handler)(ex, &ofio, NULL);
159 else
160 printf("%s\n", ofio.of_buf);
161 }
162 } else {
163 ofio.of_buf = &ofio_buf[0];
164 ofio.of_buflen = sizeof(ofio_buf);
165 if (ioctl(fd, OFIOCGET, (char *)&ofio) < 0)
166 BARF("OFIOCGET", strerror(errno));
167
168 if (ofio.of_buflen <= 0) {
169 (void)snprintf(err_str, sizeof err_str,
170 "nothing available for %s", keyword);
171 return (err_str);
172 }
173
174 if (ex->ex_keyword != NULL)
175 (*ex->ex_handler)(ex, &ofio, NULL);
176 else
177 printf("%s=%s\n", keyword, ofio.of_buf);
178 }
179
180 (void)close(fd);
181 return (NULL);
182 }
183
184 /* ARGSUSED */
185 static void
186 of_notsupp(exent, ofiop, arg)
187 struct extabent *exent;
188 struct ofiocdesc *ofiop;
189 char *arg;
190 {
191
192 warnx("property `%s' not yet supported", exent->ex_keyword);
193 }
194
195 static void
196 of_uint32h(exent, ofiop, arg)
197 struct extabent *exent;
198 struct ofiocdesc *ofiop;
199 char *arg;
200 {
201
202 printf("%s=0x%08x\n", exent->ex_keyword, *(uint32_t *)ofiop->of_buf);
203 }
204
205 static void
206 of_uint32d(exent, ofiop, arg)
207 struct extabent *exent;
208 struct ofiocdesc *ofiop;
209 char *arg;
210 {
211
212 printf("%s=%d\n", exent->ex_keyword, *(uint32_t *)ofiop->of_buf);
213 }
214
215 /*
216 * XXX: This code is quite ugly. You have been warned.
217 * (Really! This is the only way I could get it to work!)
218 */
219 void
220 of_dump()
221 {
222 struct ofiocdesc ofio1, ofio2;
223 struct extabent *ex;
224 char buf1[BUFSIZE], buf2[BUFSIZE], buf3[BUFSIZE], buf4[BUFSIZE];
225 int fd, optnode;
226
227 if ((fd = open(path_openfirm, O_RDONLY, 0640)) < 0)
228 err(1, "open: %s", path_openfirm);
229
230 if (ioctl(fd, OFIOCGETOPTNODE, (char *)&optnode) < 0)
231 err(1, "OFIOCGETOPTNODE");
232
233 memset(&ofio1, 0, sizeof(ofio1));
234
235 /* This will grab the first property name from OPIOCNEXTPROP. */
236 memset(buf1, 0, sizeof(buf1));
237 memset(buf2, 0, sizeof(buf2));
238
239 ofio1.of_nodeid = ofio2.of_nodeid = optnode;
240
241 ofio1.of_name = buf1;
242 ofio1.of_buf = buf2;
243
244 ofio2.of_name = buf3;
245 ofio2.of_buf = buf4;
246
247 /*
248 * For reference: ofio1 is for obtaining the name. Pass the
249 * name of the last property read in of_name, and the next one
250 * will be returned in of_buf. To get the first name, pass
251 * an empty string. There are no more properties when an
252 * empty string is returned.
253 *
254 * ofio2 is for obtaining the value associated with that name.
255 * For some crazy reason, it seems as if we need to do all
256 * of that gratuitious zapping and copying. *sigh*
257 */
258 for (;;) {
259 ofio1.of_namelen = strlen(ofio1.of_name);
260 ofio1.of_buflen = sizeof(buf2);
261
262 if (ioctl(fd, OFIOCNEXTPROP, (char *)&ofio1) < 0) {
263 close(fd);
264 return;
265 /* err(1, "ioctl: OFIOCNEXTPROP"); */
266 }
267
268 /*
269 * The name of the property we wish to get the
270 * value for has been stored in the value field
271 * of ofio1. If the length of the name is 0, there
272 * are no more properties left.
273 */
274 strcpy(ofio2.of_name, ofio1.of_buf); /* XXX strcpy is safe */
275 ofio2.of_namelen = strlen(ofio2.of_name);
276
277 if (ofio2.of_namelen == 0) {
278 (void)close(fd);
279 return;
280 }
281
282 memset(ofio2.of_buf, 0, sizeof(buf4));
283 ofio2.of_buflen = sizeof(buf4);
284
285 if (ioctl(fd, OFIOCGET, (char *)&ofio2) < 0)
286 err(1, "ioctl: OFIOCGET");
287
288 for (ex = ofextab; ex->ex_keyword != NULL; ++ex)
289 if (strcmp(ex->ex_keyword, ofio2.of_name) == 0)
290 break;
291
292 if (ex->ex_keyword != NULL)
293 (*ex->ex_handler)(ex, &ofio2, NULL);
294 else
295 printf("%s=%s\n", ofio2.of_name, ofio2.of_buf);
296
297 /*
298 * Place the name of the last read value back into
299 * ofio1 so that we may obtain the next name.
300 */
301 memset(ofio1.of_name, 0, sizeof(buf1));
302 memset(ofio1.of_buf, 0, sizeof(buf2));
303 strcpy(ofio1.of_name, ofio2.of_name); /* XXX strcpy is safe */
304 }
305 /* NOTREACHED */
306 }
307