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