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