xref: /freebsd/sys/powerpc/ofw/ofw_real.c (revision cdb25d827efda15643a73b0b15f1b724b6e83429)
18446b206SNathan Whitehorn /*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
28446b206SNathan Whitehorn 
38446b206SNathan Whitehorn /*-
48446b206SNathan Whitehorn  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
58446b206SNathan Whitehorn  * Copyright (C) 1995, 1996 TooLs GmbH.
68446b206SNathan Whitehorn  * All rights reserved.
78446b206SNathan Whitehorn  *
88446b206SNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
98446b206SNathan Whitehorn  * modification, are permitted provided that the following conditions
108446b206SNathan Whitehorn  * are met:
118446b206SNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
128446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
138446b206SNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
148446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
158446b206SNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
168446b206SNathan Whitehorn  * 3. All advertising materials mentioning features or use of this software
178446b206SNathan Whitehorn  *    must display the following acknowledgement:
188446b206SNathan Whitehorn  *	This product includes software developed by TooLs GmbH.
198446b206SNathan Whitehorn  * 4. The name of TooLs GmbH may not be used to endorse or promote products
208446b206SNathan Whitehorn  *    derived from this software without specific prior written permission.
218446b206SNathan Whitehorn  *
228446b206SNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
238446b206SNathan Whitehorn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
248446b206SNathan Whitehorn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
258446b206SNathan Whitehorn  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
268446b206SNathan Whitehorn  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
278446b206SNathan Whitehorn  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
288446b206SNathan Whitehorn  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
298446b206SNathan Whitehorn  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
308446b206SNathan Whitehorn  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
318446b206SNathan Whitehorn  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
328446b206SNathan Whitehorn  */
338446b206SNathan Whitehorn /*-
348446b206SNathan Whitehorn  * Copyright (C) 2000 Benno Rice.
358446b206SNathan Whitehorn  * All rights reserved.
368446b206SNathan Whitehorn  *
378446b206SNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
388446b206SNathan Whitehorn  * modification, are permitted provided that the following conditions
398446b206SNathan Whitehorn  * are met:
408446b206SNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
418446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
428446b206SNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
438446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
448446b206SNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
458446b206SNathan Whitehorn  *
468446b206SNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
478446b206SNathan Whitehorn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
488446b206SNathan Whitehorn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
498446b206SNathan Whitehorn  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
508446b206SNathan Whitehorn  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
518446b206SNathan Whitehorn  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
528446b206SNathan Whitehorn  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
538446b206SNathan Whitehorn  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
548446b206SNathan Whitehorn  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
558446b206SNathan Whitehorn  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
568446b206SNathan Whitehorn  */
578446b206SNathan Whitehorn 
588446b206SNathan Whitehorn #include <sys/cdefs.h>
598446b206SNathan Whitehorn __FBSDID("$FreeBSD$");
608446b206SNathan Whitehorn 
618446b206SNathan Whitehorn #include <sys/param.h>
628446b206SNathan Whitehorn #include <sys/kernel.h>
638446b206SNathan Whitehorn #include <sys/lock.h>
648446b206SNathan Whitehorn #include <sys/mutex.h>
658446b206SNathan Whitehorn #include <sys/systm.h>
668446b206SNathan Whitehorn 
678446b206SNathan Whitehorn #include <vm/vm.h>
6870d75337SNathan Whitehorn #include <vm/vm_page.h>
698446b206SNathan Whitehorn #include <vm/pmap.h>
708446b206SNathan Whitehorn 
718446b206SNathan Whitehorn #include <machine/bus.h>
7270d75337SNathan Whitehorn #include <machine/md_var.h>
738446b206SNathan Whitehorn #include <machine/ofw_machdep.h>
7470d75337SNathan Whitehorn #include <machine/pmap.h>
7570d75337SNathan Whitehorn #include <machine/stdarg.h>
768446b206SNathan Whitehorn 
778446b206SNathan Whitehorn #include <dev/ofw/openfirm.h>
788446b206SNathan Whitehorn #include <dev/ofw/ofwvar.h>
798446b206SNathan Whitehorn #include "ofw_if.h"
808446b206SNathan Whitehorn 
818297758aSRafal Jaworowski static int ofw_real_init(ofw_t, void *openfirm);
828446b206SNathan Whitehorn static int ofw_real_test(ofw_t, const char *name);
838446b206SNathan Whitehorn static phandle_t ofw_real_peer(ofw_t, phandle_t node);
848446b206SNathan Whitehorn static phandle_t ofw_real_child(ofw_t, phandle_t node);
858446b206SNathan Whitehorn static phandle_t ofw_real_parent(ofw_t, phandle_t node);
868446b206SNathan Whitehorn static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
878446b206SNathan Whitehorn static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
888446b206SNathan Whitehorn     const char *propname);
898446b206SNathan Whitehorn static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
908446b206SNathan Whitehorn     void *buf, size_t buflen);
918446b206SNathan Whitehorn static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
928446b206SNathan Whitehorn     char *buf, size_t);
934fc23012SAndriy Gapon static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
944fc23012SAndriy Gapon     const void *buf, size_t len);
958446b206SNathan Whitehorn static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
968446b206SNathan Whitehorn static phandle_t ofw_real_finddevice(ofw_t, const char *device);
978446b206SNathan Whitehorn static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
988446b206SNathan Whitehorn     size_t len);
998446b206SNathan Whitehorn static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
1008446b206SNathan Whitehorn     size_t len);
1018446b206SNathan Whitehorn static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
102054e5dcbSNathan Whitehorn     int nargs, int nreturns, cell_t *args_and_returns);
10370d75337SNathan Whitehorn static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
104*cdb25d82SMarius Strobl     cell_t *returns);
1058446b206SNathan Whitehorn static ihandle_t ofw_real_open(ofw_t, const char *device);
1068446b206SNathan Whitehorn static void ofw_real_close(ofw_t, ihandle_t instance);
1078446b206SNathan Whitehorn static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
1088446b206SNathan Whitehorn static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
1098446b206SNathan Whitehorn     size_t len);
1108446b206SNathan Whitehorn static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
1118446b206SNathan Whitehorn static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
1128446b206SNathan Whitehorn static void ofw_real_release(ofw_t, void *virt, size_t size);
1138446b206SNathan Whitehorn static void ofw_real_enter(ofw_t);
1148446b206SNathan Whitehorn static void ofw_real_exit(ofw_t);
1158446b206SNathan Whitehorn 
1168446b206SNathan Whitehorn static ofw_method_t ofw_real_methods[] = {
1178446b206SNathan Whitehorn 	OFWMETHOD(ofw_init,			ofw_real_init),
1188446b206SNathan Whitehorn 	OFWMETHOD(ofw_peer,			ofw_real_peer),
1198446b206SNathan Whitehorn 	OFWMETHOD(ofw_child,			ofw_real_child),
1208446b206SNathan Whitehorn 	OFWMETHOD(ofw_parent,			ofw_real_parent),
1218446b206SNathan Whitehorn 	OFWMETHOD(ofw_instance_to_package,	ofw_real_instance_to_package),
1228446b206SNathan Whitehorn 	OFWMETHOD(ofw_getproplen,		ofw_real_getproplen),
1238446b206SNathan Whitehorn 	OFWMETHOD(ofw_getprop,			ofw_real_getprop),
1248446b206SNathan Whitehorn 	OFWMETHOD(ofw_nextprop,			ofw_real_nextprop),
1258446b206SNathan Whitehorn 	OFWMETHOD(ofw_setprop,			ofw_real_setprop),
1268446b206SNathan Whitehorn 	OFWMETHOD(ofw_canon,			ofw_real_canon),
1278446b206SNathan Whitehorn 	OFWMETHOD(ofw_finddevice,		ofw_real_finddevice),
1288446b206SNathan Whitehorn 	OFWMETHOD(ofw_instance_to_path,		ofw_real_instance_to_path),
1298446b206SNathan Whitehorn 	OFWMETHOD(ofw_package_to_path,		ofw_real_package_to_path),
1308446b206SNathan Whitehorn 
1318446b206SNathan Whitehorn 	OFWMETHOD(ofw_test,			ofw_real_test),
1328446b206SNathan Whitehorn 	OFWMETHOD(ofw_call_method,		ofw_real_call_method),
13370d75337SNathan Whitehorn 	OFWMETHOD(ofw_interpret,		ofw_real_interpret),
1348446b206SNathan Whitehorn 	OFWMETHOD(ofw_open,			ofw_real_open),
1358446b206SNathan Whitehorn 	OFWMETHOD(ofw_close,			ofw_real_close),
1368446b206SNathan Whitehorn 	OFWMETHOD(ofw_read,			ofw_real_read),
1378446b206SNathan Whitehorn 	OFWMETHOD(ofw_write,			ofw_real_write),
1388446b206SNathan Whitehorn 	OFWMETHOD(ofw_seek,			ofw_real_seek),
1398446b206SNathan Whitehorn 	OFWMETHOD(ofw_claim,			ofw_real_claim),
1408446b206SNathan Whitehorn 	OFWMETHOD(ofw_release,			ofw_real_release),
1418446b206SNathan Whitehorn 	OFWMETHOD(ofw_enter,			ofw_real_enter),
1428446b206SNathan Whitehorn 	OFWMETHOD(ofw_exit,			ofw_real_exit),
1438446b206SNathan Whitehorn 
1448446b206SNathan Whitehorn 	{ 0, 0 }
1458446b206SNathan Whitehorn };
1468446b206SNathan Whitehorn 
1478446b206SNathan Whitehorn static ofw_def_t ofw_real = {
1488446b206SNathan Whitehorn 	OFW_STD_REAL,
1498446b206SNathan Whitehorn 	ofw_real_methods,
1508446b206SNathan Whitehorn 	0
1518446b206SNathan Whitehorn };
1528446b206SNathan Whitehorn OFW_DEF(ofw_real);
1538446b206SNathan Whitehorn 
15470d75337SNathan Whitehorn static ofw_def_t ofw_32bit = {
15570d75337SNathan Whitehorn 	OFW_STD_32BIT,
15670d75337SNathan Whitehorn 	ofw_real_methods,
15770d75337SNathan Whitehorn 	0
15870d75337SNathan Whitehorn };
15970d75337SNathan Whitehorn OFW_DEF(ofw_32bit);
16070d75337SNathan Whitehorn 
1618446b206SNathan Whitehorn MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page");
1628446b206SNathan Whitehorn 
1638446b206SNathan Whitehorn static int (*openfirmware)(void *);
1648446b206SNathan Whitehorn 
1658446b206SNathan Whitehorn static vm_offset_t	of_bounce_phys;
1668446b206SNathan Whitehorn static caddr_t		of_bounce_virt;
1678446b206SNathan Whitehorn static off_t		of_bounce_offset;
1688446b206SNathan Whitehorn static size_t		of_bounce_size;
1698446b206SNathan Whitehorn static struct mtx	of_bounce_mtx;
1708446b206SNathan Whitehorn 
17170d75337SNathan Whitehorn extern int		ofw_real_mode;
17270d75337SNathan Whitehorn extern struct pmap	ofw_pmap;
17370d75337SNathan Whitehorn 
1748446b206SNathan Whitehorn /*
1758446b206SNathan Whitehorn  * After the VM is up, allocate a wired, low memory bounce page.
1768446b206SNathan Whitehorn  */
1778446b206SNathan Whitehorn 
1788446b206SNathan Whitehorn static void ofw_real_bounce_alloc(void *);
1798446b206SNathan Whitehorn 
18070d75337SNathan Whitehorn SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY,
1818446b206SNathan Whitehorn     ofw_real_bounce_alloc, NULL);
1828446b206SNathan Whitehorn 
1838446b206SNathan Whitehorn static void
1848446b206SNathan Whitehorn ofw_real_start(void)
1858446b206SNathan Whitehorn {
1868446b206SNathan Whitehorn 	mtx_lock(&of_bounce_mtx);
1878446b206SNathan Whitehorn 	of_bounce_offset = 0;
1888446b206SNathan Whitehorn }
1898446b206SNathan Whitehorn 
1908446b206SNathan Whitehorn static void
1918446b206SNathan Whitehorn ofw_real_stop(void)
1928446b206SNathan Whitehorn {
1938446b206SNathan Whitehorn 	mtx_unlock(&of_bounce_mtx);
1948446b206SNathan Whitehorn }
1958446b206SNathan Whitehorn 
1968446b206SNathan Whitehorn static void
1978446b206SNathan Whitehorn ofw_real_bounce_alloc(void *junk)
1988446b206SNathan Whitehorn {
1998446b206SNathan Whitehorn 	/*
2008446b206SNathan Whitehorn 	 * Check that ofw_real is actually in use before allocating wads
2018446b206SNathan Whitehorn 	 * of memory. Do this by checking if our mutex has been set up.
2028446b206SNathan Whitehorn 	 */
2038446b206SNathan Whitehorn 	if (!mtx_initialized(&of_bounce_mtx))
2048446b206SNathan Whitehorn 		return;
2058446b206SNathan Whitehorn 
2068446b206SNathan Whitehorn 	/*
2078446b206SNathan Whitehorn 	 * Allocate a page of contiguous, wired physical memory that can
2088446b206SNathan Whitehorn 	 * fit into a 32-bit address space.
2098446b206SNathan Whitehorn 	 */
2108446b206SNathan Whitehorn 
2118446b206SNathan Whitehorn 	mtx_lock(&of_bounce_mtx);
2128446b206SNathan Whitehorn 
2138446b206SNathan Whitehorn 	of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0,
2148446b206SNathan Whitehorn 			     0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE);
21570d75337SNathan Whitehorn 
2168446b206SNathan Whitehorn 	of_bounce_phys = vtophys(of_bounce_virt);
2178446b206SNathan Whitehorn 	of_bounce_size = PAGE_SIZE;
2188446b206SNathan Whitehorn 
21970d75337SNathan Whitehorn 	/*
22070d75337SNathan Whitehorn 	 * For virtual-mode OF, direct map this physical address so that
22170d75337SNathan Whitehorn 	 * we have a 32-bit virtual address to give OF.
22270d75337SNathan Whitehorn 	 */
22370d75337SNathan Whitehorn 
22470d75337SNathan Whitehorn 	if (!ofw_real_mode && !hw_direct_map)
22570d75337SNathan Whitehorn 		pmap_kenter(of_bounce_phys, of_bounce_phys);
22670d75337SNathan Whitehorn 
2278446b206SNathan Whitehorn 	mtx_unlock(&of_bounce_mtx);
2288446b206SNathan Whitehorn }
2298446b206SNathan Whitehorn 
2308446b206SNathan Whitehorn static cell_t
2318446b206SNathan Whitehorn ofw_real_map(const void *buf, size_t len)
2328446b206SNathan Whitehorn {
23370d75337SNathan Whitehorn 	static char emergency_buffer[255];
2348446b206SNathan Whitehorn 	cell_t phys;
2358446b206SNathan Whitehorn 
2368446b206SNathan Whitehorn 	mtx_assert(&of_bounce_mtx, MA_OWNED);
2378446b206SNathan Whitehorn 
2388446b206SNathan Whitehorn 	if (of_bounce_virt == NULL) {
23970d75337SNathan Whitehorn 		/*
24070d75337SNathan Whitehorn 		 * If we haven't set up the MMU, then buf is guaranteed
24170d75337SNathan Whitehorn 		 * to be accessible to OF, because the only memory we
24270d75337SNathan Whitehorn 		 * can use right now is memory mapped by firmware.
24370d75337SNathan Whitehorn 		 */
2448446b206SNathan Whitehorn 		if (!pmap_bootstrapped)
24570d75337SNathan Whitehorn 			return (cell_t)(uintptr_t)buf;
2468446b206SNathan Whitehorn 
2478446b206SNathan Whitehorn 		/*
2488446b206SNathan Whitehorn 		 * XXX: It is possible for us to get called before the VM has
2498446b206SNathan Whitehorn 		 * come online, but after the MMU is up. We don't have the
2508446b206SNathan Whitehorn 		 * bounce buffer yet, but can no longer presume a 1:1 mapping.
25170d75337SNathan Whitehorn 		 * Copy into the emergency buffer, and reset at the end.
2528446b206SNathan Whitehorn 		 */
25370d75337SNathan Whitehorn 		of_bounce_virt = emergency_buffer;
25470d75337SNathan Whitehorn 		of_bounce_phys = (vm_offset_t)of_bounce_virt;
25570d75337SNathan Whitehorn 		of_bounce_size = sizeof(emergency_buffer);
2568446b206SNathan Whitehorn 	}
2578446b206SNathan Whitehorn 
2588446b206SNathan Whitehorn 	/*
2598446b206SNathan Whitehorn 	 * Make sure the bounce page offset satisfies any reasonable
2608446b206SNathan Whitehorn 	 * alignment constraint.
2618446b206SNathan Whitehorn 	 */
26270d75337SNathan Whitehorn 	of_bounce_offset += sizeof(register_t) - (of_bounce_offset % sizeof(register_t));
2638446b206SNathan Whitehorn 
2648446b206SNathan Whitehorn 	if (of_bounce_offset + len > of_bounce_size) {
2658446b206SNathan Whitehorn 		panic("Oversize Open Firmware call!");
2668446b206SNathan Whitehorn 		return 0;
2678446b206SNathan Whitehorn 	}
2688446b206SNathan Whitehorn 
2698446b206SNathan Whitehorn 	memcpy(of_bounce_virt + of_bounce_offset, buf, len);
2708446b206SNathan Whitehorn 	phys = of_bounce_phys + of_bounce_offset;
2718446b206SNathan Whitehorn 
2728446b206SNathan Whitehorn 	of_bounce_offset += len;
2738446b206SNathan Whitehorn 
27470d75337SNathan Whitehorn 	return (phys);
2758446b206SNathan Whitehorn }
2768446b206SNathan Whitehorn 
2778446b206SNathan Whitehorn static void
2788446b206SNathan Whitehorn ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
2798446b206SNathan Whitehorn {
2808446b206SNathan Whitehorn 	mtx_assert(&of_bounce_mtx, MA_OWNED);
2818446b206SNathan Whitehorn 
2828446b206SNathan Whitehorn 	if (of_bounce_virt == NULL)
2838446b206SNathan Whitehorn 		return;
2848446b206SNathan Whitehorn 
2858446b206SNathan Whitehorn 	memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
2868446b206SNathan Whitehorn }
2878446b206SNathan Whitehorn 
2888446b206SNathan Whitehorn /* Initialiser */
2898446b206SNathan Whitehorn 
2908297758aSRafal Jaworowski static int
2918446b206SNathan Whitehorn ofw_real_init(ofw_t ofw, void *openfirm)
2928446b206SNathan Whitehorn {
2938446b206SNathan Whitehorn 	openfirmware = (int (*)(void *))openfirm;
2948446b206SNathan Whitehorn 
2958446b206SNathan Whitehorn 	mtx_init(&of_bounce_mtx, "OF Bounce Page", MTX_DEF, 0);
2968446b206SNathan Whitehorn 	of_bounce_virt = NULL;
2978297758aSRafal Jaworowski 	return (0);
2988446b206SNathan Whitehorn }
2998446b206SNathan Whitehorn 
3008446b206SNathan Whitehorn /*
3018446b206SNathan Whitehorn  * Generic functions
3028446b206SNathan Whitehorn  */
3038446b206SNathan Whitehorn 
3048446b206SNathan Whitehorn /* Test to see if a service exists. */
3058446b206SNathan Whitehorn static int
3068446b206SNathan Whitehorn ofw_real_test(ofw_t ofw, const char *name)
3078446b206SNathan Whitehorn {
30870d75337SNathan Whitehorn 	vm_offset_t argsptr;
309d4bccd63SNathan Whitehorn 	struct {
3108446b206SNathan Whitehorn 		cell_t name;
3118446b206SNathan Whitehorn 		cell_t nargs;
3128446b206SNathan Whitehorn 		cell_t nreturns;
3138446b206SNathan Whitehorn 		cell_t service;
3148446b206SNathan Whitehorn 		cell_t missing;
31570d75337SNathan Whitehorn 	} args;
31670d75337SNathan Whitehorn 
31770d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"test";
31870d75337SNathan Whitehorn 	args.nargs = 1;
31970d75337SNathan Whitehorn 	args.nreturns = 1;
3208446b206SNathan Whitehorn 
3218446b206SNathan Whitehorn 	ofw_real_start();
3228446b206SNathan Whitehorn 
3238446b206SNathan Whitehorn 	args.service = ofw_real_map(name, strlen(name) + 1);
32470d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
32570d75337SNathan Whitehorn 	if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
3268446b206SNathan Whitehorn 		ofw_real_stop();
3278446b206SNathan Whitehorn 		return (-1);
3288446b206SNathan Whitehorn 	}
32970d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
3308446b206SNathan Whitehorn 	ofw_real_stop();
3318446b206SNathan Whitehorn 	return (args.missing);
3328446b206SNathan Whitehorn }
3338446b206SNathan Whitehorn 
3348446b206SNathan Whitehorn /*
3358446b206SNathan Whitehorn  * Device tree functions
3368446b206SNathan Whitehorn  */
3378446b206SNathan Whitehorn 
3388446b206SNathan Whitehorn /* Return the next sibling of this node or 0. */
3398446b206SNathan Whitehorn static phandle_t
3408446b206SNathan Whitehorn ofw_real_peer(ofw_t ofw, phandle_t node)
3418446b206SNathan Whitehorn {
34270d75337SNathan Whitehorn 	vm_offset_t argsptr;
343d4bccd63SNathan Whitehorn 	struct {
3448446b206SNathan Whitehorn 		cell_t name;
3458446b206SNathan Whitehorn 		cell_t nargs;
3468446b206SNathan Whitehorn 		cell_t nreturns;
3478446b206SNathan Whitehorn 		cell_t node;
3488446b206SNathan Whitehorn 		cell_t next;
34970d75337SNathan Whitehorn 	} args;
35070d75337SNathan Whitehorn 
35170d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"peer";
35270d75337SNathan Whitehorn 	args.nargs = 1;
35370d75337SNathan Whitehorn 	args.nreturns = 1;
3548446b206SNathan Whitehorn 
3558446b206SNathan Whitehorn 	args.node = node;
35670d75337SNathan Whitehorn 	ofw_real_start();
35770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
35870d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
35970d75337SNathan Whitehorn 		ofw_real_stop();
3608446b206SNathan Whitehorn 		return (-1);
36170d75337SNathan Whitehorn 	}
36270d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
36370d75337SNathan Whitehorn 	ofw_real_stop();
3648446b206SNathan Whitehorn 	return (args.next);
3658446b206SNathan Whitehorn }
3668446b206SNathan Whitehorn 
3678446b206SNathan Whitehorn /* Return the first child of this node or 0. */
3688446b206SNathan Whitehorn static phandle_t
3698446b206SNathan Whitehorn ofw_real_child(ofw_t ofw, phandle_t node)
3708446b206SNathan Whitehorn {
37170d75337SNathan Whitehorn 	vm_offset_t argsptr;
372d4bccd63SNathan Whitehorn 	struct {
3738446b206SNathan Whitehorn 		cell_t name;
3748446b206SNathan Whitehorn 		cell_t nargs;
3758446b206SNathan Whitehorn 		cell_t nreturns;
3768446b206SNathan Whitehorn 		cell_t node;
3778446b206SNathan Whitehorn 		cell_t child;
37870d75337SNathan Whitehorn 	} args;
37970d75337SNathan Whitehorn 
38070d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"child";
38170d75337SNathan Whitehorn 	args.nargs = 1;
38270d75337SNathan Whitehorn 	args.nreturns = 1;
3838446b206SNathan Whitehorn 
3848446b206SNathan Whitehorn 	args.node = node;
38570d75337SNathan Whitehorn 	ofw_real_start();
38670d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
38770d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
38870d75337SNathan Whitehorn 		ofw_real_stop();
3898446b206SNathan Whitehorn 		return (-1);
39070d75337SNathan Whitehorn 	}
39170d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
39270d75337SNathan Whitehorn 	ofw_real_stop();
3938446b206SNathan Whitehorn 	return (args.child);
3948446b206SNathan Whitehorn }
3958446b206SNathan Whitehorn 
3968446b206SNathan Whitehorn /* Return the parent of this node or 0. */
3978446b206SNathan Whitehorn static phandle_t
3988446b206SNathan Whitehorn ofw_real_parent(ofw_t ofw, phandle_t node)
3998446b206SNathan Whitehorn {
40070d75337SNathan Whitehorn 	vm_offset_t argsptr;
401d4bccd63SNathan Whitehorn 	struct {
4028446b206SNathan Whitehorn 		cell_t name;
4038446b206SNathan Whitehorn 		cell_t nargs;
4048446b206SNathan Whitehorn 		cell_t nreturns;
4058446b206SNathan Whitehorn 		cell_t node;
4068446b206SNathan Whitehorn 		cell_t parent;
40770d75337SNathan Whitehorn 	} args;
40870d75337SNathan Whitehorn 
40970d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"parent";
41070d75337SNathan Whitehorn 	args.nargs = 1;
41170d75337SNathan Whitehorn 	args.nreturns = 1;
4128446b206SNathan Whitehorn 
4138446b206SNathan Whitehorn 	args.node = node;
41470d75337SNathan Whitehorn 	ofw_real_start();
41570d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
41670d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
41770d75337SNathan Whitehorn 		ofw_real_stop();
4188446b206SNathan Whitehorn 		return (-1);
41970d75337SNathan Whitehorn 	}
42070d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
42170d75337SNathan Whitehorn 	ofw_real_stop();
4228446b206SNathan Whitehorn 	return (args.parent);
4238446b206SNathan Whitehorn }
4248446b206SNathan Whitehorn 
4258446b206SNathan Whitehorn /* Return the package handle that corresponds to an instance handle. */
4268446b206SNathan Whitehorn static phandle_t
4278446b206SNathan Whitehorn ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
4288446b206SNathan Whitehorn {
42970d75337SNathan Whitehorn 	vm_offset_t argsptr;
430d4bccd63SNathan Whitehorn 	struct {
4318446b206SNathan Whitehorn 		cell_t name;
4328446b206SNathan Whitehorn 		cell_t nargs;
4338446b206SNathan Whitehorn 		cell_t nreturns;
4348446b206SNathan Whitehorn 		cell_t instance;
4358446b206SNathan Whitehorn 		cell_t package;
43670d75337SNathan Whitehorn 	} args;
43770d75337SNathan Whitehorn 
43870d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"instance-to-package";
43970d75337SNathan Whitehorn 	args.nargs = 1;
44070d75337SNathan Whitehorn 	args.nreturns = 1;
4418446b206SNathan Whitehorn 
4428446b206SNathan Whitehorn 	args.instance = instance;
44370d75337SNathan Whitehorn 	ofw_real_start();
44470d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
44570d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
44670d75337SNathan Whitehorn 		ofw_real_stop();
4478446b206SNathan Whitehorn 		return (-1);
44870d75337SNathan Whitehorn 	}
44970d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
45070d75337SNathan Whitehorn 	ofw_real_stop();
4518446b206SNathan Whitehorn 	return (args.package);
4528446b206SNathan Whitehorn }
4538446b206SNathan Whitehorn 
4548446b206SNathan Whitehorn /* Get the length of a property of a package. */
4558446b206SNathan Whitehorn static ssize_t
4568446b206SNathan Whitehorn ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
4578446b206SNathan Whitehorn {
45870d75337SNathan Whitehorn 	vm_offset_t argsptr;
459d4bccd63SNathan Whitehorn 	struct {
4608446b206SNathan Whitehorn 		cell_t name;
4618446b206SNathan Whitehorn 		cell_t nargs;
4628446b206SNathan Whitehorn 		cell_t nreturns;
4638446b206SNathan Whitehorn 		cell_t package;
4648446b206SNathan Whitehorn 		cell_t propname;
46570d75337SNathan Whitehorn 		int32_t proplen;
46670d75337SNathan Whitehorn 	} args;
46770d75337SNathan Whitehorn 
46870d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"getproplen";
46970d75337SNathan Whitehorn 	args.nargs = 2;
47070d75337SNathan Whitehorn 	args.nreturns = 1;
4718446b206SNathan Whitehorn 
4728446b206SNathan Whitehorn 	ofw_real_start();
4738446b206SNathan Whitehorn 
4748446b206SNathan Whitehorn 	args.package = package;
4758446b206SNathan Whitehorn 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
47670d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
47770d75337SNathan Whitehorn 	if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
4788446b206SNathan Whitehorn 		ofw_real_stop();
4798446b206SNathan Whitehorn 		return (-1);
4808446b206SNathan Whitehorn 	}
48170d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
4828446b206SNathan Whitehorn 	ofw_real_stop();
4838446b206SNathan Whitehorn 	return (args.proplen);
4848446b206SNathan Whitehorn }
4858446b206SNathan Whitehorn 
4868446b206SNathan Whitehorn /* Get the value of a property of a package. */
4878446b206SNathan Whitehorn static ssize_t
4888446b206SNathan Whitehorn ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
4898446b206SNathan Whitehorn     size_t buflen)
4908446b206SNathan Whitehorn {
49170d75337SNathan Whitehorn 	vm_offset_t argsptr;
492d4bccd63SNathan Whitehorn 	struct {
4938446b206SNathan Whitehorn 		cell_t name;
4948446b206SNathan Whitehorn 		cell_t nargs;
4958446b206SNathan Whitehorn 		cell_t nreturns;
4968446b206SNathan Whitehorn 		cell_t package;
4978446b206SNathan Whitehorn 		cell_t propname;
4988446b206SNathan Whitehorn 		cell_t buf;
4998446b206SNathan Whitehorn 		cell_t buflen;
50070d75337SNathan Whitehorn 		int32_t size;
50170d75337SNathan Whitehorn 	} args;
50270d75337SNathan Whitehorn 
50370d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"getprop";
50470d75337SNathan Whitehorn 	args.nargs = 4;
50570d75337SNathan Whitehorn 	args.nreturns = 1;
5068446b206SNathan Whitehorn 
5078446b206SNathan Whitehorn 	ofw_real_start();
5088446b206SNathan Whitehorn 
5098446b206SNathan Whitehorn 	args.package = package;
5108446b206SNathan Whitehorn 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
5118446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, buflen);
5128446b206SNathan Whitehorn 	args.buflen = buflen;
51370d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
51470d75337SNathan Whitehorn 	if (args.propname == 0 || args.buf == 0 ||
51570d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
5168446b206SNathan Whitehorn 		ofw_real_stop();
5178446b206SNathan Whitehorn 		return (-1);
5188446b206SNathan Whitehorn 	}
51970d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
5208446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, buflen);
5218446b206SNathan Whitehorn 
5228446b206SNathan Whitehorn 	ofw_real_stop();
5238446b206SNathan Whitehorn 	return (args.size);
5248446b206SNathan Whitehorn }
5258446b206SNathan Whitehorn 
5268446b206SNathan Whitehorn /* Get the next property of a package. */
5278446b206SNathan Whitehorn static int
5288446b206SNathan Whitehorn ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
5298446b206SNathan Whitehorn     char *buf, size_t size)
5308446b206SNathan Whitehorn {
53170d75337SNathan Whitehorn 	vm_offset_t argsptr;
532d4bccd63SNathan Whitehorn 	struct {
5338446b206SNathan Whitehorn 		cell_t name;
5348446b206SNathan Whitehorn 		cell_t nargs;
5358446b206SNathan Whitehorn 		cell_t nreturns;
5368446b206SNathan Whitehorn 		cell_t package;
5378446b206SNathan Whitehorn 		cell_t previous;
5388446b206SNathan Whitehorn 		cell_t buf;
5398446b206SNathan Whitehorn 		cell_t flag;
54070d75337SNathan Whitehorn 	} args;
54170d75337SNathan Whitehorn 
54270d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"nextprop";
54370d75337SNathan Whitehorn 	args.nargs = 3;
54470d75337SNathan Whitehorn 	args.nreturns = 1;
5458446b206SNathan Whitehorn 
5468446b206SNathan Whitehorn 	ofw_real_start();
5478446b206SNathan Whitehorn 
5488446b206SNathan Whitehorn 	args.package = package;
5498446b206SNathan Whitehorn 	args.previous = ofw_real_map(previous, strlen(previous) + 1);
5508446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, size);
55170d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
55270d75337SNathan Whitehorn 	if (args.previous == 0 || args.buf == 0 ||
55370d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
5548446b206SNathan Whitehorn 		ofw_real_stop();
5558446b206SNathan Whitehorn 		return (-1);
5568446b206SNathan Whitehorn 	}
55770d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
5588446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, size);
5598446b206SNathan Whitehorn 
5608446b206SNathan Whitehorn 	ofw_real_stop();
5618446b206SNathan Whitehorn 	return (args.flag);
5628446b206SNathan Whitehorn }
5638446b206SNathan Whitehorn 
5648446b206SNathan Whitehorn /* Set the value of a property of a package. */
5658446b206SNathan Whitehorn /* XXX Has a bug on FirePower */
5668446b206SNathan Whitehorn static int
5674fc23012SAndriy Gapon ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
5684fc23012SAndriy Gapon     const void *buf, size_t len)
5698446b206SNathan Whitehorn {
57070d75337SNathan Whitehorn 	vm_offset_t argsptr;
571d4bccd63SNathan Whitehorn 	struct {
5728446b206SNathan Whitehorn 		cell_t name;
5738446b206SNathan Whitehorn 		cell_t nargs;
5748446b206SNathan Whitehorn 		cell_t nreturns;
5758446b206SNathan Whitehorn 		cell_t package;
5768446b206SNathan Whitehorn 		cell_t propname;
5778446b206SNathan Whitehorn 		cell_t buf;
5788446b206SNathan Whitehorn 		cell_t len;
5798446b206SNathan Whitehorn 		cell_t size;
58070d75337SNathan Whitehorn 	} args;
58170d75337SNathan Whitehorn 
58270d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"setprop";
58370d75337SNathan Whitehorn 	args.nargs = 4;
58470d75337SNathan Whitehorn 	args.nreturns = 1;
5858446b206SNathan Whitehorn 
5868446b206SNathan Whitehorn 	ofw_real_start();
5878446b206SNathan Whitehorn 
5888446b206SNathan Whitehorn 	args.package = package;
5898446b206SNathan Whitehorn 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
5908446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
5918446b206SNathan Whitehorn 	args.len = len;
59270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
59370d75337SNathan Whitehorn 	if (args.propname == 0 || args.buf == 0 ||
59470d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
5958446b206SNathan Whitehorn 		ofw_real_stop();
5968446b206SNathan Whitehorn 		return (-1);
5978446b206SNathan Whitehorn 	}
59870d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
5998446b206SNathan Whitehorn 	ofw_real_stop();
6008446b206SNathan Whitehorn 	return (args.size);
6018446b206SNathan Whitehorn }
6028446b206SNathan Whitehorn 
6038446b206SNathan Whitehorn /* Convert a device specifier to a fully qualified pathname. */
6048446b206SNathan Whitehorn static ssize_t
6058446b206SNathan Whitehorn ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
6068446b206SNathan Whitehorn {
60770d75337SNathan Whitehorn 	vm_offset_t argsptr;
608d4bccd63SNathan Whitehorn 	struct {
6098446b206SNathan Whitehorn 		cell_t name;
6108446b206SNathan Whitehorn 		cell_t nargs;
6118446b206SNathan Whitehorn 		cell_t nreturns;
6128446b206SNathan Whitehorn 		cell_t device;
6138446b206SNathan Whitehorn 		cell_t buf;
6148446b206SNathan Whitehorn 		cell_t len;
61570d75337SNathan Whitehorn 		int32_t size;
61670d75337SNathan Whitehorn 	} args;
61770d75337SNathan Whitehorn 
61870d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"canon";
61970d75337SNathan Whitehorn 	args.nargs = 3;
62070d75337SNathan Whitehorn 	args.nreturns = 1;
6218446b206SNathan Whitehorn 
6228446b206SNathan Whitehorn 	ofw_real_start();
6238446b206SNathan Whitehorn 
6248446b206SNathan Whitehorn 	args.device = ofw_real_map(device, strlen(device) + 1);
6258446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
6268446b206SNathan Whitehorn 	args.len = len;
62770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
62870d75337SNathan Whitehorn 	if (args.device == 0 || args.buf == 0 ||
62970d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
6308446b206SNathan Whitehorn 		ofw_real_stop();
6318446b206SNathan Whitehorn 		return (-1);
6328446b206SNathan Whitehorn 	}
63370d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
6348446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, len);
6358446b206SNathan Whitehorn 
6368446b206SNathan Whitehorn 	ofw_real_stop();
6378446b206SNathan Whitehorn 	return (args.size);
6388446b206SNathan Whitehorn }
6398446b206SNathan Whitehorn 
6408446b206SNathan Whitehorn /* Return a package handle for the specified device. */
6418446b206SNathan Whitehorn static phandle_t
6428446b206SNathan Whitehorn ofw_real_finddevice(ofw_t ofw, const char *device)
6438446b206SNathan Whitehorn {
64470d75337SNathan Whitehorn 	vm_offset_t argsptr;
645d4bccd63SNathan Whitehorn 	struct {
6468446b206SNathan Whitehorn 		cell_t name;
6478446b206SNathan Whitehorn 		cell_t nargs;
6488446b206SNathan Whitehorn 		cell_t nreturns;
6498446b206SNathan Whitehorn 		cell_t device;
6508446b206SNathan Whitehorn 		cell_t package;
65170d75337SNathan Whitehorn 	} args;
65270d75337SNathan Whitehorn 
65370d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"finddevice";
65470d75337SNathan Whitehorn 	args.nargs = 1;
65570d75337SNathan Whitehorn 	args.nreturns = 1;
6568446b206SNathan Whitehorn 
6578446b206SNathan Whitehorn 	ofw_real_start();
6588446b206SNathan Whitehorn 
6598446b206SNathan Whitehorn 	args.device = ofw_real_map(device, strlen(device) + 1);
66070d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
66170d75337SNathan Whitehorn 	if (args.device == 0 ||
66270d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
6638446b206SNathan Whitehorn 		ofw_real_stop();
6648446b206SNathan Whitehorn 		return (-1);
6658446b206SNathan Whitehorn 	}
66670d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
6678446b206SNathan Whitehorn 	ofw_real_stop();
6688446b206SNathan Whitehorn 	return (args.package);
6698446b206SNathan Whitehorn }
6708446b206SNathan Whitehorn 
6718446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to an instance. */
6728446b206SNathan Whitehorn static ssize_t
6738446b206SNathan Whitehorn ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
6748446b206SNathan Whitehorn {
67570d75337SNathan Whitehorn 	vm_offset_t argsptr;
676d4bccd63SNathan Whitehorn 	struct {
6778446b206SNathan Whitehorn 		cell_t name;
6788446b206SNathan Whitehorn 		cell_t nargs;
6798446b206SNathan Whitehorn 		cell_t nreturns;
6808446b206SNathan Whitehorn 		cell_t instance;
6818446b206SNathan Whitehorn 		cell_t buf;
6828446b206SNathan Whitehorn 		cell_t len;
68370d75337SNathan Whitehorn 		int32_t size;
68470d75337SNathan Whitehorn 	} args;
68570d75337SNathan Whitehorn 
68670d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"instance-to-path";
68770d75337SNathan Whitehorn 	args.nargs = 3;
68870d75337SNathan Whitehorn 	args.nreturns = 1;
6898446b206SNathan Whitehorn 
6908446b206SNathan Whitehorn 	ofw_real_start();
6918446b206SNathan Whitehorn 
6928446b206SNathan Whitehorn 	args.instance = instance;
6938446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
6948446b206SNathan Whitehorn 	args.len = len;
69570d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
69670d75337SNathan Whitehorn 	if (args.buf == 0 ||
69770d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
6988446b206SNathan Whitehorn 		ofw_real_stop();
6998446b206SNathan Whitehorn 		return (-1);
7008446b206SNathan Whitehorn 	}
70170d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
7028446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, len);
7038446b206SNathan Whitehorn 
7048446b206SNathan Whitehorn 	ofw_real_stop();
7058446b206SNathan Whitehorn 	return (args.size);
7068446b206SNathan Whitehorn }
7078446b206SNathan Whitehorn 
7088446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to a package. */
7098446b206SNathan Whitehorn static ssize_t
7108446b206SNathan Whitehorn ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
7118446b206SNathan Whitehorn {
71270d75337SNathan Whitehorn 	vm_offset_t argsptr;
713d4bccd63SNathan Whitehorn 	struct {
7148446b206SNathan Whitehorn 		cell_t name;
7158446b206SNathan Whitehorn 		cell_t nargs;
7168446b206SNathan Whitehorn 		cell_t nreturns;
7178446b206SNathan Whitehorn 		cell_t package;
7188446b206SNathan Whitehorn 		cell_t buf;
7198446b206SNathan Whitehorn 		cell_t len;
72070d75337SNathan Whitehorn 		int32_t size;
72170d75337SNathan Whitehorn 	} args;
72270d75337SNathan Whitehorn 
72370d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"package-to-path";
72470d75337SNathan Whitehorn 	args.nargs = 3;
72570d75337SNathan Whitehorn 	args.nreturns = 1;
7268446b206SNathan Whitehorn 
7278446b206SNathan Whitehorn 	ofw_real_start();
7288446b206SNathan Whitehorn 
7298446b206SNathan Whitehorn 	args.package = package;
7308446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
7318446b206SNathan Whitehorn 	args.len = len;
73270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
73370d75337SNathan Whitehorn 	if (args.buf == 0 ||
73470d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
7358446b206SNathan Whitehorn 		ofw_real_stop();
7368446b206SNathan Whitehorn 		return (-1);
7378446b206SNathan Whitehorn 	}
73870d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
7398446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, len);
7408446b206SNathan Whitehorn 
7418446b206SNathan Whitehorn 	ofw_real_stop();
7428446b206SNathan Whitehorn 	return (args.size);
7438446b206SNathan Whitehorn }
7448446b206SNathan Whitehorn 
7458446b206SNathan Whitehorn /*  Call the method in the scope of a given instance. */
7468446b206SNathan Whitehorn static int
7478446b206SNathan Whitehorn ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
748054e5dcbSNathan Whitehorn     int nargs, int nreturns, cell_t *args_and_returns)
7498446b206SNathan Whitehorn {
75070d75337SNathan Whitehorn 	vm_offset_t argsptr;
751d4bccd63SNathan Whitehorn 	struct {
7528446b206SNathan Whitehorn 		cell_t name;
7538446b206SNathan Whitehorn 		cell_t nargs;
7548446b206SNathan Whitehorn 		cell_t nreturns;
7558446b206SNathan Whitehorn 		cell_t method;
7568446b206SNathan Whitehorn 		cell_t instance;
7578446b206SNathan Whitehorn 		cell_t args_n_results[12];
75870d75337SNathan Whitehorn 	} args;
759*cdb25d82SMarius Strobl 	cell_t *ap, *cp;
7608446b206SNathan Whitehorn 	int n;
7618446b206SNathan Whitehorn 
76270d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"call-method";
76370d75337SNathan Whitehorn 	args.nargs = 2;
76470d75337SNathan Whitehorn 	args.nreturns = 1;
76570d75337SNathan Whitehorn 
7668446b206SNathan Whitehorn 	if (nargs > 6)
7678446b206SNathan Whitehorn 		return (-1);
7688446b206SNathan Whitehorn 
7698446b206SNathan Whitehorn 	ofw_real_start();
7708446b206SNathan Whitehorn 	args.nargs = nargs + 2;
7718446b206SNathan Whitehorn 	args.nreturns = nreturns + 1;
7728446b206SNathan Whitehorn 	args.method = ofw_real_map(method, strlen(method) + 1);
7738446b206SNathan Whitehorn 	args.instance = instance;
7748446b206SNathan Whitehorn 
7758446b206SNathan Whitehorn 	ap = args_and_returns;
7768446b206SNathan Whitehorn 	for (cp = args.args_n_results + (n = nargs); --n >= 0;)
7778446b206SNathan Whitehorn 		*--cp = *(ap++);
77870d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
77970d75337SNathan Whitehorn 	if (args.method == 0 ||
78070d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
7818446b206SNathan Whitehorn 		ofw_real_stop();
7828446b206SNathan Whitehorn 		return (-1);
7838446b206SNathan Whitehorn 	}
78470d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
7858446b206SNathan Whitehorn 	ofw_real_stop();
7868446b206SNathan Whitehorn 	if (args.args_n_results[nargs])
7878446b206SNathan Whitehorn 		return (args.args_n_results[nargs]);
7888446b206SNathan Whitehorn 	for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
7898446b206SNathan Whitehorn 		*(ap++) = *--cp;
7908446b206SNathan Whitehorn 	return (0);
7918446b206SNathan Whitehorn }
7928446b206SNathan Whitehorn 
79370d75337SNathan Whitehorn static int
794*cdb25d82SMarius Strobl ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
79570d75337SNathan Whitehorn {
79670d75337SNathan Whitehorn 	vm_offset_t argsptr;
79770d75337SNathan Whitehorn 	struct {
79870d75337SNathan Whitehorn 		cell_t name;
79970d75337SNathan Whitehorn 		cell_t nargs;
80070d75337SNathan Whitehorn 		cell_t nreturns;
80170d75337SNathan Whitehorn 		cell_t slot[16];
80270d75337SNathan Whitehorn 	} args;
80370d75337SNathan Whitehorn 	cell_t status;
80470d75337SNathan Whitehorn 	int i = 0, j = 0;
80570d75337SNathan Whitehorn 
80670d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"interpret";
80770d75337SNathan Whitehorn 	args.nargs = 1;
80870d75337SNathan Whitehorn 
80970d75337SNathan Whitehorn 	ofw_real_start();
81070d75337SNathan Whitehorn 	args.nreturns = ++nreturns;
81170d75337SNathan Whitehorn 	args.slot[i++] = ofw_real_map(cmd, strlen(cmd) + 1);
81270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
81370d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
81470d75337SNathan Whitehorn 		ofw_real_stop();
81570d75337SNathan Whitehorn 		return (-1);
81670d75337SNathan Whitehorn 	}
81770d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
81870d75337SNathan Whitehorn 	ofw_real_stop();
81970d75337SNathan Whitehorn 	status = args.slot[i++];
82070d75337SNathan Whitehorn 	while (i < 1 + nreturns)
82170d75337SNathan Whitehorn 		returns[j++] = args.slot[i++];
82270d75337SNathan Whitehorn 	return (status);
82370d75337SNathan Whitehorn }
82470d75337SNathan Whitehorn 
8258446b206SNathan Whitehorn /*
8268446b206SNathan Whitehorn  * Device I/O functions
8278446b206SNathan Whitehorn  */
8288446b206SNathan Whitehorn 
8298446b206SNathan Whitehorn /* Open an instance for a device. */
8308446b206SNathan Whitehorn static ihandle_t
8318446b206SNathan Whitehorn ofw_real_open(ofw_t ofw, const char *device)
8328446b206SNathan Whitehorn {
83370d75337SNathan Whitehorn 	vm_offset_t argsptr;
834d4bccd63SNathan Whitehorn 	struct {
8358446b206SNathan Whitehorn 		cell_t name;
8368446b206SNathan Whitehorn 		cell_t nargs;
8378446b206SNathan Whitehorn 		cell_t nreturns;
8388446b206SNathan Whitehorn 		cell_t device;
8398446b206SNathan Whitehorn 		cell_t instance;
84070d75337SNathan Whitehorn 	} args;
84170d75337SNathan Whitehorn 
84270d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"open";
84370d75337SNathan Whitehorn 	args.nargs = 1;
84470d75337SNathan Whitehorn 	args.nreturns = 1;
8458446b206SNathan Whitehorn 
8468446b206SNathan Whitehorn 	ofw_real_start();
8478446b206SNathan Whitehorn 
8488446b206SNathan Whitehorn 	args.device = ofw_real_map(device, strlen(device) + 1);
84970d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
85070d75337SNathan Whitehorn 	if (args.device == 0 || openfirmware((void *)argsptr) == -1
8518446b206SNathan Whitehorn 	    || args.instance == 0) {
8528446b206SNathan Whitehorn 		ofw_real_stop();
8538446b206SNathan Whitehorn 		return (-1);
8548446b206SNathan Whitehorn 	}
85570d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
8568446b206SNathan Whitehorn 	ofw_real_stop();
8578446b206SNathan Whitehorn 	return (args.instance);
8588446b206SNathan Whitehorn }
8598446b206SNathan Whitehorn 
8608446b206SNathan Whitehorn /* Close an instance. */
8618446b206SNathan Whitehorn static void
8628446b206SNathan Whitehorn ofw_real_close(ofw_t ofw, ihandle_t instance)
8638446b206SNathan Whitehorn {
86470d75337SNathan Whitehorn 	vm_offset_t argsptr;
865d4bccd63SNathan Whitehorn 	struct {
8668446b206SNathan Whitehorn 		cell_t name;
8678446b206SNathan Whitehorn 		cell_t nargs;
8688446b206SNathan Whitehorn 		cell_t nreturns;
8698446b206SNathan Whitehorn 		cell_t instance;
87070d75337SNathan Whitehorn 	} args;
8718446b206SNathan Whitehorn 
87270d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"close";
87370d75337SNathan Whitehorn 	args.nargs = 1;
87470d75337SNathan Whitehorn 	args.nreturns = 0;
8758446b206SNathan Whitehorn 	args.instance = instance;
87670d75337SNathan Whitehorn 	ofw_real_start();
87770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
87870d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
87970d75337SNathan Whitehorn 	ofw_real_stop();
8808446b206SNathan Whitehorn }
8818446b206SNathan Whitehorn 
8828446b206SNathan Whitehorn /* Read from an instance. */
8838446b206SNathan Whitehorn static ssize_t
8848446b206SNathan Whitehorn ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
8858446b206SNathan Whitehorn {
88670d75337SNathan Whitehorn 	vm_offset_t argsptr;
887d4bccd63SNathan Whitehorn 	struct {
8888446b206SNathan Whitehorn 		cell_t name;
8898446b206SNathan Whitehorn 		cell_t nargs;
8908446b206SNathan Whitehorn 		cell_t nreturns;
8918446b206SNathan Whitehorn 		cell_t instance;
8928446b206SNathan Whitehorn 		cell_t addr;
8938446b206SNathan Whitehorn 		cell_t len;
89470d75337SNathan Whitehorn 		int32_t actual;
89570d75337SNathan Whitehorn 	} args;
89670d75337SNathan Whitehorn 
89770d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"read";
89870d75337SNathan Whitehorn 	args.nargs = 3;
89970d75337SNathan Whitehorn 	args.nreturns = 1;
9008446b206SNathan Whitehorn 
9018446b206SNathan Whitehorn 	ofw_real_start();
9028446b206SNathan Whitehorn 
9038446b206SNathan Whitehorn 	args.instance = instance;
9048446b206SNathan Whitehorn 	args.addr = ofw_real_map(addr, len);
9058446b206SNathan Whitehorn 	args.len = len;
90670d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
90770d75337SNathan Whitehorn 	if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
9088446b206SNathan Whitehorn 		ofw_real_stop();
9098446b206SNathan Whitehorn 		return (-1);
9108446b206SNathan Whitehorn 	}
91170d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
9128446b206SNathan Whitehorn 	ofw_real_unmap(args.addr, addr, len);
9138446b206SNathan Whitehorn 
9148446b206SNathan Whitehorn 	ofw_real_stop();
9158446b206SNathan Whitehorn 	return (args.actual);
9168446b206SNathan Whitehorn }
9178446b206SNathan Whitehorn 
9188446b206SNathan Whitehorn /* Write to an instance. */
9198446b206SNathan Whitehorn static ssize_t
9208446b206SNathan Whitehorn ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
9218446b206SNathan Whitehorn {
92270d75337SNathan Whitehorn 	vm_offset_t argsptr;
923d4bccd63SNathan Whitehorn 	struct {
9248446b206SNathan Whitehorn 		cell_t name;
9258446b206SNathan Whitehorn 		cell_t nargs;
9268446b206SNathan Whitehorn 		cell_t nreturns;
9278446b206SNathan Whitehorn 		cell_t instance;
9288446b206SNathan Whitehorn 		cell_t addr;
9298446b206SNathan Whitehorn 		cell_t len;
93070d75337SNathan Whitehorn 		int32_t actual;
93170d75337SNathan Whitehorn 	} args;
93270d75337SNathan Whitehorn 
93370d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"write";
93470d75337SNathan Whitehorn 	args.nargs = 3;
93570d75337SNathan Whitehorn 	args.nreturns = 1;
9368446b206SNathan Whitehorn 
9378446b206SNathan Whitehorn 	ofw_real_start();
9388446b206SNathan Whitehorn 
9398446b206SNathan Whitehorn 	args.instance = instance;
9408446b206SNathan Whitehorn 	args.addr = ofw_real_map(addr, len);
9418446b206SNathan Whitehorn 	args.len = len;
94270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
94370d75337SNathan Whitehorn 	if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
9448446b206SNathan Whitehorn 		ofw_real_stop();
9458446b206SNathan Whitehorn 		return (-1);
9468446b206SNathan Whitehorn 	}
94770d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
9488446b206SNathan Whitehorn 	ofw_real_stop();
9498446b206SNathan Whitehorn 	return (args.actual);
9508446b206SNathan Whitehorn }
9518446b206SNathan Whitehorn 
9528446b206SNathan Whitehorn /* Seek to a position. */
9538446b206SNathan Whitehorn static int
9548446b206SNathan Whitehorn ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
9558446b206SNathan Whitehorn {
95670d75337SNathan Whitehorn 	vm_offset_t argsptr;
957d4bccd63SNathan Whitehorn 	struct {
9588446b206SNathan Whitehorn 		cell_t name;
9598446b206SNathan Whitehorn 		cell_t nargs;
9608446b206SNathan Whitehorn 		cell_t nreturns;
9618446b206SNathan Whitehorn 		cell_t instance;
9628446b206SNathan Whitehorn 		cell_t poshi;
9638446b206SNathan Whitehorn 		cell_t poslo;
9648446b206SNathan Whitehorn 		cell_t status;
96570d75337SNathan Whitehorn 	} args;
96670d75337SNathan Whitehorn 
96770d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"seek";
96870d75337SNathan Whitehorn 	args.nargs = 3;
96970d75337SNathan Whitehorn 	args.nreturns = 1;
9708446b206SNathan Whitehorn 
9718446b206SNathan Whitehorn 	args.instance = instance;
9728446b206SNathan Whitehorn 	args.poshi = pos >> 32;
9738446b206SNathan Whitehorn 	args.poslo = pos;
97470d75337SNathan Whitehorn 	ofw_real_start();
97570d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
97670d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
97770d75337SNathan Whitehorn 		ofw_real_stop();
9788446b206SNathan Whitehorn 		return (-1);
97970d75337SNathan Whitehorn 	}
98070d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
98170d75337SNathan Whitehorn 	ofw_real_stop();
9828446b206SNathan Whitehorn 	return (args.status);
9838446b206SNathan Whitehorn }
9848446b206SNathan Whitehorn 
9858446b206SNathan Whitehorn /*
9868446b206SNathan Whitehorn  * Memory functions
9878446b206SNathan Whitehorn  */
9888446b206SNathan Whitehorn 
9898446b206SNathan Whitehorn /* Claim an area of memory. */
9908446b206SNathan Whitehorn static caddr_t
9918446b206SNathan Whitehorn ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
9928446b206SNathan Whitehorn {
99370d75337SNathan Whitehorn 	vm_offset_t argsptr;
994d4bccd63SNathan Whitehorn 	struct {
9958446b206SNathan Whitehorn 		cell_t name;
9968446b206SNathan Whitehorn 		cell_t nargs;
9978446b206SNathan Whitehorn 		cell_t nreturns;
9988446b206SNathan Whitehorn 		cell_t virt;
9998446b206SNathan Whitehorn 		cell_t size;
10008446b206SNathan Whitehorn 		cell_t align;
10018446b206SNathan Whitehorn 		cell_t baseaddr;
100270d75337SNathan Whitehorn 	} args;
10038446b206SNathan Whitehorn 
100470d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"claim";
100570d75337SNathan Whitehorn 	args.nargs = 3;
100670d75337SNathan Whitehorn 	args.nreturns = 1;
100770d75337SNathan Whitehorn 
100870d75337SNathan Whitehorn 	args.virt = (cell_t)(uintptr_t)virt;
10098446b206SNathan Whitehorn 	args.size = size;
10108446b206SNathan Whitehorn 	args.align = align;
101170d75337SNathan Whitehorn 	ofw_real_start();
101270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
101370d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
101470d75337SNathan Whitehorn 		ofw_real_stop();
10158446b206SNathan Whitehorn 		return ((void *)-1);
101670d75337SNathan Whitehorn 	}
101770d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
101870d75337SNathan Whitehorn 	ofw_real_stop();
101970d75337SNathan Whitehorn 	return ((void *)(uintptr_t)args.baseaddr);
10208446b206SNathan Whitehorn }
10218446b206SNathan Whitehorn 
10228446b206SNathan Whitehorn /* Release an area of memory. */
10238446b206SNathan Whitehorn static void
10248446b206SNathan Whitehorn ofw_real_release(ofw_t ofw, void *virt, size_t size)
10258446b206SNathan Whitehorn {
102670d75337SNathan Whitehorn 	vm_offset_t argsptr;
1027d4bccd63SNathan Whitehorn 	struct {
10288446b206SNathan Whitehorn 		cell_t name;
10298446b206SNathan Whitehorn 		cell_t nargs;
10308446b206SNathan Whitehorn 		cell_t nreturns;
10318446b206SNathan Whitehorn 		cell_t virt;
10328446b206SNathan Whitehorn 		cell_t size;
103370d75337SNathan Whitehorn 	} args;
10348446b206SNathan Whitehorn 
103570d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"release";
103670d75337SNathan Whitehorn 	args.nargs = 2;
103770d75337SNathan Whitehorn 	args.nreturns = 0;
103870d75337SNathan Whitehorn 
103970d75337SNathan Whitehorn 	args.virt = (cell_t)(uintptr_t)virt;
10408446b206SNathan Whitehorn 	args.size = size;
104170d75337SNathan Whitehorn 	ofw_real_start();
104270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
104370d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
104470d75337SNathan Whitehorn 	ofw_real_stop();
10458446b206SNathan Whitehorn }
10468446b206SNathan Whitehorn 
10478446b206SNathan Whitehorn /*
10488446b206SNathan Whitehorn  * Control transfer functions
10498446b206SNathan Whitehorn  */
10508446b206SNathan Whitehorn 
10518446b206SNathan Whitehorn /* Suspend and drop back to the Open Firmware interface. */
10528446b206SNathan Whitehorn static void
10538446b206SNathan Whitehorn ofw_real_enter(ofw_t ofw)
10548446b206SNathan Whitehorn {
105570d75337SNathan Whitehorn 	vm_offset_t argsptr;
1056d4bccd63SNathan Whitehorn 	struct {
10578446b206SNathan Whitehorn 		cell_t name;
10588446b206SNathan Whitehorn 		cell_t nargs;
10598446b206SNathan Whitehorn 		cell_t nreturns;
106070d75337SNathan Whitehorn 	} args;
10618446b206SNathan Whitehorn 
106270d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"enter";
106370d75337SNathan Whitehorn 	args.nargs = 0;
106470d75337SNathan Whitehorn 	args.nreturns = 0;
106570d75337SNathan Whitehorn 
106670d75337SNathan Whitehorn 	ofw_real_start();
106770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
106870d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
10698446b206SNathan Whitehorn 	/* We may come back. */
107070d75337SNathan Whitehorn 	ofw_real_stop();
10718446b206SNathan Whitehorn }
10728446b206SNathan Whitehorn 
10738446b206SNathan Whitehorn /* Shut down and drop back to the Open Firmware interface. */
10748446b206SNathan Whitehorn static void
10758446b206SNathan Whitehorn ofw_real_exit(ofw_t ofw)
10768446b206SNathan Whitehorn {
107770d75337SNathan Whitehorn 	vm_offset_t argsptr;
1078d4bccd63SNathan Whitehorn 	struct {
10798446b206SNathan Whitehorn 		cell_t name;
10808446b206SNathan Whitehorn 		cell_t nargs;
10818446b206SNathan Whitehorn 		cell_t nreturns;
108270d75337SNathan Whitehorn 	} args;
10838446b206SNathan Whitehorn 
108470d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"exit";
108570d75337SNathan Whitehorn 	args.nargs = 0;
108670d75337SNathan Whitehorn 	args.nreturns = 0;
108770d75337SNathan Whitehorn 
108870d75337SNathan Whitehorn 	ofw_real_start();
108970d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
109070d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
10918446b206SNathan Whitehorn 	for (;;)			/* just in case */
10928446b206SNathan Whitehorn 		;
109370d75337SNathan Whitehorn 	ofw_real_stop();
10948446b206SNathan Whitehorn }
10958446b206SNathan Whitehorn 
1096