1 /* $NetBSD: methods.c,v 1.4 2001/02/21 13:09:18 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 * 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 int bauds[] = {75, 150, 300, 600, 1200, 2400, 4800, 9600, 17361, 0}; 465 const char parities[] = "noe"; 466 int i; 467 468 while (*p == ' ' || *p == '\t') p++; 469 470 /* speed */ 471 baud = atoi_ (&p); 472 if (p == 0) { 473 warnx ("%s: Invalid value", value); 474 return -1; 475 } 476 for (i = 0; bauds[i]; i++) 477 if (baud == bauds[i]) 478 break; 479 if (bauds[i] == 0) { 480 warnx ("%d: Invalid speed", baud); 481 return -1; 482 } 483 baud = i; 484 485 NEXTSPEC; 486 487 /* bit size */ 488 if (*p < '5' || *p > '8') { 489 warnx ("%c: Invalid bit size", *p); 490 return -1; 491 } 492 bit = *p++ - '5'; 493 494 NEXTSPEC; 495 496 /* parity */ 497 q = strchr(parities, *p++); 498 if (q == 0) { 499 warnx ("%c: Invalid parity spec", *p); 500 return -1; 501 } 502 parity = q - parities; 503 504 NEXTSPEC; 505 506 /* stop bit */ 507 if (strncmp (p, "1.5", 3) == 0) { 508 stop = 2; 509 p += 3; 510 } else if (strncmp (p, "2", 1) == 0) { 511 stop = 0; 512 p++; 513 } else if (strncmp (p, "1", 1) == 0) { 514 stop = 1; 515 p++; 516 } else { 517 warnx ("%s: Invalid value", value); 518 return -1; 519 } 520 521 NEXTSPEC; 522 523 /* flow */ 524 if (*p == '-') 525 flow = 0; 526 else if (*p == 's') 527 flow = 1; 528 else { 529 warnx ("%s: Invalid value", value); 530 return -1; 531 } 532 533 p++; 534 while (*p == ' ' || *p == '\t') p++; 535 if (*p != 0) { 536 warnx ("%s: Invalid value", value); 537 return -1; 538 } 539 540 prop->modified = 1; 541 prop->modified_value.word[0] = ((stop << 14) + 542 (parity << 12) + 543 (bit << 10) + 544 (flow << 9) + 545 baud); 546 547 return 0; 548 } 549 #undef NEXTSPEC 550 551 int 552 parse_srammode (prop, value) 553 struct property *prop; 554 const char *value; 555 { 556 const char *sramstrs[] = {"unused", "SRAMDISK", "program"}; 557 int i; 558 559 for (i = 0; i <= 2; i++) { 560 if (strcasecmp (value, sramstrs[i]) == 0) 561 break; 562 } 563 if (i > 2) { 564 warnx ("%s: Invalid value", value); 565 return -1; 566 } 567 568 prop->modified = 1; 569 prop->modified_value.byte[0] = i; 570 571 return 0; 572 } 573 574 int 575 print_uchar (prop, str) 576 struct property *prop; 577 char *str; 578 { 579 if (prop->modified) 580 snprintf (str, MAXVALUELEN, 581 "%d", prop->modified_value.byte[0]); 582 else { 583 if (!prop->value_valid) 584 prop->fill (prop); 585 snprintf (str, MAXVALUELEN, "%d", 586 prop->current_value.byte[0]); 587 } 588 589 return 0; 590 } 591 592 int 593 print_ucharh (prop, str) 594 struct property *prop; 595 char *str; 596 { 597 if (prop->modified) 598 snprintf (str, MAXVALUELEN, 599 "0x%4.4x", prop->modified_value.byte[0]); 600 else { 601 if (!prop->value_valid) 602 prop->fill (prop); 603 snprintf (str, MAXVALUELEN, 604 "0x%4.4x", prop->current_value.byte[0]); 605 } 606 607 return 0; 608 } 609 610 int 611 print_ushorth (prop, str) 612 struct property *prop; 613 char *str; 614 { 615 if (prop->modified) 616 snprintf (str, MAXVALUELEN, 617 "0x%4.4x", prop->modified_value.word[0]); 618 else { 619 if (!prop->value_valid) 620 prop->fill (prop); 621 snprintf (str, MAXVALUELEN, 622 "0x%4.4x", prop->current_value.word[0]); 623 } 624 625 return 0; 626 } 627 628 int 629 print_ulong (prop, str) 630 struct property *prop; 631 char *str; 632 { 633 if (prop->modified) 634 snprintf (str, MAXVALUELEN, 635 "%ld", prop->modified_value.longword); 636 else { 637 if (!prop->value_valid) 638 prop->fill (prop); 639 snprintf (str, MAXVALUELEN, 640 "%ld", prop->current_value.longword); 641 } 642 643 return 0; 644 } 645 646 int 647 print_ulongh (prop, str) 648 struct property *prop; 649 char *str; 650 { 651 if (prop->modified) 652 snprintf (str, MAXVALUELEN, 653 "0x%8.8lx", prop->modified_value.longword); 654 else { 655 if (!prop->value_valid) 656 prop->fill (prop); 657 snprintf (str, MAXVALUELEN, 658 "0x%8.8lx", prop->current_value.longword); 659 } 660 661 return 0; 662 } 663 664 int 665 print_magic (prop, str) 666 struct property *prop; 667 char *str; 668 { 669 if (!prop->value_valid) 670 prop->fill (prop); 671 snprintf (str, MAXVALUELEN, "%c%c%c%c", 672 prop->current_value.byte[0], 673 prop->current_value.byte[1], 674 prop->current_value.byte[2], 675 prop->current_value.byte[3]); 676 677 return 0; 678 } 679 680 int 681 print_timesec (prop, str) 682 struct property *prop; 683 char *str; 684 { 685 if (prop->modified) 686 snprintf (str, MAXVALUELEN, 687 "%ld second", prop->modified_value.longword); 688 else { 689 if (!prop->value_valid) 690 prop->fill (prop); 691 snprintf (str, MAXVALUELEN, 692 "%ld second", prop->current_value.longword); 693 } 694 695 return 0; 696 } 697 698 int 699 print_bootdev (prop, str) 700 struct property *prop; 701 char *str; 702 { 703 unsigned int v; 704 705 if (prop->modified) 706 v = prop->modified_value.word[0]; 707 else { 708 if (!prop->value_valid) 709 prop->fill (prop); 710 v = prop->current_value.word[0]; 711 } 712 713 if (v == 0) 714 strcpy (str, "STD"); 715 else if (v == 0xa000) 716 strcpy (str, "ROM"); 717 else if (v == 0xb000) 718 strcpy (str, "RAM"); 719 else if (v >= 0x8000 && v < 0x9000) 720 snprintf (str, MAXVALUELEN, "HD%d", (v & 0x0f00) >> 8); 721 else if (v >= 0x9000 && v < 0xa000) 722 snprintf (str, MAXVALUELEN, "FD%d", (v & 0x0f00) >> 8); 723 else 724 snprintf (str, MAXVALUELEN, "%8.8x", v); 725 726 return 0; 727 } 728 729 int 730 print_serial (prop, str) 731 struct property *prop; 732 char *str; 733 { 734 unsigned int v; 735 const char *baud, *stop; 736 char bit, parity, flow; 737 const char *bauds[] = {"75", "150", "300", "600", "1200", 738 "2400", "4800", "9600", "17361"}; 739 const char bits[] = "5678"; 740 const char parities[] = "noen"; 741 const char *stops[] = {"2", "1", "1.5", "2"}; 742 const char flows[] = "-s"; 743 744 if (prop->modified) 745 v = prop->modified_value.word[0]; 746 else { 747 if (!prop->value_valid) 748 prop->fill (prop); 749 v = prop->current_value.word[0]; 750 } 751 752 baud = bauds[v & 0x000f]; 753 bit = bits[(v & 0x0c00) >> 10]; 754 parity = parities[(v & 0x3000) >> 12]; 755 stop = stops[(v & 0xe000) >> 14]; 756 flow = flows[(v & 0x0200) >> 9]; 757 sprintf (str, "%s,%c,%c,%s,%c", baud, bit, parity, stop, flow); 758 759 return 0; 760 } 761 762 int 763 print_srammode (prop, str) 764 struct property *prop; 765 char *str; 766 { 767 int v; 768 const char *sramstrs[] = {"unused", "SRAMDISK", "program"}; 769 770 if (prop->modified) 771 v = prop->modified_value.byte[0]; 772 else { 773 if (!prop->value_valid) 774 prop->fill (prop); 775 v = prop->current_value.byte[0]; 776 } 777 778 if (v < 0 || v > 2) 779 strcpy (str, "INVALID"); 780 else 781 strcpy (str, sramstrs[v]); 782 783 return 0; 784 } 785