Home | History | Annotate | Line # | Download | only in powerpc
      1 /*	$NetBSD: openfirm.c,v 1.33 2021/02/13 01:48:33 thorpej 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.33 2021/02/13 01:48:33 thorpej Exp $");
     36 
     37 #ifdef _KERNEL_OPT
     38 #include "opt_multiprocessor.h"
     39 #endif
     40 
     41 #include <sys/param.h>
     42 #include <sys/systm.h>
     43 
     44 #include <uvm/uvm_extern.h>
     45 
     46 #include <machine/psl.h>
     47 #include <machine/autoconf.h>
     48 
     49 #include <dev/ofw/openfirm.h>
     50 
     51 char *OF_buf;
     52 
     53 static void ofbcopy(const void *, void *, size_t);
     54 
     55 #ifdef MULTIPROCESSOR
     56 void OF_start_cpu(int, u_int, int);
     57 
     58 
     59 static __cpu_simple_lock_t ofw_mutex = __SIMPLELOCK_UNLOCKED;
     60 #endif /* MULTIPROCESSOR */
     61 
     62 static inline register_t
     63 ofw_lock(void)
     64 {
     65 	const register_t s = mfmsr();
     66 
     67 	mtmsr(s & ~(PSL_EE|PSL_RI));	/* disable interrupts */
     68 
     69 #ifdef MULTIPROCESSOR
     70 	__cpu_simple_lock(&ofw_mutex);
     71 #endif /* MULTIPROCESSOR */
     72 
     73 	return s;
     74 }
     75 
     76 static inline void
     77 ofw_unlock(register_t s)
     78 {
     79 #ifdef MULTIPROCESSOR
     80 	__cpu_simple_unlock(&ofw_mutex);
     81 #endif /* MULTIPROCESSOR */
     82 	mtmsr(s);
     83 }
     84 
     85 int
     86 OF_peer(int phandle)
     87 {
     88 	static struct {
     89 		const char *name;
     90 		int nargs;
     91 		int nreturns;
     92 		int phandle;
     93 		int sibling;
     94 	} args = {
     95 		"peer",
     96 		1,
     97 		1,
     98 	};
     99 
    100 	const register_t s = ofw_lock();
    101 	int rv;
    102 
    103 	args.phandle = phandle;
    104 	if (openfirmware(&args) == -1)
    105 		rv = 0;
    106 	else
    107 		rv = args.sibling;
    108 
    109 	ofw_unlock(s);
    110 	return rv;
    111 }
    112 
    113 int
    114 OF_child(int phandle)
    115 {
    116 	static struct {
    117 		const char *name;
    118 		int nargs;
    119 		int nreturns;
    120 		int phandle;
    121 		int child;
    122 	} args = {
    123 		"child",
    124 		1,
    125 		1,
    126 	};
    127 
    128 	const register_t s = ofw_lock();
    129 	int rv;
    130 
    131 	args.phandle = phandle;
    132 	if (openfirmware(&args) == -1)
    133 		rv = 0;
    134 	else
    135 		rv = args.child;
    136 
    137 	ofw_unlock(s);
    138 	return rv;
    139 }
    140 
    141 int
    142 OF_parent(int phandle)
    143 {
    144 	static struct {
    145 		const char *name;
    146 		int nargs;
    147 		int nreturns;
    148 		int phandle;
    149 		int parent;
    150 	} args = {
    151 		"parent",
    152 		1,
    153 		1,
    154 	};
    155 
    156 	const register_t s = ofw_lock();
    157 	int rv;
    158 
    159 	args.phandle = phandle;
    160 	if (openfirmware(&args) == -1)
    161 		rv = 0;
    162 	else
    163 		rv = args.parent;
    164 
    165 	ofw_unlock(s);
    166 	return rv;
    167 }
    168 
    169 int
    170 OF_instance_to_package(int ihandle)
    171 {
    172 	static struct {
    173 		const char *name;
    174 		int nargs;
    175 		int nreturns;
    176 		int ihandle;
    177 		int phandle;
    178 	} args = {
    179 		"instance-to-package",
    180 		1,
    181 		1,
    182 	};
    183 
    184 	const register_t s = ofw_lock();
    185 	int rv;
    186 
    187 	args.ihandle = ihandle;
    188 	if (openfirmware(&args) == -1)
    189 		rv = -1;
    190 	else
    191 		rv = args.phandle;
    192 
    193 	ofw_unlock(s);
    194 	return rv;
    195 }
    196 
    197 int
    198 OF_getproplen(int handle, const char *prop)
    199 {
    200 	static struct {
    201 		const char *name;
    202 		int nargs;
    203 		int nreturns;
    204 		int phandle;
    205 		const char *prop;
    206 		int proplen;
    207 	} args = {
    208 		"getproplen",
    209 		2,
    210 		1,
    211 	};
    212 
    213 	const register_t s = ofw_lock();
    214 	int rv;
    215 
    216 	strncpy(OF_buf, prop, 32);
    217 	args.phandle = handle;
    218 	args.prop = OF_buf;
    219 	if (openfirmware(&args) == -1)
    220 		rv = -1;
    221 	else
    222 		rv = args.proplen;
    223 
    224 	ofw_unlock(s);
    225 	return rv;
    226 }
    227 
    228 int
    229 OF_getprop(int handle, const char *prop, void *buf, int buflen)
    230 {
    231 	static struct {
    232 		const char *name;
    233 		int nargs;
    234 		int nreturns;
    235 		int phandle;
    236 		const char *prop;
    237 		void *buf;
    238 		int buflen;
    239 		int size;
    240 	} args = {
    241 		"getprop",
    242 		4,
    243 		1,
    244 	};
    245 
    246 	if (buflen > PAGE_SIZE)
    247 		return -1;
    248 
    249 	const register_t s = ofw_lock();
    250 	int rv;
    251 
    252 	strncpy(OF_buf, prop, 32);
    253 	args.phandle = handle;
    254 	args.prop = OF_buf;
    255 	args.buf = &OF_buf[33];
    256 	args.buflen = buflen;
    257 	if (openfirmware(&args) == -1)
    258 		rv = -1;
    259 	else {
    260 		if (args.size > buflen)
    261 			args.size = buflen;
    262 		if (args.size > 0)
    263 			ofbcopy(&OF_buf[33], buf, args.size);
    264 		rv = args.size;
    265 	}
    266 
    267 	ofw_unlock(s);
    268 	return rv;
    269 }
    270 
    271 int
    272 OF_setprop(int handle, const char *prop, const void *buf, int buflen)
    273 {
    274 	struct {
    275 		const char *name;
    276 		int nargs;
    277 		int nreturns;
    278 		int phandle;
    279 		const char *prop;
    280 		const void *buf;
    281 		int buflen;
    282 		int size;
    283 	} args = {
    284 		"setprop",
    285 		4,
    286 		1
    287 	};
    288 
    289 	if (buflen > PAGE_SIZE)
    290 		return -1;
    291 
    292 	const register_t s = ofw_lock();
    293 	int rv;
    294 
    295 	ofbcopy(buf, OF_buf, buflen);
    296 	args.phandle = handle;
    297 	args.prop = prop;
    298 	args.buf = OF_buf;
    299 	args.buflen = buflen;
    300 	if (openfirmware(&args) == -1)
    301 		rv = -1;
    302 	else
    303 		rv = args.size;
    304 
    305 	ofw_unlock(s);
    306 	return rv;
    307 }
    308 
    309 int
    310 OF_nextprop(int handle, const char *prop, void *nextprop)
    311 {
    312 	static struct {
    313 		const char *name;
    314 		int nargs;
    315 		int nreturns;
    316 		int phandle;
    317 		const char *prop;
    318 		char *buf;
    319 		int flag;
    320 	} args = {
    321 		"nextprop",
    322 		3,
    323 		1,
    324 	};
    325 
    326 	const register_t s = ofw_lock();
    327 	int rv;
    328 
    329 	strncpy(OF_buf, prop, 32);
    330 	args.phandle = handle;
    331 	args.prop = OF_buf;
    332 	args.buf = &OF_buf[33];
    333 	if (openfirmware(&args) == -1)
    334 		rv = -1;
    335 	else {
    336 		strncpy(nextprop, &OF_buf[33], 32);
    337 		rv = args.flag;
    338 	}
    339 
    340 	ofw_unlock(s);
    341 	return rv;
    342 }
    343 
    344 int
    345 OF_finddevice(const char *name)
    346 {
    347 	static struct {
    348 		const char *name;
    349 		int nargs;
    350 		int nreturns;
    351 		const char *device;
    352 		int phandle;
    353 	} args = {
    354 		"finddevice",
    355 		1,
    356 		1,
    357 	};
    358 
    359 	const register_t s = ofw_lock();
    360 	int rv;
    361 
    362 	strncpy(OF_buf, name, NBPG);
    363 	args.device = OF_buf;
    364 	if (openfirmware(&args) == -1)
    365 		rv = -1;
    366 	else
    367 		rv = args.phandle;
    368 
    369 	ofw_unlock(s);
    370 	return rv;
    371 }
    372 
    373 int
    374 OF_instance_to_path(int ihandle, char *buf, int buflen)
    375 {
    376 	static struct {
    377 		const char *name;
    378 		int nargs;
    379 		int nreturns;
    380 		int ihandle;
    381 		char *buf;
    382 		int buflen;
    383 		int length;
    384 	} args = {
    385 		"instance-to-path",
    386 		3,
    387 		1,
    388 	};
    389 
    390 	if (buflen > PAGE_SIZE)
    391 		return -1;
    392 
    393 	const register_t s = ofw_lock();
    394 	int rv;
    395 
    396 	args.ihandle = ihandle;
    397 	args.buf = OF_buf;
    398 	args.buflen = buflen;
    399 	if (openfirmware(&args) < 0)
    400 		rv = -1;
    401 	else {
    402 		if (args.length > buflen)
    403 			args.length = buflen;
    404 		if (args.length > 0)
    405 			ofbcopy(OF_buf, buf, args.length);
    406 		rv = args.length;
    407 	}
    408 
    409 	ofw_unlock(s);
    410 	return rv;
    411 }
    412 
    413 int
    414 OF_package_to_path(int phandle, char *buf, int buflen)
    415 {
    416 	static struct {
    417 		const char *name;
    418 		int nargs;
    419 		int nreturns;
    420 		int phandle;
    421 		char *buf;
    422 		int buflen;
    423 		int length;
    424 	} args = {
    425 		"package-to-path",
    426 		3,
    427 		1,
    428 	};
    429 
    430 	if (buflen > PAGE_SIZE)
    431 		return -1;
    432 
    433 	const register_t s = ofw_lock();
    434 	int rv;
    435 
    436 	args.phandle = phandle;
    437 	args.buf = OF_buf;
    438 	args.buflen = buflen;
    439 	if (openfirmware(&args) < 0)
    440 		rv = -1;
    441 	else {
    442 		if (args.length > buflen)
    443 			args.length = buflen;
    444 		if (args.length > 0)
    445 			ofbcopy(OF_buf, buf, args.length);
    446 		rv = args.length;
    447 	}
    448 
    449 	ofw_unlock(s);
    450 	return rv;
    451 }
    452 
    453 int
    454 OF_call_method(const char *method, int ihandle, int nargs, int nreturns, ...)
    455 {
    456 	static struct {
    457 		const char *name;
    458 		int nargs;
    459 		int nreturns;
    460 		const char *method;
    461 		int ihandle;
    462 		int args_n_results[12];
    463 	} args = {
    464 		"call-method",
    465 		2,
    466 		1,
    467 	};
    468 
    469 	if (nargs > 6)
    470 		return -1;
    471 
    472 	va_list ap;
    473 	int *ip, n;
    474 	int rv;
    475 
    476 	const register_t s = ofw_lock();
    477 
    478 	args.nargs = nargs + 2;
    479 	args.nreturns = nreturns + 1;
    480 	args.method = method;
    481 	args.ihandle = ihandle;
    482 
    483 	va_start(ap, nreturns);
    484 
    485 	for (ip = args.args_n_results + (n = nargs); --n >= 0;) {
    486 		*--ip = va_arg(ap, int);
    487 	}
    488 
    489 	if (openfirmware(&args) == -1) {
    490 		rv = -1;
    491 	} else if (args.args_n_results[nargs]) {
    492 		rv = args.args_n_results[nargs];
    493 	} else {
    494 		for (ip = args.args_n_results + nargs + (n = args.nreturns);
    495 		     --n > 0;) {
    496 			*va_arg(ap, int *) = *--ip;
    497 		}
    498 		rv = 0;
    499 	}
    500 
    501 	va_end(ap);
    502 
    503 	ofw_unlock(s);
    504 	return rv;
    505 }
    506 
    507 int
    508 OF_call_method_1(const char *method, int ihandle, int nargs, ...)
    509 {
    510 	static struct {
    511 		const char *name;
    512 		int nargs;
    513 		int nreturns;
    514 		const char *method;
    515 		int ihandle;
    516 		int args_n_results[8];
    517 	} args = {
    518 		"call-method",
    519 		2,
    520 		2,
    521 	};
    522 
    523 	if (nargs > 6)
    524 		return -1;
    525 
    526 	va_list ap;
    527 	int *ip, n;
    528 	int rv;
    529 
    530 	const register_t s = ofw_lock();
    531 
    532 	args.nargs = nargs + 2;
    533 	args.method = method;
    534 	args.ihandle = ihandle;
    535 
    536 	va_start(ap, nargs);
    537 	for (ip = args.args_n_results + (n = nargs); --n >= 0;) {
    538 		*--ip = va_arg(ap, int);
    539 	}
    540 	va_end(ap);
    541 
    542 	if (openfirmware(&args) == -1)
    543 		rv = -1;
    544 	else if (args.args_n_results[nargs])
    545 		rv = -1;
    546 	else
    547 		rv = args.args_n_results[nargs + 1];
    548 
    549 	ofw_unlock(s);
    550 	return rv;
    551 }
    552 
    553 int
    554 OF_open(const char *dname)
    555 {
    556 	static struct {
    557 		const char *name;
    558 		int nargs;
    559 		int nreturns;
    560 		const char *dname;
    561 		int handle;
    562 	} args = {
    563 		"open",
    564 		1,
    565 		1,
    566 	};
    567 	int l;
    568 
    569 	if ((l = strlen(dname)) >= PAGE_SIZE)
    570 		return -1;
    571 
    572 	const register_t s = ofw_lock();
    573 	int rv;
    574 
    575 	ofbcopy(dname, OF_buf, l + 1);
    576 	args.dname = OF_buf;
    577 	if (openfirmware(&args) == -1)
    578 		rv = -1;
    579 	else
    580 		rv = args.handle;
    581 
    582 	ofw_unlock(s);
    583 	return rv;
    584 }
    585 
    586 void
    587 OF_close(int handle)
    588 {
    589 	static struct {
    590 		const char *name;
    591 		int nargs;
    592 		int nreturns;
    593 		int handle;
    594 	} args = {
    595 		"close",
    596 		1,
    597 		0,
    598 	};
    599 
    600 	const register_t s = ofw_lock();
    601 
    602 	args.handle = handle;
    603 	openfirmware(&args);
    604 
    605 	ofw_unlock(s);
    606 }
    607 
    608 /*
    609  * This assumes that character devices don't read in multiples of PAGE_SIZE.
    610  */
    611 int
    612 OF_read(int handle, void *addr, int len)
    613 {
    614 	static struct {
    615 		const char *name;
    616 		int nargs;
    617 		int nreturns;
    618 		int ihandle;
    619 		void *addr;
    620 		int len;
    621 		int actual;
    622 	} args = {
    623 		"read",
    624 		3,
    625 		1,
    626 	};
    627 	int l, act = 0;
    628 	char *p = addr;
    629 
    630 	const register_t s = ofw_lock();
    631 
    632 	args.ihandle = handle;
    633 	args.addr = OF_buf;
    634 	for (; len > 0; len -= l, p += l) {
    635 		l = uimin(PAGE_SIZE, len);
    636 		args.len = l;
    637 		if (openfirmware(&args) == -1) {
    638 			act = -1;
    639 			goto out;
    640 		}
    641 		if (args.actual > 0) {
    642 			ofbcopy(OF_buf, p, args.actual);
    643 			act += args.actual;
    644 		}
    645 		if (args.actual < l) {
    646 			if (act == 0) {
    647 				act = args.actual;
    648 			}
    649 			goto out;
    650 		}
    651 	}
    652 
    653  out:
    654 	ofw_unlock(s);
    655 	return act;
    656 }
    657 
    658 int
    659 OF_write(int handle, const void *addr, int len)
    660 {
    661 	static struct {
    662 		const char *name;
    663 		int nargs;
    664 		int nreturns;
    665 		int ihandle;
    666 		void *addr;
    667 		int len;
    668 		int actual;
    669 	} args = {
    670 		"write",
    671 		3,
    672 		1,
    673 	};
    674 	int l, act = 0;
    675 	const char *p = addr;
    676 
    677 	const register_t s = ofw_lock();
    678 
    679 	args.ihandle = handle;
    680 	args.addr = OF_buf;
    681 	for (; len > 0; len -= l, p += l) {
    682 		l = uimin(PAGE_SIZE, len);
    683 		ofbcopy(p, OF_buf, l);
    684 		args.len = l;
    685 		args.actual = l;	/* work around a PIBS bug */
    686 		if (openfirmware(&args) == -1) {
    687 			act = -1;
    688 			goto out;
    689 		}
    690 		l = args.actual;
    691 		act += l;
    692 	}
    693 
    694  out:
    695 	ofw_unlock(s);
    696 	return act;
    697 }
    698 
    699 int
    700 OF_seek(int handle, u_quad_t pos)
    701 {
    702 	static struct {
    703 		const char *name;
    704 		int nargs;
    705 		int nreturns;
    706 		int handle;
    707 		int poshi;
    708 		int poslo;
    709 		int status;
    710 	} args = {
    711 		"seek",
    712 		3,
    713 		1,
    714 	};
    715 
    716 	const register_t s = ofw_lock();
    717 	int rv;
    718 
    719 	args.handle = handle;
    720 	args.poshi = (int)(pos >> 32);
    721 	args.poslo = (int)pos;
    722 	if (openfirmware(&args) == -1)
    723 		rv = -1;
    724 	else
    725 		rv = args.status;
    726 
    727 	ofw_unlock(s);
    728 	return rv;
    729 }
    730 
    731 #ifdef MULTIPROCESSOR
    732 void
    733 OF_start_cpu(int phandle, u_int pc, int arg)
    734 {
    735 	static struct {
    736 		const char *name;
    737 		int nargs;
    738 		int nreturns;
    739 		int phandle;
    740 		u_int pc;
    741 		int arg;
    742 	} args = {
    743 		"start-cpu",
    744 		3,
    745 		0,
    746 	};
    747 
    748 	const register_t s = ofw_lock();
    749 	bool failed = false;
    750 
    751 	args.phandle = phandle;
    752 	args.pc = pc;
    753 	args.arg = arg;
    754 	if (openfirmware(&args) == -1)
    755 		failed = true;
    756 
    757 	ofw_unlock(s);
    758 	if (failed) {
    759 		panic("WTF?");
    760 	}
    761 }
    762 #endif
    763 
    764 void
    765 OF_boot(const char *bstr)
    766 {
    767 	static struct {
    768 		const char *name;
    769 		int nargs;
    770 		int nreturns;
    771 		char *bootspec;
    772 	} args = {
    773 		"boot",
    774 		1,
    775 		0,
    776 	};
    777 	int l;
    778 
    779 	if ((l = strlen(bstr)) >= PAGE_SIZE)
    780 		panic("OF_boot");
    781 
    782 	const register_t s = ofw_lock();
    783 
    784 	ofbcopy(bstr, OF_buf, l + 1);
    785 	args.bootspec = OF_buf;
    786 	openfirmware(&args);
    787 
    788 	ofw_unlock(s);
    789 	panic("OF_boot didn't");
    790 }
    791 
    792 void
    793 OF_enter(void)
    794 {
    795 	static struct {
    796 		const char *name;
    797 		int nargs;
    798 		int nreturns;
    799 	} args = {
    800 		"enter",
    801 		0,
    802 		0,
    803 	};
    804 
    805 	const register_t s = ofw_lock();
    806 
    807 	openfirmware(&args);
    808 
    809 	ofw_unlock(s);
    810 }
    811 
    812 void
    813 OF_exit(void)
    814 {
    815 	static struct {
    816 		const char *name;
    817 		int nargs;
    818 		int nreturns;
    819 	} args = {
    820 		"exit",
    821 		0,
    822 		0,
    823 	};
    824 
    825 	const register_t s = ofw_lock();
    826 
    827 	openfirmware(&args);
    828 
    829 	ofw_unlock(s);
    830 	while (1);			/* just in case */
    831 }
    832 
    833 void
    834 (*OF_set_callback (void (*newfunc)(void *))) (void *)
    835 {
    836 	static struct {
    837 		const char *name;
    838 		int nargs;
    839 		int nreturns;
    840 		void (*newfunc)(void *);
    841 		void (*oldfunc)(void *);
    842 	} args = {
    843 		"set-callback",
    844 		1,
    845 		1,
    846 	};
    847 
    848 	const register_t s = ofw_lock();
    849 	void (*rv)(void *);
    850 
    851 	args.newfunc = newfunc;
    852 	if (openfirmware(&args) == -1)
    853 		rv = NULL;
    854 	else
    855 		rv = args.oldfunc;
    856 
    857 	ofw_unlock(s);
    858 	return rv;
    859 }
    860 
    861 int
    862 OF_interpret(const char *cmd, int nargs, int nreturns, ...)
    863 {
    864 	static struct {
    865 		const char *name;
    866 		uint32_t nargs;
    867 		uint32_t nreturns;
    868 		uint32_t slots[16];
    869 	} args = {
    870 		"interpret",
    871 		1,
    872 		2,
    873 	};
    874 
    875 	va_list ap;
    876 	int i, len;
    877 	int rv;
    878 
    879 	if (nreturns > 8)
    880 		return -1;
    881 	if ((len = strlen(cmd)) >= PAGE_SIZE)
    882 		return -1;
    883 
    884 	const register_t s = ofw_lock();
    885 
    886 	ofbcopy(cmd, OF_buf, len + 1);
    887 	i = 0;
    888 	args.slots[i] = (uintptr_t)OF_buf;
    889 	args.nargs = nargs + 1;
    890 	args.nreturns = nreturns + 1;
    891 	va_start(ap, nreturns);
    892 	i++;
    893 	while (i < args.nargs) {
    894 		args.slots[i] = (uintptr_t)va_arg(ap, uint32_t *);
    895 		i++;
    896 	}
    897 
    898 	if (openfirmware(&args) == -1)
    899 		rv = -1;
    900 	else {
    901 		rv = args.slots[i];
    902 		i++;
    903 
    904 		while (i < args.nargs + args.nreturns) {
    905 			*va_arg(ap, uint32_t *) = args.slots[i];
    906 			i++;
    907 		}
    908 	}
    909 	va_end(ap);
    910 
    911 	ofw_unlock(s);
    912 	return rv;
    913 }
    914 
    915 void
    916 OF_quiesce(void)
    917 {
    918 	static struct {
    919 		const char *name;
    920 		int nargs;
    921 		int nreturns;
    922 	} args = {
    923 		"quiesce",
    924 		0,
    925 		0,
    926 	};
    927 
    928 	const register_t s = ofw_lock();
    929 
    930 	openfirmware(&args);
    931 
    932 	ofw_unlock(s);
    933 }
    934 
    935 /*
    936  * This version of bcopy doesn't work for overlapping regions!
    937  */
    938 static void
    939 ofbcopy(const void *src, void *dst, size_t len)
    940 {
    941 	const char *sp = src;
    942 	char *dp = dst;
    943 
    944 	if (src == dst)
    945 		return;
    946 
    947 	while (len-- > 0)
    948 		*dp++ = *sp++;
    949 }
    950