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