xref: /openbsd-src/usr.sbin/eeprom/ophandlers.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: ophandlers.c,v 1.4 1996/08/31 13:12:12 deraadt Exp $	*/
2 /*	$NetBSD: ophandlers.c,v 1.2 1996/02/28 01:13:30 thorpej Exp $	*/
3 
4 /*-
5  * Copyright (c) 1996 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *        This product includes software developed by the NetBSD
22  *        Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #include <sys/types.h>
41 #include <sys/ioctl.h>
42 #include <err.h>
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <string.h>
46 #include <stdio.h>
47 #include <string.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 __P((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 	bzero(&opio_buf[0], sizeof(opio_buf));
100 	bzero(&opio, 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");
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 			snprintf(err_str, sizeof err_str,
150 			    "nothing available for %s",
151 			    keyword);
152 			return (err_str);
153 		}
154 
155 		if (ex->ex_keyword != NULL)
156 			(*ex->ex_handler)(ex, &opio, NULL);
157 		else
158 			printf("%s=%s\n", keyword, opio.op_buf);
159 	}
160 
161 	(void)close(fd);
162 	return (NULL);
163 }
164 
165 /* ARGSUSED */
166 static void
167 op_notsupp(exent, opiop, arg)
168 	struct extabent *exent;
169 	struct opiocdesc *opiop;
170 	char *arg;
171 {
172 
173 	warnx("property `%s' not yet supported", exent->ex_keyword);
174 }
175 
176 /*
177  * XXX: This code is quite ugly.  You have been warned.
178  * (Really!  This is the only way I could get it to work!)
179  */
180 void
181 op_dump()
182 {
183 	struct opiocdesc opio1, opio2;
184 	struct extabent *ex;
185 	char buf1[BUFSIZE], buf2[BUFSIZE], buf3[BUFSIZE], buf4[BUFSIZE];
186 	int fd, optnode;
187 
188 	if ((fd = open(path_openprom, O_RDONLY, 0640)) < 0)
189 		err(1, "open: %s", path_openprom);
190 
191 	if (ioctl(fd, OPIOCGETOPTNODE, (char *)&optnode) < 0)
192 		err(1, "OPIOCGETOPTNODE");
193 
194 	bzero(&opio1, sizeof(opio1));
195 
196 	/* This will grab the first property name from OPIOCNEXTPROP. */
197 	bzero(buf1, sizeof(buf1));
198 	bzero(buf2, sizeof(buf2));
199 
200 	opio1.op_nodeid = opio2.op_nodeid = optnode;
201 
202 	opio1.op_name = buf1;
203 	opio1.op_buf = buf2;
204 
205 	opio2.op_name = buf3;
206 	opio2.op_buf = buf4;
207 
208 	/*
209 	 * For reference: opio1 is for obtaining the name.  Pass the
210 	 * name of the last property read in op_name, and the next one
211 	 * will be returned in op_buf.  To get the first name, pass
212 	 * an empty string.  There are no more properties when an
213 	 * empty string is returned.
214 	 *
215 	 * opio2 is for obtaining the value associated with that name.
216 	 * For some crazy reason, it seems as if we need to do all
217 	 * of that gratuitious zapping and copying.  *sigh*
218 	 */
219 	for (;;) {
220 		opio1.op_namelen = strlen(opio1.op_name);
221 		opio1.op_buflen = sizeof(buf2);
222 
223 		if (ioctl(fd, OPIOCNEXTPROP, (char *)&opio1) < 0)
224 			err(1, "ioctl: OPIOCNEXTPROP");
225 
226 		/*
227 		 * The name of the property we wish to get the
228 		 * value for has been stored in the value field
229 		 * of opio1.  If the length of the name is 0, there
230 		 * are no more properties left.
231 		 */
232 		sprintf(opio2.op_name, opio1.op_buf);
233 		opio2.op_namelen = strlen(opio2.op_name);
234 
235 		if (opio2.op_namelen == 0) {
236 			(void)close(fd);
237 			return;
238 		}
239 
240 		bzero(opio2.op_buf, sizeof(buf4));
241 		opio2.op_buflen = sizeof(buf4);
242 
243 		if (ioctl(fd, OPIOCGET, (char *)&opio2) < 0)
244 			err(1, "ioctl: OPIOCGET");
245 
246 		for (ex = opextab; ex->ex_keyword != NULL; ++ex)
247 			if (strcmp(ex->ex_keyword, opio2.op_name) == 0)
248 				break;
249 
250 		if (ex->ex_keyword != NULL)
251 			(*ex->ex_handler)(ex, &opio2, NULL);
252 		else
253 			printf("%s=%s\n", opio2.op_name, opio2.op_buf);
254 
255 		/*
256 		 * Place the name of the last read value back into
257 		 * opio1 so that we may obtain the next name.
258 		 */
259 		bzero(opio1.op_name, sizeof(buf1));
260 		bzero(opio1.op_buf, sizeof(buf2));
261 		sprintf(opio1.op_name, opio2.op_name);
262 	}
263 	/* NOTREACHED */
264 }
265