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