1*df508298Sisaki /* $NetBSD: memswitch.c,v 1.17 2019/02/08 08:55:35 isaki Exp $ */
212769637Sminoura
312769637Sminoura /*-
412769637Sminoura * Copyright (c) 1999 The NetBSD Foundation, Inc.
512769637Sminoura * All rights reserved.
612769637Sminoura *
712769637Sminoura * This code is derived from software contributed to The NetBSD Foundation
812769637Sminoura * by Minoura Makoto.
912769637Sminoura *
1012769637Sminoura * Redistribution and use in source and binary forms, with or without
1112769637Sminoura * modification, are permitted provided that the following conditions
1212769637Sminoura * are met:
1312769637Sminoura * 1. Redistributions of source code must retain the above copyright
1412769637Sminoura * notice, this list of conditions and the following disclaimer.
1512769637Sminoura * 2. Redistributions in binary form must reproduce the above copyright
1612769637Sminoura * notice, this list of conditions and the following disclaimer in the
1712769637Sminoura * documentation and/or other materials provided with the distribution.
1812769637Sminoura *
1912769637Sminoura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2012769637Sminoura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2112769637Sminoura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2212769637Sminoura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2312769637Sminoura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2412769637Sminoura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2512769637Sminoura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2612769637Sminoura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2712769637Sminoura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2812769637Sminoura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2912769637Sminoura * POSSIBILITY OF SUCH DAMAGE.
3012769637Sminoura */
3112769637Sminoura
3212769637Sminoura /* memswitch.c */
3312769637Sminoura
3412769637Sminoura #include <stdio.h>
3512769637Sminoura #include <stdlib.h>
3612769637Sminoura #include <string.h>
3712769637Sminoura #include <err.h>
3812769637Sminoura #include <unistd.h>
3912769637Sminoura #include <fcntl.h>
40b6f7807aSminoura #include <errno.h>
4112769637Sminoura
4212769637Sminoura #include <sys/ioctl.h>
4312769637Sminoura
44a3bd8746Schristos #ifndef SRAMDEBUG
4512769637Sminoura #include <machine/sram.h>
46b6f7807aSminoura #else
47b6f7807aSminoura /*
48a3bd8746Schristos * SRAMDEBUG -- works on other (faster) platforms;
49b6f7807aSminoura * store in a regular file instead of actual non-volatile static RAM.
50b6f7807aSminoura */
519d27cfd2Sisaki #include <sys/stat.h>
52b6f7807aSminoura #define PATH_RAMFILE "/tmp/sramfile"
53b6f7807aSminoura #endif
5412769637Sminoura
5512769637Sminoura #include "memswitch.h"
5612769637Sminoura
5712769637Sminoura char *progname;
5812769637Sminoura int nflag = 0;
5912769637Sminoura u_int8_t *current_values = 0;
6012769637Sminoura u_int8_t *modified_values = 0;
61b6f7807aSminoura
62421949a3Ssevan static void
usage(void)6312769637Sminoura usage(void)
6412769637Sminoura {
65b635f565Sjmmv fprintf(stderr, "usage: %s -a\n", progname);
6612769637Sminoura fprintf(stderr, " %s [-h] variable ...\n", progname);
678ecdc3e5Sminoura fprintf(stderr, " %s -w variable=value ...\n", progname);
6812769637Sminoura fprintf(stderr, " %s [-rs] filename\n", progname);
6912769637Sminoura exit(1);
7012769637Sminoura }
7112769637Sminoura
7212769637Sminoura int
main(int argc,char * argv[])73421949a3Ssevan main(int argc, char *argv[])
7412769637Sminoura {
7512769637Sminoura int ch;
7612769637Sminoura enum md {
7712769637Sminoura MD_NONE, MD_WRITE, MD_HELP, MD_SHOWALL, MD_SAVE, MD_RESTORE
7812769637Sminoura } mode = MD_NONE;
7912769637Sminoura
8012769637Sminoura progname = argv[0];
8112769637Sminoura
8212769637Sminoura while ((ch = getopt(argc, argv, "whanrs")) != -1) {
8312769637Sminoura switch (ch) {
8412769637Sminoura case 'w': /* write */
8512769637Sminoura mode = MD_WRITE;
8612769637Sminoura break;
8712769637Sminoura case 'h':
8812769637Sminoura mode = MD_HELP;
8912769637Sminoura break;
9012769637Sminoura case 'a':
9112769637Sminoura mode = MD_SHOWALL;
9212769637Sminoura break;
9312769637Sminoura case 'n':
9412769637Sminoura nflag = 1;
9512769637Sminoura break;
9612769637Sminoura case 's':
9712769637Sminoura mode = MD_SAVE;
9812769637Sminoura break;
9912769637Sminoura case 'r':
10012769637Sminoura mode = MD_RESTORE;
10112769637Sminoura break;
10212769637Sminoura }
10312769637Sminoura }
10412769637Sminoura argc -= optind;
10512769637Sminoura argv += optind;
10612769637Sminoura
10712769637Sminoura switch (mode) {
10812769637Sminoura case MD_NONE:
10912769637Sminoura if (argc == 0)
11012769637Sminoura usage();
11112769637Sminoura while (argv[0]) {
11212769637Sminoura show_single(argv[0]);
11312769637Sminoura argv++;
11412769637Sminoura }
11512769637Sminoura break;
11612769637Sminoura case MD_SHOWALL:
11712769637Sminoura if (argc)
11812769637Sminoura usage();
11912769637Sminoura show_all();
12012769637Sminoura break;
12112769637Sminoura case MD_WRITE:
12212769637Sminoura if (argc == 0)
12312769637Sminoura usage();
12412769637Sminoura while (argv[0]) {
12512769637Sminoura modify_single (argv[0]);
12612769637Sminoura argv++;
12712769637Sminoura }
12812769637Sminoura flush();
12912769637Sminoura break;
13012769637Sminoura case MD_HELP:
13112769637Sminoura if (argc == 0)
13212769637Sminoura usage();
13312769637Sminoura while (argv[0]) {
13412769637Sminoura help_single(argv[0]);
13512769637Sminoura argv++;
13612769637Sminoura }
13712769637Sminoura break;
13812769637Sminoura case MD_SAVE:
13912769637Sminoura if (argc != 1)
14012769637Sminoura usage();
14112769637Sminoura save(argv[0]);
14212769637Sminoura break;
14312769637Sminoura case MD_RESTORE:
14412769637Sminoura if (argc != 1)
14512769637Sminoura usage();
14612769637Sminoura restore(argv[0]);
14712769637Sminoura break;
14812769637Sminoura
14912769637Sminoura }
15012769637Sminoura
15112769637Sminoura return 0;
15212769637Sminoura }
15312769637Sminoura
15412769637Sminoura void
show_single(const char * name)155421949a3Ssevan show_single(const char *name)
15612769637Sminoura {
15712769637Sminoura int i;
158f42a521bSminoura int n = 0;
15912769637Sminoura char fullname[50];
16012769637Sminoura char valuestr[MAXVALUELEN];
16112769637Sminoura
16212769637Sminoura for (i = 0; i < number_of_props; i++) {
163d0a2aaaaSitojun snprintf(fullname, sizeof(fullname), "%s.%s",
16412769637Sminoura properties[i].class, properties[i].node);
165f42a521bSminoura if (strcmp(name, fullname) == 0 || strcmp(name, properties[i].class) == 0) {
16612769637Sminoura properties[i].print(&properties[i], valuestr);
16712769637Sminoura if (!nflag)
16812769637Sminoura printf("%s=%s\n", fullname, valuestr);
169f42a521bSminoura n++;
17012769637Sminoura }
17112769637Sminoura }
172f42a521bSminoura if (n == 0) {
173f42a521bSminoura errx(1, "No such %s: %s", strstr(name, ".")?"property":"class", name);
17412769637Sminoura }
17512769637Sminoura
17612769637Sminoura return;
17712769637Sminoura }
17812769637Sminoura
17912769637Sminoura void
show_all(void)18012769637Sminoura show_all(void)
18112769637Sminoura {
18212769637Sminoura int i;
18312769637Sminoura char valuestr[MAXVALUELEN];
18412769637Sminoura
18512769637Sminoura for (i = 0; i < number_of_props; i++) {
18612769637Sminoura properties[i].print(&properties[i], valuestr);
18712769637Sminoura if (!nflag)
18812769637Sminoura printf("%s.%s=",
18912769637Sminoura properties[i].class, properties[i].node);
19012769637Sminoura printf("%s\n", valuestr);
19112769637Sminoura }
19212769637Sminoura
19312769637Sminoura return;
19412769637Sminoura }
19512769637Sminoura
19612769637Sminoura void
modify_single(const char * expr)197421949a3Ssevan modify_single(const char *expr)
19812769637Sminoura {
199*df508298Sisaki int i;
200*df508298Sisaki char *buf;
201*df508298Sisaki char *p;
202*df508298Sisaki const char *class;
203*df508298Sisaki const char *node;
20412769637Sminoura const char *value;
20512769637Sminoura char valuestr[MAXVALUELEN];
20612769637Sminoura
207*df508298Sisaki buf = strdup(expr);
208*df508298Sisaki if (buf == NULL)
209*df508298Sisaki err(EXIT_FAILURE, "strdup failed");
210*df508298Sisaki
211*df508298Sisaki p = buf;
212*df508298Sisaki for (class = p; *p; p++) {
213*df508298Sisaki if (*p == '.') {
214*df508298Sisaki *p++ = '\0';
21512769637Sminoura break;
21612769637Sminoura }
21712769637Sminoura }
21812769637Sminoura
219*df508298Sisaki for (node = p; *p; p++) {
220*df508298Sisaki if (*p == '=') {
221*df508298Sisaki *p++ = '\0';
22212769637Sminoura break;
22312769637Sminoura }
22412769637Sminoura }
22512769637Sminoura
226*df508298Sisaki value = p;
227*df508298Sisaki
228*df508298Sisaki if (class[0] == '\0' || node[0] == '\0' || value[0] == '\0')
229*df508298Sisaki errx(1, "Invalid expression: %s", expr);
23012769637Sminoura
23112769637Sminoura for (i = 0; i < number_of_props; i++) {
23212769637Sminoura if (strcmp(properties[i].class, class) == 0 &&
23312769637Sminoura strcmp(properties[i].node, node) == 0) {
23412769637Sminoura if (properties[i].parse(&properties[i], value) < 0) {
23512769637Sminoura /* error: do nothing */
23612769637Sminoura } else {
23712769637Sminoura properties[i].print(&properties[i], valuestr);
23812769637Sminoura printf("%s.%s -> %s\n", class, node, valuestr);
23912769637Sminoura }
24012769637Sminoura break;
24112769637Sminoura }
24212769637Sminoura }
24312769637Sminoura if (i >= number_of_props) {
244f42a521bSminoura errx(1, "No such property: %s.%s", class, node);
24512769637Sminoura }
24612769637Sminoura
247*df508298Sisaki free(buf);
24812769637Sminoura }
24912769637Sminoura
25012769637Sminoura void
help_single(const char * name)251421949a3Ssevan help_single(const char *name)
25212769637Sminoura {
25312769637Sminoura int i;
25412769637Sminoura char fullname[50];
25512769637Sminoura char valuestr[MAXVALUELEN];
25612769637Sminoura
25712769637Sminoura for (i = 0; i < number_of_props; i++) {
258d0a2aaaaSitojun snprintf(fullname, sizeof(fullname), "%s.%s",
25912769637Sminoura properties[i].class, properties[i].node);
26012769637Sminoura if (strcmp(name, fullname) == 0) {
26112769637Sminoura properties[i].print(&properties[i], valuestr);
26212769637Sminoura if (!nflag)
26312769637Sminoura printf("%s=", fullname);
26412769637Sminoura printf("%s\n", valuestr);
26512769637Sminoura printf("%s", properties[i].descr);
26612769637Sminoura break;
26712769637Sminoura }
26812769637Sminoura }
26912769637Sminoura if (i >= number_of_props) {
270f42a521bSminoura errx(1, "No such property: %s", name);
27112769637Sminoura }
27212769637Sminoura
27312769637Sminoura return;
27412769637Sminoura }
27512769637Sminoura
27612769637Sminoura void
alloc_modified_values(void)27712769637Sminoura alloc_modified_values(void)
27812769637Sminoura {
27912769637Sminoura if (current_values == 0)
28012769637Sminoura alloc_current_values();
28112769637Sminoura modified_values = malloc(256);
28212769637Sminoura if (modified_values == 0)
283909e46e9Sminoura err(1, "malloc");
28412769637Sminoura memcpy(modified_values, current_values, 256);
28512769637Sminoura }
28612769637Sminoura
28712769637Sminoura void
alloc_current_values(void)28812769637Sminoura alloc_current_values(void)
28912769637Sminoura {
290a3bd8746Schristos #ifndef SRAMDEBUG
29112769637Sminoura int i;
29212769637Sminoura int sramfd = 0;
29312769637Sminoura struct sram_io buffer;
29412769637Sminoura
29512769637Sminoura current_values = malloc(256);
29612769637Sminoura if (current_values == 0)
297909e46e9Sminoura err(1, "malloc");
29812769637Sminoura
29912769637Sminoura sramfd = open(_PATH_DEVSRAM, O_RDONLY);
30012769637Sminoura if (sramfd < 0)
30112769637Sminoura err(1, "Opening %s", _PATH_DEVSRAM);
30212769637Sminoura
30312769637Sminoura /* Assume SRAM_IO_SIZE = n * 16. */
30412769637Sminoura for (i = 0; i < 256; i += SRAM_IO_SIZE) {
30512769637Sminoura buffer.offset = i;
30612769637Sminoura if (ioctl(sramfd, SIOGSRAM, &buffer) < 0)
30712769637Sminoura err(1, "ioctl");
30812769637Sminoura memcpy(¤t_values[i], buffer.sram, SRAM_IO_SIZE);
30912769637Sminoura }
31012769637Sminoura
31112769637Sminoura close(sramfd);
312b6f7807aSminoura #else
313b6f7807aSminoura int i;
314b6f7807aSminoura int fd;
315b6f7807aSminoura struct stat st;
316b6f7807aSminoura
317b6f7807aSminoura current_values = malloc(256);
318b6f7807aSminoura if (current_values == 0)
319b6f7807aSminoura err(1, "malloc");
320b6f7807aSminoura
321b6f7807aSminoura fd = open(PATH_RAMFILE, O_RDONLY);
322b6f7807aSminoura if (fd < 0 && errno == ENOENT) {
323b6f7807aSminoura modified_values = malloc(256);
324b6f7807aSminoura if (modified_values == 0)
325b6f7807aSminoura err(1, NULL);
326b6f7807aSminoura for (i = 0; i < number_of_props; i++) {
327b6f7807aSminoura properties[i].modified_value
328b6f7807aSminoura = properties[i].default_value;
329b6f7807aSminoura properties[i].modified = 1;
330b6f7807aSminoura properties[i].flush(&properties[i]);
331b6f7807aSminoura }
332b6f7807aSminoura
333b6f7807aSminoura fd = creat(PATH_RAMFILE, 0666);
334b6f7807aSminoura if (fd < 0)
335b6f7807aSminoura err(1, "Creating %s", PATH_RAMFILE);
336b6f7807aSminoura if (write(fd, modified_values, 256) != 256)
337b6f7807aSminoura err(1, "Writing %s", PATH_RAMFILE);
338b6f7807aSminoura close(fd);
339b6f7807aSminoura free(modified_values);
340b6f7807aSminoura modified_values = 0;
341b6f7807aSminoura
342b6f7807aSminoura fd = open(PATH_RAMFILE, O_RDONLY);
343b6f7807aSminoura }
344b6f7807aSminoura if (fd < 0)
345b6f7807aSminoura err(1, "Opening %s", PATH_RAMFILE);
346b6f7807aSminoura if (fstat(fd, &st) < 0)
347b6f7807aSminoura err(1, "fstat");
348b6f7807aSminoura if (st.st_size != 256)
349b6f7807aSminoura errx(1, "PANIC! INVALID RAMFILE");
350b6f7807aSminoura if (read(fd, current_values, 256) != 256)
351b6f7807aSminoura err(1, "reading %s", PATH_RAMFILE);
352b6f7807aSminoura close(fd);
353b6f7807aSminoura #endif
35412769637Sminoura
35512769637Sminoura properties[PROP_MAGIC1].fill(&properties[PROP_MAGIC1]);
35612769637Sminoura properties[PROP_MAGIC2].fill(&properties[PROP_MAGIC2]);
35712769637Sminoura if ((properties[PROP_MAGIC1].current_value.longword != MAGIC1) ||
35812769637Sminoura (properties[PROP_MAGIC2].current_value.longword != MAGIC2))
35912769637Sminoura errx(1, "PANIC! INVALID MAGIC");
36012769637Sminoura }
36112769637Sminoura
36212769637Sminoura void
flush(void)36312769637Sminoura flush(void)
36412769637Sminoura {
36512769637Sminoura int i;
36612769637Sminoura int sramfd = 0;
367a3bd8746Schristos #ifndef SRAMDEBUG
36812769637Sminoura struct sram_io buffer;
369b6f7807aSminoura #endif
37012769637Sminoura
37112769637Sminoura for (i = 0; i < number_of_props; i++) {
37212769637Sminoura if (properties[i].modified)
37312769637Sminoura properties[i].flush(&properties[i]);
37412769637Sminoura }
37512769637Sminoura
37612769637Sminoura if (modified_values == 0)
37712769637Sminoura /* Not modified at all. */
37812769637Sminoura return;
37912769637Sminoura
380a3bd8746Schristos #ifndef SRAMDEBUG
38112769637Sminoura /* Assume SRAM_IO_SIZE = n * 16. */
38212769637Sminoura for (i = 0; i < 256; i += SRAM_IO_SIZE) {
38312769637Sminoura if (memcmp(¤t_values[i], &modified_values[i],
38412769637Sminoura SRAM_IO_SIZE) == 0)
38512769637Sminoura continue;
38612769637Sminoura
38712769637Sminoura if (sramfd == 0) {
38812769637Sminoura sramfd = open(_PATH_DEVSRAM, O_RDWR);
38912769637Sminoura if (sramfd < 0)
39012769637Sminoura err(1, "Opening %s", _PATH_DEVSRAM);
39112769637Sminoura }
39212769637Sminoura buffer.offset = i;
39312769637Sminoura memcpy(buffer.sram, &modified_values[i], SRAM_IO_SIZE);
39412769637Sminoura if (ioctl(sramfd, SIOPSRAM, &buffer) < 0)
39512769637Sminoura err(1, "ioctl");
39612769637Sminoura }
397b6f7807aSminoura #else
398b6f7807aSminoura sramfd = open(PATH_RAMFILE, O_WRONLY);
399b6f7807aSminoura if (sramfd < 0)
400b6f7807aSminoura err(1, "Opening %s", PATH_RAMFILE);
401b6f7807aSminoura if (write(sramfd, modified_values, 256) != 256)
402b6f7807aSminoura err(1, "Writing %s", PATH_RAMFILE);
403b6f7807aSminoura #endif
40412769637Sminoura
40512769637Sminoura if (sramfd != 0)
40612769637Sminoura close(sramfd);
40712769637Sminoura
40812769637Sminoura return;
40912769637Sminoura }
41012769637Sminoura
41112769637Sminoura int
save(const char * name)412421949a3Ssevan save(const char *name)
41312769637Sminoura {
414a3bd8746Schristos #ifndef SRAMDEBUG
41512769637Sminoura int fd;
41612769637Sminoura
41712769637Sminoura alloc_current_values();
41812769637Sminoura
41912769637Sminoura if (strcmp(name, "-") == 0)
42012769637Sminoura fd = 1; /* standard output */
42112769637Sminoura else {
42212769637Sminoura fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0666);
42312769637Sminoura if (fd < 0)
42412769637Sminoura err(1, "Opening output file");
42512769637Sminoura }
42612769637Sminoura
42712769637Sminoura if (write(fd, current_values, 256) != 256)
42812769637Sminoura err(1, "Writing output file");
42912769637Sminoura
43012769637Sminoura if (fd != 1)
43112769637Sminoura close(fd);
432b6f7807aSminoura #else
433b6f7807aSminoura fprintf(stderr, "Skipping save...\n");
434b6f7807aSminoura #endif
43512769637Sminoura
43612769637Sminoura return 0;
43712769637Sminoura }
43812769637Sminoura
43912769637Sminoura int
restore(const char * name)440421949a3Ssevan restore(const char *name)
44112769637Sminoura {
442a3bd8746Schristos #ifndef SRAMDEBUG
44312769637Sminoura int sramfd, fd, i;
44412769637Sminoura struct sram_io buffer;
44512769637Sminoura
44612769637Sminoura modified_values = malloc(256);
44712769637Sminoura if (modified_values == 0)
44812769637Sminoura err(1, "Opening %s", _PATH_DEVSRAM);
44912769637Sminoura
45012769637Sminoura if (strcmp(name, "-") == 0)
45112769637Sminoura fd = 0; /* standard input */
45212769637Sminoura else {
45312769637Sminoura fd = open(name, O_RDONLY);
45412769637Sminoura if (fd < 0)
45512769637Sminoura err(1, "Opening input file");
45612769637Sminoura }
45712769637Sminoura
458c98325a1Sminoura if (read(fd, modified_values, 256) != 256)
459c98325a1Sminoura err(1, "Reading input file");
460c98325a1Sminoura
461c98325a1Sminoura if (fd != 0)
462c98325a1Sminoura close(fd);
463c98325a1Sminoura
464c98325a1Sminoura sramfd = open(_PATH_DEVSRAM, O_RDWR);
46512769637Sminoura if (sramfd < 0)
46612769637Sminoura err(1, "Opening %s", _PATH_DEVSRAM);
46712769637Sminoura
46812769637Sminoura /* Assume SRAM_IO_SIZE = n * 16. */
46912769637Sminoura for (i = 0; i < 256; i += SRAM_IO_SIZE) {
47012769637Sminoura buffer.offset = i;
47112769637Sminoura memcpy(buffer.sram, &modified_values[i], SRAM_IO_SIZE);
47212769637Sminoura if (ioctl(sramfd, SIOPSRAM, &buffer) < 0)
47312769637Sminoura err(1, "ioctl");
47412769637Sminoura }
47512769637Sminoura
47612769637Sminoura close(sramfd);
477b6f7807aSminoura #else
478b6f7807aSminoura fprintf(stderr, "Skipping restore...\n");
479b6f7807aSminoura #endif
48012769637Sminoura
48112769637Sminoura return 0;
48212769637Sminoura }
483