1 /* $NetBSD: openfirm.c,v 1.24 2021/02/27 18:10:46 palle 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 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: openfirm.c,v 1.24 2021/02/27 18:10:46 palle Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <machine/lock.h> 40 #include <machine/psl.h> 41 #include <machine/promlib.h> 42 #include <lib/libkern/libkern.h> 43 44 #ifndef _KERNEL 45 #include <sys/stdarg.h> 46 #endif 47 48 #ifdef SUN4V 49 #ifdef __arch64__ 50 #define OFBOUNCE_MAXSIZE 1024 51 /* 52 * Sun4v OpenBoot is not always happy with 64-bit addresses - an example is the 53 * addr parameter in the OF_write() call which can be truncated to a 32-bit 54 * value. 55 * Avoid this behaviour by using a static buffer which is assumed to be mapped 56 * in on a 32-bit address. 57 * Use a mutex to protect access to the buffer from multiple threads. 58 * 59 */ 60 static __cpu_simple_lock_t ofcall_lock; 61 static char ofbounce[OFBOUNCE_MAXSIZE]; 62 #endif 63 #endif 64 65 void 66 OF_init(void) 67 { 68 #ifdef SUN4V 69 #ifdef __arch64__ 70 KASSERT(((uint64_t)&ofbounce & 0xffffffffUL)==(uint64_t)&ofbounce); 71 __cpu_simple_lock_init(&ofcall_lock); 72 #endif 73 #endif 74 } 75 76 int 77 OF_peer(int phandle) 78 { 79 struct { 80 cell_t name; 81 cell_t nargs; 82 cell_t nreturns; 83 cell_t phandle; 84 cell_t sibling; 85 } args; 86 87 args.name = ADR2CELL("peer"); 88 args.nargs = 1; 89 args.nreturns = 1; 90 args.phandle = HDL2CELL(phandle); 91 if (openfirmware(&args) == -1) 92 return 0; 93 return args.sibling; 94 } 95 96 int 97 OF_child(int phandle) 98 { 99 struct { 100 cell_t name; 101 cell_t nargs; 102 cell_t nreturns; 103 cell_t phandle; 104 cell_t child; 105 } args; 106 107 args.name = ADR2CELL("child"); 108 args.nargs = 1; 109 args.nreturns = 1; 110 args.phandle = HDL2CELL(phandle); 111 if (openfirmware(&args) == -1) 112 return 0; 113 return args.child; 114 } 115 116 int 117 OF_parent(int phandle) 118 { 119 struct { 120 cell_t name; 121 cell_t nargs; 122 cell_t nreturns; 123 cell_t phandle; 124 cell_t parent; 125 } args; 126 127 args.name = ADR2CELL("parent"); 128 args.nargs = 1; 129 args.nreturns = 1; 130 args.phandle = HDL2CELL(phandle); 131 if (openfirmware(&args) == -1) 132 return 0; 133 return args.parent; 134 } 135 136 int 137 OF_instance_to_package(int ihandle) 138 { 139 static struct { 140 cell_t name; 141 cell_t nargs; 142 cell_t nreturns; 143 cell_t ihandle; 144 cell_t phandle; 145 } args; 146 147 args.name = ADR2CELL("instance-to-package"); 148 args.nargs = 1; 149 args.nreturns = 1; 150 args.ihandle = HDL2CELL(ihandle); 151 if (openfirmware(&args) == -1) 152 return -1; 153 return args.phandle; 154 } 155 156 /* Should really return a `long' */ 157 int 158 OF_getproplen(int handle, const char *prop) 159 { 160 struct { 161 cell_t name; 162 cell_t nargs; 163 cell_t nreturns; 164 cell_t phandle; 165 cell_t prop; 166 cell_t size; 167 } args; 168 169 KASSERT(handle != 0); 170 args.name = ADR2CELL("getproplen"); 171 args.nargs = 2; 172 args.nreturns = 1; 173 args.phandle = HDL2CELL(handle); 174 args.prop = ADR2CELL(prop); 175 if (openfirmware(&args) == -1) 176 return -1; 177 return args.size; 178 } 179 180 int 181 OF_getprop(int handle, const char *prop, void *buf, int buflen) 182 { 183 struct { 184 cell_t name; 185 cell_t nargs; 186 cell_t nreturns; 187 cell_t phandle; 188 cell_t prop; 189 cell_t buf; 190 cell_t buflen; 191 cell_t size; 192 } args; 193 194 KASSERT(handle != 0); 195 if (buflen > NBPG) 196 return -1; 197 args.name = ADR2CELL("getprop"); 198 args.nargs = 4; 199 args.nreturns = 1; 200 args.phandle = HDL2CELL(handle); 201 args.prop = ADR2CELL(prop); 202 args.buf = ADR2CELL(buf); 203 args.buflen = buflen; 204 if (openfirmware(&args) == -1) 205 return -1; 206 return args.size; 207 } 208 209 int 210 OF_setprop(int handle, const char *prop, const void *buf, int buflen) 211 { 212 struct { 213 cell_t name; 214 cell_t nargs; 215 cell_t nreturns; 216 cell_t phandle; 217 cell_t prop; 218 cell_t buf; 219 cell_t buflen; 220 cell_t size; 221 } args; 222 223 if (buflen > NBPG) 224 return -1; 225 args.name = ADR2CELL("setprop"); 226 args.nargs = 4; 227 args.nreturns = 1; 228 args.phandle = HDL2CELL(handle); 229 args.prop = ADR2CELL(prop); 230 args.buf = ADR2CELL(buf); 231 args.buflen = buflen; 232 if (openfirmware(&args) == -1) 233 return -1; 234 return args.size; 235 } 236 237 int 238 OF_nextprop(int handle, const char *prop, void *buf) 239 { 240 struct { 241 cell_t name; 242 cell_t nargs; 243 cell_t nreturns; 244 cell_t phandle; 245 cell_t prev; 246 cell_t buf; 247 cell_t next; 248 } args; 249 250 args.name = ADR2CELL("nextprop"); 251 args.nargs = 3; 252 args.nreturns = 1; 253 args.phandle = HDL2CELL(handle); 254 args.prev = ADR2CELL(prop); 255 args.buf = ADR2CELL(buf); 256 if (openfirmware(&args) == -1) 257 return -1; 258 return args.next; 259 } 260 261 int 262 OF_finddevice(const char *name) 263 { 264 struct { 265 cell_t name; 266 cell_t nargs; 267 cell_t nreturns; 268 cell_t device; 269 cell_t phandle; 270 } args; 271 272 args.name = ADR2CELL("finddevice"); 273 args.nargs = 1; 274 args.nreturns = 1; 275 args.device = ADR2CELL(name); 276 if (openfirmware(&args) == -1) 277 return -1; 278 return args.phandle; 279 } 280 281 int 282 OF_instance_to_path(int ihandle, char *buf, int buflen) 283 { 284 struct { 285 cell_t name; 286 cell_t nargs; 287 cell_t nreturns; 288 cell_t ihandle; 289 cell_t buf; 290 cell_t buflen; 291 cell_t length; 292 } args; 293 294 if (buflen > NBPG) 295 return -1; 296 args.name = ADR2CELL("instance-to-path"); 297 args.nargs = 3; 298 args.nreturns = 1; 299 args.ihandle = HDL2CELL(ihandle); 300 args.buf = ADR2CELL(buf); 301 args.buflen = buflen; 302 if (openfirmware(&args) < 0) 303 return -1; 304 return args.length; 305 } 306 307 int 308 OF_package_to_path(int phandle, char *buf, int buflen) 309 { 310 struct { 311 cell_t name; 312 cell_t nargs; 313 cell_t nreturns; 314 cell_t phandle; 315 cell_t buf; 316 cell_t buflen; 317 cell_t length; 318 } args; 319 320 if (buflen > NBPG) 321 return -1; 322 args.name = ADR2CELL("package-to-path"); 323 args.nargs = 3; 324 args.nreturns = 1; 325 args.phandle = HDL2CELL(phandle); 326 args.buf = ADR2CELL(buf); 327 args.buflen = buflen; 328 if (openfirmware(&args) < 0) 329 return -1; 330 return args.length; 331 } 332 333 /* 334 * The following two functions may need to be re-worked to be 64-bit clean. 335 */ 336 int 337 OF_call_method(const char *method, int ihandle, int nargs, int nreturns, ...) 338 { 339 va_list ap; 340 struct { 341 cell_t name; 342 cell_t nargs; 343 cell_t nreturns; 344 cell_t method; 345 cell_t ihandle; 346 cell_t args_n_results[12]; 347 } args; 348 long *ip, n; 349 350 if (nargs > 6) 351 return -1; 352 args.name = ADR2CELL("call-method"); 353 args.nargs = nargs + 2; 354 args.nreturns = nreturns + 1; 355 args.method = ADR2CELL(method); 356 args.ihandle = HDL2CELL(ihandle); 357 va_start(ap, nreturns); 358 for (ip = (long*)(args.args_n_results + (n = nargs)); --n >= 0;) 359 *--ip = va_arg(ap, unsigned long); 360 if (openfirmware(&args) == -1) { 361 va_end(ap); 362 return -1; 363 } 364 if (args.args_n_results[nargs]) { 365 va_end(ap); 366 return args.args_n_results[nargs]; 367 } 368 for (ip = (long*)(args.args_n_results + nargs + (n = args.nreturns)); --n > 0;) 369 *va_arg(ap, unsigned long *) = *--ip; 370 va_end(ap); 371 return 0; 372 } 373 374 int 375 OF_call_method_1(const char *method, int ihandle, int nargs, ...) 376 { 377 va_list ap; 378 struct { 379 cell_t name; 380 cell_t nargs; 381 cell_t nreturns; 382 cell_t method; 383 cell_t ihandle; 384 cell_t args_n_results[16]; 385 } args; 386 long *ip, n; 387 388 if (nargs > 6) 389 return -1; 390 args.name = ADR2CELL("call-method"); 391 args.nargs = nargs + 2; 392 args.nreturns = 1; 393 args.method = ADR2CELL(method); 394 args.ihandle = HDL2CELL(ihandle); 395 va_start(ap, nargs); 396 for (ip = (long*)(args.args_n_results + (n = nargs)); --n >= 0;) 397 *--ip = va_arg(ap, unsigned long); 398 va_end(ap); 399 if (openfirmware(&args) == -1) 400 return -1; 401 if (args.args_n_results[nargs]) 402 return -1; 403 return args.args_n_results[nargs + 1]; 404 } 405 406 int 407 OF_open(const char *dname) 408 { 409 struct { 410 cell_t name; 411 cell_t nargs; 412 cell_t nreturns; 413 cell_t dname; 414 cell_t handle; 415 } args; 416 int l; 417 418 if ((l = strlen(dname)) >= NBPG) 419 return -1; 420 args.name = ADR2CELL("open"); 421 args.nargs = 1; 422 args.nreturns = 1; 423 args.dname = ADR2CELL(dname); 424 if (openfirmware(&args) == -1) 425 return -1; 426 return args.handle; 427 } 428 429 void 430 OF_close(int handle) 431 { 432 struct { 433 cell_t name; 434 cell_t nargs; 435 cell_t nreturns; 436 cell_t handle; 437 } args; 438 439 args.name = ADR2CELL("close"); 440 args.nargs = 1; 441 args.nreturns = 0; 442 args.handle = HDL2CELL(handle); 443 openfirmware(&args); 444 } 445 446 int 447 OF_test(const char* service) 448 { 449 struct { 450 cell_t name; 451 cell_t nargs; 452 cell_t nreturns; 453 cell_t service; 454 cell_t status; 455 } args; 456 457 args.name = ADR2CELL("test"); 458 args.nargs = 1; 459 args.nreturns = 1; 460 args.service = ADR2CELL(service); 461 if (openfirmware(&args) == -1) 462 return -1; 463 return args.status; 464 } 465 466 int 467 OF_test_method(int service, const char* method) 468 { 469 struct { 470 cell_t name; 471 cell_t nargs; 472 cell_t nreturns; 473 cell_t service; 474 cell_t method; 475 cell_t status; 476 } args; 477 478 args.name = ADR2CELL("test-method"); 479 args.nargs = 2; 480 args.nreturns = 1; 481 args.service = HDL2CELL(service); 482 args.method = ADR2CELL(method); 483 if (openfirmware(&args) == -1) 484 return -1; 485 return args.status; 486 } 487 488 489 /* 490 * This assumes that character devices don't read in multiples of NBPG. 491 */ 492 int 493 OF_read(int handle, void *addr, int len) 494 { 495 struct { 496 cell_t name; 497 cell_t nargs; 498 cell_t nreturns; 499 cell_t ihandle; 500 cell_t addr; 501 cell_t len; 502 cell_t actual; 503 } args; 504 int l, act = 0; 505 506 #ifdef SUN4V 507 #if __arch64__ 508 void *oaddr = addr; 509 __cpu_simple_lock(&ofcall_lock); 510 if (len > OFBOUNCE_MAXSIZE) 511 panic("OF_read(len = %d) exceedes bounce buffer\n", len); 512 addr = ofbounce; 513 #endif 514 #endif 515 args.name = ADR2CELL("read"); 516 args.nargs = 3; 517 args.nreturns = 1; 518 args.ihandle = HDL2CELL(handle); 519 args.addr = ADR2CELL(addr); 520 for (; len > 0; len -= l) { 521 l = MIN(NBPG, len); 522 args.len = l; 523 if (openfirmware(&args) == -1) { 524 act = -1; 525 goto OF_read_exit; 526 } 527 if (args.actual > 0) { 528 act += args.actual; 529 } 530 if (args.actual < l) { 531 if (act) 532 goto OF_read_exit; 533 else { 534 act = args.actual; 535 goto OF_read_exit; 536 } 537 } 538 } 539 OF_read_exit: 540 #ifdef SUN4V 541 #if __arch64__ 542 if (act > 0) { 543 memcpy(oaddr, addr, act); 544 } 545 __cpu_simple_unlock(&ofcall_lock); 546 #endif 547 #endif 548 return act; 549 } 550 551 int 552 OF_write(int handle, const void *addr, int len) 553 { 554 struct { 555 cell_t name; 556 cell_t nargs; 557 cell_t nreturns; 558 cell_t ihandle; 559 cell_t addr; 560 cell_t len; 561 cell_t actual; 562 } args; 563 int l, act = 0; 564 565 if (len > 1024) { 566 panic("OF_write(len = %d)\n", len); 567 } 568 #ifdef SUN4V 569 #if __arch64__ 570 __cpu_simple_lock(&ofcall_lock); 571 if (len > OFBOUNCE_MAXSIZE) 572 panic("OF_write(len = %d) exceedes bounce buffer\n", len); 573 memcpy(ofbounce, addr, len); 574 addr = ofbounce; 575 #endif 576 #endif 577 args.name = ADR2CELL("write"); 578 args.nargs = 3; 579 args.nreturns = 1; 580 args.ihandle = HDL2CELL(handle); 581 args.addr = ADR2CELL(addr); 582 for (; len > 0; len -= l) { 583 l = MIN(NBPG, len); 584 args.len = l; 585 if (openfirmware(&args) == -1) 586 return -1; 587 l = args.actual; 588 act += l; 589 } 590 #ifdef SUN4V 591 #if __arch64__ 592 __cpu_simple_unlock(&ofcall_lock); 593 #endif 594 #endif 595 return act; 596 } 597 598 599 int 600 OF_seek(int handle, u_quad_t pos) 601 { 602 struct { 603 cell_t name; 604 cell_t nargs; 605 cell_t nreturns; 606 cell_t handle; 607 cell_t poshi; 608 cell_t poslo; 609 cell_t status; 610 } args; 611 612 args.name = ADR2CELL("seek"); 613 args.nargs = 3; 614 args.nreturns = 1; 615 args.handle = HDL2CELL(handle); 616 args.poshi = HDQ2CELL_HI(pos); 617 args.poslo = HDQ2CELL_LO(pos); 618 if (openfirmware(&args) == -1) 619 return -1; 620 return args.status; 621 } 622 623 void 624 OF_boot(const char *bspec) 625 { 626 struct { 627 cell_t name; 628 cell_t nargs; 629 cell_t nreturns; 630 cell_t bootspec; 631 } args; 632 int l; 633 634 if ((l = strlen(bspec)) >= NBPG) 635 panic("OF_boot"); 636 args.name = ADR2CELL("boot"); 637 args.nargs = 1; 638 args.nreturns = 0; 639 args.bootspec = ADR2CELL(bspec); 640 openfirmware(&args); 641 panic("OF_boot failed"); 642 } 643 644 void 645 OF_enter(void) 646 { 647 struct { 648 cell_t name; 649 cell_t nargs; 650 cell_t nreturns; 651 } args; 652 653 args.name = ADR2CELL("enter"); 654 args.nargs = 0; 655 args.nreturns = 0; 656 openfirmware(&args); 657 } 658 659 void 660 OF_exit(void) 661 { 662 struct { 663 cell_t name; 664 cell_t nargs; 665 cell_t nreturns; 666 } args; 667 668 args.name = ADR2CELL("exit"); 669 args.nargs = 0; 670 args.nreturns = 0; 671 openfirmware(&args); 672 panic("OF_exit failed"); 673 } 674 675 void 676 OF_poweroff(void) 677 { 678 struct { 679 cell_t name; 680 cell_t nargs; 681 cell_t nreturns; 682 } args; 683 684 args.name = ADR2CELL("SUNW,power-off"); 685 args.nargs = 0; 686 args.nreturns = 0; 687 openfirmware(&args); 688 panic("OF_poweroff failed"); 689 } 690 691 void 692 (*OF_set_callback(void (*newfunc)(void *)))(void *) 693 { 694 struct { 695 cell_t name; 696 cell_t nargs; 697 cell_t nreturns; 698 cell_t newfunc; 699 cell_t oldfunc; 700 } args; 701 702 args.name = ADR2CELL("set-callback"); 703 args.nargs = 1; 704 args.nreturns = 1; 705 args.newfunc = ADR2CELL(newfunc); 706 if (openfirmware(&args) == -1) 707 return 0; 708 return (void*)(long)args.oldfunc; 709 } 710 711 void 712 OF_set_symbol_lookup(void (*s2v)(void *), void (*v2s)(void *)) 713 { 714 struct { 715 cell_t name; 716 cell_t nargs; 717 cell_t nreturns; 718 cell_t sym2val; 719 cell_t val2sym; 720 } args; 721 722 args.name = ADR2CELL("set-symbol-lookup"); 723 args.nargs = 2; 724 args.nreturns = 0; 725 args.sym2val = ADR2CELL(s2v); 726 args.val2sym = ADR2CELL(v2s); 727 728 (void)openfirmware(&args); 729 } 730 731 int 732 OF_interpret(const char *cmd, int nargs, int nreturns, ...) 733 { 734 va_list ap; 735 struct { 736 cell_t name; 737 cell_t nargs; 738 cell_t nreturns; 739 cell_t slot[16]; 740 } args; 741 cell_t status; 742 int i = 0; 743 744 args.name = ADR2CELL("interpret"); 745 args.nargs = ++nargs; 746 args.nreturns = ++nreturns; 747 args.slot[i++] = ADR2CELL(cmd); 748 va_start(ap, nreturns); 749 while (i < nargs) { 750 args.slot[i++] = va_arg(ap, cell_t); 751 } 752 if (openfirmware(&args) == -1) { 753 va_end(ap); 754 return (-1); 755 } 756 status = args.slot[i++]; 757 while (i < nargs+nreturns) { 758 *va_arg(ap, cell_t *) = args.slot[i++]; 759 } 760 va_end(ap); 761 return (status); 762 } 763 764 int 765 OF_milliseconds(void) 766 { 767 struct { 768 cell_t name; 769 cell_t nargs; 770 cell_t nreturns; 771 cell_t ticks; 772 } args; 773 774 args.name = ADR2CELL("milliseconds"); 775 args.nargs = 0; 776 args.nreturns = 1; 777 if (openfirmware(&args) == -1) 778 return -1; 779 return (args.ticks); 780 } 781 782 /* Claim an area of memory. */ 783 void * 784 OF_claim(void *virt, u_int size, u_int align) 785 { 786 static struct { 787 cell_t name; 788 cell_t nargs; 789 cell_t nreturns; 790 cell_t virt; 791 cell_t size; 792 cell_t align; 793 cell_t baseaddr; 794 } args; 795 796 args.name = ADR2CELL("claim"); 797 args.nargs = 3; 798 args.nreturns = 1; 799 args.virt = ADR2CELL(virt); 800 args.size = size; 801 args.align = align; 802 if (openfirmware(&args) == -1) 803 return (void *)-1; 804 return (void *)(long)args.baseaddr; 805 } 806 807 #if defined(_KERNEL_OPT) 808 #include "opt_ddb.h" 809 #endif 810 811 #ifdef DDB 812 #include <machine/db_machdep.h> 813 #include <ddb/db_sym.h> 814 #include <ddb/db_extern.h> 815 816 int obp_symbol_debug = 0; 817 818 void 819 OF_sym2val(void *cells) 820 { 821 struct args { 822 cell_t service; 823 cell_t nargs; 824 cell_t nreturns; 825 cell_t symbol; 826 cell_t result; 827 cell_t value; 828 } *args = (struct args*)cells; 829 char *symbol; 830 db_expr_t value; 831 832 /* Set data segment pointer */ 833 __asm volatile("clr %%g4" : :); 834 835 /* No args? Nothing to do. */ 836 if (args->nargs == 0 || args->nreturns == 0) 837 return; 838 839 /* Do we have a place for the value? */ 840 if (args->nreturns != 2) { 841 args->nreturns = 1; 842 args->result = -1; 843 return; 844 } 845 846 symbol = (char *)(u_long)args->symbol; 847 if (obp_symbol_debug) 848 prom_printf("looking up symbol %s\n", symbol); 849 args->result = (db_value_of_name(symbol, &value) == true) ? 0 : -1; 850 if (obp_symbol_debug) 851 prom_printf("%s is %lx\n", symbol, value); 852 args->value = ADR2CELL(value); 853 } 854 855 void 856 OF_val2sym(void *cells) 857 { 858 struct args { 859 cell_t service; 860 cell_t nargs; 861 cell_t nreturns; 862 cell_t value; 863 cell_t offset; 864 cell_t symbol; 865 } *args = (struct args*)cells; 866 db_sym_t symbol; 867 db_expr_t value; 868 db_expr_t offset; 869 870 /* Set data segment pointer */ 871 __asm volatile("clr %%g4" : :); 872 873 if (obp_symbol_debug) 874 prom_printf("OF_val2sym: nargs %lx nreturns %lx\n", 875 args->nargs, args->nreturns); 876 877 /* No args? Nothing to do. */ 878 if (args->nargs == 0 || args->nreturns == 0) 879 return; 880 881 /* Do we have a place for the value? */ 882 if (args->nreturns != 2) { 883 args->nreturns = 1; 884 args->offset = -1; 885 return; 886 } 887 888 value = args->value; 889 if (obp_symbol_debug) 890 prom_printf("looking up value %ld\n", value); 891 symbol = db_search_symbol(value, 0, &offset); 892 if (symbol == DB_SYM_NULL) { 893 if (obp_symbol_debug) 894 prom_printf("OF_val2sym: not found\n"); 895 args->nreturns = 1; 896 args->offset = -1; 897 return; 898 } 899 args->offset = offset; 900 args->symbol = ADR2CELL(symbol); 901 } 902 #endif /* DDB */ 903