xref: /netbsd/usr.sbin/memswitch/memswitch.c (revision bf9ec67e)
1 /*	$NetBSD: memswitch.c,v 1.6 2001/02/04 08:37:33 minoura Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Minoura Makoto.
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 /* memswitch.c */
40 
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <err.h>
45 #include <unistd.h>
46 #include <fcntl.h>
47 #include <errno.h>
48 
49 #include <sys/ioctl.h>
50 
51 #ifndef DEBUG
52 #include <machine/sram.h>
53 #else
54 /*
55  * DEBUG -- works on other (faster) platforms;
56  *   store in a regular file instead of actual non-volatile static RAM.
57  */
58 #define PATH_RAMFILE "/tmp/sramfile"
59 #endif
60 
61 #include "memswitch.h"
62 
63 char *progname;
64 int nflag = 0;
65 u_int8_t *current_values = 0;
66 u_int8_t *modified_values = 0;
67 
68 int main __P((int, char*[]));
69 
70 void
71 usage(void)
72 {
73 	fprintf (stderr, "Usage: %s -a\n", progname);
74 	fprintf (stderr, "       %s [-h] variable ...\n", progname);
75 	fprintf (stderr, "       %s -w variable=value ...\n", progname);
76 	fprintf (stderr, "       %s [-rs] filename\n", progname);
77 	exit(1);
78 }
79 
80 int
81 main(argc, argv)
82 	int argc;
83 	char *argv[];
84 {
85 	int ch;
86 	enum md {
87 		MD_NONE, MD_WRITE, MD_HELP, MD_SHOWALL, MD_SAVE, MD_RESTORE
88 	} mode = MD_NONE;
89 
90 	progname = argv[0];
91 
92 	while ((ch = getopt(argc, argv, "whanrs")) != -1) {
93 		switch (ch) {
94 		case 'w':	/* write */
95 			mode = MD_WRITE;
96 			break;
97 		case 'h':
98 			mode = MD_HELP;
99 			break;
100 		case 'a':
101 			mode = MD_SHOWALL;
102 			break;
103 		case 'n':
104 			nflag = 1;
105 			break;
106 		case 's':
107 			mode = MD_SAVE;
108 			break;
109 		case 'r':
110 			mode = MD_RESTORE;
111 			break;
112 		}
113 	}
114 	argc -= optind;
115 	argv += optind;
116 
117 	switch (mode) {
118 	case MD_NONE:
119 		if (argc == 0)
120 			usage();
121 		while (argv[0]) {
122 			show_single (argv[0]);
123 			argv++;
124 		}
125 		break;
126 	case MD_SHOWALL:
127 		if (argc)
128 			usage();
129 		show_all();
130 		break;
131 	case MD_WRITE:
132 		if (argc == 0)
133 			usage();
134 		while (argv[0]) {
135 			modify_single (argv[0]);
136 			argv++;
137 		}
138 		flush ();
139 		break;
140 	case MD_HELP:
141 		if (argc == 0)
142 			usage();
143 		while (argv[0]) {
144 			help_single (argv[0]);
145 			argv++;
146 		}
147 		break;
148 	case MD_SAVE:
149 		if (argc != 1)
150 			usage();
151 		save(argv[0]);
152 		break;
153 	case MD_RESTORE:
154 		if (argc != 1)
155 			usage();
156 		restore(argv[0]);
157 		break;
158 
159 	}
160 
161 	return 0;
162 }
163 
164 void
165 show_single(name)
166 	const char *name;
167 {
168 	int i;
169 	int n = 0;
170 	char fullname[50];
171 	char valuestr[MAXVALUELEN];
172 
173 	for (i = 0; i < number_of_props; i++) {
174 		sprintf(fullname, "%s.%s",
175 			properties[i].class, properties[i].node);
176 		if (strcmp(name, fullname) == 0 || strcmp(name, properties[i].class) == 0) {
177 			properties[i].print (&properties[i], valuestr);
178 			if (!nflag)
179 				printf ("%s=%s\n", fullname, valuestr);
180 			n++;
181 		}
182 	}
183 	if (n == 0) {
184 		errx (1, "No such %s: %s", strstr(name, ".")?"property":"class", name);
185 	}
186 
187 	return;
188 }
189 
190 void
191 show_all(void)
192 {
193 	int i;
194 	char valuestr[MAXVALUELEN];
195 
196 	for (i = 0; i < number_of_props; i++) {
197 		properties[i].print (&properties[i], valuestr);
198 		if (!nflag)
199 			printf ("%s.%s=",
200 				properties[i].class, properties[i].node);
201 		printf ("%s\n", valuestr);
202 	}
203 
204 	return;
205 }
206 
207 void
208 modify_single(expr)
209 	const char *expr;
210 {
211 	int i, l, n;
212 	char *class, *node;
213 	const char *value;
214 	char valuestr[MAXVALUELEN];
215 
216 	l = 0;
217 	n = strlen(expr);
218 	for (i = 0; i < n; i++) {
219 		if (expr[i] == '.') {
220 			l = i + 1;
221 			class = alloca(l);
222 			if (class == 0)
223 				err (1, "alloca");
224 			strncpy (class, expr, i);
225 			class[i] = 0;
226 			break;
227 		}
228 	}
229 	if (i >= n)
230 		errx (1, "Invalid expression: %s", expr);
231 
232 	for ( ; i < n; i++) {
233 		if (expr[i] == '=') {
234 			node = alloca(i - l + 1);
235 			if (node == 0)
236 				err (1, "alloca");
237 			strncpy (node, &(expr[l]), i - l);
238 			node[i - l] = 0;
239 			break;
240 		}
241 	}
242 	if (i >= n)
243 		errx (1, "Invalid expression: %s", expr);
244 
245 	value = &(expr[++i]);
246 
247 	for (i = 0; i < number_of_props; i++) {
248 		if (strcmp(properties[i].class, class) == 0 &&
249 		    strcmp(properties[i].node, node) == 0) {
250 			if (properties[i].parse(&properties[i], value) < 0) {
251 				/* error: do nothing */
252 			} else {
253 				properties[i].print (&properties[i], valuestr);
254 				printf("%s.%s -> %s\n", class, node, valuestr);
255 			}
256 			break;
257 		}
258 	}
259 	if (i >= number_of_props) {
260 		errx (1, "No such property: %s.%s", class, node);
261 	}
262 
263 	return;
264 }
265 
266 void
267 help_single(name)
268 	const char *name;
269 {
270 	int i;
271 	char fullname[50];
272 	char valuestr[MAXVALUELEN];
273 
274 	for (i = 0; i < number_of_props; i++) {
275 		sprintf(fullname, "%s.%s",
276 			properties[i].class, properties[i].node);
277 		if (strcmp(name, fullname) == 0) {
278 			properties[i].print (&properties[i], valuestr);
279 			if (!nflag)
280 				printf ("%s=", fullname);
281 			printf ("%s\n", valuestr);
282 			printf ("%s", properties[i].descr);
283 			break;
284 		}
285 	}
286 	if (i >= number_of_props) {
287 		errx (1, "No such property: %s", name);
288 	}
289 
290 	return;
291 }
292 
293 void
294 alloc_modified_values(void)
295 {
296 	if (current_values == 0)
297 		alloc_current_values();
298 	modified_values = malloc (256);
299 	if (modified_values == 0)
300 		err (1, "malloc");
301 	memcpy (modified_values, current_values, 256);
302 }
303 
304 void
305 alloc_current_values(void)
306 {
307 #ifndef DEBUG
308 	int i;
309 	int sramfd = 0;
310 	struct sram_io buffer;
311 
312 	current_values = malloc (256);
313 	if (current_values == 0)
314 		err (1, "malloc");
315 
316 	sramfd = open (_PATH_DEVSRAM, O_RDONLY);
317 	if (sramfd < 0)
318 		err (1, "Opening %s", _PATH_DEVSRAM);
319 
320 	/* Assume SRAM_IO_SIZE = n * 16. */
321 	for (i = 0; i < 256; i += SRAM_IO_SIZE) {
322 		buffer.offset = i;
323 		if (ioctl (sramfd, SIOGSRAM, &buffer) < 0)
324 			err (1, "ioctl");
325 		memcpy (&current_values[i], buffer.sram, SRAM_IO_SIZE);
326 	}
327 
328 	close (sramfd);
329 #else
330 	int i;
331 	int fd;
332 	struct stat st;
333 
334 	current_values = malloc (256);
335 	if (current_values == 0)
336 		err (1, "malloc");
337 
338 	fd = open (PATH_RAMFILE, O_RDONLY);
339 	if (fd < 0 && errno == ENOENT) {
340 		modified_values = malloc (256);
341 		if (modified_values == 0)
342 			err (1, NULL);
343 		for (i = 0; i < number_of_props; i++) {
344 			properties[i].modified_value
345 			    = properties[i].default_value;
346 			properties[i].modified = 1;
347 			properties[i].flush (&properties[i]);
348 		}
349 
350 		fd = creat (PATH_RAMFILE, 0666);
351 		if (fd < 0)
352 			err (1, "Creating %s", PATH_RAMFILE);
353 		if (write (fd, modified_values, 256) != 256)
354 			err (1, "Writing %s", PATH_RAMFILE);
355 		close (fd);
356 		free (modified_values);
357 		modified_values = 0;
358 
359 		fd = open (PATH_RAMFILE, O_RDONLY);
360 	}
361 	if (fd < 0)
362 		err (1, "Opening %s", PATH_RAMFILE);
363 	if (fstat (fd, &st) < 0)
364 		err (1, "fstat");
365 	if (st.st_size != 256)
366 		errx (1, "PANIC! INVALID RAMFILE");
367 	if (read (fd, current_values, 256) != 256)
368 		err (1, "reading %s", PATH_RAMFILE);
369 	close (fd);
370 #endif
371 
372 	properties[PROP_MAGIC1].fill (&properties[PROP_MAGIC1]);
373 	properties[PROP_MAGIC2].fill (&properties[PROP_MAGIC2]);
374 	if ((properties[PROP_MAGIC1].current_value.longword != MAGIC1) ||
375 	    (properties[PROP_MAGIC2].current_value.longword != MAGIC2))
376 		errx (1, "PANIC! INVALID MAGIC");
377 }
378 
379 void
380 flush(void)
381 {
382 	int i;
383 	int sramfd = 0;
384 #ifndef DEBUG
385 	struct sram_io buffer;
386 #endif
387 
388 	for (i = 0; i < number_of_props; i++) {
389 		if (properties[i].modified)
390 			properties[i].flush(&properties[i]);
391 	}
392 
393 	if (modified_values == 0)
394 		/* Not modified at all. */
395 		return;
396 
397 #ifndef DEBUG
398 	/* Assume SRAM_IO_SIZE = n * 16. */
399 	for (i = 0; i < 256; i += SRAM_IO_SIZE) {
400 		if (memcmp (&current_values[i], &modified_values[i],
401 			    SRAM_IO_SIZE) == 0)
402 			continue;
403 
404 		if (sramfd == 0) {
405 			sramfd = open (_PATH_DEVSRAM, O_RDWR);
406 			if (sramfd < 0)
407 				err (1, "Opening %s", _PATH_DEVSRAM);
408 		}
409 		buffer.offset = i;
410 		memcpy (buffer.sram, &modified_values[i], SRAM_IO_SIZE);
411 		if (ioctl (sramfd, SIOPSRAM, &buffer) < 0)
412 			err (1, "ioctl");
413 	}
414 #else
415 	sramfd = open (PATH_RAMFILE, O_WRONLY);
416 	if (sramfd < 0)
417 		err (1, "Opening %s", PATH_RAMFILE);
418 	if (write (sramfd, modified_values, 256) != 256)
419 		err (1, "Writing %s", PATH_RAMFILE);
420 #endif
421 
422 	if (sramfd != 0)
423 		close (sramfd);
424 
425 	return;
426 }
427 
428 int
429 save(name)
430 	const char *name;
431 {
432 #ifndef DEBUG
433 	int fd;
434 
435 	alloc_current_values ();
436 
437 	if (strcmp (name, "-") == 0)
438 		fd = 1;		/* standard output */
439 	else {
440 		fd = open (name, O_WRONLY|O_CREAT|O_TRUNC, 0666);
441 		if (fd < 0)
442 			err (1, "Opening output file");
443 	}
444 
445 	if (write (fd, current_values, 256) != 256)
446 		err (1, "Writing output file");
447 
448 	if (fd != 1)
449 		close (fd);
450 #else
451 	fprintf (stderr, "Skipping save...\n");
452 #endif
453 
454 	return 0;
455 }
456 
457 int
458 restore (name)
459 	const char *name;
460 {
461 #ifndef DEBUG
462 	int sramfd, fd, i;
463 	struct sram_io buffer;
464 
465 	modified_values = malloc (256);
466 	if (modified_values == 0)
467 		err (1, "Opening %s", _PATH_DEVSRAM);
468 
469 	if (strcmp (name, "-") == 0)
470 		fd = 0;		/* standard input */
471 	else {
472 		fd = open (name, O_RDONLY);
473 		if (fd < 0)
474 			err (1, "Opening input file");
475 	}
476 
477 	sramfd = open (_PATH_DEVSRAM, O_RDONLY);
478 	if (sramfd < 0)
479 		err (1, "Opening %s", _PATH_DEVSRAM);
480 
481 	/* Assume SRAM_IO_SIZE = n * 16. */
482 	for (i = 0; i < 256; i += SRAM_IO_SIZE) {
483 		buffer.offset = i;
484 		memcpy (buffer.sram, &modified_values[i], SRAM_IO_SIZE);
485 		if (ioctl (sramfd, SIOPSRAM, &buffer) < 0)
486 			err (1, "ioctl");
487 	}
488 
489 	close (sramfd);
490 #else
491 	fprintf (stderr, "Skipping restore...\n");
492 #endif
493 
494 	return 0;
495 }
496