ophandlers.c revision 1.2 1 /* $NetBSD: ophandlers.c,v 1.2 1996/02/28 01:13:30 thorpej 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 REGENTS OR CONTRIBUTORS BE
30 * 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 <string.h>
45 #include <stdio.h>
46 #include <string.h>
47
48 #include <machine/eeprom.h>
49 #include <machine/openpromio.h>
50
51 #include "defs.h"
52
53 extern char *path_openprom;
54 extern int eval;
55 extern int verbose;
56
57 static char err_str[BUFSIZE];
58
59 static void op_notsupp __P((struct extabent *, struct opiocdesc *, char *));
60
61 /*
62 * There are several known fields that I either don't know how to
63 * deal with or require special treatment.
64 */
65 static struct extabent opextab[] = {
66 { "security-password", op_notsupp },
67 { "security-mode", op_notsupp },
68 { "oem-logo", op_notsupp },
69 { NULL, op_notsupp },
70 };
71
72 #define BARF(str1, str2) { \
73 sprintf(err_str, "%s: %s", (str1), (str2)); \
74 ++eval; \
75 return (err_str); \
76 };
77
78 char *
79 op_handler(keyword, arg)
80 char *keyword, *arg;
81 {
82 struct opiocdesc opio;
83 struct extabent *ex;
84 char opio_buf[BUFSIZE];
85 int fd, optnode;
86
87 if ((fd = open(path_openprom, arg ? O_RDWR : O_RDONLY, 0640)) < 0)
88 BARF(path_openprom, strerror(errno));
89
90 /* Check to see if it's a special-case keyword. */
91 for (ex = opextab; ex->ex_keyword != NULL; ++ex)
92 if (strcmp(ex->ex_keyword, keyword) == 0)
93 break;
94
95 if (ioctl(fd, OPIOCGETOPTNODE, (char *)&optnode) < 0)
96 BARF("OPIOCGETOPTNODE", strerror(errno));
97
98 bzero(&opio_buf[0], sizeof(opio_buf));
99 bzero(&opio, sizeof(opio));
100 opio.op_nodeid = optnode;
101 opio.op_name = keyword;
102 opio.op_namelen = strlen(opio.op_name);
103
104 if (arg) {
105 if (verbose) {
106 printf("old: ");
107
108 opio.op_buf = &opio_buf[0];
109 opio.op_buflen = sizeof(opio_buf);
110 if (ioctl(fd, OPIOCGET, (char *)&opio) < 0)
111 BARF("OPIOCGET", strerror(errno));
112
113 if (opio.op_buflen <= 0) {
114 printf("nothing available for %s\n");
115 goto out;
116 }
117
118 if (ex->ex_keyword != NULL)
119 (*ex->ex_handler)(ex, &opio, NULL);
120 else
121 printf("%s\n", opio.op_buf);
122 }
123 out:
124 if (ex->ex_keyword != NULL)
125 (*ex->ex_handler)(ex, &opio, arg);
126 else {
127 opio.op_buf = arg;
128 opio.op_buflen = strlen(arg);
129 }
130
131 if (ioctl(fd, OPIOCSET, (char *)&opio) < 0)
132 BARF("invalid keyword", keyword);
133
134 if (verbose) {
135 printf("new: ");
136 if (ex->ex_keyword != NULL)
137 (*ex->ex_handler)(ex, &opio, NULL);
138 else
139 printf("%s\n", opio.op_buf);
140 }
141 } else {
142 opio.op_buf = &opio_buf[0];
143 opio.op_buflen = sizeof(opio_buf);
144 if (ioctl(fd, OPIOCGET, (char *)&opio) < 0)
145 BARF("OPIOCGET", strerror(errno));
146
147 if (opio.op_buflen <= 0) {
148 sprintf(err_str, "nothing available for %s",
149 keyword);
150 return (err_str);
151 }
152
153 if (ex->ex_keyword != NULL)
154 (*ex->ex_handler)(ex, &opio, NULL);
155 else
156 printf("%s=%s\n", keyword, opio.op_buf);
157 }
158
159 (void)close(fd);
160 return (NULL);
161 }
162
163 /* ARGSUSED */
164 static void
165 op_notsupp(exent, opiop, arg)
166 struct extabent *exent;
167 struct opiocdesc *opiop;
168 char *arg;
169 {
170
171 warnx("property `%s' not yet supported", exent->ex_keyword);
172 }
173
174 /*
175 * XXX: This code is quite ugly. You have been warned.
176 * (Really! This is the only way I could get it to work!)
177 */
178 void
179 op_dump()
180 {
181 struct opiocdesc opio1, opio2;
182 struct extabent *ex;
183 char buf1[BUFSIZE], buf2[BUFSIZE], buf3[BUFSIZE], buf4[BUFSIZE];
184 int fd, optnode;
185
186 if ((fd = open(path_openprom, O_RDONLY, 0640)) < 0)
187 err(1, "open: %s", path_openprom);
188
189 if (ioctl(fd, OPIOCGETOPTNODE, (char *)&optnode) < 0)
190 err(1, "OPIOCGETOPTNODE");
191
192 bzero(&opio1, sizeof(opio1));
193
194 /* This will grab the first property name from OPIOCNEXTPROP. */
195 bzero(buf1, sizeof(buf1));
196 bzero(buf2, sizeof(buf2));
197
198 opio1.op_nodeid = opio2.op_nodeid = optnode;
199
200 opio1.op_name = buf1;
201 opio1.op_buf = buf2;
202
203 opio2.op_name = buf3;
204 opio2.op_buf = buf4;
205
206 /*
207 * For reference: opio1 is for obtaining the name. Pass the
208 * name of the last property read in op_name, and the next one
209 * will be returned in op_buf. To get the first name, pass
210 * an empty string. There are no more properties when an
211 * empty string is returned.
212 *
213 * opio2 is for obtaining the value associated with that name.
214 * For some crazy reason, it seems as if we need to do all
215 * of that gratuitious zapping and copying. *sigh*
216 */
217 for (;;) {
218 opio1.op_namelen = strlen(opio1.op_name);
219 opio1.op_buflen = sizeof(buf2);
220
221 if (ioctl(fd, OPIOCNEXTPROP, (char *)&opio1) < 0)
222 err(1, "ioctl: OPIOCNEXTPROP");
223
224 /*
225 * The name of the property we wish to get the
226 * value for has been stored in the value field
227 * of opio1. If the length of the name is 0, there
228 * are no more properties left.
229 */
230 sprintf(opio2.op_name, opio1.op_buf);
231 opio2.op_namelen = strlen(opio2.op_name);
232
233 if (opio2.op_namelen == 0) {
234 (void)close(fd);
235 return;
236 }
237
238 bzero(opio2.op_buf, sizeof(buf4));
239 opio2.op_buflen = sizeof(buf4);
240
241 if (ioctl(fd, OPIOCGET, (char *)&opio2) < 0)
242 err(1, "ioctl: OPIOCGET");
243
244 for (ex = opextab; ex->ex_keyword != NULL; ++ex)
245 if (strcmp(ex->ex_keyword, opio2.op_name) == 0)
246 break;
247
248 if (ex->ex_keyword != NULL)
249 (*ex->ex_handler)(ex, &opio2, NULL);
250 else
251 printf("%s=%s\n", opio2.op_name, opio2.op_buf);
252
253 /*
254 * Place the name of the last read value back into
255 * opio1 so that we may obtain the next name.
256 */
257 bzero(opio1.op_name, sizeof(buf1));
258 bzero(opio1.op_buf, sizeof(buf2));
259 sprintf(opio1.op_name, opio2.op_name);
260 }
261 /* NOTREACHED */
262 }
263