Home | History | Annotate | Line # | Download | only in sparc
      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