xref: /freebsd/sys/powerpc/ofw/ofw_real.c (revision 3982006ed5587cfd83cc1955186e0aa4b92b3fcd)
1 /*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
2 
3 /*-
4  * SPDX-License-Identifier:BSD-4-Clause AND BSD-2-Clause-FreeBSD
5  *
6  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
7  * Copyright (C) 1995, 1996 TooLs GmbH.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by TooLs GmbH.
21  * 4. The name of TooLs GmbH may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 /*-
36  * Copyright (C) 2000 Benno Rice.
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  *    notice, this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright
45  *    notice, this list of conditions and the following disclaimer in the
46  *    documentation and/or other materials provided with the distribution.
47  *
48  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
49  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
50  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
53  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
54  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
55  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
56  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
57  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58  */
59 
60 #include <sys/cdefs.h>
61 __FBSDID("$FreeBSD$");
62 
63 #include <sys/param.h>
64 #include <sys/kernel.h>
65 #include <sys/lock.h>
66 #include <sys/mutex.h>
67 #include <sys/systm.h>
68 
69 #include <vm/vm.h>
70 #include <vm/vm_page.h>
71 #include <vm/pmap.h>
72 
73 #include <machine/bus.h>
74 #include <machine/md_var.h>
75 #include <machine/ofw_machdep.h>
76 #include <machine/stdarg.h>
77 
78 #include <dev/ofw/openfirm.h>
79 #include <dev/ofw/ofwvar.h>
80 #include "ofw_if.h"
81 
82 static int ofw_real_init(ofw_t, void *openfirm);
83 static int ofw_real_test(ofw_t, const char *name);
84 static phandle_t ofw_real_peer(ofw_t, phandle_t node);
85 static phandle_t ofw_real_child(ofw_t, phandle_t node);
86 static phandle_t ofw_real_parent(ofw_t, phandle_t node);
87 static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
88 static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
89     const char *propname);
90 static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
91     void *buf, size_t buflen);
92 static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
93     char *buf, size_t);
94 static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
95     const void *buf, size_t len);
96 static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
97 static phandle_t ofw_real_finddevice(ofw_t, const char *device);
98 static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
99     size_t len);
100 static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
101     size_t len);
102 static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
103     int nargs, int nreturns, cell_t *args_and_returns);
104 static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
105     cell_t *returns);
106 static ihandle_t ofw_real_open(ofw_t, const char *device);
107 static void ofw_real_close(ofw_t, ihandle_t instance);
108 static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
109 static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
110     size_t len);
111 static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
112 static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
113 static void ofw_real_release(ofw_t, void *virt, size_t size);
114 static void ofw_real_enter(ofw_t);
115 static void ofw_real_exit(ofw_t);
116 
117 static ofw_method_t ofw_real_methods[] = {
118 	OFWMETHOD(ofw_init,			ofw_real_init),
119 	OFWMETHOD(ofw_peer,			ofw_real_peer),
120 	OFWMETHOD(ofw_child,			ofw_real_child),
121 	OFWMETHOD(ofw_parent,			ofw_real_parent),
122 	OFWMETHOD(ofw_instance_to_package,	ofw_real_instance_to_package),
123 	OFWMETHOD(ofw_getproplen,		ofw_real_getproplen),
124 	OFWMETHOD(ofw_getprop,			ofw_real_getprop),
125 	OFWMETHOD(ofw_nextprop,			ofw_real_nextprop),
126 	OFWMETHOD(ofw_setprop,			ofw_real_setprop),
127 	OFWMETHOD(ofw_canon,			ofw_real_canon),
128 	OFWMETHOD(ofw_finddevice,		ofw_real_finddevice),
129 	OFWMETHOD(ofw_instance_to_path,		ofw_real_instance_to_path),
130 	OFWMETHOD(ofw_package_to_path,		ofw_real_package_to_path),
131 
132 	OFWMETHOD(ofw_test,			ofw_real_test),
133 	OFWMETHOD(ofw_call_method,		ofw_real_call_method),
134 	OFWMETHOD(ofw_interpret,		ofw_real_interpret),
135 	OFWMETHOD(ofw_open,			ofw_real_open),
136 	OFWMETHOD(ofw_close,			ofw_real_close),
137 	OFWMETHOD(ofw_read,			ofw_real_read),
138 	OFWMETHOD(ofw_write,			ofw_real_write),
139 	OFWMETHOD(ofw_seek,			ofw_real_seek),
140 	OFWMETHOD(ofw_claim,			ofw_real_claim),
141 	OFWMETHOD(ofw_release,			ofw_real_release),
142 	OFWMETHOD(ofw_enter,			ofw_real_enter),
143 	OFWMETHOD(ofw_exit,			ofw_real_exit),
144 
145 	{ 0, 0 }
146 };
147 
148 static ofw_def_t ofw_real = {
149 	OFW_STD_REAL,
150 	ofw_real_methods,
151 	0
152 };
153 OFW_DEF(ofw_real);
154 
155 static ofw_def_t ofw_32bit = {
156 	OFW_STD_32BIT,
157 	ofw_real_methods,
158 	0
159 };
160 OFW_DEF(ofw_32bit);
161 
162 static MALLOC_DEFINE(M_OFWREAL, "ofwreal",
163     "Open Firmware Real Mode Bounce Page");
164 
165 static int (*openfirmware)(void *);
166 
167 static vm_offset_t	of_bounce_phys;
168 static caddr_t		of_bounce_virt;
169 static off_t		of_bounce_offset;
170 static size_t		of_bounce_size;
171 static struct mtx	of_bounce_mtx;
172 
173 extern int		ofw_real_mode;
174 
175 /*
176  * After the VM is up, allocate a wired, low memory bounce page.
177  */
178 
179 static void ofw_real_bounce_alloc(void *);
180 
181 SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY,
182     ofw_real_bounce_alloc, NULL);
183 
184 static void
185 ofw_real_start(void)
186 {
187 	mtx_lock(&of_bounce_mtx);
188 	of_bounce_offset = 0;
189 }
190 
191 static void
192 ofw_real_stop(void)
193 {
194 	mtx_unlock(&of_bounce_mtx);
195 }
196 
197 static void
198 ofw_real_bounce_alloc(void *junk)
199 {
200 	/*
201 	 * Check that ofw_real is actually in use before allocating wads
202 	 * of memory. Do this by checking if our mutex has been set up.
203 	 */
204 	if (!mtx_initialized(&of_bounce_mtx))
205 		return;
206 
207 	/*
208 	 * Allocate a page of contiguous, wired physical memory that can
209 	 * fit into a 32-bit address space and accessed from real mode.
210 	 */
211 
212 	mtx_lock(&of_bounce_mtx);
213 
214 	of_bounce_virt = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0,
215 	    ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
216 	    4 * PAGE_SIZE);
217 
218 	of_bounce_phys = vtophys(of_bounce_virt);
219 	of_bounce_size = 4 * PAGE_SIZE;
220 
221 	/*
222 	 * For virtual-mode OF, direct map this physical address so that
223 	 * we have a 32-bit virtual address to give OF.
224 	 */
225 
226 	if (!ofw_real_mode && !hw_direct_map)
227 		pmap_kenter(of_bounce_phys, of_bounce_phys);
228 
229 	mtx_unlock(&of_bounce_mtx);
230 }
231 
232 static cell_t
233 ofw_real_map(const void *buf, size_t len)
234 {
235 	static char emergency_buffer[255];
236 	cell_t phys;
237 
238 	mtx_assert(&of_bounce_mtx, MA_OWNED);
239 
240 	if (of_bounce_virt == NULL) {
241 		/*
242 		 * If we haven't set up the MMU, then buf is guaranteed
243 		 * to be accessible to OF, because the only memory we
244 		 * can use right now is memory mapped by firmware.
245 		 */
246 		if (!pmap_bootstrapped)
247 			return (cell_t)(uintptr_t)buf;
248 
249 		/*
250 		 * XXX: It is possible for us to get called before the VM has
251 		 * come online, but after the MMU is up. We don't have the
252 		 * bounce buffer yet, but can no longer presume a 1:1 mapping.
253 		 * Copy into the emergency buffer, and reset at the end.
254 		 */
255 		of_bounce_virt = emergency_buffer;
256 		of_bounce_phys = (vm_offset_t)of_bounce_virt;
257 		of_bounce_size = sizeof(emergency_buffer);
258 	}
259 
260 	/*
261 	 * Make sure the bounce page offset satisfies any reasonable
262 	 * alignment constraint.
263 	 */
264 	of_bounce_offset += sizeof(register_t) - (of_bounce_offset % sizeof(register_t));
265 
266 	if (of_bounce_offset + len > of_bounce_size) {
267 		panic("Oversize Open Firmware call!");
268 		return 0;
269 	}
270 
271 	if (buf != NULL)
272 		memcpy(of_bounce_virt + of_bounce_offset, buf, len);
273 	else
274 		return (0);
275 
276 	phys = of_bounce_phys + of_bounce_offset;
277 
278 	of_bounce_offset += len;
279 
280 	return (phys);
281 }
282 
283 static void
284 ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
285 {
286 	mtx_assert(&of_bounce_mtx, MA_OWNED);
287 
288 	if (of_bounce_virt == NULL)
289 		return;
290 
291 	if (physaddr == 0)
292 		return;
293 
294 	memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
295 }
296 
297 /* Initialiser */
298 
299 static int
300 ofw_real_init(ofw_t ofw, void *openfirm)
301 {
302 	openfirmware = (int (*)(void *))openfirm;
303 
304 	mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF);
305 	of_bounce_virt = NULL;
306 	return (0);
307 }
308 
309 /*
310  * Generic functions
311  */
312 
313 /* Test to see if a service exists. */
314 static int
315 ofw_real_test(ofw_t ofw, const char *name)
316 {
317 	vm_offset_t argsptr;
318 	struct {
319 		cell_t name;
320 		cell_t nargs;
321 		cell_t nreturns;
322 		cell_t service;
323 		cell_t missing;
324 	} args;
325 
326 	args.name = (cell_t)(uintptr_t)"test";
327 	args.nargs = 1;
328 	args.nreturns = 1;
329 
330 	ofw_real_start();
331 
332 	args.service = ofw_real_map(name, strlen(name) + 1);
333 	argsptr = ofw_real_map(&args, sizeof(args));
334 	if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
335 		ofw_real_stop();
336 		return (-1);
337 	}
338 	ofw_real_unmap(argsptr, &args, sizeof(args));
339 	ofw_real_stop();
340 	return (args.missing);
341 }
342 
343 /*
344  * Device tree functions
345  */
346 
347 /* Return the next sibling of this node or 0. */
348 static phandle_t
349 ofw_real_peer(ofw_t ofw, phandle_t node)
350 {
351 	vm_offset_t argsptr;
352 	struct {
353 		cell_t name;
354 		cell_t nargs;
355 		cell_t nreturns;
356 		cell_t node;
357 		cell_t next;
358 	} args;
359 
360 	args.name = (cell_t)(uintptr_t)"peer";
361 	args.nargs = 1;
362 	args.nreturns = 1;
363 
364 	args.node = node;
365 	ofw_real_start();
366 	argsptr = ofw_real_map(&args, sizeof(args));
367 	if (openfirmware((void *)argsptr) == -1) {
368 		ofw_real_stop();
369 		return (0);
370 	}
371 	ofw_real_unmap(argsptr, &args, sizeof(args));
372 	ofw_real_stop();
373 	return (args.next);
374 }
375 
376 /* Return the first child of this node or 0. */
377 static phandle_t
378 ofw_real_child(ofw_t ofw, phandle_t node)
379 {
380 	vm_offset_t argsptr;
381 	struct {
382 		cell_t name;
383 		cell_t nargs;
384 		cell_t nreturns;
385 		cell_t node;
386 		cell_t child;
387 	} args;
388 
389 	args.name = (cell_t)(uintptr_t)"child";
390 	args.nargs = 1;
391 	args.nreturns = 1;
392 
393 	args.node = node;
394 	ofw_real_start();
395 	argsptr = ofw_real_map(&args, sizeof(args));
396 	if (openfirmware((void *)argsptr) == -1) {
397 		ofw_real_stop();
398 		return (0);
399 	}
400 	ofw_real_unmap(argsptr, &args, sizeof(args));
401 	ofw_real_stop();
402 	return (args.child);
403 }
404 
405 /* Return the parent of this node or 0. */
406 static phandle_t
407 ofw_real_parent(ofw_t ofw, phandle_t node)
408 {
409 	vm_offset_t argsptr;
410 	struct {
411 		cell_t name;
412 		cell_t nargs;
413 		cell_t nreturns;
414 		cell_t node;
415 		cell_t parent;
416 	} args;
417 
418 	args.name = (cell_t)(uintptr_t)"parent";
419 	args.nargs = 1;
420 	args.nreturns = 1;
421 
422 	args.node = node;
423 	ofw_real_start();
424 	argsptr = ofw_real_map(&args, sizeof(args));
425 	if (openfirmware((void *)argsptr) == -1) {
426 		ofw_real_stop();
427 		return (0);
428 	}
429 	ofw_real_unmap(argsptr, &args, sizeof(args));
430 	ofw_real_stop();
431 	return (args.parent);
432 }
433 
434 /* Return the package handle that corresponds to an instance handle. */
435 static phandle_t
436 ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
437 {
438 	vm_offset_t argsptr;
439 	struct {
440 		cell_t name;
441 		cell_t nargs;
442 		cell_t nreturns;
443 		cell_t instance;
444 		cell_t package;
445 	} args;
446 
447 	args.name = (cell_t)(uintptr_t)"instance-to-package";
448 	args.nargs = 1;
449 	args.nreturns = 1;
450 
451 	args.instance = instance;
452 	ofw_real_start();
453 	argsptr = ofw_real_map(&args, sizeof(args));
454 	if (openfirmware((void *)argsptr) == -1) {
455 		ofw_real_stop();
456 		return (-1);
457 	}
458 	ofw_real_unmap(argsptr, &args, sizeof(args));
459 	ofw_real_stop();
460 	return (args.package);
461 }
462 
463 /* Get the length of a property of a package. */
464 static ssize_t
465 ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
466 {
467 	vm_offset_t argsptr;
468 	struct {
469 		cell_t name;
470 		cell_t nargs;
471 		cell_t nreturns;
472 		cell_t package;
473 		cell_t propname;
474 		int32_t proplen;
475 	} args;
476 
477 	args.name = (cell_t)(uintptr_t)"getproplen";
478 	args.nargs = 2;
479 	args.nreturns = 1;
480 
481 	ofw_real_start();
482 
483 	args.package = package;
484 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
485 	argsptr = ofw_real_map(&args, sizeof(args));
486 	if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
487 		ofw_real_stop();
488 		return (-1);
489 	}
490 	ofw_real_unmap(argsptr, &args, sizeof(args));
491 	ofw_real_stop();
492 	return (args.proplen);
493 }
494 
495 /* Get the value of a property of a package. */
496 static ssize_t
497 ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
498     size_t buflen)
499 {
500 	vm_offset_t argsptr;
501 	struct {
502 		cell_t name;
503 		cell_t nargs;
504 		cell_t nreturns;
505 		cell_t package;
506 		cell_t propname;
507 		cell_t buf;
508 		cell_t buflen;
509 		int32_t size;
510 	} args;
511 
512 	args.name = (cell_t)(uintptr_t)"getprop";
513 	args.nargs = 4;
514 	args.nreturns = 1;
515 
516 	ofw_real_start();
517 
518 	args.package = package;
519 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
520 	args.buf = ofw_real_map(buf, buflen);
521 	args.buflen = buflen;
522 	argsptr = ofw_real_map(&args, sizeof(args));
523 	if (args.propname == 0 || args.buf == 0 ||
524 	    openfirmware((void *)argsptr) == -1) {
525 		ofw_real_stop();
526 		return (-1);
527 	}
528 	ofw_real_unmap(argsptr, &args, sizeof(args));
529 	ofw_real_unmap(args.buf, buf, buflen);
530 
531 	ofw_real_stop();
532 	return (args.size);
533 }
534 
535 /* Get the next property of a package. */
536 static int
537 ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
538     char *buf, size_t size)
539 {
540 	vm_offset_t argsptr;
541 	struct {
542 		cell_t name;
543 		cell_t nargs;
544 		cell_t nreturns;
545 		cell_t package;
546 		cell_t previous;
547 		cell_t buf;
548 		cell_t flag;
549 	} args;
550 
551 	args.name = (cell_t)(uintptr_t)"nextprop";
552 	args.nargs = 3;
553 	args.nreturns = 1;
554 
555 	ofw_real_start();
556 
557 	args.package = package;
558 	args.previous = ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0);
559 	args.buf = ofw_real_map(buf, size);
560 	argsptr = ofw_real_map(&args, sizeof(args));
561 	if (args.buf == 0 || openfirmware((void *)argsptr) == -1) {
562 		ofw_real_stop();
563 		return (-1);
564 	}
565 	ofw_real_unmap(argsptr, &args, sizeof(args));
566 	ofw_real_unmap(args.buf, buf, size);
567 
568 	ofw_real_stop();
569 	return (args.flag);
570 }
571 
572 /* Set the value of a property of a package. */
573 /* XXX Has a bug on FirePower */
574 static int
575 ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
576     const void *buf, size_t len)
577 {
578 	vm_offset_t argsptr;
579 	struct {
580 		cell_t name;
581 		cell_t nargs;
582 		cell_t nreturns;
583 		cell_t package;
584 		cell_t propname;
585 		cell_t buf;
586 		cell_t len;
587 		cell_t size;
588 	} args;
589 
590 	args.name = (cell_t)(uintptr_t)"setprop";
591 	args.nargs = 4;
592 	args.nreturns = 1;
593 
594 	ofw_real_start();
595 
596 	args.package = package;
597 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
598 	args.buf = ofw_real_map(buf, len);
599 	args.len = len;
600 	argsptr = ofw_real_map(&args, sizeof(args));
601 	if (args.propname == 0 || args.buf == 0 ||
602 	    openfirmware((void *)argsptr) == -1) {
603 		ofw_real_stop();
604 		return (-1);
605 	}
606 	ofw_real_unmap(argsptr, &args, sizeof(args));
607 	ofw_real_stop();
608 	return (args.size);
609 }
610 
611 /* Convert a device specifier to a fully qualified pathname. */
612 static ssize_t
613 ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
614 {
615 	vm_offset_t argsptr;
616 	struct {
617 		cell_t name;
618 		cell_t nargs;
619 		cell_t nreturns;
620 		cell_t device;
621 		cell_t buf;
622 		cell_t len;
623 		int32_t size;
624 	} args;
625 
626 	args.name = (cell_t)(uintptr_t)"canon";
627 	args.nargs = 3;
628 	args.nreturns = 1;
629 
630 	ofw_real_start();
631 
632 	args.device = ofw_real_map(device, strlen(device) + 1);
633 	args.buf = ofw_real_map(buf, len);
634 	args.len = len;
635 	argsptr = ofw_real_map(&args, sizeof(args));
636 	if (args.device == 0 || args.buf == 0 ||
637 	    openfirmware((void *)argsptr) == -1) {
638 		ofw_real_stop();
639 		return (-1);
640 	}
641 	ofw_real_unmap(argsptr, &args, sizeof(args));
642 	ofw_real_unmap(args.buf, buf, len);
643 
644 	ofw_real_stop();
645 	return (args.size);
646 }
647 
648 /* Return a package handle for the specified device. */
649 static phandle_t
650 ofw_real_finddevice(ofw_t ofw, const char *device)
651 {
652 	vm_offset_t argsptr;
653 	struct {
654 		cell_t name;
655 		cell_t nargs;
656 		cell_t nreturns;
657 		cell_t device;
658 		cell_t package;
659 	} args;
660 
661 	args.name = (cell_t)(uintptr_t)"finddevice";
662 	args.nargs = 1;
663 	args.nreturns = 1;
664 
665 	ofw_real_start();
666 
667 	args.device = ofw_real_map(device, strlen(device) + 1);
668 	argsptr = ofw_real_map(&args, sizeof(args));
669 	if (args.device == 0 ||
670 	    openfirmware((void *)argsptr) == -1) {
671 		ofw_real_stop();
672 		return (-1);
673 	}
674 	ofw_real_unmap(argsptr, &args, sizeof(args));
675 	ofw_real_stop();
676 	return (args.package);
677 }
678 
679 /* Return the fully qualified pathname corresponding to an instance. */
680 static ssize_t
681 ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
682 {
683 	vm_offset_t argsptr;
684 	struct {
685 		cell_t name;
686 		cell_t nargs;
687 		cell_t nreturns;
688 		cell_t instance;
689 		cell_t buf;
690 		cell_t len;
691 		int32_t size;
692 	} args;
693 
694 	args.name = (cell_t)(uintptr_t)"instance-to-path";
695 	args.nargs = 3;
696 	args.nreturns = 1;
697 
698 	ofw_real_start();
699 
700 	args.instance = instance;
701 	args.buf = ofw_real_map(buf, len);
702 	args.len = len;
703 	argsptr = ofw_real_map(&args, sizeof(args));
704 	if (args.buf == 0 ||
705 	    openfirmware((void *)argsptr) == -1) {
706 		ofw_real_stop();
707 		return (-1);
708 	}
709 	ofw_real_unmap(argsptr, &args, sizeof(args));
710 	ofw_real_unmap(args.buf, buf, len);
711 
712 	ofw_real_stop();
713 	return (args.size);
714 }
715 
716 /* Return the fully qualified pathname corresponding to a package. */
717 static ssize_t
718 ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
719 {
720 	vm_offset_t argsptr;
721 	struct {
722 		cell_t name;
723 		cell_t nargs;
724 		cell_t nreturns;
725 		cell_t package;
726 		cell_t buf;
727 		cell_t len;
728 		int32_t size;
729 	} args;
730 
731 	args.name = (cell_t)(uintptr_t)"package-to-path";
732 	args.nargs = 3;
733 	args.nreturns = 1;
734 
735 	ofw_real_start();
736 
737 	args.package = package;
738 	args.buf = ofw_real_map(buf, len);
739 	args.len = len;
740 	argsptr = ofw_real_map(&args, sizeof(args));
741 	if (args.buf == 0 ||
742 	    openfirmware((void *)argsptr) == -1) {
743 		ofw_real_stop();
744 		return (-1);
745 	}
746 	ofw_real_unmap(argsptr, &args, sizeof(args));
747 	ofw_real_unmap(args.buf, buf, len);
748 
749 	ofw_real_stop();
750 	return (args.size);
751 }
752 
753 /*  Call the method in the scope of a given instance. */
754 static int
755 ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
756     int nargs, int nreturns, cell_t *args_and_returns)
757 {
758 	vm_offset_t argsptr;
759 	struct {
760 		cell_t name;
761 		cell_t nargs;
762 		cell_t nreturns;
763 		cell_t method;
764 		cell_t instance;
765 		cell_t args_n_results[12];
766 	} args;
767 	cell_t *ap, *cp;
768 	int n;
769 
770 	args.name = (cell_t)(uintptr_t)"call-method";
771 	args.nargs = 2;
772 	args.nreturns = 1;
773 
774 	if (nargs > 6)
775 		return (-1);
776 
777 	ofw_real_start();
778 	args.nargs = nargs + 2;
779 	args.nreturns = nreturns + 1;
780 	args.method = ofw_real_map(method, strlen(method) + 1);
781 	args.instance = instance;
782 
783 	ap = args_and_returns;
784 	for (cp = args.args_n_results + (n = nargs); --n >= 0;)
785 		*--cp = *(ap++);
786 	argsptr = ofw_real_map(&args, sizeof(args));
787 	if (args.method == 0 ||
788 	    openfirmware((void *)argsptr) == -1) {
789 		ofw_real_stop();
790 		return (-1);
791 	}
792 	ofw_real_unmap(argsptr, &args, sizeof(args));
793 	ofw_real_stop();
794 	if (args.args_n_results[nargs])
795 		return (args.args_n_results[nargs]);
796 	for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
797 		*(ap++) = *--cp;
798 	return (0);
799 }
800 
801 static int
802 ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
803 {
804 	vm_offset_t argsptr;
805 	struct {
806 		cell_t name;
807 		cell_t nargs;
808 		cell_t nreturns;
809 		cell_t slot[16];
810 	} args;
811 	cell_t status;
812 	int i = 0, j = 0;
813 
814 	args.name = (cell_t)(uintptr_t)"interpret";
815 	args.nargs = 1;
816 
817 	ofw_real_start();
818 	args.nreturns = ++nreturns;
819 	args.slot[i++] = ofw_real_map(cmd, strlen(cmd) + 1);
820 	argsptr = ofw_real_map(&args, sizeof(args));
821 	if (openfirmware((void *)argsptr) == -1) {
822 		ofw_real_stop();
823 		return (-1);
824 	}
825 	ofw_real_unmap(argsptr, &args, sizeof(args));
826 	ofw_real_stop();
827 	status = args.slot[i++];
828 	while (i < 1 + nreturns)
829 		returns[j++] = args.slot[i++];
830 	return (status);
831 }
832 
833 /*
834  * Device I/O functions
835  */
836 
837 /* Open an instance for a device. */
838 static ihandle_t
839 ofw_real_open(ofw_t ofw, const char *device)
840 {
841 	vm_offset_t argsptr;
842 	struct {
843 		cell_t name;
844 		cell_t nargs;
845 		cell_t nreturns;
846 		cell_t device;
847 		cell_t instance;
848 	} args;
849 
850 	args.name = (cell_t)(uintptr_t)"open";
851 	args.nargs = 1;
852 	args.nreturns = 1;
853 
854 	ofw_real_start();
855 
856 	args.device = ofw_real_map(device, strlen(device) + 1);
857 	argsptr = ofw_real_map(&args, sizeof(args));
858 	if (args.device == 0 || openfirmware((void *)argsptr) == -1
859 	    || args.instance == 0) {
860 		ofw_real_stop();
861 		return (-1);
862 	}
863 	ofw_real_unmap(argsptr, &args, sizeof(args));
864 	ofw_real_stop();
865 	return (args.instance);
866 }
867 
868 /* Close an instance. */
869 static void
870 ofw_real_close(ofw_t ofw, ihandle_t instance)
871 {
872 	vm_offset_t argsptr;
873 	struct {
874 		cell_t name;
875 		cell_t nargs;
876 		cell_t nreturns;
877 		cell_t instance;
878 	} args;
879 
880 	args.name = (cell_t)(uintptr_t)"close";
881 	args.nargs = 1;
882 	args.nreturns = 0;
883 	args.instance = instance;
884 	ofw_real_start();
885 	argsptr = ofw_real_map(&args, sizeof(args));
886 	openfirmware((void *)argsptr);
887 	ofw_real_stop();
888 }
889 
890 /* Read from an instance. */
891 static ssize_t
892 ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
893 {
894 	vm_offset_t argsptr;
895 	struct {
896 		cell_t name;
897 		cell_t nargs;
898 		cell_t nreturns;
899 		cell_t instance;
900 		cell_t addr;
901 		cell_t len;
902 		int32_t actual;
903 	} args;
904 
905 	args.name = (cell_t)(uintptr_t)"read";
906 	args.nargs = 3;
907 	args.nreturns = 1;
908 
909 	ofw_real_start();
910 
911 	args.instance = instance;
912 	args.addr = ofw_real_map(addr, len);
913 	args.len = len;
914 	argsptr = ofw_real_map(&args, sizeof(args));
915 	if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
916 		ofw_real_stop();
917 		return (-1);
918 	}
919 	ofw_real_unmap(argsptr, &args, sizeof(args));
920 	ofw_real_unmap(args.addr, addr, len);
921 
922 	ofw_real_stop();
923 	return (args.actual);
924 }
925 
926 /* Write to an instance. */
927 static ssize_t
928 ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
929 {
930 	vm_offset_t argsptr;
931 	struct {
932 		cell_t name;
933 		cell_t nargs;
934 		cell_t nreturns;
935 		cell_t instance;
936 		cell_t addr;
937 		cell_t len;
938 		int32_t actual;
939 	} args;
940 
941 	args.name = (cell_t)(uintptr_t)"write";
942 	args.nargs = 3;
943 	args.nreturns = 1;
944 
945 	ofw_real_start();
946 
947 	args.instance = instance;
948 	args.addr = ofw_real_map(addr, len);
949 	args.len = len;
950 	argsptr = ofw_real_map(&args, sizeof(args));
951 	if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
952 		ofw_real_stop();
953 		return (-1);
954 	}
955 	ofw_real_unmap(argsptr, &args, sizeof(args));
956 	ofw_real_stop();
957 	return (args.actual);
958 }
959 
960 /* Seek to a position. */
961 static int
962 ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
963 {
964 	vm_offset_t argsptr;
965 	struct {
966 		cell_t name;
967 		cell_t nargs;
968 		cell_t nreturns;
969 		cell_t instance;
970 		cell_t poshi;
971 		cell_t poslo;
972 		cell_t status;
973 	} args;
974 
975 	args.name = (cell_t)(uintptr_t)"seek";
976 	args.nargs = 3;
977 	args.nreturns = 1;
978 
979 	args.instance = instance;
980 	args.poshi = pos >> 32;
981 	args.poslo = pos;
982 	ofw_real_start();
983 	argsptr = ofw_real_map(&args, sizeof(args));
984 	if (openfirmware((void *)argsptr) == -1) {
985 		ofw_real_stop();
986 		return (-1);
987 	}
988 	ofw_real_unmap(argsptr, &args, sizeof(args));
989 	ofw_real_stop();
990 	return (args.status);
991 }
992 
993 /*
994  * Memory functions
995  */
996 
997 /* Claim an area of memory. */
998 static caddr_t
999 ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
1000 {
1001 	vm_offset_t argsptr;
1002 	struct {
1003 		cell_t name;
1004 		cell_t nargs;
1005 		cell_t nreturns;
1006 		cell_t virt;
1007 		cell_t size;
1008 		cell_t align;
1009 		cell_t baseaddr;
1010 	} args;
1011 
1012 	args.name = (cell_t)(uintptr_t)"claim";
1013 	args.nargs = 3;
1014 	args.nreturns = 1;
1015 
1016 	args.virt = (cell_t)(uintptr_t)virt;
1017 	args.size = size;
1018 	args.align = align;
1019 	ofw_real_start();
1020 	argsptr = ofw_real_map(&args, sizeof(args));
1021 	if (openfirmware((void *)argsptr) == -1) {
1022 		ofw_real_stop();
1023 		return ((void *)-1);
1024 	}
1025 	ofw_real_unmap(argsptr, &args, sizeof(args));
1026 	ofw_real_stop();
1027 	return ((void *)(uintptr_t)args.baseaddr);
1028 }
1029 
1030 /* Release an area of memory. */
1031 static void
1032 ofw_real_release(ofw_t ofw, void *virt, size_t size)
1033 {
1034 	vm_offset_t argsptr;
1035 	struct {
1036 		cell_t name;
1037 		cell_t nargs;
1038 		cell_t nreturns;
1039 		cell_t virt;
1040 		cell_t size;
1041 	} args;
1042 
1043 	args.name = (cell_t)(uintptr_t)"release";
1044 	args.nargs = 2;
1045 	args.nreturns = 0;
1046 
1047 	args.virt = (cell_t)(uintptr_t)virt;
1048 	args.size = size;
1049 	ofw_real_start();
1050 	argsptr = ofw_real_map(&args, sizeof(args));
1051 	openfirmware((void *)argsptr);
1052 	ofw_real_stop();
1053 }
1054 
1055 /*
1056  * Control transfer functions
1057  */
1058 
1059 /* Suspend and drop back to the Open Firmware interface. */
1060 static void
1061 ofw_real_enter(ofw_t ofw)
1062 {
1063 	vm_offset_t argsptr;
1064 	struct {
1065 		cell_t name;
1066 		cell_t nargs;
1067 		cell_t nreturns;
1068 	} args;
1069 
1070 	args.name = (cell_t)(uintptr_t)"enter";
1071 	args.nargs = 0;
1072 	args.nreturns = 0;
1073 
1074 	ofw_real_start();
1075 	argsptr = ofw_real_map(&args, sizeof(args));
1076 	openfirmware((void *)argsptr);
1077 	/* We may come back. */
1078 	ofw_real_stop();
1079 }
1080 
1081 /* Shut down and drop back to the Open Firmware interface. */
1082 static void
1083 ofw_real_exit(ofw_t ofw)
1084 {
1085 	vm_offset_t argsptr;
1086 	struct {
1087 		cell_t name;
1088 		cell_t nargs;
1089 		cell_t nreturns;
1090 	} args;
1091 
1092 	args.name = (cell_t)(uintptr_t)"exit";
1093 	args.nargs = 0;
1094 	args.nreturns = 0;
1095 
1096 	ofw_real_start();
1097 	argsptr = ofw_real_map(&args, sizeof(args));
1098 	openfirmware((void *)argsptr);
1099 	for (;;)			/* just in case */
1100 		;
1101 	ofw_real_stop();
1102 }
1103 
1104