/* $NetBSD: memswitch.c,v 1.8 2004/01/05 23:23:38 jmmv 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * 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 DEBUG #include #else /* * DEBUG -- works on other (faster) platforms; * store in a regular file instead of actual non-volatile static RAM. */ #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; int main __P((int, char*[])); 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(argc, argv) 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(name) 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(expr) const char *expr; { int i, l, n; char *class, *node; const char *value; char valuestr[MAXVALUELEN]; l = 0; n = strlen(expr); for (i = 0; i < n; i++) { if (expr[i] == '.') { l = i + 1; class = alloca(l); if (class == 0) err (1, "alloca"); strncpy (class, expr, i); class[i] = 0; break; } } if (i >= n) errx (1, "Invalid expression: %s", expr); for ( ; i < n; i++) { if (expr[i] == '=') { node = alloca(i - l + 1); if (node == 0) err (1, "alloca"); strncpy (node, &(expr[l]), i - l); node[i - l] = 0; break; } } if (i >= n) errx (1, "Invalid expression: %s", expr); value = &(expr[++i]); 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); } return; } void help_single(name) 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 DEBUG 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 DEBUG 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 DEBUG /* 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(name) const char *name; { #ifndef DEBUG 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 (name) const char *name; { #ifndef DEBUG 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"); } 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; 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; }