memswitch.c revision 1.12 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(¤t_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(¤t_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