1/* $NetBSD: methods.c,v 1.6 2008/04/28 20:24:17 martin 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#include <stdio.h> 33#include <string.h> 34#include <err.h> 35#include <sys/types.h> 36 37#include "memswitch.h" 38#include "methods.h" 39 40int 41atoi_(p) 42 const char **p; 43{ 44 const char *p1 = *p; 45 int v = 0; 46 int first = 1; 47 48 while (*p1 == ' ' || *p1 == '\t') 49 p1++; 50 51 if (*p1 == 0) { 52 *p = 0; 53 return 0; 54 } 55 if (strlen(p1) >= 2 && strncasecmp("0x", p1, 2) == 0) { 56 p1 += 2; 57 while (1) { 58 if (*p1 >= '0' && *p1 <= '9') { 59 v *= 16; 60 v += *p1 - '0'; 61 first = 0; 62 } else if (*p1 >= 'A' && *p1 <= 'F') { 63 v *= 16; 64 v += *p1 - 'A' + 10; 65 first = 0; 66 } else if (*p1 >= 'a' && *p1 <= 'f') { 67 v *= 16; 68 v += *p1 - 'a' + 10; 69 first = 0; 70 } else { 71 break; 72 } 73 p1++; 74 } 75 } else { 76 while (1) { 77 if (*p1 >= '0' && *p1 <= '9') { 78 v *= 10; 79 v += *p1 - '0'; 80 first = 0; 81 } else { 82 break; 83 } 84 p1++; 85 } 86 } 87 88 if (first) { 89 *p = 0; 90 return 0; 91 } 92 93 while (*p1 == ' ' || *p1 == '\t') p1++; 94 *p = p1; 95 return v; 96} 97 98int 99fill_uchar(prop) 100 struct property *prop; 101{ 102 if (current_values == 0) 103 alloc_current_values(); 104 105 prop->current_value.byte[0] = current_values[prop->offset]; 106 prop->current_value.byte[1] = 0; 107 prop->current_value.byte[2] = 0; 108 prop->current_value.byte[3] = 0; 109 prop->value_valid = 1; 110 111 return 0; 112} 113 114int 115fill_ushort(prop) 116 struct property *prop; 117{ 118 if (current_values == 0) 119 alloc_current_values(); 120 121 prop->current_value.byte[0] = current_values[prop->offset]; 122 prop->current_value.byte[1] = current_values[prop->offset+1]; 123 prop->current_value.byte[2] = 0; 124 prop->current_value.byte[3] = 0; 125 prop->value_valid = 1; 126 127 return 0; 128} 129 130int 131fill_ulong(prop) 132 struct property *prop; 133{ 134 if (current_values == 0) 135 alloc_current_values(); 136 137 prop->current_value.byte[0] = current_values[prop->offset]; 138 prop->current_value.byte[1] = current_values[prop->offset+1]; 139 prop->current_value.byte[2] = current_values[prop->offset+2]; 140 prop->current_value.byte[3] = current_values[prop->offset+3]; 141 prop->value_valid = 1; 142 143 return 0; 144} 145 146int 147flush_uchar(prop) 148 struct property *prop; 149{ 150 if (!prop->modified) 151 return 0; 152 153 if (modified_values == 0) 154 alloc_modified_values(); 155 156 modified_values[prop->offset] = prop->modified_value.byte[0]; 157 158 return 0; 159} 160 161int 162flush_ushort(prop) 163 struct property *prop; 164{ 165 if (!prop->modified) 166 return 0; 167 168 if (modified_values == 0) 169 alloc_modified_values(); 170 171 modified_values[prop->offset] = prop->modified_value.byte[0]; 172 modified_values[prop->offset+1] = prop->modified_value.byte[1]; 173 174 return 0; 175} 176 177int 178flush_ulong(prop) 179 struct property *prop; 180{ 181 if (!prop->modified) 182 return 0; 183 184 if (modified_values == 0) 185 alloc_modified_values(); 186 187 modified_values[prop->offset] = prop->modified_value.byte[0]; 188 modified_values[prop->offset+1] = prop->modified_value.byte[1]; 189 modified_values[prop->offset+2] = prop->modified_value.byte[2]; 190 modified_values[prop->offset+3] = prop->modified_value.byte[3]; 191 192 return 0; 193} 194 195int 196flush_dummy(prop) 197 struct property *prop; 198{ 199 return 0; 200} 201 202int 203parse_dummy(prop, value) 204 struct property *prop; 205 const char *value; 206{ 207 warnx("Cannot modify %s.%s", prop->class, prop->node); 208 209 return -1; 210} 211 212int 213parse_byte(prop, value) 214 struct property *prop; 215 const char *value; 216{ 217 const char *p = value; 218 int v; 219 220 v = atoi_(&p); 221 if (p == 0) { 222 warnx("%s: Invalid value", value); 223 return -1; 224 } 225 226 if (strcasecmp("MB", p) == 0) 227 v *= 1024 * 1024; 228 else if (strcasecmp("KB", p) == 0) 229 v *= 1024; 230 else if (*p != 0 && 231 strcasecmp("B", p) != 0) { 232 warnx("%s: Invalid value", value); 233 return -1; 234 } 235 236 if (v < prop->min) { 237 warnx("%s: Too small", value); 238 return -1; 239 } else if (v > prop->max) { 240 warnx("%s: Too large", value); 241 return -1; 242 } 243 244 prop->modified = 1; 245 prop->modified_value.longword = v; 246 247 return 0; 248} 249 250int 251parse_uchar(prop, value) 252 struct property *prop; 253 const char *value; 254{ 255 const char *p = value; 256 int v; 257 258 v = atoi_(&p); 259 if (p == 0) { 260 warnx("%s: Invalid value", value); 261 return -1; 262 } 263 264 if (v < prop->min) { 265 warnx("%s: Too small", value); 266 return -1; 267 } else if (v > prop->max) { 268 warnx("%s: Too large", value); 269 return -1; 270 } 271 272 prop->modified = 1; 273 prop->modified_value.byte[0] = v; 274 275 return 0; 276} 277 278int 279parse_ulong(prop, value) 280 struct property *prop; 281 const char *value; 282{ 283 const char *p = value; 284 int v; 285 286 v = atoi_(&p); 287 if (p == 0) { 288 warnx("%s: Invalid value", value); 289 return -1; 290 } 291 292 if (v < prop->min) { 293 warnx("%s: Too small", value); 294 return -1; 295 } else if (v > prop->max) { 296 warnx("%s: Too large", value); 297 return -1; 298 } 299 300 prop->modified = 1; 301 prop->modified_value.longword = v; 302 303 return 0; 304} 305 306int 307parse_ushort(prop, value) 308 struct property *prop; 309 const char *value; 310{ 311 const char *p = value; 312 int v; 313 314 v = atoi_(&p); 315 if (p == 0) { 316 warnx("%s: Invalid value", value); 317 return -1; 318 } 319 320 if (v < prop->min) { 321 warnx("%s: Too small", value); 322 return -1; 323 } else if (v > prop->max) { 324 warnx("%s: Too large", value); 325 return -1; 326 } 327 328 prop->modified = 1; 329 prop->modified_value.word[0] = v; 330 331 return 0; 332} 333 334int 335parse_time(prop, value) 336 struct property *prop; 337 const char *value; 338{ 339 const char *p = value; 340 int v; 341 342 while (*p == ' ' || *p == '\t') p++; 343 if (*p == '-') { 344 p++; 345 v = -atoi_(&p); 346 } else 347 v = atoi_(&p); 348 if (p == 0) { 349 warnx("%s: Invalid value", value); 350 return -1; 351 } 352 353 if (strcasecmp("hours", p) == 0 || strcasecmp("hour", p) == 0) 354 v *= 60 * 60; 355 else if (strcasecmp("minutes", p) == 0 || 356 strcasecmp("minute", p) == 0) 357 v *= 60; 358 else if (*p != 0 && 359 strcasecmp("second", p) != 0 && 360 strcasecmp("seconds", p) != 0) { 361 warnx("%s: Invalid value", value); 362 return -1; 363 } 364 365 if (v < prop->min) { 366 warnx("%s: Too small", value); 367 return -1; 368 } else if (v > prop->max) { 369 warnx("%s: Too large", value); 370 return -1; 371 } 372 373 prop->modified = 1; 374 prop->modified_value.longword = v; 375 376 return 0; 377} 378 379int 380parse_bootdev(prop, value) 381 struct property *prop; 382 const char *value; 383{ 384 const char *p = value; 385 int v; 386 char expr_scsi[32]; 387 388 while (*p == ' ' || *p == '\t') p++; 389 390 if (strcasecmp("STD", p) == 0) 391 v = 0; 392 else if (strcasecmp("ROM", p) == 0) 393 v = 0xa000; 394 else if (strcasecmp("RAM", p) == 0) 395 v = 0xb000; 396 else if (strncasecmp("HD", p, 2) == 0) { 397 p += 2; 398 v = atoi_(&p); 399 if (p == 0 || v < 0 || v > 15) { 400 warnx("%s: Invalid value", value); 401 return -1; 402 } 403 v *= 0x0100; 404 v += 0x8000; 405 } else if (strncasecmp("FD", p, 2) == 0) { 406 p += 2; 407 v = atoi_(&p); 408 if (p == 0 || v < 0 || v > 3) { 409 warnx("%s: Invalid value", value); 410 return -1; 411 } 412 v *= 0x0100; 413 v += 0x9070; 414 } else if (strncasecmp("INSCSI", p, 6) == 0 || 415 strncasecmp("EXSCSI", p, 6) == 0) { 416 int isin = strncasecmp("EXSCSI", p, 6); 417 418 p += 6; 419 v = atoi_(&p); 420 if (p == 0 || v < 0 || v > 7) { 421 warnx("%s: Invalid value", value); 422 return -1; 423 } 424 425 /* change boot.romaddr */ 426 sprintf(expr_scsi, "boot.romaddr=0x%06x", 427 (isin ? 0xfc0000 : 0xea0020) + v * 4); 428 modify_single(expr_scsi); 429 430 /* boot.device again */ 431 v = 0xa000; 432 } else { 433 warnx("%s: Invalid value", value); 434 return -1; 435 } 436 437 prop->modified = 1; 438 prop->modified_value.word[0] = v; 439 440 return 0; 441} 442 443int 444parse_serial(prop, value) 445 struct property *prop; 446 const char *value; 447#define NEXTSPEC while (*p == ' ' || *p == '\t') p++; \ 448 if (*p++ != ',') { \ 449 warnx("%s: Invalid value", value); \ 450 return -1; \ 451 } \ 452 while (*p == ' ' || *p == '\t') p++; 453{ 454 const char *p = value; 455 const char *q; 456 int baud, bit, parity, stop, flow; 457 static const int bauds[] = {75, 150, 300, 600, 1200, 2400, 4800, 9600, 458 17361, 0}; 459 static const char parities[] = "noe"; 460 int i; 461 462 while (*p == ' ' || *p == '\t') p++; 463 464 /* speed */ 465 baud = atoi_(&p); 466 if (p == 0) { 467 warnx("%s: Invalid value", value); 468 return -1; 469 } 470 for (i = 0; bauds[i]; i++) 471 if (baud == bauds[i]) 472 break; 473 if (bauds[i] == 0) { 474 warnx("%d: Invalid speed", baud); 475 return -1; 476 } 477 baud = i; 478 479 NEXTSPEC; 480 481 /* bit size */ 482 if (*p < '5' || *p > '8') { 483 warnx("%c: Invalid bit size", *p); 484 return -1; 485 } 486 bit = *p++ - '5'; 487 488 NEXTSPEC; 489 490 /* parity */ 491 q = strchr(parities, *p++); 492 if (q == 0) { 493 warnx("%c: Invalid parity spec", *p); 494 return -1; 495 } 496 parity = q - parities; 497 498 NEXTSPEC; 499 500 /* stop bit */ 501 if (strncmp(p, "1.5", 3) == 0) { 502 stop = 2; 503 p += 3; 504 } else if (strncmp(p, "2", 1) == 0) { 505 stop = 0; 506 p++; 507 } else if (strncmp(p, "1", 1) == 0) { 508 stop = 1; 509 p++; 510 } else { 511 warnx("%s: Invalid value", value); 512 return -1; 513 } 514 515 NEXTSPEC; 516 517 /* flow */ 518 if (*p == '-') 519 flow = 0; 520 else if (*p == 's') 521 flow = 1; 522 else { 523 warnx("%s: Invalid value", value); 524 return -1; 525 } 526 527 p++; 528 while (*p == ' ' || *p == '\t') p++; 529 if (*p != 0) { 530 warnx("%s: Invalid value", value); 531 return -1; 532 } 533 534 prop->modified = 1; 535 prop->modified_value.word[0] = ((stop << 14) + 536 (parity << 12) + 537 (bit << 10) + 538 (flow << 9) + 539 baud); 540 541 return 0; 542} 543#undef NEXTSPEC 544 545int 546parse_srammode(prop, value) 547 struct property *prop; 548 const char *value; 549{ 550 static const char *const sramstrs[] = {"unused", "SRAMDISK", "program"}; 551 int i; 552 553 for (i = 0; i <= 2; i++) { 554 if (strcasecmp(value, sramstrs[i]) == 0) 555 break; 556 } 557 if (i > 2) { 558 warnx("%s: Invalid value", value); 559 return -1; 560 } 561 562 prop->modified = 1; 563 prop->modified_value.byte[0] = i; 564 565 return 0; 566} 567 568int 569print_uchar(prop, str) 570 struct property *prop; 571 char *str; 572{ 573 if (prop->modified) 574 snprintf(str, MAXVALUELEN, 575 "%d", prop->modified_value.byte[0]); 576 else { 577 if (!prop->value_valid) 578 prop->fill(prop); 579 snprintf(str, MAXVALUELEN, "%d", 580 prop->current_value.byte[0]); 581 } 582 583 return 0; 584} 585 586int 587print_ucharh(prop, str) 588 struct property *prop; 589 char *str; 590{ 591 if (prop->modified) 592 snprintf(str, MAXVALUELEN, 593 "0x%4.4x", prop->modified_value.byte[0]); 594 else { 595 if (!prop->value_valid) 596 prop->fill(prop); 597 snprintf(str, MAXVALUELEN, 598 "0x%4.4x", prop->current_value.byte[0]); 599 } 600 601 return 0; 602} 603 604int 605print_ushorth(prop, str) 606 struct property *prop; 607 char *str; 608{ 609 if (prop->modified) 610 snprintf(str, MAXVALUELEN, 611 "0x%4.4x", prop->modified_value.word[0]); 612 else { 613 if (!prop->value_valid) 614 prop->fill(prop); 615 snprintf(str, MAXVALUELEN, 616 "0x%4.4x", prop->current_value.word[0]); 617 } 618 619 return 0; 620} 621 622int 623print_ulong(prop, str) 624 struct property *prop; 625 char *str; 626{ 627 if (prop->modified) 628 snprintf(str, MAXVALUELEN, 629 "%ld", prop->modified_value.longword); 630 else { 631 if (!prop->value_valid) 632 prop->fill(prop); 633 snprintf(str, MAXVALUELEN, 634 "%ld", prop->current_value.longword); 635 } 636 637 return 0; 638} 639 640int 641print_ulongh(prop, str) 642 struct property *prop; 643 char *str; 644{ 645 if (prop->modified) 646 snprintf(str, MAXVALUELEN, 647 "0x%8.8lx", prop->modified_value.longword); 648 else { 649 if (!prop->value_valid) 650 prop->fill(prop); 651 snprintf(str, MAXVALUELEN, 652 "0x%8.8lx", prop->current_value.longword); 653 } 654 655 return 0; 656} 657 658int 659print_magic(prop, str) 660 struct property *prop; 661 char *str; 662{ 663 if (!prop->value_valid) 664 prop->fill(prop); 665 snprintf(str, MAXVALUELEN, "%c%c%c%c", 666 prop->current_value.byte[0], 667 prop->current_value.byte[1], 668 prop->current_value.byte[2], 669 prop->current_value.byte[3]); 670 671 return 0; 672} 673 674int 675print_timesec(prop, str) 676 struct property *prop; 677 char *str; 678{ 679 if (prop->modified) 680 snprintf(str, MAXVALUELEN, 681 "%ld second", prop->modified_value.longword); 682 else { 683 if (!prop->value_valid) 684 prop->fill(prop); 685 snprintf(str, MAXVALUELEN, 686 "%ld second", prop->current_value.longword); 687 } 688 689 return 0; 690} 691 692int 693print_bootdev(prop, str) 694 struct property *prop; 695 char *str; 696{ 697 unsigned int v; 698 699 if (prop->modified) 700 v = prop->modified_value.word[0]; 701 else { 702 if (!prop->value_valid) 703 prop->fill(prop); 704 v = prop->current_value.word[0]; 705 } 706 707 if (v == 0) 708 strcpy(str, "STD"); 709 else if (v == 0xa000) 710 strcpy(str, "ROM"); 711 else if (v == 0xb000) 712 strcpy(str, "RAM"); 713 else if (v >= 0x8000 && v < 0x9000) 714 snprintf(str, MAXVALUELEN, "HD%d", (v & 0x0f00) >> 8); 715 else if (v >= 0x9000 && v < 0xa000) 716 snprintf(str, MAXVALUELEN, "FD%d", (v & 0x0f00) >> 8); 717 else 718 snprintf(str, MAXVALUELEN, "%8.8x", v); 719 720 return 0; 721} 722 723int 724print_serial(prop, str) 725 struct property *prop; 726 char *str; 727{ 728 unsigned int v; 729 const char *baud, *stop; 730 char bit, parity, flow; 731 static const char *const bauds[] = {"75", "150", "300", "600", "1200", 732 "2400", "4800", "9600", "17361"}; 733 static const char bits[] = "5678"; 734 static const char parities[] = "noen"; 735 static const char *const stops[] = {"2", "1", "1.5", "2"}; 736 static const char flows[] = "-s"; 737 738 if (prop->modified) 739 v = prop->modified_value.word[0]; 740 else { 741 if (!prop->value_valid) 742 prop->fill(prop); 743 v = prop->current_value.word[0]; 744 } 745 746 baud = bauds[v & 0x000f]; 747 bit = bits[(v & 0x0c00) >> 10]; 748 parity = parities[(v & 0x3000) >> 12]; 749 stop = stops[(v & 0xe000) >> 14]; 750 flow = flows[(v & 0x0200) >> 9]; 751 sprintf(str, "%s,%c,%c,%s,%c", baud, bit, parity, stop, flow); 752 753 return 0; 754} 755 756int 757print_srammode(prop, str) 758 struct property *prop; 759 char *str; 760{ 761 int v; 762 static const char *const sramstrs[] = {"unused", "SRAMDISK", "program"}; 763 764 if (prop->modified) 765 v = prop->modified_value.byte[0]; 766 else { 767 if (!prop->value_valid) 768 prop->fill(prop); 769 v = prop->current_value.byte[0]; 770 } 771 772 if (v < 0 || v > 2) 773 strcpy(str, "INVALID"); 774 else 775 strcpy(str, sramstrs[v]); 776 777 return 0; 778} 779