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