xref: /netbsd-src/usr.sbin/memswitch/memswitch.c (revision 4472dbe5e3bd91ef2540bada7a7ca7384627ff9b)
1 /*	$NetBSD: memswitch.c,v 1.4 2000/04/14 06:26:53 simonb 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 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 	char fullname[50];
170 	char valuestr[MAXVALUELEN];
171 
172 	for (i = 0; i < number_of_props; i++) {
173 		sprintf(fullname, "%s.%s",
174 			properties[i].class, properties[i].node);
175 		if (strcmp(name, fullname) == 0) {
176 			properties[i].print (&properties[i], valuestr);
177 			if (!nflag)
178 				printf ("%s=%s\n", fullname, valuestr);
179 			break;
180 		}
181 	}
182 	if (i >= number_of_props) {
183 		errx (1, "No such property: %s\n", name);
184 	}
185 
186 	return;
187 }
188 
189 void
190 show_all(void)
191 {
192 	int i;
193 	char valuestr[MAXVALUELEN];
194 
195 	for (i = 0; i < number_of_props; i++) {
196 		properties[i].print (&properties[i], valuestr);
197 		if (!nflag)
198 			printf ("%s.%s=",
199 				properties[i].class, properties[i].node);
200 		printf ("%s\n", valuestr);
201 	}
202 
203 	return;
204 }
205 
206 void
207 modify_single(expr)
208 	const char *expr;
209 {
210 	int i, l, n;
211 	char *class, *node;
212 	const char *value;
213 	char valuestr[MAXVALUELEN];
214 
215 	l = 0;
216 	n = strlen(expr);
217 	for (i = 0; i < n; i++) {
218 		if (expr[i] == '.') {
219 			l = i + 1;
220 			class = alloca(l);
221 			if (class == 0)
222 				err (1, "alloca");
223 			strncpy (class, expr, i);
224 			class[i] = 0;
225 			break;
226 		}
227 	}
228 	if (i >= n)
229 		errx (1, "Invalid expression: %s\n", expr);
230 
231 	for ( ; i < n; i++) {
232 		if (expr[i] == '=') {
233 			node = alloca(i - l + 1);
234 			if (node == 0)
235 				err (1, "alloca");
236 			strncpy (node, &(expr[l]), i - l);
237 			node[i - l] = 0;
238 			break;
239 		}
240 	}
241 	if (i >= n)
242 		errx (1, "Invalid expression: %s\n", expr);
243 
244 	value = &(expr[++i]);
245 
246 	for (i = 0; i < number_of_props; i++) {
247 		if (strcmp(properties[i].class, class) == 0 &&
248 		    strcmp(properties[i].node, node) == 0) {
249 			if (properties[i].parse(&properties[i], value) < 0) {
250 				/* error: do nothing */
251 			} else {
252 				properties[i].print (&properties[i], valuestr);
253 				printf("%s.%s -> %s\n", class, node, valuestr);
254 			}
255 			break;
256 		}
257 	}
258 	if (i >= number_of_props) {
259 		errx (1, "No such property: %s.%s\n", class, node);
260 	}
261 
262 	return;
263 }
264 
265 void
266 help_single(name)
267 	const char *name;
268 {
269 	int i;
270 	char fullname[50];
271 	char valuestr[MAXVALUELEN];
272 
273 	for (i = 0; i < number_of_props; i++) {
274 		sprintf(fullname, "%s.%s",
275 			properties[i].class, properties[i].node);
276 		if (strcmp(name, fullname) == 0) {
277 			properties[i].print (&properties[i], valuestr);
278 			if (!nflag)
279 				printf ("%s=", fullname);
280 			printf ("%s\n", valuestr);
281 			printf ("%s", properties[i].descr);
282 			break;
283 		}
284 	}
285 	if (i >= number_of_props) {
286 		errx (1, "No such property: %s\n", name);
287 	}
288 
289 	return;
290 }
291 
292 void
293 alloc_modified_values(void)
294 {
295 	if (current_values == 0)
296 		alloc_current_values();
297 	modified_values = malloc (256);
298 	if (modified_values == 0)
299 		err (1, "malloc");
300 	memcpy (modified_values, current_values, 256);
301 }
302 
303 void
304 alloc_current_values(void)
305 {
306 #ifndef DEBUG
307 	int i;
308 	int sramfd = 0;
309 	struct sram_io buffer;
310 
311 	current_values = malloc (256);
312 	if (current_values == 0)
313 		err (1, "malloc");
314 
315 	sramfd = open (_PATH_DEVSRAM, O_RDONLY);
316 	if (sramfd < 0)
317 		err (1, "Opening %s", _PATH_DEVSRAM);
318 
319 	/* Assume SRAM_IO_SIZE = n * 16. */
320 	for (i = 0; i < 256; i += SRAM_IO_SIZE) {
321 		buffer.offset = i;
322 		if (ioctl (sramfd, SIOGSRAM, &buffer) < 0)
323 			err (1, "ioctl");
324 		memcpy (&current_values[i], buffer.sram, SRAM_IO_SIZE);
325 	}
326 
327 	close (sramfd);
328 #else
329 	int i;
330 	int fd;
331 	struct stat st;
332 
333 	current_values = malloc (256);
334 	if (current_values == 0)
335 		err (1, "malloc");
336 
337 	fd = open (PATH_RAMFILE, O_RDONLY);
338 	if (fd < 0 && errno == ENOENT) {
339 		modified_values = malloc (256);
340 		if (modified_values == 0)
341 			err (1, NULL);
342 		for (i = 0; i < number_of_props; i++) {
343 			properties[i].modified_value
344 			    = properties[i].default_value;
345 			properties[i].modified = 1;
346 			properties[i].flush (&properties[i]);
347 		}
348 
349 		fd = creat (PATH_RAMFILE, 0666);
350 		if (fd < 0)
351 			err (1, "Creating %s", PATH_RAMFILE);
352 		if (write (fd, modified_values, 256) != 256)
353 			err (1, "Writing %s", PATH_RAMFILE);
354 		close (fd);
355 		free (modified_values);
356 		modified_values = 0;
357 
358 		fd = open (PATH_RAMFILE, O_RDONLY);
359 	}
360 	if (fd < 0)
361 		err (1, "Opening %s", PATH_RAMFILE);
362 	if (fstat (fd, &st) < 0)
363 		err (1, "fstat");
364 	if (st.st_size != 256)
365 		errx (1, "PANIC! INVALID RAMFILE");
366 	if (read (fd, current_values, 256) != 256)
367 		err (1, "reading %s", PATH_RAMFILE);
368 	close (fd);
369 #endif
370 
371 	properties[PROP_MAGIC1].fill (&properties[PROP_MAGIC1]);
372 	properties[PROP_MAGIC2].fill (&properties[PROP_MAGIC2]);
373 	if ((properties[PROP_MAGIC1].current_value.longword != MAGIC1) ||
374 	    (properties[PROP_MAGIC2].current_value.longword != MAGIC2))
375 		errx (1, "PANIC! INVALID MAGIC");
376 }
377 
378 void
379 flush(void)
380 {
381 	int i;
382 	int sramfd = 0;
383 #ifndef DEBUG
384 	struct sram_io buffer;
385 #endif
386 
387 	for (i = 0; i < number_of_props; i++) {
388 		if (properties[i].modified)
389 			properties[i].flush(&properties[i]);
390 	}
391 
392 	if (modified_values == 0)
393 		/* Not modified at all. */
394 		return;
395 
396 #ifndef DEBUG
397 	/* Assume SRAM_IO_SIZE = n * 16. */
398 	for (i = 0; i < 256; i += SRAM_IO_SIZE) {
399 		if (memcmp (&current_values[i], &modified_values[i],
400 			    SRAM_IO_SIZE) == 0)
401 			continue;
402 
403 		if (sramfd == 0) {
404 			sramfd = open (_PATH_DEVSRAM, O_RDWR);
405 			if (sramfd < 0)
406 				err (1, "Opening %s", _PATH_DEVSRAM);
407 		}
408 		buffer.offset = i;
409 		memcpy (buffer.sram, &modified_values[i], SRAM_IO_SIZE);
410 		if (ioctl (sramfd, SIOPSRAM, &buffer) < 0)
411 			err (1, "ioctl");
412 	}
413 #else
414 	sramfd = open (PATH_RAMFILE, O_WRONLY);
415 	if (sramfd < 0)
416 		err (1, "Opening %s", PATH_RAMFILE);
417 	if (write (sramfd, modified_values, 256) != 256)
418 		err (1, "Writing %s", PATH_RAMFILE);
419 #endif
420 
421 	if (sramfd != 0)
422 		close (sramfd);
423 
424 	return;
425 }
426 
427 int
428 save(name)
429 	const char *name;
430 {
431 #ifndef DEBUG
432 	int fd;
433 
434 	alloc_current_values ();
435 
436 	if (strcmp (name, "-") == 0)
437 		fd = 1;		/* standard output */
438 	else {
439 		fd = open (name, O_WRONLY|O_CREAT|O_TRUNC, 0666);
440 		if (fd < 0)
441 			err (1, "Opening output file");
442 	}
443 
444 	if (write (fd, current_values, 256) != 256)
445 		err (1, "Writing output file");
446 
447 	if (fd != 1)
448 		close (fd);
449 #else
450 	fprintf (stderr, "Skipping save...\n");
451 #endif
452 
453 	return 0;
454 }
455 
456 int
457 restore (name)
458 	const char *name;
459 {
460 #ifndef DEBUG
461 	int sramfd, fd, i;
462 	struct sram_io buffer;
463 
464 	modified_values = malloc (256);
465 	if (modified_values == 0)
466 		err (1, "Opening %s", _PATH_DEVSRAM);
467 
468 	if (strcmp (name, "-") == 0)
469 		fd = 0;		/* standard input */
470 	else {
471 		fd = open (name, O_RDONLY);
472 		if (fd < 0)
473 			err (1, "Opening input file");
474 	}
475 
476 	sramfd = open (_PATH_DEVSRAM, O_RDONLY);
477 	if (sramfd < 0)
478 		err (1, "Opening %s", _PATH_DEVSRAM);
479 
480 	/* Assume SRAM_IO_SIZE = n * 16. */
481 	for (i = 0; i < 256; i += SRAM_IO_SIZE) {
482 		buffer.offset = i;
483 		memcpy (buffer.sram, &modified_values[i], SRAM_IO_SIZE);
484 		if (ioctl (sramfd, SIOPSRAM, &buffer) < 0)
485 			err (1, "ioctl");
486 	}
487 
488 	close (sramfd);
489 #else
490 	fprintf (stderr, "Skipping restore...\n");
491 #endif
492 
493 	return 0;
494 }
495