xref: /netbsd-src/usr.sbin/eeprom/ofhandlers.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
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