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