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