1 /* $NetBSD: memswitch.c,v 1.3 1999/06/28 08:48:35 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* memswitch.c */ 40 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <err.h> 45 #include <unistd.h> 46 #include <fcntl.h> 47 #include <errno.h> 48 49 #include <sys/ioctl.h> 50 51 #ifndef DEBUG 52 #include <machine/sram.h> 53 #else 54 /* 55 * DEBUG -- works on other (faster) platforms; 56 * store in a regular file instead of actual non-volatile static RAM. 57 */ 58 #define PATH_RAMFILE "/tmp/sramfile" 59 #endif 60 61 #include "memswitch.h" 62 63 char *progname; 64 int nflag = 0; 65 u_int8_t *current_values = 0; 66 u_int8_t *modified_values = 0; 67 68 int main __P((int, char*[])); 69 70 void 71 usage(void) 72 { 73 fprintf (stderr, "Usage: %s -a\n", progname); 74 fprintf (stderr, " %s [-h] variable ...\n", progname); 75 fprintf (stderr, " %s variable=value ...\n", progname); 76 fprintf (stderr, " %s [-rs] filename\n", progname); 77 exit(1); 78 } 79 80 int 81 main(argc, argv) 82 int argc; 83 char *argv[]; 84 { 85 int ch; 86 extern char *optarg; 87 extern int optind; 88 enum md { 89 MD_NONE, MD_WRITE, MD_HELP, MD_SHOWALL, MD_SAVE, MD_RESTORE 90 } mode = MD_NONE; 91 92 progname = argv[0]; 93 94 while ((ch = getopt(argc, argv, "whanrs")) != -1) { 95 switch (ch) { 96 case 'w': /* write */ 97 mode = MD_WRITE; 98 break; 99 case 'h': 100 mode = MD_HELP; 101 break; 102 case 'a': 103 mode = MD_SHOWALL; 104 break; 105 case 'n': 106 nflag = 1; 107 break; 108 case 's': 109 mode = MD_SAVE; 110 break; 111 case 'r': 112 mode = MD_RESTORE; 113 break; 114 } 115 } 116 argc -= optind; 117 argv += optind; 118 119 switch (mode) { 120 case MD_NONE: 121 if (argc == 0) 122 usage(); 123 while (argv[0]) { 124 show_single (argv[0]); 125 argv++; 126 } 127 break; 128 case MD_SHOWALL: 129 if (argc) 130 usage(); 131 show_all(); 132 break; 133 case MD_WRITE: 134 if (argc == 0) 135 usage(); 136 while (argv[0]) { 137 modify_single (argv[0]); 138 argv++; 139 } 140 flush (); 141 break; 142 case MD_HELP: 143 if (argc == 0) 144 usage(); 145 while (argv[0]) { 146 help_single (argv[0]); 147 argv++; 148 } 149 break; 150 case MD_SAVE: 151 if (argc != 1) 152 usage(); 153 save(argv[0]); 154 break; 155 case MD_RESTORE: 156 if (argc != 1) 157 usage(); 158 restore(argv[0]); 159 break; 160 161 } 162 163 return 0; 164 } 165 166 void 167 show_single(name) 168 const char *name; 169 { 170 int i; 171 char fullname[50]; 172 char valuestr[MAXVALUELEN]; 173 174 for (i = 0; i < number_of_props; i++) { 175 sprintf(fullname, "%s.%s", 176 properties[i].class, properties[i].node); 177 if (strcmp(name, fullname) == 0) { 178 properties[i].print (&properties[i], valuestr); 179 if (!nflag) 180 printf ("%s=%s\n", fullname, valuestr); 181 break; 182 } 183 } 184 if (i >= number_of_props) { 185 errx (1, "No such property: %s\n", name); 186 } 187 188 return; 189 } 190 191 void 192 show_all(void) 193 { 194 int i; 195 char valuestr[MAXVALUELEN]; 196 197 for (i = 0; i < number_of_props; i++) { 198 properties[i].print (&properties[i], valuestr); 199 if (!nflag) 200 printf ("%s.%s=", 201 properties[i].class, properties[i].node); 202 printf ("%s\n", valuestr); 203 } 204 205 return; 206 } 207 208 void 209 modify_single(expr) 210 const char *expr; 211 { 212 int i, l, n; 213 char *class, *node; 214 const char *value; 215 char valuestr[MAXVALUELEN]; 216 217 l = 0; 218 n = strlen(expr); 219 for (i = 0; i < n; i++) { 220 if (expr[i] == '.') { 221 l = i + 1; 222 class = alloca(l); 223 if (class == 0) 224 err (1, "alloca"); 225 strncpy (class, expr, i); 226 class[i] = 0; 227 break; 228 } 229 } 230 if (i >= n) 231 errx (1, "Invalid expression: %s\n", expr); 232 233 for ( ; i < n; i++) { 234 if (expr[i] == '=') { 235 node = alloca(i - l + 1); 236 if (node == 0) 237 err (1, "alloca"); 238 strncpy (node, &(expr[l]), i - l); 239 node[i - l] = 0; 240 break; 241 } 242 } 243 if (i >= n) 244 errx (1, "Invalid expression: %s\n", expr); 245 246 value = &(expr[++i]); 247 248 for (i = 0; i < number_of_props; i++) { 249 if (strcmp(properties[i].class, class) == 0 && 250 strcmp(properties[i].node, node) == 0) { 251 if (properties[i].parse(&properties[i], value) < 0) { 252 /* error: do nothing */ 253 } else { 254 properties[i].print (&properties[i], valuestr); 255 printf("%s.%s -> %s\n", class, node, valuestr); 256 } 257 break; 258 } 259 } 260 if (i >= number_of_props) { 261 errx (1, "No such property: %s.%s\n", class, node); 262 } 263 264 return; 265 } 266 267 void 268 help_single(name) 269 const char *name; 270 { 271 int i; 272 char fullname[50]; 273 char valuestr[MAXVALUELEN]; 274 275 for (i = 0; i < number_of_props; i++) { 276 sprintf(fullname, "%s.%s", 277 properties[i].class, properties[i].node); 278 if (strcmp(name, fullname) == 0) { 279 properties[i].print (&properties[i], valuestr); 280 if (!nflag) 281 printf ("%s=", fullname); 282 printf ("%s\n", valuestr); 283 printf ("%s", properties[i].descr); 284 break; 285 } 286 } 287 if (i >= number_of_props) { 288 errx (1, "No such property: %s\n", name); 289 } 290 291 return; 292 } 293 294 void 295 alloc_modified_values(void) 296 { 297 if (current_values == 0) 298 alloc_current_values(); 299 modified_values = malloc (256); 300 if (modified_values == 0) 301 err (1, "malloc"); 302 memcpy (modified_values, current_values, 256); 303 } 304 305 void 306 alloc_current_values(void) 307 { 308 #ifndef DEBUG 309 int i; 310 int sramfd = 0; 311 struct sram_io buffer; 312 313 current_values = malloc (256); 314 if (current_values == 0) 315 err (1, "malloc"); 316 317 sramfd = open (_PATH_DEVSRAM, O_RDONLY); 318 if (sramfd < 0) 319 err (1, "Opening %s", _PATH_DEVSRAM); 320 321 /* Assume SRAM_IO_SIZE = n * 16. */ 322 for (i = 0; i < 256; i += SRAM_IO_SIZE) { 323 buffer.offset = i; 324 if (ioctl (sramfd, SIOGSRAM, &buffer) < 0) 325 err (1, "ioctl"); 326 memcpy (¤t_values[i], buffer.sram, SRAM_IO_SIZE); 327 } 328 329 close (sramfd); 330 #else 331 int i; 332 int fd; 333 struct stat st; 334 335 current_values = malloc (256); 336 if (current_values == 0) 337 err (1, "malloc"); 338 339 fd = open (PATH_RAMFILE, O_RDONLY); 340 if (fd < 0 && errno == ENOENT) { 341 modified_values = malloc (256); 342 if (modified_values == 0) 343 err (1, NULL); 344 for (i = 0; i < number_of_props; i++) { 345 properties[i].modified_value 346 = properties[i].default_value; 347 properties[i].modified = 1; 348 properties[i].flush (&properties[i]); 349 } 350 351 fd = creat (PATH_RAMFILE, 0666); 352 if (fd < 0) 353 err (1, "Creating %s", PATH_RAMFILE); 354 if (write (fd, modified_values, 256) != 256) 355 err (1, "Writing %s", PATH_RAMFILE); 356 close (fd); 357 free (modified_values); 358 modified_values = 0; 359 360 fd = open (PATH_RAMFILE, O_RDONLY); 361 } 362 if (fd < 0) 363 err (1, "Opening %s", PATH_RAMFILE); 364 if (fstat (fd, &st) < 0) 365 err (1, "fstat"); 366 if (st.st_size != 256) 367 errx (1, "PANIC! INVALID RAMFILE"); 368 if (read (fd, current_values, 256) != 256) 369 err (1, "reading %s", PATH_RAMFILE); 370 close (fd); 371 #endif 372 373 properties[PROP_MAGIC1].fill (&properties[PROP_MAGIC1]); 374 properties[PROP_MAGIC2].fill (&properties[PROP_MAGIC2]); 375 if ((properties[PROP_MAGIC1].current_value.longword != MAGIC1) || 376 (properties[PROP_MAGIC2].current_value.longword != MAGIC2)) 377 errx (1, "PANIC! INVALID MAGIC"); 378 } 379 380 void 381 flush(void) 382 { 383 int i; 384 int sramfd = 0; 385 #ifndef DEBUG 386 struct sram_io buffer; 387 #endif 388 389 for (i = 0; i < number_of_props; i++) { 390 if (properties[i].modified) 391 properties[i].flush(&properties[i]); 392 } 393 394 if (modified_values == 0) 395 /* Not modified at all. */ 396 return; 397 398 #ifndef DEBUG 399 /* Assume SRAM_IO_SIZE = n * 16. */ 400 for (i = 0; i < 256; i += SRAM_IO_SIZE) { 401 if (memcmp (¤t_values[i], &modified_values[i], 402 SRAM_IO_SIZE) == 0) 403 continue; 404 405 if (sramfd == 0) { 406 sramfd = open (_PATH_DEVSRAM, O_RDWR); 407 if (sramfd < 0) 408 err (1, "Opening %s", _PATH_DEVSRAM); 409 } 410 buffer.offset = i; 411 memcpy (buffer.sram, &modified_values[i], SRAM_IO_SIZE); 412 if (ioctl (sramfd, SIOPSRAM, &buffer) < 0) 413 err (1, "ioctl"); 414 } 415 #else 416 sramfd = open (PATH_RAMFILE, O_WRONLY); 417 if (sramfd < 0) 418 err (1, "Opening %s", PATH_RAMFILE); 419 if (write (sramfd, modified_values, 256) != 256) 420 err (1, "Writing %s", PATH_RAMFILE); 421 #endif 422 423 if (sramfd != 0) 424 close (sramfd); 425 426 return; 427 } 428 429 int 430 save(name) 431 const char *name; 432 { 433 #ifndef DEBUG 434 int fd; 435 436 alloc_current_values (); 437 438 if (strcmp (name, "-") == 0) 439 fd = 1; /* standard output */ 440 else { 441 fd = open (name, O_WRONLY|O_CREAT|O_TRUNC, 0666); 442 if (fd < 0) 443 err (1, "Opening output file"); 444 } 445 446 if (write (fd, current_values, 256) != 256) 447 err (1, "Writing output file"); 448 449 if (fd != 1) 450 close (fd); 451 #else 452 fprintf (stderr, "Skipping save...\n"); 453 #endif 454 455 return 0; 456 } 457 458 int 459 restore (name) 460 const char *name; 461 { 462 #ifndef DEBUG 463 int sramfd, fd, i; 464 struct sram_io buffer; 465 466 modified_values = malloc (256); 467 if (modified_values == 0) 468 err (1, "Opening %s", _PATH_DEVSRAM); 469 470 if (strcmp (name, "-") == 0) 471 fd = 0; /* standard input */ 472 else { 473 fd = open (name, O_RDONLY); 474 if (fd < 0) 475 err (1, "Opening input file"); 476 } 477 478 sramfd = open (_PATH_DEVSRAM, O_RDONLY); 479 if (sramfd < 0) 480 err (1, "Opening %s", _PATH_DEVSRAM); 481 482 /* Assume SRAM_IO_SIZE = n * 16. */ 483 for (i = 0; i < 256; i += SRAM_IO_SIZE) { 484 buffer.offset = i; 485 memcpy (buffer.sram, &modified_values[i], SRAM_IO_SIZE); 486 if (ioctl (sramfd, SIOPSRAM, &buffer) < 0) 487 err (1, "ioctl"); 488 } 489 490 close (sramfd); 491 #else 492 fprintf (stderr, "Skipping restore...\n"); 493 #endif 494 495 return 0; 496 } 497