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