/* $NetBSD: memswitch.c,v 1.17 2019/02/08 08:55:35 isaki Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Minoura Makoto. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* memswitch.c */ #include #include #include #include #include #include #include #include #ifndef SRAMDEBUG #include #else /* * SRAMDEBUG -- works on other (faster) platforms; * store in a regular file instead of actual non-volatile static RAM. */ #include #define PATH_RAMFILE "/tmp/sramfile" #endif #include "memswitch.h" char *progname; int nflag = 0; u_int8_t *current_values = 0; u_int8_t *modified_values = 0; static void usage(void) { fprintf(stderr, "usage: %s -a\n", progname); fprintf(stderr, " %s [-h] variable ...\n", progname); fprintf(stderr, " %s -w variable=value ...\n", progname); fprintf(stderr, " %s [-rs] filename\n", progname); exit(1); } int main(int argc, char *argv[]) { int ch; enum md { MD_NONE, MD_WRITE, MD_HELP, MD_SHOWALL, MD_SAVE, MD_RESTORE } mode = MD_NONE; progname = argv[0]; while ((ch = getopt(argc, argv, "whanrs")) != -1) { switch (ch) { case 'w': /* write */ mode = MD_WRITE; break; case 'h': mode = MD_HELP; break; case 'a': mode = MD_SHOWALL; break; case 'n': nflag = 1; break; case 's': mode = MD_SAVE; break; case 'r': mode = MD_RESTORE; break; } } argc -= optind; argv += optind; switch (mode) { case MD_NONE: if (argc == 0) usage(); while (argv[0]) { show_single(argv[0]); argv++; } break; case MD_SHOWALL: if (argc) usage(); show_all(); break; case MD_WRITE: if (argc == 0) usage(); while (argv[0]) { modify_single (argv[0]); argv++; } flush(); break; case MD_HELP: if (argc == 0) usage(); while (argv[0]) { help_single(argv[0]); argv++; } break; case MD_SAVE: if (argc != 1) usage(); save(argv[0]); break; case MD_RESTORE: if (argc != 1) usage(); restore(argv[0]); break; } return 0; } void show_single(const char *name) { int i; int n = 0; char fullname[50]; char valuestr[MAXVALUELEN]; for (i = 0; i < number_of_props; i++) { snprintf(fullname, sizeof(fullname), "%s.%s", properties[i].class, properties[i].node); if (strcmp(name, fullname) == 0 || strcmp(name, properties[i].class) == 0) { properties[i].print(&properties[i], valuestr); if (!nflag) printf("%s=%s\n", fullname, valuestr); n++; } } if (n == 0) { errx(1, "No such %s: %s", strstr(name, ".")?"property":"class", name); } return; } void show_all(void) { int i; char valuestr[MAXVALUELEN]; for (i = 0; i < number_of_props; i++) { properties[i].print(&properties[i], valuestr); if (!nflag) printf("%s.%s=", properties[i].class, properties[i].node); printf("%s\n", valuestr); } return; } void modify_single(const char *expr) { int i; char *buf; char *p; const char *class; const char *node; const char *value; char valuestr[MAXVALUELEN]; buf = strdup(expr); if (buf == NULL) err(EXIT_FAILURE, "strdup failed"); p = buf; for (class = p; *p; p++) { if (*p == '.') { *p++ = '\0'; break; } } for (node = p; *p; p++) { if (*p == '=') { *p++ = '\0'; break; } } value = p; if (class[0] == '\0' || node[0] == '\0' || value[0] == '\0') errx(1, "Invalid expression: %s", expr); for (i = 0; i < number_of_props; i++) { if (strcmp(properties[i].class, class) == 0 && strcmp(properties[i].node, node) == 0) { if (properties[i].parse(&properties[i], value) < 0) { /* error: do nothing */ } else { properties[i].print(&properties[i], valuestr); printf("%s.%s -> %s\n", class, node, valuestr); } break; } } if (i >= number_of_props) { errx(1, "No such property: %s.%s", class, node); } free(buf); } void help_single(const char *name) { int i; char fullname[50]; char valuestr[MAXVALUELEN]; for (i = 0; i < number_of_props; i++) { snprintf(fullname, sizeof(fullname), "%s.%s", properties[i].class, properties[i].node); if (strcmp(name, fullname) == 0) { properties[i].print(&properties[i], valuestr); if (!nflag) printf("%s=", fullname); printf("%s\n", valuestr); printf("%s", properties[i].descr); break; } } if (i >= number_of_props) { errx(1, "No such property: %s", name); } return; } void alloc_modified_values(void) { if (current_values == 0) alloc_current_values(); modified_values = malloc(256); if (modified_values == 0) err(1, "malloc"); memcpy(modified_values, current_values, 256); } void alloc_current_values(void) { #ifndef SRAMDEBUG int i; int sramfd = 0; struct sram_io buffer; current_values = malloc(256); if (current_values == 0) err(1, "malloc"); sramfd = open(_PATH_DEVSRAM, O_RDONLY); if (sramfd < 0) err(1, "Opening %s", _PATH_DEVSRAM); /* Assume SRAM_IO_SIZE = n * 16. */ for (i = 0; i < 256; i += SRAM_IO_SIZE) { buffer.offset = i; if (ioctl(sramfd, SIOGSRAM, &buffer) < 0) err(1, "ioctl"); memcpy(¤t_values[i], buffer.sram, SRAM_IO_SIZE); } close(sramfd); #else int i; int fd; struct stat st; current_values = malloc(256); if (current_values == 0) err(1, "malloc"); fd = open(PATH_RAMFILE, O_RDONLY); if (fd < 0 && errno == ENOENT) { modified_values = malloc(256); if (modified_values == 0) err(1, NULL); for (i = 0; i < number_of_props; i++) { properties[i].modified_value = properties[i].default_value; properties[i].modified = 1; properties[i].flush(&properties[i]); } fd = creat(PATH_RAMFILE, 0666); if (fd < 0) err(1, "Creating %s", PATH_RAMFILE); if (write(fd, modified_values, 256) != 256) err(1, "Writing %s", PATH_RAMFILE); close(fd); free(modified_values); modified_values = 0; fd = open(PATH_RAMFILE, O_RDONLY); } if (fd < 0) err(1, "Opening %s", PATH_RAMFILE); if (fstat(fd, &st) < 0) err(1, "fstat"); if (st.st_size != 256) errx(1, "PANIC! INVALID RAMFILE"); if (read(fd, current_values, 256) != 256) err(1, "reading %s", PATH_RAMFILE); close(fd); #endif properties[PROP_MAGIC1].fill(&properties[PROP_MAGIC1]); properties[PROP_MAGIC2].fill(&properties[PROP_MAGIC2]); if ((properties[PROP_MAGIC1].current_value.longword != MAGIC1) || (properties[PROP_MAGIC2].current_value.longword != MAGIC2)) errx(1, "PANIC! INVALID MAGIC"); } void flush(void) { int i; int sramfd = 0; #ifndef SRAMDEBUG struct sram_io buffer; #endif for (i = 0; i < number_of_props; i++) { if (properties[i].modified) properties[i].flush(&properties[i]); } if (modified_values == 0) /* Not modified at all. */ return; #ifndef SRAMDEBUG /* Assume SRAM_IO_SIZE = n * 16. */ for (i = 0; i < 256; i += SRAM_IO_SIZE) { if (memcmp(¤t_values[i], &modified_values[i], SRAM_IO_SIZE) == 0) continue; if (sramfd == 0) { sramfd = open(_PATH_DEVSRAM, O_RDWR); if (sramfd < 0) err(1, "Opening %s", _PATH_DEVSRAM); } buffer.offset = i; memcpy(buffer.sram, &modified_values[i], SRAM_IO_SIZE); if (ioctl(sramfd, SIOPSRAM, &buffer) < 0) err(1, "ioctl"); } #else sramfd = open(PATH_RAMFILE, O_WRONLY); if (sramfd < 0) err(1, "Opening %s", PATH_RAMFILE); if (write(sramfd, modified_values, 256) != 256) err(1, "Writing %s", PATH_RAMFILE); #endif if (sramfd != 0) close(sramfd); return; } int save(const char *name) { #ifndef SRAMDEBUG int fd; alloc_current_values(); if (strcmp(name, "-") == 0) fd = 1; /* standard output */ else { fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0) err(1, "Opening output file"); } if (write(fd, current_values, 256) != 256) err(1, "Writing output file"); if (fd != 1) close(fd); #else fprintf(stderr, "Skipping save...\n"); #endif return 0; } int restore(const char *name) { #ifndef SRAMDEBUG int sramfd, fd, i; struct sram_io buffer; modified_values = malloc(256); if (modified_values == 0) err(1, "Opening %s", _PATH_DEVSRAM); if (strcmp(name, "-") == 0) fd = 0; /* standard input */ else { fd = open(name, O_RDONLY); if (fd < 0) err(1, "Opening input file"); } if (read(fd, modified_values, 256) != 256) err(1, "Reading input file"); if (fd != 0) close(fd); sramfd = open(_PATH_DEVSRAM, O_RDWR); if (sramfd < 0) err(1, "Opening %s", _PATH_DEVSRAM); /* Assume SRAM_IO_SIZE = n * 16. */ for (i = 0; i < 256; i += SRAM_IO_SIZE) { buffer.offset = i; memcpy(buffer.sram, &modified_values[i], SRAM_IO_SIZE); if (ioctl(sramfd, SIOPSRAM, &buffer) < 0) err(1, "ioctl"); } close(sramfd); #else fprintf(stderr, "Skipping restore...\n"); #endif return 0; }