memswitch.c revision 1.5 1 /* $NetBSD: memswitch.c,v 1.5 2001/02/01 00:51:22 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 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 (¤t_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 (¤t_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