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