xref: /freebsd/sys/powerpc/ofw/ofw_real.c (revision d6d06708)
18446b206SNathan Whitehorn /*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
28446b206SNathan Whitehorn 
38446b206SNathan Whitehorn /*-
471e3c308SPedro F. Giffuni  * SPDX-License-Identifier:BSD-4-Clause AND BSD-2-Clause-FreeBSD
571e3c308SPedro F. Giffuni  *
68446b206SNathan Whitehorn  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
78446b206SNathan Whitehorn  * Copyright (C) 1995, 1996 TooLs GmbH.
88446b206SNathan Whitehorn  * All rights reserved.
98446b206SNathan Whitehorn  *
108446b206SNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
118446b206SNathan Whitehorn  * modification, are permitted provided that the following conditions
128446b206SNathan Whitehorn  * are met:
138446b206SNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
148446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
158446b206SNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
168446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
178446b206SNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
188446b206SNathan Whitehorn  * 3. All advertising materials mentioning features or use of this software
198446b206SNathan Whitehorn  *    must display the following acknowledgement:
208446b206SNathan Whitehorn  *	This product includes software developed by TooLs GmbH.
218446b206SNathan Whitehorn  * 4. The name of TooLs GmbH may not be used to endorse or promote products
228446b206SNathan Whitehorn  *    derived from this software without specific prior written permission.
238446b206SNathan Whitehorn  *
248446b206SNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
258446b206SNathan Whitehorn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
268446b206SNathan Whitehorn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
278446b206SNathan Whitehorn  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
288446b206SNathan Whitehorn  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
298446b206SNathan Whitehorn  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
308446b206SNathan Whitehorn  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
318446b206SNathan Whitehorn  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
328446b206SNathan Whitehorn  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
338446b206SNathan Whitehorn  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
348446b206SNathan Whitehorn  */
358446b206SNathan Whitehorn /*-
368446b206SNathan Whitehorn  * Copyright (C) 2000 Benno Rice.
378446b206SNathan Whitehorn  * All rights reserved.
388446b206SNathan Whitehorn  *
398446b206SNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
408446b206SNathan Whitehorn  * modification, are permitted provided that the following conditions
418446b206SNathan Whitehorn  * are met:
428446b206SNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
438446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
448446b206SNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
458446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
468446b206SNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
478446b206SNathan Whitehorn  *
488446b206SNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
498446b206SNathan Whitehorn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
508446b206SNathan Whitehorn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
518446b206SNathan Whitehorn  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
528446b206SNathan Whitehorn  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
538446b206SNathan Whitehorn  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
548446b206SNathan Whitehorn  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
558446b206SNathan Whitehorn  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
568446b206SNathan Whitehorn  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
578446b206SNathan Whitehorn  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
588446b206SNathan Whitehorn  */
598446b206SNathan Whitehorn 
608446b206SNathan Whitehorn #include <sys/cdefs.h>
618446b206SNathan Whitehorn __FBSDID("$FreeBSD$");
628446b206SNathan Whitehorn 
638446b206SNathan Whitehorn #include <sys/param.h>
648446b206SNathan Whitehorn #include <sys/kernel.h>
658446b206SNathan Whitehorn #include <sys/lock.h>
668446b206SNathan Whitehorn #include <sys/mutex.h>
678446b206SNathan Whitehorn #include <sys/systm.h>
688446b206SNathan Whitehorn 
698446b206SNathan Whitehorn #include <vm/vm.h>
7070d75337SNathan Whitehorn #include <vm/vm_page.h>
718446b206SNathan Whitehorn #include <vm/pmap.h>
728446b206SNathan Whitehorn 
738446b206SNathan Whitehorn #include <machine/bus.h>
7470d75337SNathan Whitehorn #include <machine/md_var.h>
758446b206SNathan Whitehorn #include <machine/ofw_machdep.h>
7670d75337SNathan Whitehorn #include <machine/stdarg.h>
778446b206SNathan Whitehorn 
788446b206SNathan Whitehorn #include <dev/ofw/openfirm.h>
798446b206SNathan Whitehorn #include <dev/ofw/ofwvar.h>
808446b206SNathan Whitehorn #include "ofw_if.h"
818446b206SNathan Whitehorn 
828297758aSRafal Jaworowski static int ofw_real_init(ofw_t, void *openfirm);
838446b206SNathan Whitehorn static int ofw_real_test(ofw_t, const char *name);
848446b206SNathan Whitehorn static phandle_t ofw_real_peer(ofw_t, phandle_t node);
858446b206SNathan Whitehorn static phandle_t ofw_real_child(ofw_t, phandle_t node);
868446b206SNathan Whitehorn static phandle_t ofw_real_parent(ofw_t, phandle_t node);
878446b206SNathan Whitehorn static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
888446b206SNathan Whitehorn static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
898446b206SNathan Whitehorn     const char *propname);
908446b206SNathan Whitehorn static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
918446b206SNathan Whitehorn     void *buf, size_t buflen);
928446b206SNathan Whitehorn static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
938446b206SNathan Whitehorn     char *buf, size_t);
944fc23012SAndriy Gapon static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
954fc23012SAndriy Gapon     const void *buf, size_t len);
968446b206SNathan Whitehorn static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
978446b206SNathan Whitehorn static phandle_t ofw_real_finddevice(ofw_t, const char *device);
988446b206SNathan Whitehorn static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
998446b206SNathan Whitehorn     size_t len);
1008446b206SNathan Whitehorn static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
1018446b206SNathan Whitehorn     size_t len);
1028446b206SNathan Whitehorn static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
103054e5dcbSNathan Whitehorn     int nargs, int nreturns, cell_t *args_and_returns);
10470d75337SNathan Whitehorn static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
105cdb25d82SMarius Strobl     cell_t *returns);
1068446b206SNathan Whitehorn static ihandle_t ofw_real_open(ofw_t, const char *device);
1078446b206SNathan Whitehorn static void ofw_real_close(ofw_t, ihandle_t instance);
1088446b206SNathan Whitehorn static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
1098446b206SNathan Whitehorn static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
1108446b206SNathan Whitehorn     size_t len);
1118446b206SNathan Whitehorn static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
1128446b206SNathan Whitehorn static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
1138446b206SNathan Whitehorn static void ofw_real_release(ofw_t, void *virt, size_t size);
1148446b206SNathan Whitehorn static void ofw_real_enter(ofw_t);
1158446b206SNathan Whitehorn static void ofw_real_exit(ofw_t);
1168446b206SNathan Whitehorn 
1178446b206SNathan Whitehorn static ofw_method_t ofw_real_methods[] = {
1188446b206SNathan Whitehorn 	OFWMETHOD(ofw_init,			ofw_real_init),
1198446b206SNathan Whitehorn 	OFWMETHOD(ofw_peer,			ofw_real_peer),
1208446b206SNathan Whitehorn 	OFWMETHOD(ofw_child,			ofw_real_child),
1218446b206SNathan Whitehorn 	OFWMETHOD(ofw_parent,			ofw_real_parent),
1228446b206SNathan Whitehorn 	OFWMETHOD(ofw_instance_to_package,	ofw_real_instance_to_package),
1238446b206SNathan Whitehorn 	OFWMETHOD(ofw_getproplen,		ofw_real_getproplen),
1248446b206SNathan Whitehorn 	OFWMETHOD(ofw_getprop,			ofw_real_getprop),
1258446b206SNathan Whitehorn 	OFWMETHOD(ofw_nextprop,			ofw_real_nextprop),
1268446b206SNathan Whitehorn 	OFWMETHOD(ofw_setprop,			ofw_real_setprop),
1278446b206SNathan Whitehorn 	OFWMETHOD(ofw_canon,			ofw_real_canon),
1288446b206SNathan Whitehorn 	OFWMETHOD(ofw_finddevice,		ofw_real_finddevice),
1298446b206SNathan Whitehorn 	OFWMETHOD(ofw_instance_to_path,		ofw_real_instance_to_path),
1308446b206SNathan Whitehorn 	OFWMETHOD(ofw_package_to_path,		ofw_real_package_to_path),
1318446b206SNathan Whitehorn 
1328446b206SNathan Whitehorn 	OFWMETHOD(ofw_test,			ofw_real_test),
1338446b206SNathan Whitehorn 	OFWMETHOD(ofw_call_method,		ofw_real_call_method),
13470d75337SNathan Whitehorn 	OFWMETHOD(ofw_interpret,		ofw_real_interpret),
1358446b206SNathan Whitehorn 	OFWMETHOD(ofw_open,			ofw_real_open),
1368446b206SNathan Whitehorn 	OFWMETHOD(ofw_close,			ofw_real_close),
1378446b206SNathan Whitehorn 	OFWMETHOD(ofw_read,			ofw_real_read),
1388446b206SNathan Whitehorn 	OFWMETHOD(ofw_write,			ofw_real_write),
1398446b206SNathan Whitehorn 	OFWMETHOD(ofw_seek,			ofw_real_seek),
1408446b206SNathan Whitehorn 	OFWMETHOD(ofw_claim,			ofw_real_claim),
1418446b206SNathan Whitehorn 	OFWMETHOD(ofw_release,			ofw_real_release),
1428446b206SNathan Whitehorn 	OFWMETHOD(ofw_enter,			ofw_real_enter),
1438446b206SNathan Whitehorn 	OFWMETHOD(ofw_exit,			ofw_real_exit),
1448446b206SNathan Whitehorn 
1458446b206SNathan Whitehorn 	{ 0, 0 }
1468446b206SNathan Whitehorn };
1478446b206SNathan Whitehorn 
1488446b206SNathan Whitehorn static ofw_def_t ofw_real = {
1498446b206SNathan Whitehorn 	OFW_STD_REAL,
1508446b206SNathan Whitehorn 	ofw_real_methods,
1518446b206SNathan Whitehorn 	0
1528446b206SNathan Whitehorn };
1538446b206SNathan Whitehorn OFW_DEF(ofw_real);
1548446b206SNathan Whitehorn 
15570d75337SNathan Whitehorn static ofw_def_t ofw_32bit = {
15670d75337SNathan Whitehorn 	OFW_STD_32BIT,
15770d75337SNathan Whitehorn 	ofw_real_methods,
15870d75337SNathan Whitehorn 	0
15970d75337SNathan Whitehorn };
16070d75337SNathan Whitehorn OFW_DEF(ofw_32bit);
16170d75337SNathan Whitehorn 
162d745c852SEd Schouten static MALLOC_DEFINE(M_OFWREAL, "ofwreal",
163d745c852SEd Schouten     "Open Firmware Real Mode Bounce Page");
1648446b206SNathan Whitehorn 
1658446b206SNathan Whitehorn static int (*openfirmware)(void *);
1668446b206SNathan Whitehorn 
1678446b206SNathan Whitehorn static vm_offset_t	of_bounce_phys;
1688446b206SNathan Whitehorn static caddr_t		of_bounce_virt;
1698446b206SNathan Whitehorn static off_t		of_bounce_offset;
1708446b206SNathan Whitehorn static size_t		of_bounce_size;
1718446b206SNathan Whitehorn static struct mtx	of_bounce_mtx;
1728446b206SNathan Whitehorn 
17370d75337SNathan Whitehorn extern int		ofw_real_mode;
17470d75337SNathan Whitehorn 
1758446b206SNathan Whitehorn /*
1768446b206SNathan Whitehorn  * After the VM is up, allocate a wired, low memory bounce page.
1778446b206SNathan Whitehorn  */
1788446b206SNathan Whitehorn 
1798446b206SNathan Whitehorn static void ofw_real_bounce_alloc(void *);
1808446b206SNathan Whitehorn 
18170d75337SNathan Whitehorn SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY,
1828446b206SNathan Whitehorn     ofw_real_bounce_alloc, NULL);
1838446b206SNathan Whitehorn 
1848446b206SNathan Whitehorn static void
1858446b206SNathan Whitehorn ofw_real_start(void)
1868446b206SNathan Whitehorn {
1878446b206SNathan Whitehorn 	mtx_lock(&of_bounce_mtx);
1888446b206SNathan Whitehorn 	of_bounce_offset = 0;
1898446b206SNathan Whitehorn }
1908446b206SNathan Whitehorn 
1918446b206SNathan Whitehorn static void
1928446b206SNathan Whitehorn ofw_real_stop(void)
1938446b206SNathan Whitehorn {
1948446b206SNathan Whitehorn 	mtx_unlock(&of_bounce_mtx);
1958446b206SNathan Whitehorn }
1968446b206SNathan Whitehorn 
1978446b206SNathan Whitehorn static void
1988446b206SNathan Whitehorn ofw_real_bounce_alloc(void *junk)
1998446b206SNathan Whitehorn {
200d6d06708SJustin Hibbits 	caddr_t temp;
201d6d06708SJustin Hibbits 
2028446b206SNathan Whitehorn 	/*
2038446b206SNathan Whitehorn 	 * Check that ofw_real is actually in use before allocating wads
2048446b206SNathan Whitehorn 	 * of memory. Do this by checking if our mutex has been set up.
2058446b206SNathan Whitehorn 	 */
2068446b206SNathan Whitehorn 	if (!mtx_initialized(&of_bounce_mtx))
2078446b206SNathan Whitehorn 		return;
2088446b206SNathan Whitehorn 
2098446b206SNathan Whitehorn 	/*
2108446b206SNathan Whitehorn 	 * Allocate a page of contiguous, wired physical memory that can
21117879090SNathan Whitehorn 	 * fit into a 32-bit address space and accessed from real mode.
2128446b206SNathan Whitehorn 	 */
213d6d06708SJustin Hibbits 	temp = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0,
214d6d06708SJustin Hibbits 	    ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
215d6d06708SJustin Hibbits 	    4 * PAGE_SIZE);
216d6d06708SJustin Hibbits 	if (temp == NULL)
217d6d06708SJustin Hibbits 		panic("%s: Not able to allocated contiguous memory\n", __func__);
2188446b206SNathan Whitehorn 
2198446b206SNathan Whitehorn 	mtx_lock(&of_bounce_mtx);
2208446b206SNathan Whitehorn 
221d6d06708SJustin Hibbits 	of_bounce_virt = temp;
22270d75337SNathan Whitehorn 
2238446b206SNathan Whitehorn 	of_bounce_phys = vtophys(of_bounce_virt);
22415b5b0acSJustin Hibbits 	of_bounce_size = 4 * PAGE_SIZE;
2258446b206SNathan Whitehorn 
22670d75337SNathan Whitehorn 	/*
22770d75337SNathan Whitehorn 	 * For virtual-mode OF, direct map this physical address so that
22870d75337SNathan Whitehorn 	 * we have a 32-bit virtual address to give OF.
22970d75337SNathan Whitehorn 	 */
23070d75337SNathan Whitehorn 
231f9edb09dSNathan Whitehorn 	if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0))
23270d75337SNathan Whitehorn 		pmap_kenter(of_bounce_phys, of_bounce_phys);
23370d75337SNathan Whitehorn 
2348446b206SNathan Whitehorn 	mtx_unlock(&of_bounce_mtx);
2358446b206SNathan Whitehorn }
2368446b206SNathan Whitehorn 
2378446b206SNathan Whitehorn static cell_t
2388446b206SNathan Whitehorn ofw_real_map(const void *buf, size_t len)
2398446b206SNathan Whitehorn {
24070d75337SNathan Whitehorn 	static char emergency_buffer[255];
2418446b206SNathan Whitehorn 	cell_t phys;
2428446b206SNathan Whitehorn 
2438446b206SNathan Whitehorn 	mtx_assert(&of_bounce_mtx, MA_OWNED);
2448446b206SNathan Whitehorn 
2458446b206SNathan Whitehorn 	if (of_bounce_virt == NULL) {
24670d75337SNathan Whitehorn 		/*
24770d75337SNathan Whitehorn 		 * If we haven't set up the MMU, then buf is guaranteed
24870d75337SNathan Whitehorn 		 * to be accessible to OF, because the only memory we
24970d75337SNathan Whitehorn 		 * can use right now is memory mapped by firmware.
25070d75337SNathan Whitehorn 		 */
2518446b206SNathan Whitehorn 		if (!pmap_bootstrapped)
252f9edb09dSNathan Whitehorn 			return (cell_t)((uintptr_t)buf & ~DMAP_BASE_ADDRESS);
2538446b206SNathan Whitehorn 
2548446b206SNathan Whitehorn 		/*
2558446b206SNathan Whitehorn 		 * XXX: It is possible for us to get called before the VM has
2568446b206SNathan Whitehorn 		 * come online, but after the MMU is up. We don't have the
2578446b206SNathan Whitehorn 		 * bounce buffer yet, but can no longer presume a 1:1 mapping.
25870d75337SNathan Whitehorn 		 * Copy into the emergency buffer, and reset at the end.
2598446b206SNathan Whitehorn 		 */
26070d75337SNathan Whitehorn 		of_bounce_virt = emergency_buffer;
261f9edb09dSNathan Whitehorn 		of_bounce_phys = (vm_offset_t)of_bounce_virt &
262f9edb09dSNathan Whitehorn 		    ~DMAP_BASE_ADDRESS;
26370d75337SNathan Whitehorn 		of_bounce_size = sizeof(emergency_buffer);
2648446b206SNathan Whitehorn 	}
2658446b206SNathan Whitehorn 
2668446b206SNathan Whitehorn 	/*
2678446b206SNathan Whitehorn 	 * Make sure the bounce page offset satisfies any reasonable
2688446b206SNathan Whitehorn 	 * alignment constraint.
2698446b206SNathan Whitehorn 	 */
270f9edb09dSNathan Whitehorn 	of_bounce_offset += sizeof(register_t) -
271f9edb09dSNathan Whitehorn 	    (of_bounce_offset % sizeof(register_t));
2728446b206SNathan Whitehorn 
2738446b206SNathan Whitehorn 	if (of_bounce_offset + len > of_bounce_size) {
2748446b206SNathan Whitehorn 		panic("Oversize Open Firmware call!");
2758446b206SNathan Whitehorn 		return 0;
2768446b206SNathan Whitehorn 	}
2778446b206SNathan Whitehorn 
278ec664c11SAndreas Tobler 	if (buf != NULL)
2798446b206SNathan Whitehorn 		memcpy(of_bounce_virt + of_bounce_offset, buf, len);
280ec664c11SAndreas Tobler 	else
281ec664c11SAndreas Tobler 		return (0);
282ec664c11SAndreas Tobler 
2838446b206SNathan Whitehorn 	phys = of_bounce_phys + of_bounce_offset;
2848446b206SNathan Whitehorn 
2858446b206SNathan Whitehorn 	of_bounce_offset += len;
2868446b206SNathan Whitehorn 
28770d75337SNathan Whitehorn 	return (phys);
2888446b206SNathan Whitehorn }
2898446b206SNathan Whitehorn 
2908446b206SNathan Whitehorn static void
2918446b206SNathan Whitehorn ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
2928446b206SNathan Whitehorn {
2938446b206SNathan Whitehorn 	mtx_assert(&of_bounce_mtx, MA_OWNED);
2948446b206SNathan Whitehorn 
2958446b206SNathan Whitehorn 	if (of_bounce_virt == NULL)
2968446b206SNathan Whitehorn 		return;
2978446b206SNathan Whitehorn 
298ec664c11SAndreas Tobler 	if (physaddr == 0)
299ec664c11SAndreas Tobler 		return;
300ec664c11SAndreas Tobler 
3018446b206SNathan Whitehorn 	memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
3028446b206SNathan Whitehorn }
3038446b206SNathan Whitehorn 
3048446b206SNathan Whitehorn /* Initialiser */
3058446b206SNathan Whitehorn 
3068297758aSRafal Jaworowski static int
3078446b206SNathan Whitehorn ofw_real_init(ofw_t ofw, void *openfirm)
3088446b206SNathan Whitehorn {
3098446b206SNathan Whitehorn 	openfirmware = (int (*)(void *))openfirm;
3108446b206SNathan Whitehorn 
311d01195e3SChristian Brueffer 	mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF);
3128446b206SNathan Whitehorn 	of_bounce_virt = NULL;
3138297758aSRafal Jaworowski 	return (0);
3148446b206SNathan Whitehorn }
3158446b206SNathan Whitehorn 
3168446b206SNathan Whitehorn /*
3178446b206SNathan Whitehorn  * Generic functions
3188446b206SNathan Whitehorn  */
3198446b206SNathan Whitehorn 
3208446b206SNathan Whitehorn /* Test to see if a service exists. */
3218446b206SNathan Whitehorn static int
3228446b206SNathan Whitehorn ofw_real_test(ofw_t ofw, const char *name)
3238446b206SNathan Whitehorn {
32470d75337SNathan Whitehorn 	vm_offset_t argsptr;
325d4bccd63SNathan Whitehorn 	struct {
3268446b206SNathan Whitehorn 		cell_t name;
3278446b206SNathan Whitehorn 		cell_t nargs;
3288446b206SNathan Whitehorn 		cell_t nreturns;
3298446b206SNathan Whitehorn 		cell_t service;
3308446b206SNathan Whitehorn 		cell_t missing;
33170d75337SNathan Whitehorn 	} args;
33270d75337SNathan Whitehorn 
33370d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"test";
33470d75337SNathan Whitehorn 	args.nargs = 1;
33570d75337SNathan Whitehorn 	args.nreturns = 1;
3368446b206SNathan Whitehorn 
3378446b206SNathan Whitehorn 	ofw_real_start();
3388446b206SNathan Whitehorn 
3398446b206SNathan Whitehorn 	args.service = ofw_real_map(name, strlen(name) + 1);
34070d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
34170d75337SNathan Whitehorn 	if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
3428446b206SNathan Whitehorn 		ofw_real_stop();
3438446b206SNathan Whitehorn 		return (-1);
3448446b206SNathan Whitehorn 	}
34570d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
3468446b206SNathan Whitehorn 	ofw_real_stop();
3478446b206SNathan Whitehorn 	return (args.missing);
3488446b206SNathan Whitehorn }
3498446b206SNathan Whitehorn 
3508446b206SNathan Whitehorn /*
3518446b206SNathan Whitehorn  * Device tree functions
3528446b206SNathan Whitehorn  */
3538446b206SNathan Whitehorn 
3548446b206SNathan Whitehorn /* Return the next sibling of this node or 0. */
3558446b206SNathan Whitehorn static phandle_t
3568446b206SNathan Whitehorn ofw_real_peer(ofw_t ofw, phandle_t node)
3578446b206SNathan Whitehorn {
35870d75337SNathan Whitehorn 	vm_offset_t argsptr;
359d4bccd63SNathan Whitehorn 	struct {
3608446b206SNathan Whitehorn 		cell_t name;
3618446b206SNathan Whitehorn 		cell_t nargs;
3628446b206SNathan Whitehorn 		cell_t nreturns;
3638446b206SNathan Whitehorn 		cell_t node;
3648446b206SNathan Whitehorn 		cell_t next;
36570d75337SNathan Whitehorn 	} args;
36670d75337SNathan Whitehorn 
36770d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"peer";
36870d75337SNathan Whitehorn 	args.nargs = 1;
36970d75337SNathan Whitehorn 	args.nreturns = 1;
3708446b206SNathan Whitehorn 
3718446b206SNathan Whitehorn 	args.node = node;
37270d75337SNathan Whitehorn 	ofw_real_start();
37370d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
37470d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
37570d75337SNathan Whitehorn 		ofw_real_stop();
37665184f89SNathan Whitehorn 		return (0);
37770d75337SNathan Whitehorn 	}
37870d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
37970d75337SNathan Whitehorn 	ofw_real_stop();
3808446b206SNathan Whitehorn 	return (args.next);
3818446b206SNathan Whitehorn }
3828446b206SNathan Whitehorn 
3838446b206SNathan Whitehorn /* Return the first child of this node or 0. */
3848446b206SNathan Whitehorn static phandle_t
3858446b206SNathan Whitehorn ofw_real_child(ofw_t ofw, phandle_t node)
3868446b206SNathan Whitehorn {
38770d75337SNathan Whitehorn 	vm_offset_t argsptr;
388d4bccd63SNathan Whitehorn 	struct {
3898446b206SNathan Whitehorn 		cell_t name;
3908446b206SNathan Whitehorn 		cell_t nargs;
3918446b206SNathan Whitehorn 		cell_t nreturns;
3928446b206SNathan Whitehorn 		cell_t node;
3938446b206SNathan Whitehorn 		cell_t child;
39470d75337SNathan Whitehorn 	} args;
39570d75337SNathan Whitehorn 
39670d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"child";
39770d75337SNathan Whitehorn 	args.nargs = 1;
39870d75337SNathan Whitehorn 	args.nreturns = 1;
3998446b206SNathan Whitehorn 
4008446b206SNathan Whitehorn 	args.node = node;
40170d75337SNathan Whitehorn 	ofw_real_start();
40270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
40370d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
40470d75337SNathan Whitehorn 		ofw_real_stop();
40565184f89SNathan Whitehorn 		return (0);
40670d75337SNathan Whitehorn 	}
40770d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
40870d75337SNathan Whitehorn 	ofw_real_stop();
4098446b206SNathan Whitehorn 	return (args.child);
4108446b206SNathan Whitehorn }
4118446b206SNathan Whitehorn 
4128446b206SNathan Whitehorn /* Return the parent of this node or 0. */
4138446b206SNathan Whitehorn static phandle_t
4148446b206SNathan Whitehorn ofw_real_parent(ofw_t ofw, phandle_t node)
4158446b206SNathan Whitehorn {
41670d75337SNathan Whitehorn 	vm_offset_t argsptr;
417d4bccd63SNathan Whitehorn 	struct {
4188446b206SNathan Whitehorn 		cell_t name;
4198446b206SNathan Whitehorn 		cell_t nargs;
4208446b206SNathan Whitehorn 		cell_t nreturns;
4218446b206SNathan Whitehorn 		cell_t node;
4228446b206SNathan Whitehorn 		cell_t parent;
42370d75337SNathan Whitehorn 	} args;
42470d75337SNathan Whitehorn 
42570d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"parent";
42670d75337SNathan Whitehorn 	args.nargs = 1;
42770d75337SNathan Whitehorn 	args.nreturns = 1;
4288446b206SNathan Whitehorn 
4298446b206SNathan Whitehorn 	args.node = node;
43070d75337SNathan Whitehorn 	ofw_real_start();
43170d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
43270d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
43370d75337SNathan Whitehorn 		ofw_real_stop();
43465184f89SNathan Whitehorn 		return (0);
43570d75337SNathan Whitehorn 	}
43670d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
43770d75337SNathan Whitehorn 	ofw_real_stop();
4388446b206SNathan Whitehorn 	return (args.parent);
4398446b206SNathan Whitehorn }
4408446b206SNathan Whitehorn 
4418446b206SNathan Whitehorn /* Return the package handle that corresponds to an instance handle. */
4428446b206SNathan Whitehorn static phandle_t
4438446b206SNathan Whitehorn ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
4448446b206SNathan Whitehorn {
44570d75337SNathan Whitehorn 	vm_offset_t argsptr;
446d4bccd63SNathan Whitehorn 	struct {
4478446b206SNathan Whitehorn 		cell_t name;
4488446b206SNathan Whitehorn 		cell_t nargs;
4498446b206SNathan Whitehorn 		cell_t nreturns;
4508446b206SNathan Whitehorn 		cell_t instance;
4518446b206SNathan Whitehorn 		cell_t package;
45270d75337SNathan Whitehorn 	} args;
45370d75337SNathan Whitehorn 
45470d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"instance-to-package";
45570d75337SNathan Whitehorn 	args.nargs = 1;
45670d75337SNathan Whitehorn 	args.nreturns = 1;
4578446b206SNathan Whitehorn 
4588446b206SNathan Whitehorn 	args.instance = instance;
45970d75337SNathan Whitehorn 	ofw_real_start();
46070d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
46170d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
46270d75337SNathan Whitehorn 		ofw_real_stop();
4638446b206SNathan Whitehorn 		return (-1);
46470d75337SNathan Whitehorn 	}
46570d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
46670d75337SNathan Whitehorn 	ofw_real_stop();
4678446b206SNathan Whitehorn 	return (args.package);
4688446b206SNathan Whitehorn }
4698446b206SNathan Whitehorn 
4708446b206SNathan Whitehorn /* Get the length of a property of a package. */
4718446b206SNathan Whitehorn static ssize_t
4728446b206SNathan Whitehorn ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
4738446b206SNathan Whitehorn {
47470d75337SNathan Whitehorn 	vm_offset_t argsptr;
475d4bccd63SNathan Whitehorn 	struct {
4768446b206SNathan Whitehorn 		cell_t name;
4778446b206SNathan Whitehorn 		cell_t nargs;
4788446b206SNathan Whitehorn 		cell_t nreturns;
4798446b206SNathan Whitehorn 		cell_t package;
4808446b206SNathan Whitehorn 		cell_t propname;
48170d75337SNathan Whitehorn 		int32_t proplen;
48270d75337SNathan Whitehorn 	} args;
48370d75337SNathan Whitehorn 
48470d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"getproplen";
48570d75337SNathan Whitehorn 	args.nargs = 2;
48670d75337SNathan Whitehorn 	args.nreturns = 1;
4878446b206SNathan Whitehorn 
4888446b206SNathan Whitehorn 	ofw_real_start();
4898446b206SNathan Whitehorn 
4908446b206SNathan Whitehorn 	args.package = package;
4918446b206SNathan Whitehorn 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
49270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
49370d75337SNathan Whitehorn 	if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
4948446b206SNathan Whitehorn 		ofw_real_stop();
4958446b206SNathan Whitehorn 		return (-1);
4968446b206SNathan Whitehorn 	}
49770d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
4988446b206SNathan Whitehorn 	ofw_real_stop();
4998446b206SNathan Whitehorn 	return (args.proplen);
5008446b206SNathan Whitehorn }
5018446b206SNathan Whitehorn 
5028446b206SNathan Whitehorn /* Get the value of a property of a package. */
5038446b206SNathan Whitehorn static ssize_t
5048446b206SNathan Whitehorn ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
5058446b206SNathan Whitehorn     size_t buflen)
5068446b206SNathan Whitehorn {
50770d75337SNathan Whitehorn 	vm_offset_t argsptr;
508d4bccd63SNathan Whitehorn 	struct {
5098446b206SNathan Whitehorn 		cell_t name;
5108446b206SNathan Whitehorn 		cell_t nargs;
5118446b206SNathan Whitehorn 		cell_t nreturns;
5128446b206SNathan Whitehorn 		cell_t package;
5138446b206SNathan Whitehorn 		cell_t propname;
5148446b206SNathan Whitehorn 		cell_t buf;
5158446b206SNathan Whitehorn 		cell_t buflen;
51670d75337SNathan Whitehorn 		int32_t size;
51770d75337SNathan Whitehorn 	} args;
51870d75337SNathan Whitehorn 
51970d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"getprop";
52070d75337SNathan Whitehorn 	args.nargs = 4;
52170d75337SNathan Whitehorn 	args.nreturns = 1;
5228446b206SNathan Whitehorn 
5238446b206SNathan Whitehorn 	ofw_real_start();
5248446b206SNathan Whitehorn 
5258446b206SNathan Whitehorn 	args.package = package;
5268446b206SNathan Whitehorn 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
5278446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, buflen);
5288446b206SNathan Whitehorn 	args.buflen = buflen;
52970d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
53070d75337SNathan Whitehorn 	if (args.propname == 0 || args.buf == 0 ||
53170d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
5328446b206SNathan Whitehorn 		ofw_real_stop();
5338446b206SNathan Whitehorn 		return (-1);
5348446b206SNathan Whitehorn 	}
53570d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
5368446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, buflen);
5378446b206SNathan Whitehorn 
5388446b206SNathan Whitehorn 	ofw_real_stop();
5398446b206SNathan Whitehorn 	return (args.size);
5408446b206SNathan Whitehorn }
5418446b206SNathan Whitehorn 
5428446b206SNathan Whitehorn /* Get the next property of a package. */
5438446b206SNathan Whitehorn static int
5448446b206SNathan Whitehorn ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
5458446b206SNathan Whitehorn     char *buf, size_t size)
5468446b206SNathan Whitehorn {
54770d75337SNathan Whitehorn 	vm_offset_t argsptr;
548d4bccd63SNathan Whitehorn 	struct {
5498446b206SNathan Whitehorn 		cell_t name;
5508446b206SNathan Whitehorn 		cell_t nargs;
5518446b206SNathan Whitehorn 		cell_t nreturns;
5528446b206SNathan Whitehorn 		cell_t package;
5538446b206SNathan Whitehorn 		cell_t previous;
5548446b206SNathan Whitehorn 		cell_t buf;
5558446b206SNathan Whitehorn 		cell_t flag;
55670d75337SNathan Whitehorn 	} args;
55770d75337SNathan Whitehorn 
55870d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"nextprop";
55970d75337SNathan Whitehorn 	args.nargs = 3;
56070d75337SNathan Whitehorn 	args.nreturns = 1;
5618446b206SNathan Whitehorn 
5628446b206SNathan Whitehorn 	ofw_real_start();
5638446b206SNathan Whitehorn 
5648446b206SNathan Whitehorn 	args.package = package;
565ec664c11SAndreas Tobler 	args.previous = ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0);
5668446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, size);
56770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
568ec664c11SAndreas Tobler 	if (args.buf == 0 || openfirmware((void *)argsptr) == -1) {
5698446b206SNathan Whitehorn 		ofw_real_stop();
5708446b206SNathan Whitehorn 		return (-1);
5718446b206SNathan Whitehorn 	}
57270d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
5738446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, size);
5748446b206SNathan Whitehorn 
5758446b206SNathan Whitehorn 	ofw_real_stop();
5768446b206SNathan Whitehorn 	return (args.flag);
5778446b206SNathan Whitehorn }
5788446b206SNathan Whitehorn 
5798446b206SNathan Whitehorn /* Set the value of a property of a package. */
5808446b206SNathan Whitehorn /* XXX Has a bug on FirePower */
5818446b206SNathan Whitehorn static int
5824fc23012SAndriy Gapon ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
5834fc23012SAndriy Gapon     const void *buf, size_t len)
5848446b206SNathan Whitehorn {
58570d75337SNathan Whitehorn 	vm_offset_t argsptr;
586d4bccd63SNathan Whitehorn 	struct {
5878446b206SNathan Whitehorn 		cell_t name;
5888446b206SNathan Whitehorn 		cell_t nargs;
5898446b206SNathan Whitehorn 		cell_t nreturns;
5908446b206SNathan Whitehorn 		cell_t package;
5918446b206SNathan Whitehorn 		cell_t propname;
5928446b206SNathan Whitehorn 		cell_t buf;
5938446b206SNathan Whitehorn 		cell_t len;
5948446b206SNathan Whitehorn 		cell_t size;
59570d75337SNathan Whitehorn 	} args;
59670d75337SNathan Whitehorn 
59770d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"setprop";
59870d75337SNathan Whitehorn 	args.nargs = 4;
59970d75337SNathan Whitehorn 	args.nreturns = 1;
6008446b206SNathan Whitehorn 
6018446b206SNathan Whitehorn 	ofw_real_start();
6028446b206SNathan Whitehorn 
6038446b206SNathan Whitehorn 	args.package = package;
6048446b206SNathan Whitehorn 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
6058446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
6068446b206SNathan Whitehorn 	args.len = len;
60770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
60870d75337SNathan Whitehorn 	if (args.propname == 0 || args.buf == 0 ||
60970d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
6108446b206SNathan Whitehorn 		ofw_real_stop();
6118446b206SNathan Whitehorn 		return (-1);
6128446b206SNathan Whitehorn 	}
61370d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
6148446b206SNathan Whitehorn 	ofw_real_stop();
6158446b206SNathan Whitehorn 	return (args.size);
6168446b206SNathan Whitehorn }
6178446b206SNathan Whitehorn 
6188446b206SNathan Whitehorn /* Convert a device specifier to a fully qualified pathname. */
6198446b206SNathan Whitehorn static ssize_t
6208446b206SNathan Whitehorn ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
6218446b206SNathan Whitehorn {
62270d75337SNathan Whitehorn 	vm_offset_t argsptr;
623d4bccd63SNathan Whitehorn 	struct {
6248446b206SNathan Whitehorn 		cell_t name;
6258446b206SNathan Whitehorn 		cell_t nargs;
6268446b206SNathan Whitehorn 		cell_t nreturns;
6278446b206SNathan Whitehorn 		cell_t device;
6288446b206SNathan Whitehorn 		cell_t buf;
6298446b206SNathan Whitehorn 		cell_t len;
63070d75337SNathan Whitehorn 		int32_t size;
63170d75337SNathan Whitehorn 	} args;
63270d75337SNathan Whitehorn 
63370d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"canon";
63470d75337SNathan Whitehorn 	args.nargs = 3;
63570d75337SNathan Whitehorn 	args.nreturns = 1;
6368446b206SNathan Whitehorn 
6378446b206SNathan Whitehorn 	ofw_real_start();
6388446b206SNathan Whitehorn 
6398446b206SNathan Whitehorn 	args.device = ofw_real_map(device, strlen(device) + 1);
6408446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
6418446b206SNathan Whitehorn 	args.len = len;
64270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
64370d75337SNathan Whitehorn 	if (args.device == 0 || args.buf == 0 ||
64470d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
6458446b206SNathan Whitehorn 		ofw_real_stop();
6468446b206SNathan Whitehorn 		return (-1);
6478446b206SNathan Whitehorn 	}
64870d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
6498446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, len);
6508446b206SNathan Whitehorn 
6518446b206SNathan Whitehorn 	ofw_real_stop();
6528446b206SNathan Whitehorn 	return (args.size);
6538446b206SNathan Whitehorn }
6548446b206SNathan Whitehorn 
6558446b206SNathan Whitehorn /* Return a package handle for the specified device. */
6568446b206SNathan Whitehorn static phandle_t
6578446b206SNathan Whitehorn ofw_real_finddevice(ofw_t ofw, const char *device)
6588446b206SNathan Whitehorn {
65970d75337SNathan Whitehorn 	vm_offset_t argsptr;
660d4bccd63SNathan Whitehorn 	struct {
6618446b206SNathan Whitehorn 		cell_t name;
6628446b206SNathan Whitehorn 		cell_t nargs;
6638446b206SNathan Whitehorn 		cell_t nreturns;
6648446b206SNathan Whitehorn 		cell_t device;
6658446b206SNathan Whitehorn 		cell_t package;
66670d75337SNathan Whitehorn 	} args;
66770d75337SNathan Whitehorn 
66870d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"finddevice";
66970d75337SNathan Whitehorn 	args.nargs = 1;
67070d75337SNathan Whitehorn 	args.nreturns = 1;
6718446b206SNathan Whitehorn 
6728446b206SNathan Whitehorn 	ofw_real_start();
6738446b206SNathan Whitehorn 
6748446b206SNathan Whitehorn 	args.device = ofw_real_map(device, strlen(device) + 1);
67570d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
67670d75337SNathan Whitehorn 	if (args.device == 0 ||
67770d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
6788446b206SNathan Whitehorn 		ofw_real_stop();
6798446b206SNathan Whitehorn 		return (-1);
6808446b206SNathan Whitehorn 	}
68170d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
6828446b206SNathan Whitehorn 	ofw_real_stop();
6838446b206SNathan Whitehorn 	return (args.package);
6848446b206SNathan Whitehorn }
6858446b206SNathan Whitehorn 
6868446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to an instance. */
6878446b206SNathan Whitehorn static ssize_t
6888446b206SNathan Whitehorn ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
6898446b206SNathan Whitehorn {
69070d75337SNathan Whitehorn 	vm_offset_t argsptr;
691d4bccd63SNathan Whitehorn 	struct {
6928446b206SNathan Whitehorn 		cell_t name;
6938446b206SNathan Whitehorn 		cell_t nargs;
6948446b206SNathan Whitehorn 		cell_t nreturns;
6958446b206SNathan Whitehorn 		cell_t instance;
6968446b206SNathan Whitehorn 		cell_t buf;
6978446b206SNathan Whitehorn 		cell_t len;
69870d75337SNathan Whitehorn 		int32_t size;
69970d75337SNathan Whitehorn 	} args;
70070d75337SNathan Whitehorn 
70170d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"instance-to-path";
70270d75337SNathan Whitehorn 	args.nargs = 3;
70370d75337SNathan Whitehorn 	args.nreturns = 1;
7048446b206SNathan Whitehorn 
7058446b206SNathan Whitehorn 	ofw_real_start();
7068446b206SNathan Whitehorn 
7078446b206SNathan Whitehorn 	args.instance = instance;
7088446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
7098446b206SNathan Whitehorn 	args.len = len;
71070d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
71170d75337SNathan Whitehorn 	if (args.buf == 0 ||
71270d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
7138446b206SNathan Whitehorn 		ofw_real_stop();
7148446b206SNathan Whitehorn 		return (-1);
7158446b206SNathan Whitehorn 	}
71670d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
7178446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, len);
7188446b206SNathan Whitehorn 
7198446b206SNathan Whitehorn 	ofw_real_stop();
7208446b206SNathan Whitehorn 	return (args.size);
7218446b206SNathan Whitehorn }
7228446b206SNathan Whitehorn 
7238446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to a package. */
7248446b206SNathan Whitehorn static ssize_t
7258446b206SNathan Whitehorn ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
7268446b206SNathan Whitehorn {
72770d75337SNathan Whitehorn 	vm_offset_t argsptr;
728d4bccd63SNathan Whitehorn 	struct {
7298446b206SNathan Whitehorn 		cell_t name;
7308446b206SNathan Whitehorn 		cell_t nargs;
7318446b206SNathan Whitehorn 		cell_t nreturns;
7328446b206SNathan Whitehorn 		cell_t package;
7338446b206SNathan Whitehorn 		cell_t buf;
7348446b206SNathan Whitehorn 		cell_t len;
73570d75337SNathan Whitehorn 		int32_t size;
73670d75337SNathan Whitehorn 	} args;
73770d75337SNathan Whitehorn 
73870d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"package-to-path";
73970d75337SNathan Whitehorn 	args.nargs = 3;
74070d75337SNathan Whitehorn 	args.nreturns = 1;
7418446b206SNathan Whitehorn 
7428446b206SNathan Whitehorn 	ofw_real_start();
7438446b206SNathan Whitehorn 
7448446b206SNathan Whitehorn 	args.package = package;
7458446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
7468446b206SNathan Whitehorn 	args.len = len;
74770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
74870d75337SNathan Whitehorn 	if (args.buf == 0 ||
74970d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
7508446b206SNathan Whitehorn 		ofw_real_stop();
7518446b206SNathan Whitehorn 		return (-1);
7528446b206SNathan Whitehorn 	}
75370d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
7548446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, len);
7558446b206SNathan Whitehorn 
7568446b206SNathan Whitehorn 	ofw_real_stop();
7578446b206SNathan Whitehorn 	return (args.size);
7588446b206SNathan Whitehorn }
7598446b206SNathan Whitehorn 
7608446b206SNathan Whitehorn /*  Call the method in the scope of a given instance. */
7618446b206SNathan Whitehorn static int
7628446b206SNathan Whitehorn ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
763054e5dcbSNathan Whitehorn     int nargs, int nreturns, cell_t *args_and_returns)
7648446b206SNathan Whitehorn {
76570d75337SNathan Whitehorn 	vm_offset_t argsptr;
766d4bccd63SNathan Whitehorn 	struct {
7678446b206SNathan Whitehorn 		cell_t name;
7688446b206SNathan Whitehorn 		cell_t nargs;
7698446b206SNathan Whitehorn 		cell_t nreturns;
7708446b206SNathan Whitehorn 		cell_t method;
7718446b206SNathan Whitehorn 		cell_t instance;
7728446b206SNathan Whitehorn 		cell_t args_n_results[12];
77370d75337SNathan Whitehorn 	} args;
774cdb25d82SMarius Strobl 	cell_t *ap, *cp;
7758446b206SNathan Whitehorn 	int n;
7768446b206SNathan Whitehorn 
77770d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"call-method";
77870d75337SNathan Whitehorn 	args.nargs = 2;
77970d75337SNathan Whitehorn 	args.nreturns = 1;
78070d75337SNathan Whitehorn 
7818446b206SNathan Whitehorn 	if (nargs > 6)
7828446b206SNathan Whitehorn 		return (-1);
7838446b206SNathan Whitehorn 
7848446b206SNathan Whitehorn 	ofw_real_start();
7858446b206SNathan Whitehorn 	args.nargs = nargs + 2;
7868446b206SNathan Whitehorn 	args.nreturns = nreturns + 1;
7878446b206SNathan Whitehorn 	args.method = ofw_real_map(method, strlen(method) + 1);
7888446b206SNathan Whitehorn 	args.instance = instance;
7898446b206SNathan Whitehorn 
7908446b206SNathan Whitehorn 	ap = args_and_returns;
7918446b206SNathan Whitehorn 	for (cp = args.args_n_results + (n = nargs); --n >= 0;)
7928446b206SNathan Whitehorn 		*--cp = *(ap++);
79370d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
79470d75337SNathan Whitehorn 	if (args.method == 0 ||
79570d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
7968446b206SNathan Whitehorn 		ofw_real_stop();
7978446b206SNathan Whitehorn 		return (-1);
7988446b206SNathan Whitehorn 	}
79970d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
8008446b206SNathan Whitehorn 	ofw_real_stop();
8018446b206SNathan Whitehorn 	if (args.args_n_results[nargs])
8028446b206SNathan Whitehorn 		return (args.args_n_results[nargs]);
8038446b206SNathan Whitehorn 	for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
8048446b206SNathan Whitehorn 		*(ap++) = *--cp;
8058446b206SNathan Whitehorn 	return (0);
8068446b206SNathan Whitehorn }
8078446b206SNathan Whitehorn 
80870d75337SNathan Whitehorn static int
809cdb25d82SMarius Strobl ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
81070d75337SNathan Whitehorn {
81170d75337SNathan Whitehorn 	vm_offset_t argsptr;
81270d75337SNathan Whitehorn 	struct {
81370d75337SNathan Whitehorn 		cell_t name;
81470d75337SNathan Whitehorn 		cell_t nargs;
81570d75337SNathan Whitehorn 		cell_t nreturns;
81670d75337SNathan Whitehorn 		cell_t slot[16];
81770d75337SNathan Whitehorn 	} args;
81870d75337SNathan Whitehorn 	cell_t status;
81970d75337SNathan Whitehorn 	int i = 0, j = 0;
82070d75337SNathan Whitehorn 
82170d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"interpret";
82270d75337SNathan Whitehorn 	args.nargs = 1;
82370d75337SNathan Whitehorn 
82470d75337SNathan Whitehorn 	ofw_real_start();
82570d75337SNathan Whitehorn 	args.nreturns = ++nreturns;
82670d75337SNathan Whitehorn 	args.slot[i++] = ofw_real_map(cmd, strlen(cmd) + 1);
82770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
82870d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
82970d75337SNathan Whitehorn 		ofw_real_stop();
83070d75337SNathan Whitehorn 		return (-1);
83170d75337SNathan Whitehorn 	}
83270d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
83370d75337SNathan Whitehorn 	ofw_real_stop();
83470d75337SNathan Whitehorn 	status = args.slot[i++];
83570d75337SNathan Whitehorn 	while (i < 1 + nreturns)
83670d75337SNathan Whitehorn 		returns[j++] = args.slot[i++];
83770d75337SNathan Whitehorn 	return (status);
83870d75337SNathan Whitehorn }
83970d75337SNathan Whitehorn 
8408446b206SNathan Whitehorn /*
8418446b206SNathan Whitehorn  * Device I/O functions
8428446b206SNathan Whitehorn  */
8438446b206SNathan Whitehorn 
8448446b206SNathan Whitehorn /* Open an instance for a device. */
8458446b206SNathan Whitehorn static ihandle_t
8468446b206SNathan Whitehorn ofw_real_open(ofw_t ofw, const char *device)
8478446b206SNathan Whitehorn {
84870d75337SNathan Whitehorn 	vm_offset_t argsptr;
849d4bccd63SNathan Whitehorn 	struct {
8508446b206SNathan Whitehorn 		cell_t name;
8518446b206SNathan Whitehorn 		cell_t nargs;
8528446b206SNathan Whitehorn 		cell_t nreturns;
8538446b206SNathan Whitehorn 		cell_t device;
8548446b206SNathan Whitehorn 		cell_t instance;
85570d75337SNathan Whitehorn 	} args;
85670d75337SNathan Whitehorn 
85770d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"open";
85870d75337SNathan Whitehorn 	args.nargs = 1;
85970d75337SNathan Whitehorn 	args.nreturns = 1;
8608446b206SNathan Whitehorn 
8618446b206SNathan Whitehorn 	ofw_real_start();
8628446b206SNathan Whitehorn 
8638446b206SNathan Whitehorn 	args.device = ofw_real_map(device, strlen(device) + 1);
86470d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
86570d75337SNathan Whitehorn 	if (args.device == 0 || openfirmware((void *)argsptr) == -1
8668446b206SNathan Whitehorn 	    || args.instance == 0) {
8678446b206SNathan Whitehorn 		ofw_real_stop();
8688446b206SNathan Whitehorn 		return (-1);
8698446b206SNathan Whitehorn 	}
87070d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
8718446b206SNathan Whitehorn 	ofw_real_stop();
8728446b206SNathan Whitehorn 	return (args.instance);
8738446b206SNathan Whitehorn }
8748446b206SNathan Whitehorn 
8758446b206SNathan Whitehorn /* Close an instance. */
8768446b206SNathan Whitehorn static void
8778446b206SNathan Whitehorn ofw_real_close(ofw_t ofw, ihandle_t instance)
8788446b206SNathan Whitehorn {
87970d75337SNathan Whitehorn 	vm_offset_t argsptr;
880d4bccd63SNathan Whitehorn 	struct {
8818446b206SNathan Whitehorn 		cell_t name;
8828446b206SNathan Whitehorn 		cell_t nargs;
8838446b206SNathan Whitehorn 		cell_t nreturns;
8848446b206SNathan Whitehorn 		cell_t instance;
88570d75337SNathan Whitehorn 	} args;
8868446b206SNathan Whitehorn 
88770d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"close";
88870d75337SNathan Whitehorn 	args.nargs = 1;
88970d75337SNathan Whitehorn 	args.nreturns = 0;
8908446b206SNathan Whitehorn 	args.instance = instance;
89170d75337SNathan Whitehorn 	ofw_real_start();
89270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
89370d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
89470d75337SNathan Whitehorn 	ofw_real_stop();
8958446b206SNathan Whitehorn }
8968446b206SNathan Whitehorn 
8978446b206SNathan Whitehorn /* Read from an instance. */
8988446b206SNathan Whitehorn static ssize_t
8998446b206SNathan Whitehorn ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
9008446b206SNathan Whitehorn {
90170d75337SNathan Whitehorn 	vm_offset_t argsptr;
902d4bccd63SNathan Whitehorn 	struct {
9038446b206SNathan Whitehorn 		cell_t name;
9048446b206SNathan Whitehorn 		cell_t nargs;
9058446b206SNathan Whitehorn 		cell_t nreturns;
9068446b206SNathan Whitehorn 		cell_t instance;
9078446b206SNathan Whitehorn 		cell_t addr;
9088446b206SNathan Whitehorn 		cell_t len;
90970d75337SNathan Whitehorn 		int32_t actual;
91070d75337SNathan Whitehorn 	} args;
91170d75337SNathan Whitehorn 
91270d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"read";
91370d75337SNathan Whitehorn 	args.nargs = 3;
91470d75337SNathan Whitehorn 	args.nreturns = 1;
9158446b206SNathan Whitehorn 
9168446b206SNathan Whitehorn 	ofw_real_start();
9178446b206SNathan Whitehorn 
9188446b206SNathan Whitehorn 	args.instance = instance;
9198446b206SNathan Whitehorn 	args.addr = ofw_real_map(addr, len);
9208446b206SNathan Whitehorn 	args.len = len;
92170d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
92270d75337SNathan Whitehorn 	if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
9238446b206SNathan Whitehorn 		ofw_real_stop();
9248446b206SNathan Whitehorn 		return (-1);
9258446b206SNathan Whitehorn 	}
92670d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
9278446b206SNathan Whitehorn 	ofw_real_unmap(args.addr, addr, len);
9288446b206SNathan Whitehorn 
9298446b206SNathan Whitehorn 	ofw_real_stop();
9308446b206SNathan Whitehorn 	return (args.actual);
9318446b206SNathan Whitehorn }
9328446b206SNathan Whitehorn 
9338446b206SNathan Whitehorn /* Write to an instance. */
9348446b206SNathan Whitehorn static ssize_t
9358446b206SNathan Whitehorn ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
9368446b206SNathan Whitehorn {
93770d75337SNathan Whitehorn 	vm_offset_t argsptr;
938d4bccd63SNathan Whitehorn 	struct {
9398446b206SNathan Whitehorn 		cell_t name;
9408446b206SNathan Whitehorn 		cell_t nargs;
9418446b206SNathan Whitehorn 		cell_t nreturns;
9428446b206SNathan Whitehorn 		cell_t instance;
9438446b206SNathan Whitehorn 		cell_t addr;
9448446b206SNathan Whitehorn 		cell_t len;
94570d75337SNathan Whitehorn 		int32_t actual;
94670d75337SNathan Whitehorn 	} args;
94770d75337SNathan Whitehorn 
94870d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"write";
94970d75337SNathan Whitehorn 	args.nargs = 3;
95070d75337SNathan Whitehorn 	args.nreturns = 1;
9518446b206SNathan Whitehorn 
9528446b206SNathan Whitehorn 	ofw_real_start();
9538446b206SNathan Whitehorn 
9548446b206SNathan Whitehorn 	args.instance = instance;
9558446b206SNathan Whitehorn 	args.addr = ofw_real_map(addr, len);
9568446b206SNathan Whitehorn 	args.len = len;
95770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
95870d75337SNathan Whitehorn 	if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
9598446b206SNathan Whitehorn 		ofw_real_stop();
9608446b206SNathan Whitehorn 		return (-1);
9618446b206SNathan Whitehorn 	}
96270d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
9638446b206SNathan Whitehorn 	ofw_real_stop();
9648446b206SNathan Whitehorn 	return (args.actual);
9658446b206SNathan Whitehorn }
9668446b206SNathan Whitehorn 
9678446b206SNathan Whitehorn /* Seek to a position. */
9688446b206SNathan Whitehorn static int
9698446b206SNathan Whitehorn ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
9708446b206SNathan Whitehorn {
97170d75337SNathan Whitehorn 	vm_offset_t argsptr;
972d4bccd63SNathan Whitehorn 	struct {
9738446b206SNathan Whitehorn 		cell_t name;
9748446b206SNathan Whitehorn 		cell_t nargs;
9758446b206SNathan Whitehorn 		cell_t nreturns;
9768446b206SNathan Whitehorn 		cell_t instance;
9778446b206SNathan Whitehorn 		cell_t poshi;
9788446b206SNathan Whitehorn 		cell_t poslo;
9798446b206SNathan Whitehorn 		cell_t status;
98070d75337SNathan Whitehorn 	} args;
98170d75337SNathan Whitehorn 
98270d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"seek";
98370d75337SNathan Whitehorn 	args.nargs = 3;
98470d75337SNathan Whitehorn 	args.nreturns = 1;
9858446b206SNathan Whitehorn 
9868446b206SNathan Whitehorn 	args.instance = instance;
9878446b206SNathan Whitehorn 	args.poshi = pos >> 32;
9888446b206SNathan Whitehorn 	args.poslo = pos;
98970d75337SNathan Whitehorn 	ofw_real_start();
99070d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
99170d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
99270d75337SNathan Whitehorn 		ofw_real_stop();
9938446b206SNathan Whitehorn 		return (-1);
99470d75337SNathan Whitehorn 	}
99570d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
99670d75337SNathan Whitehorn 	ofw_real_stop();
9978446b206SNathan Whitehorn 	return (args.status);
9988446b206SNathan Whitehorn }
9998446b206SNathan Whitehorn 
10008446b206SNathan Whitehorn /*
10018446b206SNathan Whitehorn  * Memory functions
10028446b206SNathan Whitehorn  */
10038446b206SNathan Whitehorn 
10048446b206SNathan Whitehorn /* Claim an area of memory. */
10058446b206SNathan Whitehorn static caddr_t
10068446b206SNathan Whitehorn ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
10078446b206SNathan Whitehorn {
100870d75337SNathan Whitehorn 	vm_offset_t argsptr;
1009d4bccd63SNathan Whitehorn 	struct {
10108446b206SNathan Whitehorn 		cell_t name;
10118446b206SNathan Whitehorn 		cell_t nargs;
10128446b206SNathan Whitehorn 		cell_t nreturns;
10138446b206SNathan Whitehorn 		cell_t virt;
10148446b206SNathan Whitehorn 		cell_t size;
10158446b206SNathan Whitehorn 		cell_t align;
10168446b206SNathan Whitehorn 		cell_t baseaddr;
101770d75337SNathan Whitehorn 	} args;
10188446b206SNathan Whitehorn 
101970d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"claim";
102070d75337SNathan Whitehorn 	args.nargs = 3;
102170d75337SNathan Whitehorn 	args.nreturns = 1;
102270d75337SNathan Whitehorn 
102370d75337SNathan Whitehorn 	args.virt = (cell_t)(uintptr_t)virt;
10248446b206SNathan Whitehorn 	args.size = size;
10258446b206SNathan Whitehorn 	args.align = align;
102670d75337SNathan Whitehorn 	ofw_real_start();
102770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
102870d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
102970d75337SNathan Whitehorn 		ofw_real_stop();
10308446b206SNathan Whitehorn 		return ((void *)-1);
103170d75337SNathan Whitehorn 	}
103270d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
103370d75337SNathan Whitehorn 	ofw_real_stop();
103470d75337SNathan Whitehorn 	return ((void *)(uintptr_t)args.baseaddr);
10358446b206SNathan Whitehorn }
10368446b206SNathan Whitehorn 
10378446b206SNathan Whitehorn /* Release an area of memory. */
10388446b206SNathan Whitehorn static void
10398446b206SNathan Whitehorn ofw_real_release(ofw_t ofw, void *virt, size_t size)
10408446b206SNathan Whitehorn {
104170d75337SNathan Whitehorn 	vm_offset_t argsptr;
1042d4bccd63SNathan Whitehorn 	struct {
10438446b206SNathan Whitehorn 		cell_t name;
10448446b206SNathan Whitehorn 		cell_t nargs;
10458446b206SNathan Whitehorn 		cell_t nreturns;
10468446b206SNathan Whitehorn 		cell_t virt;
10478446b206SNathan Whitehorn 		cell_t size;
104870d75337SNathan Whitehorn 	} args;
10498446b206SNathan Whitehorn 
105070d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"release";
105170d75337SNathan Whitehorn 	args.nargs = 2;
105270d75337SNathan Whitehorn 	args.nreturns = 0;
105370d75337SNathan Whitehorn 
105470d75337SNathan Whitehorn 	args.virt = (cell_t)(uintptr_t)virt;
10558446b206SNathan Whitehorn 	args.size = size;
105670d75337SNathan Whitehorn 	ofw_real_start();
105770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
105870d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
105970d75337SNathan Whitehorn 	ofw_real_stop();
10608446b206SNathan Whitehorn }
10618446b206SNathan Whitehorn 
10628446b206SNathan Whitehorn /*
10638446b206SNathan Whitehorn  * Control transfer functions
10648446b206SNathan Whitehorn  */
10658446b206SNathan Whitehorn 
10668446b206SNathan Whitehorn /* Suspend and drop back to the Open Firmware interface. */
10678446b206SNathan Whitehorn static void
10688446b206SNathan Whitehorn ofw_real_enter(ofw_t ofw)
10698446b206SNathan Whitehorn {
107070d75337SNathan Whitehorn 	vm_offset_t argsptr;
1071d4bccd63SNathan Whitehorn 	struct {
10728446b206SNathan Whitehorn 		cell_t name;
10738446b206SNathan Whitehorn 		cell_t nargs;
10748446b206SNathan Whitehorn 		cell_t nreturns;
107570d75337SNathan Whitehorn 	} args;
10768446b206SNathan Whitehorn 
107770d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"enter";
107870d75337SNathan Whitehorn 	args.nargs = 0;
107970d75337SNathan Whitehorn 	args.nreturns = 0;
108070d75337SNathan Whitehorn 
108170d75337SNathan Whitehorn 	ofw_real_start();
108270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
108370d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
10848446b206SNathan Whitehorn 	/* We may come back. */
108570d75337SNathan Whitehorn 	ofw_real_stop();
10868446b206SNathan Whitehorn }
10878446b206SNathan Whitehorn 
10888446b206SNathan Whitehorn /* Shut down and drop back to the Open Firmware interface. */
10898446b206SNathan Whitehorn static void
10908446b206SNathan Whitehorn ofw_real_exit(ofw_t ofw)
10918446b206SNathan Whitehorn {
109270d75337SNathan Whitehorn 	vm_offset_t argsptr;
1093d4bccd63SNathan Whitehorn 	struct {
10948446b206SNathan Whitehorn 		cell_t name;
10958446b206SNathan Whitehorn 		cell_t nargs;
10968446b206SNathan Whitehorn 		cell_t nreturns;
109770d75337SNathan Whitehorn 	} args;
10988446b206SNathan Whitehorn 
109970d75337SNathan Whitehorn 	args.name = (cell_t)(uintptr_t)"exit";
110070d75337SNathan Whitehorn 	args.nargs = 0;
110170d75337SNathan Whitehorn 	args.nreturns = 0;
110270d75337SNathan Whitehorn 
110370d75337SNathan Whitehorn 	ofw_real_start();
110470d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
110570d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
11068446b206SNathan Whitehorn 	for (;;)			/* just in case */
11078446b206SNathan Whitehorn 		;
110870d75337SNathan Whitehorn 	ofw_real_stop();
11098446b206SNathan Whitehorn }
11108446b206SNathan Whitehorn 
1111