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