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(&current_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(&current_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