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