1 /* $NetBSD: openfirm.c,v 1.2 2000/11/15 16:15:01 pk 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 return -1; 363 if (args.args_n_results[nargs]) 364 return args.args_n_results[nargs]; 365 for (ip = (long*)(args.args_n_results + nargs + (n = args.nreturns)); --n > 0;) 366 *va_arg(ap, unsigned long *) = *--ip; 367 va_end(ap); 368 return 0; 369 } 370 371 int 372 #ifdef __STDC__ 373 OF_call_method_1(char *method, int ihandle, int nargs, ...) 374 #else 375 OF_call_method_1(method, ihandle, nargs, va_alist) 376 char *method; 377 int ihandle; 378 int nargs; 379 va_dcl 380 #endif 381 { 382 va_list ap; 383 struct { 384 cell_t name; 385 cell_t nargs; 386 cell_t nreturns; 387 cell_t method; 388 cell_t ihandle; 389 cell_t args_n_results[16]; 390 } args; 391 long *ip, n; 392 393 if (nargs > 6) 394 return -1; 395 args.name = ADR2CELL("call-method"); 396 args.nargs = nargs + 2; 397 args.nreturns = 1; 398 args.method = ADR2CELL(method); 399 args.ihandle = HDL2CELL(ihandle); 400 va_start(ap, nargs); 401 for (ip = (long*)(args.args_n_results + (n = nargs)); --n >= 0;) 402 *--ip = va_arg(ap, unsigned long); 403 va_end(ap); 404 if (openfirmware(&args) == -1) 405 return -1; 406 if (args.args_n_results[nargs]) 407 return -1; 408 return args.args_n_results[nargs + 1]; 409 } 410 411 int 412 OF_open(dname) 413 char *dname; 414 { 415 struct { 416 cell_t name; 417 cell_t nargs; 418 cell_t nreturns; 419 cell_t dname; 420 cell_t handle; 421 } args; 422 int l; 423 424 if ((l = strlen(dname)) >= NBPG) 425 return -1; 426 args.name = ADR2CELL("open"); 427 args.nargs = 1; 428 args.nreturns = 1; 429 args.dname = ADR2CELL(dname); 430 if (openfirmware(&args) == -1) 431 return -1; 432 return args.handle; 433 } 434 435 void 436 OF_close(handle) 437 int handle; 438 { 439 struct { 440 cell_t name; 441 cell_t nargs; 442 cell_t nreturns; 443 cell_t handle; 444 } args; 445 446 args.name = ADR2CELL("close"); 447 args.nargs = 1; 448 args.nreturns = 0; 449 args.handle = HDL2CELL(handle); 450 openfirmware(&args); 451 } 452 453 int 454 OF_test(service) 455 char* service; 456 { 457 struct { 458 cell_t name; 459 cell_t nargs; 460 cell_t nreturns; 461 cell_t service; 462 cell_t status; 463 } args; 464 465 args.name = ADR2CELL("test"); 466 args.nargs = 1; 467 args.nreturns = 1; 468 args.service = ADR2CELL(service); 469 if (openfirmware(&args) == -1) 470 return -1; 471 return args.status; 472 } 473 474 int 475 OF_test_method(service, method) 476 int service; 477 char* method; 478 { 479 struct { 480 cell_t name; 481 cell_t nargs; 482 cell_t nreturns; 483 cell_t service; 484 cell_t method; 485 cell_t status; 486 } args; 487 488 args.name = ADR2CELL("test-method"); 489 args.nargs = 2; 490 args.nreturns = 1; 491 args.service = HDL2CELL(service); 492 args.method = ADR2CELL(method); 493 openfirmware(&args); 494 return args.status; 495 } 496 497 498 /* 499 * This assumes that character devices don't read in multiples of NBPG. 500 */ 501 int 502 OF_read(handle, addr, len) 503 int handle; 504 void *addr; 505 int len; 506 { 507 struct { 508 cell_t name; 509 cell_t nargs; 510 cell_t nreturns; 511 cell_t ihandle; 512 cell_t addr; 513 cell_t len; 514 cell_t actual; 515 } args; 516 int l, act = 0; 517 518 args.name = ADR2CELL("read"); 519 args.nargs = 3; 520 args.nreturns = 1; 521 args.ihandle = HDL2CELL(handle); 522 args.addr = ADR2CELL(addr); 523 for (; len > 0; len -= l, (u_long)addr += l) { 524 l = min(NBPG, len); 525 args.len = l; 526 if (openfirmware(&args) == -1) 527 return -1; 528 if (args.actual > 0) { 529 act += args.actual; 530 } 531 if (args.actual < l) { 532 if (act) 533 return act; 534 else 535 return args.actual; 536 } 537 } 538 return act; 539 } 540 541 void prom_printf __P((const char *fmt, ...)); /* XXX for below */ 542 543 int 544 OF_write(handle, addr, len) 545 int handle; 546 void *addr; 547 int len; 548 { 549 struct { 550 cell_t name; 551 cell_t nargs; 552 cell_t nreturns; 553 cell_t ihandle; 554 cell_t addr; 555 cell_t len; 556 cell_t actual; 557 } args; 558 int l, act = 0; 559 560 args.name = ADR2CELL("write"); 561 args.nargs = 3; 562 args.nreturns = 1; 563 args.ihandle = HDL2CELL(handle); 564 args.addr = ADR2CELL(addr); 565 if (len>1024) { prom_printf("OF_write() > 1024\n"); } 566 for (; len > 0; len -= l, (u_long)addr += l) { 567 l = min(NBPG, len); 568 args.len = l; 569 if (openfirmware(&args) == -1) 570 return -1; 571 l = args.actual; 572 act += l; 573 } 574 return act; 575 } 576 577 578 int 579 OF_seek(handle, pos) 580 int handle; 581 u_quad_t pos; 582 { 583 struct { 584 cell_t name; 585 cell_t nargs; 586 cell_t nreturns; 587 cell_t handle; 588 cell_t poshi; 589 cell_t poslo; 590 cell_t status; 591 } args; 592 593 args.name = ADR2CELL("seek"); 594 args.nargs = 3; 595 args.nreturns = 1; 596 args.handle = HDL2CELL(handle); 597 args.poshi = HDL2CELL(pos >> 32); 598 args.poslo = HDL2CELL(pos); 599 if (openfirmware(&args) == -1) 600 return -1; 601 return args.status; 602 } 603 604 void 605 OF_boot(bootspec) 606 char *bootspec; 607 { 608 struct { 609 cell_t name; 610 cell_t nargs; 611 cell_t nreturns; 612 cell_t bootspec; 613 } args; 614 int l; 615 616 if ((l = strlen(bootspec)) >= NBPG) 617 panic("OF_boot"); 618 args.name = ADR2CELL("boot"); 619 args.nargs = 1; 620 args.nreturns = 0; 621 args.bootspec = ADR2CELL(bootspec); 622 openfirmware(&args); 623 panic("OF_boot failed"); 624 } 625 626 void 627 OF_enter() 628 { 629 struct { 630 cell_t name; 631 cell_t nargs; 632 cell_t nreturns; 633 } args; 634 635 args.name = ADR2CELL("enter"); 636 args.nargs = 0; 637 args.nreturns = 0; 638 openfirmware(&args); 639 } 640 641 void 642 OF_exit() 643 { 644 struct { 645 cell_t name; 646 cell_t nargs; 647 cell_t nreturns; 648 } args; 649 650 args.name = ADR2CELL("exit"); 651 args.nargs = 0; 652 args.nreturns = 0; 653 openfirmware(&args); 654 panic("OF_exit failed"); 655 } 656 657 void 658 OF_poweroff() 659 { 660 struct { 661 cell_t name; 662 cell_t nargs; 663 cell_t nreturns; 664 } args; 665 666 args.name = ADR2CELL("SUNW,power-off"); 667 args.nargs = 0; 668 args.nreturns = 0; 669 openfirmware(&args); 670 panic("OF_poweroff failed"); 671 } 672 673 void 674 (*OF_set_callback(newfunc)) __P((void *)) 675 void (*newfunc) __P((void *)); 676 { 677 struct { 678 cell_t name; 679 cell_t nargs; 680 cell_t nreturns; 681 cell_t newfunc; 682 cell_t oldfunc; 683 } args; 684 685 args.name = ADR2CELL("set-callback"); 686 args.nargs = 1; 687 args.nreturns = 1; 688 args.newfunc = ADR2CELL(newfunc); 689 if (openfirmware(&args) == -1) 690 return 0; 691 return (void*)(long)args.oldfunc; 692 } 693 694 void 695 OF_set_symbol_lookup(s2v, v2s) 696 void (*s2v)(void *); 697 void (*v2s)(void *); 698 { 699 struct { 700 cell_t name; 701 cell_t nargs; 702 cell_t nreturns; 703 cell_t sym2val; 704 cell_t val2sym; 705 } args; 706 707 args.name = ADR2CELL("set-symbol-lookup"); 708 args.nargs = 2; 709 args.nreturns = 0; 710 args.sym2val = ADR2CELL(s2v); 711 args.val2sym = ADR2CELL(v2s); 712 713 (void)openfirmware(&args); 714 } 715 716 void 717 OF_interpret(s) 718 char *s; 719 { 720 struct { 721 cell_t name; 722 cell_t nargs; 723 cell_t nreturns; 724 cell_t verbs; 725 cell_t status; 726 } args; 727 728 args.name = ADR2CELL("interpret"); 729 args.nargs = 1; 730 args.nreturns = 1; 731 args.verbs = ADR2CELL(s); 732 openfirmware(&args); 733 } 734 735 int 736 OF_milliseconds() 737 { 738 struct { 739 cell_t name; 740 cell_t nargs; 741 cell_t nreturns; 742 cell_t ticks; 743 } args; 744 745 args.name = ADR2CELL("milliseconds"); 746 args.nargs = 0; 747 args.nreturns = 1; 748 openfirmware(&args); 749 return (args.ticks); 750 } 751 752 #if defined(_KERNEL) && !defined(_LKM) 753 #include "opt_ddb.h" 754 #endif 755 756 #ifdef DDB 757 #include <machine/db_machdep.h> 758 #include <ddb/db_sym.h> 759 #include <ddb/db_extern.h> 760 761 void OF_sym2val(cells) 762 void *cells; 763 { 764 struct args { 765 cell_t service; 766 cell_t nargs; 767 cell_t nreturns; 768 cell_t symbol; 769 cell_t result; 770 cell_t value; 771 } *args = (struct args*)cells; 772 db_sym_t symbol; 773 db_expr_t value; 774 775 /* Set data segment pointer */ 776 __asm __volatile("clr %%g4" : :); 777 778 /* No args? Nothing to do. */ 779 if (!args->nargs || 780 !args->nreturns) return; 781 782 /* Do we have a place for the value? */ 783 if (args->nreturns != 2) { 784 args->nreturns = 1; 785 args->result = -1; 786 return; 787 } 788 symbol = (db_sym_t)args->symbol; 789 prom_printf("looking up symbol %s\n", symbol); 790 db_symbol_values(symbol, (char**)NULL, &value); 791 args->result = 0; 792 args->value = ADR2CELL(value); 793 } 794 795 void OF_val2sym(cells) 796 void *cells; 797 { 798 struct args { 799 cell_t service; 800 cell_t nargs; 801 cell_t nreturns; 802 cell_t value; 803 cell_t offset; 804 cell_t symbol; 805 } *args = (struct args*)cells; 806 db_sym_t symbol; 807 db_expr_t value; 808 db_expr_t offset; 809 810 /* Set data segment pointer */ 811 __asm __volatile("clr %%g4" : :); 812 813 /* No args? Nothing to do. */ 814 if (!args->nargs || 815 !args->nreturns) return; 816 817 /* Do we have a place for the value? */ 818 if (args->nreturns != 2) { 819 args->nreturns = 1; 820 args->offset = -1; 821 return; 822 } 823 824 value = args->value; 825 prom_printf("looking up value %ld\n", value); 826 symbol = db_search_symbol(value, 0, &offset); 827 if (symbol == DB_SYM_NULL) { 828 args->nreturns = 1; 829 args->offset = -1; 830 return; 831 } 832 args->offset = offset; 833 args->symbol = ADR2CELL(symbol); 834 835 } 836 #endif 837