Home | History | Annotate | Line # | Download | only in memswitch
memswitch.c revision 1.12
      1 /*	$NetBSD: memswitch.c,v 1.12 2011/01/14 13:31:47 minoura 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 DEBUG
     45 #include <machine/sram.h>
     46 #else
     47 /*
     48  * DEBUG -- works on other (faster) platforms;
     49  *   store in a regular file instead of actual non-volatile static RAM.
     50  */
     51 #define PATH_RAMFILE "/tmp/sramfile"
     52 #endif
     53 
     54 #include "memswitch.h"
     55 
     56 char *progname;
     57 int nflag = 0;
     58 u_int8_t *current_values = 0;
     59 u_int8_t *modified_values = 0;
     60 
     61 int main __P((int, char*[]));
     62 
     63 void
     64 usage(void)
     65 {
     66 	fprintf(stderr, "usage: %s -a\n", progname);
     67 	fprintf(stderr, "       %s [-h] variable ...\n", progname);
     68 	fprintf(stderr, "       %s -w variable=value ...\n", progname);
     69 	fprintf(stderr, "       %s [-rs] filename\n", progname);
     70 	exit(1);
     71 }
     72 
     73 int
     74 main(argc, argv)
     75 	int argc;
     76 	char *argv[];
     77 {
     78 	int ch;
     79 	enum md {
     80 		MD_NONE, MD_WRITE, MD_HELP, MD_SHOWALL, MD_SAVE, MD_RESTORE
     81 	} mode = MD_NONE;
     82 
     83 	progname = argv[0];
     84 
     85 	while ((ch = getopt(argc, argv, "whanrs")) != -1) {
     86 		switch (ch) {
     87 		case 'w':	/* write */
     88 			mode = MD_WRITE;
     89 			break;
     90 		case 'h':
     91 			mode = MD_HELP;
     92 			break;
     93 		case 'a':
     94 			mode = MD_SHOWALL;
     95 			break;
     96 		case 'n':
     97 			nflag = 1;
     98 			break;
     99 		case 's':
    100 			mode = MD_SAVE;
    101 			break;
    102 		case 'r':
    103 			mode = MD_RESTORE;
    104 			break;
    105 		}
    106 	}
    107 	argc -= optind;
    108 	argv += optind;
    109 
    110 	switch (mode) {
    111 	case MD_NONE:
    112 		if (argc == 0)
    113 			usage();
    114 		while (argv[0]) {
    115 			show_single(argv[0]);
    116 			argv++;
    117 		}
    118 		break;
    119 	case MD_SHOWALL:
    120 		if (argc)
    121 			usage();
    122 		show_all();
    123 		break;
    124 	case MD_WRITE:
    125 		if (argc == 0)
    126 			usage();
    127 		while (argv[0]) {
    128 			modify_single (argv[0]);
    129 			argv++;
    130 		}
    131 		flush();
    132 		break;
    133 	case MD_HELP:
    134 		if (argc == 0)
    135 			usage();
    136 		while (argv[0]) {
    137 			help_single(argv[0]);
    138 			argv++;
    139 		}
    140 		break;
    141 	case MD_SAVE:
    142 		if (argc != 1)
    143 			usage();
    144 		save(argv[0]);
    145 		break;
    146 	case MD_RESTORE:
    147 		if (argc != 1)
    148 			usage();
    149 		restore(argv[0]);
    150 		break;
    151 
    152 	}
    153 
    154 	return 0;
    155 }
    156 
    157 void
    158 show_single(name)
    159 	const char *name;
    160 {
    161 	int i;
    162 	int n = 0;
    163 	char fullname[50];
    164 	char valuestr[MAXVALUELEN];
    165 
    166 	for (i = 0; i < number_of_props; i++) {
    167 		snprintf(fullname, sizeof(fullname), "%s.%s",
    168 			 properties[i].class, properties[i].node);
    169 		if (strcmp(name, fullname) == 0 || strcmp(name, properties[i].class) == 0) {
    170 			properties[i].print(&properties[i], valuestr);
    171 			if (!nflag)
    172 				printf("%s=%s\n", fullname, valuestr);
    173 			n++;
    174 		}
    175 	}
    176 	if (n == 0) {
    177 		errx(1, "No such %s: %s", strstr(name, ".")?"property":"class", name);
    178 	}
    179 
    180 	return;
    181 }
    182 
    183 void
    184 show_all(void)
    185 {
    186 	int i;
    187 	char valuestr[MAXVALUELEN];
    188 
    189 	for (i = 0; i < number_of_props; i++) {
    190 		properties[i].print(&properties[i], valuestr);
    191 		if (!nflag)
    192 			printf("%s.%s=",
    193 			       properties[i].class, properties[i].node);
    194 		printf("%s\n", valuestr);
    195 	}
    196 
    197 	return;
    198 }
    199 
    200 void
    201 modify_single(expr)
    202 	const char *expr;
    203 {
    204 	int i, l, n;
    205 	char *class = NULL, *node = NULL;
    206 	const char *value;
    207 	char valuestr[MAXVALUELEN];
    208 
    209 	l = 0;
    210 	n = strlen(expr);
    211 	for (i = 0; i < n; i++) {
    212 		if (expr[i] == '.') {
    213 			l = i + 1;
    214 			class = alloca(l);
    215 			if (class == 0)
    216 				err(1, "alloca");
    217 			strncpy(class, expr, i);
    218 			class[i] = 0;
    219 			break;
    220 		}
    221 	}
    222 	if (i >= n)
    223 		errx(1, "Invalid expression: %s", expr);
    224 
    225 	for ( ; i < n; i++) {
    226 		if (expr[i] == '=') {
    227 			node = alloca(i - l + 1);
    228 			if (node == 0)
    229 				err(1, "alloca");
    230 			strncpy(node, &(expr[l]), i - l);
    231 			node[i - l] = 0;
    232 			break;
    233 		}
    234 	}
    235 	if (i >= n)
    236 		errx(1, "Invalid expression: %s", expr);
    237 
    238 	value = &(expr[++i]);
    239 
    240 	for (i = 0; i < number_of_props; i++) {
    241 		if (strcmp(properties[i].class, class) == 0 &&
    242 		    strcmp(properties[i].node, node) == 0) {
    243 			if (properties[i].parse(&properties[i], value) < 0) {
    244 				/* error: do nothing */
    245 			} else {
    246 				properties[i].print(&properties[i], valuestr);
    247 				printf("%s.%s -> %s\n", class, node, valuestr);
    248 			}
    249 			break;
    250 		}
    251 	}
    252 	if (i >= number_of_props) {
    253 		errx(1, "No such property: %s.%s", class, node);
    254 	}
    255 
    256 	return;
    257 }
    258 
    259 void
    260 help_single(name)
    261 	const char *name;
    262 {
    263 	int i;
    264 	char fullname[50];
    265 	char valuestr[MAXVALUELEN];
    266 
    267 	for (i = 0; i < number_of_props; i++) {
    268 		snprintf(fullname, sizeof(fullname), "%s.%s",
    269 		    properties[i].class, properties[i].node);
    270 		if (strcmp(name, fullname) == 0) {
    271 			properties[i].print(&properties[i], valuestr);
    272 			if (!nflag)
    273 				printf("%s=", fullname);
    274 			printf("%s\n", valuestr);
    275 			printf("%s", properties[i].descr);
    276 			break;
    277 		}
    278 	}
    279 	if (i >= number_of_props) {
    280 		errx(1, "No such property: %s", name);
    281 	}
    282 
    283 	return;
    284 }
    285 
    286 void
    287 alloc_modified_values(void)
    288 {
    289 	if (current_values == 0)
    290 		alloc_current_values();
    291 	modified_values = malloc(256);
    292 	if (modified_values == 0)
    293 		err(1, "malloc");
    294 	memcpy(modified_values, current_values, 256);
    295 }
    296 
    297 void
    298 alloc_current_values(void)
    299 {
    300 #ifndef DEBUG
    301 	int i;
    302 	int sramfd = 0;
    303 	struct sram_io buffer;
    304 
    305 	current_values = malloc(256);
    306 	if (current_values == 0)
    307 		err(1, "malloc");
    308 
    309 	sramfd = open(_PATH_DEVSRAM, O_RDONLY);
    310 	if (sramfd < 0)
    311 		err(1, "Opening %s", _PATH_DEVSRAM);
    312 
    313 	/* Assume SRAM_IO_SIZE = n * 16. */
    314 	for (i = 0; i < 256; i += SRAM_IO_SIZE) {
    315 		buffer.offset = i;
    316 		if (ioctl(sramfd, SIOGSRAM, &buffer) < 0)
    317 			err(1, "ioctl");
    318 		memcpy(&current_values[i], buffer.sram, SRAM_IO_SIZE);
    319 	}
    320 
    321 	close(sramfd);
    322 #else
    323 	int i;
    324 	int fd;
    325 	struct stat st;
    326 
    327 	current_values = malloc(256);
    328 	if (current_values == 0)
    329 		err(1, "malloc");
    330 
    331 	fd = open(PATH_RAMFILE, O_RDONLY);
    332 	if (fd < 0 && errno == ENOENT) {
    333 		modified_values = malloc(256);
    334 		if (modified_values == 0)
    335 			err(1, NULL);
    336 		for (i = 0; i < number_of_props; i++) {
    337 			properties[i].modified_value
    338 			    = properties[i].default_value;
    339 			properties[i].modified = 1;
    340 			properties[i].flush(&properties[i]);
    341 		}
    342 
    343 		fd = creat(PATH_RAMFILE, 0666);
    344 		if (fd < 0)
    345 			err(1, "Creating %s", PATH_RAMFILE);
    346 		if (write(fd, modified_values, 256) != 256)
    347 			err(1, "Writing %s", PATH_RAMFILE);
    348 		close(fd);
    349 		free(modified_values);
    350 		modified_values = 0;
    351 
    352 		fd = open(PATH_RAMFILE, O_RDONLY);
    353 	}
    354 	if (fd < 0)
    355 		err(1, "Opening %s", PATH_RAMFILE);
    356 	if (fstat(fd, &st) < 0)
    357 		err(1, "fstat");
    358 	if (st.st_size != 256)
    359 		errx(1, "PANIC! INVALID RAMFILE");
    360 	if (read(fd, current_values, 256) != 256)
    361 		err(1, "reading %s", PATH_RAMFILE);
    362 	close(fd);
    363 #endif
    364 
    365 	properties[PROP_MAGIC1].fill(&properties[PROP_MAGIC1]);
    366 	properties[PROP_MAGIC2].fill(&properties[PROP_MAGIC2]);
    367 	if ((properties[PROP_MAGIC1].current_value.longword != MAGIC1) ||
    368 	    (properties[PROP_MAGIC2].current_value.longword != MAGIC2))
    369 		errx(1, "PANIC! INVALID MAGIC");
    370 }
    371 
    372 void
    373 flush(void)
    374 {
    375 	int i;
    376 	int sramfd = 0;
    377 #ifndef DEBUG
    378 	struct sram_io buffer;
    379 #endif
    380 
    381 	for (i = 0; i < number_of_props; i++) {
    382 		if (properties[i].modified)
    383 			properties[i].flush(&properties[i]);
    384 	}
    385 
    386 	if (modified_values == 0)
    387 		/* Not modified at all. */
    388 		return;
    389 
    390 #ifndef DEBUG
    391 	/* Assume SRAM_IO_SIZE = n * 16. */
    392 	for (i = 0; i < 256; i += SRAM_IO_SIZE) {
    393 		if (memcmp(&current_values[i], &modified_values[i],
    394 			   SRAM_IO_SIZE) == 0)
    395 			continue;
    396 
    397 		if (sramfd == 0) {
    398 			sramfd = open(_PATH_DEVSRAM, O_RDWR);
    399 			if (sramfd < 0)
    400 				err(1, "Opening %s", _PATH_DEVSRAM);
    401 		}
    402 		buffer.offset = i;
    403 		memcpy(buffer.sram, &modified_values[i], SRAM_IO_SIZE);
    404 		if (ioctl(sramfd, SIOPSRAM, &buffer) < 0)
    405 			err(1, "ioctl");
    406 	}
    407 #else
    408 	sramfd = open(PATH_RAMFILE, O_WRONLY);
    409 	if (sramfd < 0)
    410 		err(1, "Opening %s", PATH_RAMFILE);
    411 	if (write(sramfd, modified_values, 256) != 256)
    412 		err(1, "Writing %s", PATH_RAMFILE);
    413 #endif
    414 
    415 	if (sramfd != 0)
    416 		close(sramfd);
    417 
    418 	return;
    419 }
    420 
    421 int
    422 save(name)
    423 	const char *name;
    424 {
    425 #ifndef DEBUG
    426 	int fd;
    427 
    428 	alloc_current_values();
    429 
    430 	if (strcmp(name, "-") == 0)
    431 		fd = 1;		/* standard output */
    432 	else {
    433 		fd = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0666);
    434 		if (fd < 0)
    435 			err(1, "Opening output file");
    436 	}
    437 
    438 	if (write(fd, current_values, 256) != 256)
    439 		err(1, "Writing output file");
    440 
    441 	if (fd != 1)
    442 		close(fd);
    443 #else
    444 	fprintf(stderr, "Skipping save...\n");
    445 #endif
    446 
    447 	return 0;
    448 }
    449 
    450 int
    451 restore(name)
    452 	const char *name;
    453 {
    454 #ifndef DEBUG
    455 	int sramfd, fd, i;
    456 	struct sram_io buffer;
    457 
    458 	modified_values = malloc(256);
    459 	if (modified_values == 0)
    460 		err(1, "Opening %s", _PATH_DEVSRAM);
    461 
    462 	if (strcmp(name, "-") == 0)
    463 		fd = 0;		/* standard input */
    464 	else {
    465 		fd = open(name, O_RDONLY);
    466 		if (fd < 0)
    467 			err(1, "Opening input file");
    468 	}
    469 
    470 	if (read(fd, modified_values, 256) != 256)
    471 		err(1, "Reading input file");
    472 
    473 	if (fd != 0)
    474 		close(fd);
    475 
    476 	sramfd = open(_PATH_DEVSRAM, O_RDWR);
    477 	if (sramfd < 0)
    478 		err(1, "Opening %s", _PATH_DEVSRAM);
    479 
    480 	/* Assume SRAM_IO_SIZE = n * 16. */
    481 	for (i = 0; i < 256; i += SRAM_IO_SIZE) {
    482 		buffer.offset = i;
    483 		memcpy(buffer.sram, &modified_values[i], SRAM_IO_SIZE);
    484 		if (ioctl(sramfd, SIOPSRAM, &buffer) < 0)
    485 			err(1, "ioctl");
    486 	}
    487 
    488 	close(sramfd);
    489 #else
    490 	fprintf(stderr, "Skipping restore...\n");
    491 #endif
    492 
    493 	return 0;
    494 }
    495