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