1 /* $NetBSD: openfirm.c,v 1.6 2001/12/11 03:35:02 uwe Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <machine/psl.h> 36 #include <machine/stdarg.h> 37 38 #include <machine/openfirm.h> 39 40 #define min(x,y) ((x<y)?(x):(y)) 41 42 extern void *romp; 43 #define openfirmware(a) ((*((int (*)__P((void *)))romp))(a)) 44 45 46 int 47 OF_peer(phandle) 48 int phandle; 49 { 50 struct { 51 cell_t name; 52 cell_t nargs; 53 cell_t nreturns; 54 cell_t phandle; 55 cell_t sibling; 56 } args; 57 58 args.name = ADR2CELL("peer"); 59 args.nargs = 1; 60 args.nreturns = 1; 61 args.phandle = HDL2CELL(phandle); 62 if (openfirmware(&args) == -1) 63 return 0; 64 return args.sibling; 65 } 66 67 int 68 OF_child(phandle) 69 int phandle; 70 { 71 struct { 72 cell_t name; 73 cell_t nargs; 74 cell_t nreturns; 75 cell_t phandle; 76 cell_t child; 77 } args; 78 79 args.name = ADR2CELL("child"); 80 args.nargs = 1; 81 args.nreturns = 1; 82 args.phandle = HDL2CELL(phandle); 83 if (openfirmware(&args) == -1) 84 return 0; 85 return args.child; 86 } 87 88 int 89 OF_parent(phandle) 90 int phandle; 91 { 92 struct { 93 cell_t name; 94 cell_t nargs; 95 cell_t nreturns; 96 cell_t phandle; 97 cell_t parent; 98 } args; 99 100 args.name = ADR2CELL("parent"); 101 args.nargs = 1; 102 args.nreturns = 1; 103 args.phandle = HDL2CELL(phandle); 104 if (openfirmware(&args) == -1) 105 return 0; 106 return args.parent; 107 } 108 109 int 110 OF_instance_to_package(ihandle) 111 int ihandle; 112 { 113 static struct { 114 cell_t name; 115 cell_t nargs; 116 cell_t nreturns; 117 cell_t ihandle; 118 cell_t phandle; 119 } args; 120 121 args.name = ADR2CELL("instance-to-package"); 122 args.nargs = 1; 123 args.nreturns = 1; 124 args.ihandle = HDL2CELL(ihandle); 125 if (openfirmware(&args) == -1) 126 return -1; 127 return args.phandle; 128 } 129 130 /* Should really return a `long' */ 131 int 132 OF_getproplen(handle, prop) 133 int handle; 134 char *prop; 135 { 136 struct { 137 cell_t name; 138 cell_t nargs; 139 cell_t nreturns; 140 cell_t phandle; 141 cell_t prop; 142 cell_t size; 143 } args; 144 145 args.name = ADR2CELL("getproplen"); 146 args.nargs = 2; 147 args.nreturns = 1; 148 args.phandle = HDL2CELL(handle); 149 args.prop = ADR2CELL(prop); 150 if (openfirmware(&args) == -1) 151 return -1; 152 return args.size; 153 } 154 155 int 156 OF_getprop(handle, prop, buf, buflen) 157 int handle; 158 char *prop; 159 void *buf; 160 int buflen; 161 { 162 struct { 163 cell_t name; 164 cell_t nargs; 165 cell_t nreturns; 166 cell_t phandle; 167 cell_t prop; 168 cell_t buf; 169 cell_t buflen; 170 cell_t size; 171 } args; 172 173 if (buflen > NBPG) 174 return -1; 175 args.name = ADR2CELL("getprop"); 176 args.nargs = 4; 177 args.nreturns = 1; 178 args.phandle = HDL2CELL(handle); 179 args.prop = ADR2CELL(prop); 180 args.buf = ADR2CELL(buf); 181 args.buflen = buflen; 182 if (openfirmware(&args) == -1) 183 return -1; 184 return args.size; 185 } 186 187 int 188 OF_setprop(handle, prop, buf, buflen) 189 int handle; 190 char *prop; 191 const void *buf; 192 int buflen; 193 { 194 struct { 195 cell_t name; 196 cell_t nargs; 197 cell_t nreturns; 198 cell_t phandle; 199 cell_t prop; 200 cell_t buf; 201 cell_t buflen; 202 cell_t size; 203 } args; 204 205 if (buflen > NBPG) 206 return -1; 207 args.name = ADR2CELL("setprop"); 208 args.nargs = 4; 209 args.nreturns = 1; 210 args.phandle = HDL2CELL(handle); 211 args.prop = ADR2CELL(prop); 212 args.buf = ADR2CELL(buf); 213 args.buflen = buflen; 214 if (openfirmware(&args) == -1) 215 return -1; 216 return args.size; 217 } 218 219 int 220 OF_nextprop(handle, prop, buf) 221 int handle; 222 char *prop; 223 void *buf; 224 { 225 struct { 226 cell_t name; 227 cell_t nargs; 228 cell_t nreturns; 229 cell_t phandle; 230 cell_t prev; 231 cell_t buf; 232 cell_t next; 233 } args; 234 235 args.name = ADR2CELL("nextprop"); 236 args.nargs = 3; 237 args.nreturns = 1; 238 args.phandle = HDL2CELL(handle); 239 args.prev = ADR2CELL(prop); 240 args.buf = ADR2CELL(buf); 241 if (openfirmware(&args) == -1) 242 return -1; 243 return args.next; 244 } 245 246 int 247 OF_finddevice(name) 248 char *name; 249 { 250 struct { 251 cell_t name; 252 cell_t nargs; 253 cell_t nreturns; 254 cell_t device; 255 cell_t phandle; 256 } args; 257 258 args.name = ADR2CELL("finddevice"); 259 args.nargs = 1; 260 args.nreturns = 1; 261 args.device = ADR2CELL(name); 262 if (openfirmware(&args) == -1) 263 return -1; 264 return args.phandle; 265 } 266 267 int 268 OF_instance_to_path(ihandle, buf, buflen) 269 int ihandle; 270 char *buf; 271 int buflen; 272 { 273 struct { 274 cell_t name; 275 cell_t nargs; 276 cell_t nreturns; 277 cell_t ihandle; 278 cell_t buf; 279 cell_t buflen; 280 cell_t length; 281 } args; 282 283 if (buflen > NBPG) 284 return -1; 285 args.name = ADR2CELL("instance-to-path"); 286 args.nargs = 3; 287 args.nreturns = 1; 288 args.ihandle = HDL2CELL(ihandle); 289 args.buf = ADR2CELL(buf); 290 args.buflen = buflen; 291 if (openfirmware(&args) < 0) 292 return -1; 293 return args.length; 294 } 295 296 int 297 OF_package_to_path(phandle, buf, buflen) 298 int phandle; 299 char *buf; 300 int buflen; 301 { 302 struct { 303 cell_t name; 304 cell_t nargs; 305 cell_t nreturns; 306 cell_t phandle; 307 cell_t buf; 308 cell_t buflen; 309 cell_t length; 310 } args; 311 312 if (buflen > NBPG) 313 return -1; 314 args.name = ADR2CELL("package-to-path"); 315 args.nargs = 3; 316 args.nreturns = 1; 317 args.phandle = HDL2CELL(phandle); 318 args.buf = ADR2CELL(buf); 319 args.buflen = buflen; 320 if (openfirmware(&args) < 0) 321 return -1; 322 return args.length; 323 } 324 325 /* 326 * The following two functions may need to be re-worked to be 64-bit clean. 327 */ 328 int 329 #ifdef __STDC__ 330 OF_call_method(char *method, int ihandle, int nargs, int nreturns, ...) 331 #else 332 OF_call_method(method, ihandle, nargs, nreturns, va_alist) 333 char *method; 334 int ihandle; 335 int nargs; 336 int nreturns; 337 va_dcl 338 #endif 339 { 340 va_list ap; 341 struct { 342 cell_t name; 343 cell_t nargs; 344 cell_t nreturns; 345 cell_t method; 346 cell_t ihandle; 347 cell_t args_n_results[12]; 348 } args; 349 long *ip, n; 350 351 if (nargs > 6) 352 return -1; 353 args.name = ADR2CELL("call-method"); 354 args.nargs = nargs + 2; 355 args.nreturns = nreturns + 1; 356 args.method = ADR2CELL(method); 357 args.ihandle = HDL2CELL(ihandle); 358 va_start(ap, nreturns); 359 for (ip = (long*)(args.args_n_results + (n = nargs)); --n >= 0;) 360 *--ip = va_arg(ap, unsigned long); 361 if (openfirmware(&args) == -1) { 362 va_end(ap); 363 return -1; 364 } 365 if (args.args_n_results[nargs]) { 366 va_end(ap); 367 return args.args_n_results[nargs]; 368 } 369 for (ip = (long*)(args.args_n_results + nargs + (n = args.nreturns)); --n > 0;) 370 *va_arg(ap, unsigned long *) = *--ip; 371 va_end(ap); 372 return 0; 373 } 374 375 int 376 #ifdef __STDC__ 377 OF_call_method_1(char *method, int ihandle, int nargs, ...) 378 #else 379 OF_call_method_1(method, ihandle, nargs, va_alist) 380 char *method; 381 int ihandle; 382 int nargs; 383 va_dcl 384 #endif 385 { 386 va_list ap; 387 struct { 388 cell_t name; 389 cell_t nargs; 390 cell_t nreturns; 391 cell_t method; 392 cell_t ihandle; 393 cell_t args_n_results[16]; 394 } args; 395 long *ip, n; 396 397 if (nargs > 6) 398 return -1; 399 args.name = ADR2CELL("call-method"); 400 args.nargs = nargs + 2; 401 args.nreturns = 1; 402 args.method = ADR2CELL(method); 403 args.ihandle = HDL2CELL(ihandle); 404 va_start(ap, nargs); 405 for (ip = (long*)(args.args_n_results + (n = nargs)); --n >= 0;) 406 *--ip = va_arg(ap, unsigned long); 407 va_end(ap); 408 if (openfirmware(&args) == -1) 409 return -1; 410 if (args.args_n_results[nargs]) 411 return -1; 412 return args.args_n_results[nargs + 1]; 413 } 414 415 int 416 OF_open(dname) 417 char *dname; 418 { 419 struct { 420 cell_t name; 421 cell_t nargs; 422 cell_t nreturns; 423 cell_t dname; 424 cell_t handle; 425 } args; 426 int l; 427 428 if ((l = strlen(dname)) >= NBPG) 429 return -1; 430 args.name = ADR2CELL("open"); 431 args.nargs = 1; 432 args.nreturns = 1; 433 args.dname = ADR2CELL(dname); 434 if (openfirmware(&args) == -1) 435 return -1; 436 return args.handle; 437 } 438 439 void 440 OF_close(handle) 441 int handle; 442 { 443 struct { 444 cell_t name; 445 cell_t nargs; 446 cell_t nreturns; 447 cell_t handle; 448 } args; 449 450 args.name = ADR2CELL("close"); 451 args.nargs = 1; 452 args.nreturns = 0; 453 args.handle = HDL2CELL(handle); 454 openfirmware(&args); 455 } 456 457 int 458 OF_test(service) 459 char* service; 460 { 461 struct { 462 cell_t name; 463 cell_t nargs; 464 cell_t nreturns; 465 cell_t service; 466 cell_t status; 467 } args; 468 469 args.name = ADR2CELL("test"); 470 args.nargs = 1; 471 args.nreturns = 1; 472 args.service = ADR2CELL(service); 473 if (openfirmware(&args) == -1) 474 return -1; 475 return args.status; 476 } 477 478 int 479 OF_test_method(service, method) 480 int service; 481 char* method; 482 { 483 struct { 484 cell_t name; 485 cell_t nargs; 486 cell_t nreturns; 487 cell_t service; 488 cell_t method; 489 cell_t status; 490 } args; 491 492 args.name = ADR2CELL("test-method"); 493 args.nargs = 2; 494 args.nreturns = 1; 495 args.service = HDL2CELL(service); 496 args.method = ADR2CELL(method); 497 openfirmware(&args); 498 return args.status; 499 } 500 501 502 /* 503 * This assumes that character devices don't read in multiples of NBPG. 504 */ 505 int 506 OF_read(handle, addr, len) 507 int handle; 508 void *addr; 509 int len; 510 { 511 struct { 512 cell_t name; 513 cell_t nargs; 514 cell_t nreturns; 515 cell_t ihandle; 516 cell_t addr; 517 cell_t len; 518 cell_t actual; 519 } args; 520 int l, act = 0; 521 522 args.name = ADR2CELL("read"); 523 args.nargs = 3; 524 args.nreturns = 1; 525 args.ihandle = HDL2CELL(handle); 526 args.addr = ADR2CELL(addr); 527 for (; len > 0; len -= l, (u_long)addr += l) { 528 l = min(NBPG, len); 529 args.len = l; 530 if (openfirmware(&args) == -1) 531 return -1; 532 if (args.actual > 0) { 533 act += args.actual; 534 } 535 if (args.actual < l) { 536 if (act) 537 return act; 538 else 539 return args.actual; 540 } 541 } 542 return act; 543 } 544 545 void prom_printf __P((const char *fmt, ...)); /* XXX for below */ 546 547 int 548 OF_write(handle, addr, len) 549 int handle; 550 void *addr; 551 int len; 552 { 553 struct { 554 cell_t name; 555 cell_t nargs; 556 cell_t nreturns; 557 cell_t ihandle; 558 cell_t addr; 559 cell_t len; 560 cell_t actual; 561 } args; 562 int l, act = 0; 563 564 args.name = ADR2CELL("write"); 565 args.nargs = 3; 566 args.nreturns = 1; 567 args.ihandle = HDL2CELL(handle); 568 args.addr = ADR2CELL(addr); 569 if (len>1024) { prom_printf("OF_write() > 1024\n"); } 570 for (; len > 0; len -= l, (u_long)addr += l) { 571 l = min(NBPG, len); 572 args.len = l; 573 if (openfirmware(&args) == -1) 574 return -1; 575 l = args.actual; 576 act += l; 577 } 578 return act; 579 } 580 581 582 int 583 OF_seek(handle, pos) 584 int handle; 585 u_quad_t pos; 586 { 587 struct { 588 cell_t name; 589 cell_t nargs; 590 cell_t nreturns; 591 cell_t handle; 592 cell_t poshi; 593 cell_t poslo; 594 cell_t status; 595 } args; 596 597 args.name = ADR2CELL("seek"); 598 args.nargs = 3; 599 args.nreturns = 1; 600 args.handle = HDL2CELL(handle); 601 args.poshi = HDL2CELL(pos >> 32); 602 args.poslo = HDL2CELL(pos); 603 if (openfirmware(&args) == -1) 604 return -1; 605 return args.status; 606 } 607 608 void 609 OF_boot(bootspec) 610 char *bootspec; 611 { 612 struct { 613 cell_t name; 614 cell_t nargs; 615 cell_t nreturns; 616 cell_t bootspec; 617 } args; 618 int l; 619 620 if ((l = strlen(bootspec)) >= NBPG) 621 panic("OF_boot"); 622 args.name = ADR2CELL("boot"); 623 args.nargs = 1; 624 args.nreturns = 0; 625 args.bootspec = ADR2CELL(bootspec); 626 openfirmware(&args); 627 panic("OF_boot failed"); 628 } 629 630 void 631 OF_enter() 632 { 633 struct { 634 cell_t name; 635 cell_t nargs; 636 cell_t nreturns; 637 } args; 638 639 args.name = ADR2CELL("enter"); 640 args.nargs = 0; 641 args.nreturns = 0; 642 #if defined(MSIIEP) 643 msiiep_swap_endian(0); 644 #endif 645 openfirmware(&args); 646 #if defined(MSIIEP) 647 msiiep_swap_endian(1); 648 #endif 649 } 650 651 void 652 OF_exit() 653 { 654 struct { 655 cell_t name; 656 cell_t nargs; 657 cell_t nreturns; 658 } args; 659 660 args.name = ADR2CELL("exit"); 661 args.nargs = 0; 662 args.nreturns = 0; 663 #if defined(MSIIEP) 664 msiiep_swap_endian(0); 665 #endif 666 openfirmware(&args); 667 #if defined(MSIIEP) 668 msiiep_swap_endian(1); 669 #endif 670 panic("OF_exit failed"); 671 } 672 673 void 674 OF_poweroff() 675 { 676 struct { 677 cell_t name; 678 cell_t nargs; 679 cell_t nreturns; 680 } args; 681 682 args.name = ADR2CELL("SUNW,power-off"); 683 args.nargs = 0; 684 args.nreturns = 0; 685 openfirmware(&args); 686 panic("OF_poweroff failed"); 687 } 688 689 void 690 (*OF_set_callback(newfunc)) __P((void *)) 691 void (*newfunc) __P((void *)); 692 { 693 struct { 694 cell_t name; 695 cell_t nargs; 696 cell_t nreturns; 697 cell_t newfunc; 698 cell_t oldfunc; 699 } args; 700 701 args.name = ADR2CELL("set-callback"); 702 args.nargs = 1; 703 args.nreturns = 1; 704 args.newfunc = ADR2CELL(newfunc); 705 if (openfirmware(&args) == -1) 706 return 0; 707 return (void*)(long)args.oldfunc; 708 } 709 710 void 711 OF_set_symbol_lookup(s2v, v2s) 712 void (*s2v)(void *); 713 void (*v2s)(void *); 714 { 715 struct { 716 cell_t name; 717 cell_t nargs; 718 cell_t nreturns; 719 cell_t sym2val; 720 cell_t val2sym; 721 } args; 722 723 args.name = ADR2CELL("set-symbol-lookup"); 724 args.nargs = 2; 725 args.nreturns = 0; 726 args.sym2val = ADR2CELL(s2v); 727 args.val2sym = ADR2CELL(v2s); 728 729 (void)openfirmware(&args); 730 } 731 732 void 733 OF_interpret(s) 734 char *s; 735 { 736 struct { 737 cell_t name; 738 cell_t nargs; 739 cell_t nreturns; 740 cell_t verbs; 741 cell_t status; 742 } args; 743 744 args.name = ADR2CELL("interpret"); 745 args.nargs = 1; 746 args.nreturns = 1; 747 args.verbs = ADR2CELL(s); 748 openfirmware(&args); 749 } 750 751 int 752 OF_milliseconds() 753 { 754 struct { 755 cell_t name; 756 cell_t nargs; 757 cell_t nreturns; 758 cell_t ticks; 759 } args; 760 761 args.name = ADR2CELL("milliseconds"); 762 args.nargs = 0; 763 args.nreturns = 1; 764 openfirmware(&args); 765 return (args.ticks); 766 } 767 768 #if defined(_KERNEL_OPT) 769 #include "opt_ddb.h" 770 #endif 771 772 #ifdef DDB 773 #include <machine/db_machdep.h> 774 #include <ddb/db_sym.h> 775 #include <ddb/db_extern.h> 776 777 int obp_symbol_debug = 0; 778 779 void OF_sym2val(cells) 780 void *cells; 781 { 782 struct args { 783 cell_t service; 784 cell_t nargs; 785 cell_t nreturns; 786 cell_t symbol; 787 cell_t result; 788 cell_t value; 789 } *args = (struct args*)cells; 790 db_sym_t symbol; 791 db_expr_t value; 792 793 /* Set data segment pointer */ 794 __asm __volatile("clr %%g4" : :); 795 796 /* No args? Nothing to do. */ 797 if (!args->nargs || 798 !args->nreturns) return; 799 800 /* Do we have a place for the value? */ 801 if (args->nreturns != 2) { 802 args->nreturns = 1; 803 args->result = -1; 804 return; 805 } 806 symbol = (db_sym_t)args->symbol; 807 if (obp_symbol_debug) 808 prom_printf("looking up symbol %s\n", symbol); 809 db_symbol_values(symbol, (char**)NULL, &value); 810 if (obp_symbol_debug) 811 prom_printf("%s is %lx\r\n", symbol, value); 812 args->result = 0; 813 args->value = ADR2CELL(value); 814 } 815 816 void OF_val2sym(cells) 817 void *cells; 818 { 819 struct args { 820 cell_t service; 821 cell_t nargs; 822 cell_t nreturns; 823 cell_t value; 824 cell_t offset; 825 cell_t symbol; 826 } *args = (struct args*)cells; 827 db_sym_t symbol; 828 db_expr_t value; 829 db_expr_t offset; 830 831 /* Set data segment pointer */ 832 __asm __volatile("clr %%g4" : :); 833 834 if (obp_symbol_debug) 835 prom_printf("OF_val2sym: nargs %lx nreturns %lx\r\n", 836 args->nargs, args->nreturns); 837 /* No args? Nothing to do. */ 838 if (!args->nargs || 839 !args->nreturns) return; 840 841 /* Do we have a place for the value? */ 842 if (args->nreturns != 2) { 843 args->nreturns = 1; 844 args->offset = -1; 845 return; 846 } 847 848 value = args->value; 849 if (obp_symbol_debug) 850 prom_printf("looking up value %ld\n", value); 851 symbol = db_search_symbol(value, 0, &offset); 852 if (symbol == DB_SYM_NULL) { 853 if (obp_symbol_debug) 854 prom_printf("OF_val2sym: not found\r\n"); 855 args->nreturns = 1; 856 args->offset = -1; 857 return; 858 } 859 args->offset = offset; 860 args->symbol = ADR2CELL(symbol); 861 862 } 863 #endif 864