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