1 /* $NetBSD: memswitch.c,v 1.6 2001/02/04 08:37:33 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 -w 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 int n = 0; 170 char fullname[50]; 171 char valuestr[MAXVALUELEN]; 172 173 for (i = 0; i < number_of_props; i++) { 174 sprintf(fullname, "%s.%s", 175 properties[i].class, properties[i].node); 176 if (strcmp(name, fullname) == 0 || strcmp(name, properties[i].class) == 0) { 177 properties[i].print (&properties[i], valuestr); 178 if (!nflag) 179 printf ("%s=%s\n", fullname, valuestr); 180 n++; 181 } 182 } 183 if (n == 0) { 184 errx (1, "No such %s: %s", strstr(name, ".")?"property":"class", name); 185 } 186 187 return; 188 } 189 190 void 191 show_all(void) 192 { 193 int i; 194 char valuestr[MAXVALUELEN]; 195 196 for (i = 0; i < number_of_props; i++) { 197 properties[i].print (&properties[i], valuestr); 198 if (!nflag) 199 printf ("%s.%s=", 200 properties[i].class, properties[i].node); 201 printf ("%s\n", valuestr); 202 } 203 204 return; 205 } 206 207 void 208 modify_single(expr) 209 const char *expr; 210 { 211 int i, l, n; 212 char *class, *node; 213 const char *value; 214 char valuestr[MAXVALUELEN]; 215 216 l = 0; 217 n = strlen(expr); 218 for (i = 0; i < n; i++) { 219 if (expr[i] == '.') { 220 l = i + 1; 221 class = alloca(l); 222 if (class == 0) 223 err (1, "alloca"); 224 strncpy (class, expr, i); 225 class[i] = 0; 226 break; 227 } 228 } 229 if (i >= n) 230 errx (1, "Invalid expression: %s", expr); 231 232 for ( ; i < n; i++) { 233 if (expr[i] == '=') { 234 node = alloca(i - l + 1); 235 if (node == 0) 236 err (1, "alloca"); 237 strncpy (node, &(expr[l]), i - l); 238 node[i - l] = 0; 239 break; 240 } 241 } 242 if (i >= n) 243 errx (1, "Invalid expression: %s", expr); 244 245 value = &(expr[++i]); 246 247 for (i = 0; i < number_of_props; i++) { 248 if (strcmp(properties[i].class, class) == 0 && 249 strcmp(properties[i].node, node) == 0) { 250 if (properties[i].parse(&properties[i], value) < 0) { 251 /* error: do nothing */ 252 } else { 253 properties[i].print (&properties[i], valuestr); 254 printf("%s.%s -> %s\n", class, node, valuestr); 255 } 256 break; 257 } 258 } 259 if (i >= number_of_props) { 260 errx (1, "No such property: %s.%s", class, node); 261 } 262 263 return; 264 } 265 266 void 267 help_single(name) 268 const char *name; 269 { 270 int i; 271 char fullname[50]; 272 char valuestr[MAXVALUELEN]; 273 274 for (i = 0; i < number_of_props; i++) { 275 sprintf(fullname, "%s.%s", 276 properties[i].class, properties[i].node); 277 if (strcmp(name, fullname) == 0) { 278 properties[i].print (&properties[i], valuestr); 279 if (!nflag) 280 printf ("%s=", fullname); 281 printf ("%s\n", valuestr); 282 printf ("%s", properties[i].descr); 283 break; 284 } 285 } 286 if (i >= number_of_props) { 287 errx (1, "No such property: %s", name); 288 } 289 290 return; 291 } 292 293 void 294 alloc_modified_values(void) 295 { 296 if (current_values == 0) 297 alloc_current_values(); 298 modified_values = malloc (256); 299 if (modified_values == 0) 300 err (1, "malloc"); 301 memcpy (modified_values, current_values, 256); 302 } 303 304 void 305 alloc_current_values(void) 306 { 307 #ifndef DEBUG 308 int i; 309 int sramfd = 0; 310 struct sram_io buffer; 311 312 current_values = malloc (256); 313 if (current_values == 0) 314 err (1, "malloc"); 315 316 sramfd = open (_PATH_DEVSRAM, O_RDONLY); 317 if (sramfd < 0) 318 err (1, "Opening %s", _PATH_DEVSRAM); 319 320 /* Assume SRAM_IO_SIZE = n * 16. */ 321 for (i = 0; i < 256; i += SRAM_IO_SIZE) { 322 buffer.offset = i; 323 if (ioctl (sramfd, SIOGSRAM, &buffer) < 0) 324 err (1, "ioctl"); 325 memcpy (¤t_values[i], buffer.sram, SRAM_IO_SIZE); 326 } 327 328 close (sramfd); 329 #else 330 int i; 331 int fd; 332 struct stat st; 333 334 current_values = malloc (256); 335 if (current_values == 0) 336 err (1, "malloc"); 337 338 fd = open (PATH_RAMFILE, O_RDONLY); 339 if (fd < 0 && errno == ENOENT) { 340 modified_values = malloc (256); 341 if (modified_values == 0) 342 err (1, NULL); 343 for (i = 0; i < number_of_props; i++) { 344 properties[i].modified_value 345 = properties[i].default_value; 346 properties[i].modified = 1; 347 properties[i].flush (&properties[i]); 348 } 349 350 fd = creat (PATH_RAMFILE, 0666); 351 if (fd < 0) 352 err (1, "Creating %s", PATH_RAMFILE); 353 if (write (fd, modified_values, 256) != 256) 354 err (1, "Writing %s", PATH_RAMFILE); 355 close (fd); 356 free (modified_values); 357 modified_values = 0; 358 359 fd = open (PATH_RAMFILE, O_RDONLY); 360 } 361 if (fd < 0) 362 err (1, "Opening %s", PATH_RAMFILE); 363 if (fstat (fd, &st) < 0) 364 err (1, "fstat"); 365 if (st.st_size != 256) 366 errx (1, "PANIC! INVALID RAMFILE"); 367 if (read (fd, current_values, 256) != 256) 368 err (1, "reading %s", PATH_RAMFILE); 369 close (fd); 370 #endif 371 372 properties[PROP_MAGIC1].fill (&properties[PROP_MAGIC1]); 373 properties[PROP_MAGIC2].fill (&properties[PROP_MAGIC2]); 374 if ((properties[PROP_MAGIC1].current_value.longword != MAGIC1) || 375 (properties[PROP_MAGIC2].current_value.longword != MAGIC2)) 376 errx (1, "PANIC! INVALID MAGIC"); 377 } 378 379 void 380 flush(void) 381 { 382 int i; 383 int sramfd = 0; 384 #ifndef DEBUG 385 struct sram_io buffer; 386 #endif 387 388 for (i = 0; i < number_of_props; i++) { 389 if (properties[i].modified) 390 properties[i].flush(&properties[i]); 391 } 392 393 if (modified_values == 0) 394 /* Not modified at all. */ 395 return; 396 397 #ifndef DEBUG 398 /* Assume SRAM_IO_SIZE = n * 16. */ 399 for (i = 0; i < 256; i += SRAM_IO_SIZE) { 400 if (memcmp (¤t_values[i], &modified_values[i], 401 SRAM_IO_SIZE) == 0) 402 continue; 403 404 if (sramfd == 0) { 405 sramfd = open (_PATH_DEVSRAM, O_RDWR); 406 if (sramfd < 0) 407 err (1, "Opening %s", _PATH_DEVSRAM); 408 } 409 buffer.offset = i; 410 memcpy (buffer.sram, &modified_values[i], SRAM_IO_SIZE); 411 if (ioctl (sramfd, SIOPSRAM, &buffer) < 0) 412 err (1, "ioctl"); 413 } 414 #else 415 sramfd = open (PATH_RAMFILE, O_WRONLY); 416 if (sramfd < 0) 417 err (1, "Opening %s", PATH_RAMFILE); 418 if (write (sramfd, modified_values, 256) != 256) 419 err (1, "Writing %s", PATH_RAMFILE); 420 #endif 421 422 if (sramfd != 0) 423 close (sramfd); 424 425 return; 426 } 427 428 int 429 save(name) 430 const char *name; 431 { 432 #ifndef DEBUG 433 int fd; 434 435 alloc_current_values (); 436 437 if (strcmp (name, "-") == 0) 438 fd = 1; /* standard output */ 439 else { 440 fd = open (name, O_WRONLY|O_CREAT|O_TRUNC, 0666); 441 if (fd < 0) 442 err (1, "Opening output file"); 443 } 444 445 if (write (fd, current_values, 256) != 256) 446 err (1, "Writing output file"); 447 448 if (fd != 1) 449 close (fd); 450 #else 451 fprintf (stderr, "Skipping save...\n"); 452 #endif 453 454 return 0; 455 } 456 457 int 458 restore (name) 459 const char *name; 460 { 461 #ifndef DEBUG 462 int sramfd, fd, i; 463 struct sram_io buffer; 464 465 modified_values = malloc (256); 466 if (modified_values == 0) 467 err (1, "Opening %s", _PATH_DEVSRAM); 468 469 if (strcmp (name, "-") == 0) 470 fd = 0; /* standard input */ 471 else { 472 fd = open (name, O_RDONLY); 473 if (fd < 0) 474 err (1, "Opening input file"); 475 } 476 477 sramfd = open (_PATH_DEVSRAM, O_RDONLY); 478 if (sramfd < 0) 479 err (1, "Opening %s", _PATH_DEVSRAM); 480 481 /* Assume SRAM_IO_SIZE = n * 16. */ 482 for (i = 0; i < 256; i += SRAM_IO_SIZE) { 483 buffer.offset = i; 484 memcpy (buffer.sram, &modified_values[i], SRAM_IO_SIZE); 485 if (ioctl (sramfd, SIOPSRAM, &buffer) < 0) 486 err (1, "ioctl"); 487 } 488 489 close (sramfd); 490 #else 491 fprintf (stderr, "Skipping restore...\n"); 492 #endif 493 494 return 0; 495 } 496