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