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(¤t_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(¤t_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